blob: e9d4eb6144e1f4ce9f536a5f319591a23269c7fd [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 }
Nick Desaulniers49a41362020-11-15 20:35:32 -0800358 break;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000359 default:
360 break;
361 }
362
363 return -EINVAL;
364}
365#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000366
367/* This is the one and *ONLY* place where we actually call open
368 * firmware.
369 */
370
371static int __init call_prom(const char *service, int nargs, int nret, ...)
372{
373 int i;
374 struct prom_args args;
375 va_list list;
376
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000377 args.service = cpu_to_be32(ADDR(service));
378 args.nargs = cpu_to_be32(nargs);
379 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000380
381 va_start(list, nret);
382 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000383 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000384 va_end(list);
385
386 for (i = 0; i < nret; i++)
387 args.args[nargs+i] = 0;
388
Anton Blanchard5827d412012-11-26 17:40:03 +0000389 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000390 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000391
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000392 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000393}
394
395static int __init call_prom_ret(const char *service, int nargs, int nret,
396 prom_arg_t *rets, ...)
397{
398 int i;
399 struct prom_args args;
400 va_list list;
401
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000402 args.service = cpu_to_be32(ADDR(service));
403 args.nargs = cpu_to_be32(nargs);
404 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000405
406 va_start(list, rets);
407 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000408 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000409 va_end(list);
410
411 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100412 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000413
Anton Blanchard5827d412012-11-26 17:40:03 +0000414 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000415 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000416
417 if (rets != NULL)
418 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000419 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000420
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000421 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000422}
423
424
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000425static void __init prom_print(const char *msg)
426{
427 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000428
Anton Blanchard5827d412012-11-26 17:40:03 +0000429 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000430 return;
431
432 for (p = msg; *p != 0; p = q) {
433 for (q = p; *q != 0 && *q != '\n'; ++q)
434 ;
435 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000436 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000437 if (*q == 0)
438 break;
439 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000440 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000441 }
442}
443
444
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200445/*
446 * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that
447 * we do not need __udivdi3 or __umoddi3 on 32bits.
448 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000449static void __init prom_print_hex(unsigned long val)
450{
451 int i, nibbles = sizeof(val)*2;
452 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000453
454 for (i = nibbles-1; i >= 0; i--) {
455 buf[i] = (val & 0xf) + '0';
456 if (buf[i] > '9')
457 buf[i] += ('a'-'0'-10);
458 val >>= 4;
459 }
460 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000461 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000462}
463
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000464/* max number of decimal digits in an unsigned long */
465#define UL_DIGITS 21
466static void __init prom_print_dec(unsigned long val)
467{
468 int i, size;
469 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000470
471 for (i = UL_DIGITS-1; i >= 0; i--) {
472 buf[i] = (val % 10) + '0';
473 val = val/10;
474 if (val == 0)
475 break;
476 }
477 /* shift stuff down */
478 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000479 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000480}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000481
Mathieu Malaterreeae5f702018-04-06 22:12:19 +0200482__printf(1, 2)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000483static void __init prom_printf(const char *format, ...)
484{
485 const char *p, *q, *s;
486 va_list args;
487 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000488 long vs;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200489 int n = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000490
491 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000492 for (p = format; *p != 0; p = q) {
493 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
494 ;
495 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000496 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000497 if (*q == 0)
498 break;
499 if (*q == '\n') {
500 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000501 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000502 ADDR("\r\n"), 2);
503 continue;
504 }
505 ++q;
506 if (*q == 0)
507 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200508 while (*q == 'l') {
509 ++q;
510 ++n;
511 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000512 switch (*q) {
513 case 's':
514 ++q;
515 s = va_arg(args, const char *);
516 prom_print(s);
517 break;
518 case 'x':
519 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200520 switch (n) {
521 case 0:
522 v = va_arg(args, unsigned int);
523 break;
524 case 1:
525 v = va_arg(args, unsigned long);
526 break;
527 case 2:
528 default:
529 v = va_arg(args, unsigned long long);
530 break;
531 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000532 prom_print_hex(v);
533 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200534 case 'u':
535 ++q;
536 switch (n) {
537 case 0:
538 v = va_arg(args, unsigned int);
539 break;
540 case 1:
541 v = va_arg(args, unsigned long);
542 break;
543 case 2:
544 default:
545 v = va_arg(args, unsigned long long);
546 break;
547 }
548 prom_print_dec(v);
549 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000550 case 'd':
551 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200552 switch (n) {
553 case 0:
554 vs = va_arg(args, int);
555 break;
556 case 1:
557 vs = va_arg(args, long);
558 break;
559 case 2:
560 default:
561 vs = va_arg(args, long long);
562 break;
563 }
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000564 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000565 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000566 vs = -vs;
567 }
568 prom_print_dec(vs);
569 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000570 }
571 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100572 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000573}
574
575
Paul Mackerrasa575b802005-10-23 17:23:21 +1000576static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
577 unsigned long align)
578{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000579
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100580 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
581 /*
582 * Old OF requires we claim physical and virtual separately
583 * and then map explicitly (assuming virtual mode)
584 */
585 int ret;
586 prom_arg_t result;
587
588 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000589 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100590 align, size, virt);
591 if (ret != 0 || result == -1)
592 return -1;
593 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000594 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100595 align, size, virt);
596 if (ret != 0) {
597 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000598 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100599 return -1;
600 }
601 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000602 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000603 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100604 return virt;
605 }
606 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
607 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000608}
609
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000610static void __init __attribute__((noreturn)) prom_panic(const char *reason)
611{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000612 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100613 /* Do not call exit because it clears the screen on pmac
614 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000615 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100616 asm("trap\n");
617
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000618 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000619 call_prom("exit", 0, 0);
620
621 for (;;) /* should never get here */
622 ;
623}
624
625
626static int __init prom_next_node(phandle *nodep)
627{
628 phandle node;
629
630 if ((node = *nodep) != 0
631 && (*nodep = call_prom("child", 1, 1, node)) != 0)
632 return 1;
633 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
634 return 1;
635 for (;;) {
636 if ((node = call_prom("parent", 1, 1, node)) == 0)
637 return 0;
638 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
639 return 1;
640 }
641}
642
Masahiro Yamada480795a2019-05-14 15:42:14 -0700643static inline int __init prom_getprop(phandle node, const char *pname,
644 void *value, size_t valuelen)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000645{
646 return call_prom("getprop", 4, 1, node, ADDR(pname),
647 (u32)(unsigned long) value, (u32) valuelen);
648}
649
Masahiro Yamada480795a2019-05-14 15:42:14 -0700650static inline int __init prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000651{
652 return call_prom("getproplen", 2, 1, node, ADDR(pname));
653}
654
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100655static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000656{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100657 char *p = *str;
658
659 while (*q)
660 *p++ = *q++;
661 *p++ = ' ';
662 *str = p;
663}
664
665static char *tohex(unsigned int x)
666{
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100667 static const char digits[] __initconst = "0123456789abcdef";
668 static char result[9] __prombss;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100669 int i;
670
671 result[8] = 0;
672 i = 8;
673 do {
674 --i;
675 result[i] = digits[x & 0xf];
676 x >>= 4;
677 } while (x != 0 && i > 0);
678 return &result[i];
679}
680
681static int __init prom_setprop(phandle node, const char *nodename,
682 const char *pname, void *value, size_t valuelen)
683{
684 char cmd[256], *p;
685
686 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
687 return call_prom("setprop", 4, 1, node, ADDR(pname),
688 (u32)(unsigned long) value, (u32) valuelen);
689
690 /* gah... setprop doesn't work on longtrail, have to use interpret */
691 p = cmd;
692 add_string(&p, "dev");
693 add_string(&p, nodename);
694 add_string(&p, tohex((u32)(unsigned long) value));
695 add_string(&p, tohex(valuelen));
696 add_string(&p, tohex(ADDR(pname)));
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000697 add_string(&p, tohex(prom_strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100698 add_string(&p, "property");
699 *p = 0;
700 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000701}
702
Anton Blanchard5827d412012-11-26 17:40:03 +0000703/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000704#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
705 || ('a' <= (c) && (c) <= 'f') \
706 || ('A' <= (c) && (c) <= 'F'))
707
708#define isdigit(c) ('0' <= (c) && (c) <= '9')
709#define islower(c) ('a' <= (c) && (c) <= 'z')
710#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
711
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000712static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000713{
714 unsigned long result = 0, base = 10, value;
715
716 if (*cp == '0') {
717 base = 8;
718 cp++;
719 if (toupper(*cp) == 'X') {
720 cp++;
721 base = 16;
722 }
723 }
724
725 while (isxdigit(*cp) &&
726 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
727 result = result * base + value;
728 cp++;
729 }
730
731 if (endp)
732 *endp = cp;
733
734 return result;
735}
736
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000737static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000738{
739 unsigned long ret = prom_strtoul(ptr, retptr);
740 int shift = 0;
741
742 /*
743 * We can't use a switch here because GCC *may* generate a
744 * jump table which won't work, because we're not running at
745 * the address we're linked at.
746 */
747 if ('G' == **retptr || 'g' == **retptr)
748 shift = 30;
749
750 if ('M' == **retptr || 'm' == **retptr)
751 shift = 20;
752
753 if ('K' == **retptr || 'k' == **retptr)
754 shift = 10;
755
756 if (shift) {
757 ret <<= shift;
758 (*retptr)++;
759 }
760
761 return ret;
762}
763
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000764/*
765 * Early parsing of the command line passed to the kernel, used for
766 * "mem=x" and the options that affect the iommu
767 */
768static void __init early_cmdline_parse(void)
769{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100770 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000771
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100772 char *p;
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000773 int l = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000774
Anton Blanchard5827d412012-11-26 17:40:03 +0000775 prom_cmd_line[0] = 0;
776 p = prom_cmd_line;
Chris Packhamd79fbb32019-08-02 10:50:06 +1200777
778 if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && (long)prom.chosen > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +0000779 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Chris Packhamd79fbb32019-08-02 10:50:06 +1200780
781 if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || l <= 0 || p[0] == '\0')
782 prom_strlcat(prom_cmd_line, " " CONFIG_CMDLINE,
783 sizeof(prom_cmd_line));
784
Anton Blanchard5827d412012-11-26 17:40:03 +0000785 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000786
787#ifdef CONFIG_PPC64
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000788 opt = prom_strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000789 if (opt) {
790 prom_printf("iommu opt is: %s\n", opt);
791 opt += 6;
792 while (*opt && *opt == ' ')
793 opt++;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000794 if (!prom_strncmp(opt, "off", 3))
Anton Blanchard5827d412012-11-26 17:40:03 +0000795 prom_iommu_off = 1;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000796 else if (!prom_strncmp(opt, "force", 5))
Anton Blanchard5827d412012-11-26 17:40:03 +0000797 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000798 }
799#endif
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000800 opt = prom_strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000801 if (opt) {
802 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000803 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000804#ifdef CONFIG_PPC64
805 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000806 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000807#endif
808 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100809
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100810#ifdef CONFIG_PPC_PSERIES
811 prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000812 opt = prom_strstr(prom_cmd_line, "disable_radix");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100813 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530814 opt += 13;
815 if (*opt && *opt == '=') {
816 bool val;
817
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000818 if (prom_strtobool(++opt, &val))
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530819 prom_radix_disable = false;
820 else
821 prom_radix_disable = val;
822 } else
823 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100824 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530825 if (prom_radix_disable)
826 prom_debug("Radix disabled from cmdline\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200827
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +0530828 opt = prom_strstr(prom_cmd_line, "radix_hcall_invalidate=on");
829 if (opt) {
830 prom_radix_gtse_disable = true;
831 prom_debug("Radix GTSE disabled from cmdline\n");
832 }
833
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200834 opt = prom_strstr(prom_cmd_line, "xive=off");
835 if (opt) {
836 prom_xive_disable = true;
837 prom_debug("XIVE disabled from cmdline\n");
838 }
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100839#endif /* CONFIG_PPC_PSERIES */
Ram Pai6a9c9302019-08-19 23:13:14 -0300840
841#ifdef CONFIG_PPC_SVM
842 opt = prom_strstr(prom_cmd_line, "svm=");
843 if (opt) {
844 bool val;
845
846 opt += sizeof("svm=") - 1;
847 if (!prom_strtobool(opt, &val))
848 prom_svm_enable = val;
849 }
850#endif /* CONFIG_PPC_SVM */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000851}
852
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +1100853#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000854/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000855 * The architecture vector has an array of PVR mask/value pairs,
856 * followed by # option vectors - 1, followed by the option vectors.
857 *
858 * See prom.h for the definition of the bits specified in the
859 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000860 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000861
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000862/* Firmware expects the value to be n - 1, where n is the # of vectors */
863#define NUM_VECTORS(n) ((n) - 1)
864
865/*
866 * Firmware expects 1 + n - 2, where n is the length of the option vector in
867 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
868 */
869#define VECTOR_LENGTH(n) (1 + (n) - 2)
870
Michael Ellermand03d1d62016-11-18 23:15:41 +1100871struct option_vector1 {
872 u8 byte1;
873 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100874 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100875} __packed;
876
877struct option_vector2 {
878 u8 byte1;
879 __be16 reserved;
880 __be32 real_base;
881 __be32 real_size;
882 __be32 virt_base;
883 __be32 virt_size;
884 __be32 load_base;
885 __be32 min_rma;
886 __be32 min_load;
887 u8 min_rma_percent;
888 u8 max_pft_size;
889} __packed;
890
891struct option_vector3 {
892 u8 byte1;
893 u8 byte2;
894} __packed;
895
896struct option_vector4 {
897 u8 byte1;
898 u8 min_vp_cap;
899} __packed;
900
901struct option_vector5 {
902 u8 byte1;
903 u8 byte2;
904 u8 byte3;
905 u8 cmo;
906 u8 associativity;
907 u8 bin_opts;
908 u8 micro_checkpoint;
909 u8 reserved0;
910 __be32 max_cpus;
911 __be16 papr_level;
912 __be16 reserved1;
913 u8 platform_facilities;
914 u8 reserved2;
915 __be16 reserved3;
916 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100917 u8 byte22;
918 u8 intarch;
919 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100920 u8 hash_ext;
921 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100922} __packed;
923
924struct option_vector6 {
925 u8 reserved;
926 u8 secondary_pteg;
927 u8 os_name;
928} __packed;
929
Michael Ellerman76ffb572016-11-18 23:15:42 +1100930struct ibm_arch_vec {
Alistair Popplea3ea40d2020-05-21 11:43:41 +1000931 struct { u32 mask, val; } pvrs[14];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100932
933 u8 num_vectors;
934
935 u8 vec1_len;
936 struct option_vector1 vec1;
937
938 u8 vec2_len;
939 struct option_vector2 vec2;
940
941 u8 vec3_len;
942 struct option_vector3 vec3;
943
944 u8 vec4_len;
945 struct option_vector4 vec4;
946
947 u8 vec5_len;
948 struct option_vector5 vec5;
949
950 u8 vec6_len;
951 struct option_vector6 vec6;
952} __packed;
953
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +1100954static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100955 .pvrs = {
956 {
957 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
958 .val = cpu_to_be32(0x003a0000),
959 },
960 {
961 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
962 .val = cpu_to_be32(0x003e0000),
963 },
964 {
965 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
966 .val = cpu_to_be32(0x003f0000),
967 },
968 {
969 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
970 .val = cpu_to_be32(0x004b0000),
971 },
972 {
973 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
974 .val = cpu_to_be32(0x004c0000),
975 },
976 {
977 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
978 .val = cpu_to_be32(0x004d0000),
979 },
980 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100981 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
982 .val = cpu_to_be32(0x004e0000),
983 },
984 {
Alistair Popplea3ea40d2020-05-21 11:43:41 +1000985 .mask = cpu_to_be32(0xffff0000), /* POWER10 */
986 .val = cpu_to_be32(0x00800000),
987 },
988 {
989 .mask = cpu_to_be32(0xffffffff), /* all 3.1-compliant */
990 .val = cpu_to_be32(0x0f000006),
991 },
992 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100993 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
994 .val = cpu_to_be32(0x0f000005),
995 },
996 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100997 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
998 .val = cpu_to_be32(0x0f000004),
999 },
1000 {
1001 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
1002 .val = cpu_to_be32(0x0f000003),
1003 },
1004 {
1005 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
1006 .val = cpu_to_be32(0x0f000002),
1007 },
1008 {
1009 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
1010 .val = cpu_to_be32(0x0f000001),
1011 },
1012 },
1013
1014 .num_vectors = NUM_VECTORS(6),
1015
1016 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
1017 .vec1 = {
1018 .byte1 = 0,
1019 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
1020 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Alistair Popplea3ea40d2020-05-21 11:43:41 +10001021 .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001022 },
1023
1024 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
1025 /* option vector 2: Open Firmware options supported */
1026 .vec2 = {
1027 .byte1 = OV2_REAL_MODE,
1028 .reserved = 0,
1029 .real_base = cpu_to_be32(0xffffffff),
1030 .real_size = cpu_to_be32(0xffffffff),
1031 .virt_base = cpu_to_be32(0xffffffff),
1032 .virt_size = cpu_to_be32(0xffffffff),
1033 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -04001034 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +11001035 .min_load = cpu_to_be32(0xffffffff), /* full client load */
1036 .min_rma_percent = 0, /* min RMA percentage of total RAM */
1037 .max_pft_size = 48, /* max log_2(hash table size) */
1038 },
1039
1040 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
1041 /* option vector 3: processor options supported */
1042 .vec3 = {
1043 .byte1 = 0, /* don't ignore, don't halt */
1044 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
1045 },
1046
1047 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
1048 /* option vector 4: IBM PAPR implementation */
1049 .vec4 = {
1050 .byte1 = 0, /* don't halt */
1051 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
1052 },
1053
1054 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
1055 /* option vector 5: PAPR/OF options */
1056 .vec5 = {
1057 .byte1 = 0, /* don't ignore, don't halt */
1058 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
1059 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
1060#ifdef CONFIG_PCI_MSI
1061 /* PCIe/MSI support. Without MSI full PCIe is not supported */
1062 OV5_FEAT(OV5_MSI),
1063#else
1064 0,
1065#endif
1066 .byte3 = 0,
1067 .cmo =
1068#ifdef CONFIG_PPC_SMLPAR
1069 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
1070#else
1071 0,
1072#endif
1073 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -06001074 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +11001075 .micro_checkpoint = 0,
1076 .reserved0 = 0,
1077 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
1078 .papr_level = 0,
1079 .reserved1 = 0,
1080 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
1081 .reserved2 = 0,
1082 .reserved3 = 0,
1083 .subprocessors = 1,
Tyrel Datwyler0a87ccd2019-11-10 23:21:37 -06001084 .byte22 = OV5_FEAT(OV5_DRMEM_V2) | OV5_FEAT(OV5_DRC_INFO),
Paul Mackerrascc3d2942017-01-30 21:21:36 +11001085 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001086 .mmu = 0,
1087 .hash_ext = 0,
1088 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001089 },
1090
1091 /* option vector 6: IBM PAPR hints */
1092 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
1093 .vec6 = {
1094 .reserved = 0,
1095 .secondary_pteg = 0,
1096 .os_name = OV6_LINUX,
1097 },
1098};
1099
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001100static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned;
1101
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001102/* Old method - ELF header with PT_NOTE sections only works on BE */
1103#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +10001104static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001105 Elf32_Ehdr elfhdr;
1106 Elf32_Phdr phdr[2];
1107 struct chrpnote {
1108 u32 namesz;
1109 u32 descsz;
1110 u32 type;
1111 char name[8]; /* "PowerPC" */
1112 struct chrpdesc {
1113 u32 real_mode;
1114 u32 real_base;
1115 u32 real_size;
1116 u32 virt_base;
1117 u32 virt_size;
1118 u32 load_base;
1119 } chrpdesc;
1120 } chrpnote;
1121 struct rpanote {
1122 u32 namesz;
1123 u32 descsz;
1124 u32 type;
1125 char name[24]; /* "IBM,RPA-Client-Config" */
1126 struct rpadesc {
1127 u32 lpar_affinity;
1128 u32 min_rmo_size;
1129 u32 min_rmo_percent;
1130 u32 max_pft_size;
1131 u32 splpar;
1132 u32 min_load;
1133 u32 new_mem_def;
1134 u32 ignore_me;
1135 } rpadesc;
1136 } rpanote;
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11001137} fake_elf __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001138 .elfhdr = {
1139 .e_ident = { 0x7f, 'E', 'L', 'F',
1140 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
1141 .e_type = ET_EXEC, /* yeah right */
1142 .e_machine = EM_PPC,
1143 .e_version = EV_CURRENT,
1144 .e_phoff = offsetof(struct fake_elf, phdr),
1145 .e_phentsize = sizeof(Elf32_Phdr),
1146 .e_phnum = 2
1147 },
1148 .phdr = {
1149 [0] = {
1150 .p_type = PT_NOTE,
1151 .p_offset = offsetof(struct fake_elf, chrpnote),
1152 .p_filesz = sizeof(struct chrpnote)
1153 }, [1] = {
1154 .p_type = PT_NOTE,
1155 .p_offset = offsetof(struct fake_elf, rpanote),
1156 .p_filesz = sizeof(struct rpanote)
1157 }
1158 },
1159 .chrpnote = {
1160 .namesz = sizeof("PowerPC"),
1161 .descsz = sizeof(struct chrpdesc),
1162 .type = 0x1275,
1163 .name = "PowerPC",
1164 .chrpdesc = {
1165 .real_mode = ~0U, /* ~0 means "don't care" */
1166 .real_base = ~0U,
1167 .real_size = ~0U,
1168 .virt_base = ~0U,
1169 .virt_size = ~0U,
1170 .load_base = ~0U
1171 },
1172 },
1173 .rpanote = {
1174 .namesz = sizeof("IBM,RPA-Client-Config"),
1175 .descsz = sizeof(struct rpadesc),
1176 .type = 0x12759999,
1177 .name = "IBM,RPA-Client-Config",
1178 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001179 .lpar_affinity = 0,
1180 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001181 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001182 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001183 .splpar = 1,
1184 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001185 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001186 }
1187 }
1188};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001189#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001190
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001191static int __init prom_count_smt_threads(void)
1192{
1193 phandle node;
1194 char type[64];
1195 unsigned int plen;
1196
1197 /* Pick up th first CPU node we can find */
1198 for (node = 0; prom_next_node(&node); ) {
1199 type[0] = 0;
1200 prom_getprop(node, "device_type", type, sizeof(type));
1201
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001202 if (prom_strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001203 continue;
1204 /*
1205 * There is an entry for each smt thread, each entry being
1206 * 4 bytes long. All cpus should have the same number of
1207 * smt threads, so return after finding the first.
1208 */
1209 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1210 if (plen == PROM_ERROR)
1211 break;
1212 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001213 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001214
1215 /* Sanity check */
1216 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001217 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001218 (unsigned long)plen);
1219 return 1;
1220 }
1221 return plen;
1222 }
1223 prom_debug("No threads found, assuming 1 per core\n");
1224
1225 return 1;
1226
1227}
1228
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001229static void __init prom_parse_mmu_model(u8 val,
1230 struct platform_support *support)
1231{
1232 switch (val) {
1233 case OV5_FEAT(OV5_MMU_DYNAMIC):
1234 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1235 prom_debug("MMU - either supported\n");
1236 support->radix_mmu = !prom_radix_disable;
1237 support->hash_mmu = true;
1238 break;
1239 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1240 prom_debug("MMU - radix only\n");
1241 if (prom_radix_disable) {
1242 /*
1243 * If we __have__ to do radix, we're better off ignoring
1244 * the command line rather than not booting.
1245 */
1246 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1247 }
1248 support->radix_mmu = true;
1249 break;
1250 case OV5_FEAT(OV5_MMU_HASH):
1251 prom_debug("MMU - hash only\n");
1252 support->hash_mmu = true;
1253 break;
1254 default:
1255 prom_debug("Unknown mmu support option: 0x%x\n", val);
1256 break;
1257 }
1258}
1259
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001260static void __init prom_parse_xive_model(u8 val,
1261 struct platform_support *support)
1262{
1263 switch (val) {
1264 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1265 prom_debug("XIVE - either mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001266 support->xive = !prom_xive_disable;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001267 break;
1268 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1269 prom_debug("XIVE - exploitation mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001270 if (prom_xive_disable) {
1271 /*
1272 * If we __have__ to do XIVE, we're better off ignoring
1273 * the command line rather than not booting.
1274 */
1275 prom_printf("WARNING: Ignoring cmdline option xive=off\n");
1276 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001277 support->xive = true;
1278 break;
1279 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1280 prom_debug("XIVE - legacy mode supported\n");
1281 break;
1282 default:
1283 prom_debug("Unknown xive support option: 0x%x\n", val);
1284 break;
1285 }
1286}
1287
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001288static void __init prom_parse_platform_support(u8 index, u8 val,
1289 struct platform_support *support)
1290{
1291 switch (index) {
1292 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1293 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1294 break;
1295 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +05301296 if (val & OV5_FEAT(OV5_RADIX_GTSE))
1297 support->radix_gtse = !prom_radix_gtse_disable;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001298 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001299 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1300 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1301 support);
1302 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001303 }
1304}
1305
1306static void __init prom_check_platform_support(void)
1307{
1308 struct platform_support supported = {
1309 .hash_mmu = false,
1310 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001311 .radix_gtse = false,
1312 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001313 };
1314 int prop_len = prom_getproplen(prom.chosen,
1315 "ibm,arch-vec-5-platform-support");
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001316
Christophe Leroyadcf5912019-04-26 16:23:29 +00001317 /*
1318 * First copy the architecture vec template
1319 *
1320 * use memcpy() instead of *vec = *vec_template so that GCC replaces it
1321 * by __memcpy() when KASAN is active
1322 */
1323 memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template,
1324 sizeof(ibm_architecture_vec));
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001325
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001326 if (prop_len > 1) {
1327 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001328 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001329 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1330 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001331 if (prop_len > sizeof(vec))
1332 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1333 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001334 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1335 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001336 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001337 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1338 , vec[i]
1339 , vec[i + 1]);
1340 prom_parse_platform_support(vec[i], vec[i + 1],
1341 &supported);
1342 }
1343 }
1344
Bharata B Rao029ab302020-07-03 11:06:06 +05301345 if (supported.radix_mmu && IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
1346 /* Radix preferred - Check if GTSE is also supported */
1347 prom_debug("Asking for radix\n");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001348 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
Bharata B Rao029ab302020-07-03 11:06:06 +05301349 if (supported.radix_gtse)
1350 ibm_architecture_vec.vec5.radix_ext =
1351 OV5_FEAT(OV5_RADIX_GTSE);
1352 else
1353 prom_debug("Radix GTSE isn't supported\n");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001354 } else if (supported.hash_mmu) {
1355 /* Default to hash mmu (if we can) */
1356 prom_debug("Asking for hash\n");
1357 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1358 } else {
1359 /* We're probably on a legacy hypervisor */
1360 prom_debug("Assuming legacy hash support\n");
1361 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001362
1363 if (supported.xive) {
1364 prom_debug("Asking for XIVE\n");
1365 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1366 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001367}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001368
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001369static void __init prom_send_capabilities(void)
1370{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001371 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001372 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001373 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001374
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001375 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1376 prom_check_platform_support();
1377
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001378 root = call_prom("open", 1, 1, ADDR("/"));
1379 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001380 /* We need to tell the FW about the number of cores we support.
1381 *
1382 * To do that, we count the number of threads on the first core
1383 * (we assume this is the same for all cores) and use it to
1384 * divide NR_CPUS.
1385 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001386
Michael Ellerman76ffb572016-11-18 23:15:42 +11001387 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001388 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001389 cores, NR_CPUS);
1390
1391 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001392
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001393 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001394 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001395 if (call_prom_ret("call-method", 3, 2, &ret,
1396 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001397 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001398 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001399 /* the call exists... */
1400 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001401 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001402 "-support call FAILED!\n");
1403 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001404 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001405 return;
1406 }
1407 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001408 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001409 }
1410
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001411#ifdef __BIG_ENDIAN__
1412 {
1413 ihandle elfloader;
1414
1415 /* no ibm,client-architecture-support call, try the old way */
1416 elfloader = call_prom("open", 1, 1,
1417 ADDR("/packages/elf-loader"));
1418 if (elfloader == 0) {
1419 prom_printf("couldn't open /packages/elf-loader\n");
1420 return;
1421 }
1422 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1423 elfloader, ADDR(&fake_elf));
1424 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001425 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001426#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001427}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001428#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001429
1430/*
1431 * Memory allocation strategy... our layout is normally:
1432 *
1433 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1434 * rare cases, initrd might end up being before the kernel though.
1435 * We assume this won't override the final kernel at 0, we have no
1436 * provision to handle that in this version, but it should hopefully
1437 * never happen.
1438 *
1439 * alloc_top is set to the top of RMO, eventually shrink down if the
1440 * TCEs overlap
1441 *
1442 * alloc_bottom is set to the top of kernel/initrd
1443 *
1444 * from there, allocations are done this way : rtas is allocated
1445 * topmost, and the device-tree is allocated from the bottom. We try
1446 * to grow the device-tree allocation as we progress. If we can't,
1447 * then we fail, we don't currently have a facility to restart
1448 * elsewhere, but that shouldn't be necessary.
1449 *
1450 * Note that calls to reserve_mem have to be done explicitly, memory
1451 * allocated with either alloc_up or alloc_down isn't automatically
1452 * reserved.
1453 */
1454
1455
1456/*
1457 * Allocates memory in the RMO upward from the kernel/initrd
1458 *
1459 * When align is 0, this is a special case, it means to allocate in place
1460 * at the current location of alloc_bottom or fail (that is basically
1461 * extending the previous allocation). Used for the device-tree flattening
1462 */
1463static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1464{
Anton Blanchard5827d412012-11-26 17:40:03 +00001465 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001466 unsigned long addr = 0;
1467
Paul Mackerrasc49888202005-10-26 21:52:53 +10001468 if (align)
Christophe Leroyb7115312020-04-20 18:36:36 +00001469 base = ALIGN(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001470 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001471 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001472 prom_panic("alloc_up() called with mem not initialized\n");
1473
1474 if (align)
Christophe Leroyb7115312020-04-20 18:36:36 +00001475 base = ALIGN(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001476 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001477 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001478
Anton Blanchard5827d412012-11-26 17:40:03 +00001479 for(; (base + size) <= alloc_top;
Christophe Leroyb7115312020-04-20 18:36:36 +00001480 base = ALIGN(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001481 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001482 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001483 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001484 break;
1485 addr = 0;
1486 if (align == 0)
1487 break;
1488 }
1489 if (addr == 0)
1490 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001491 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001492
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001493 prom_debug(" -> %lx\n", addr);
1494 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1495 prom_debug(" alloc_top : %lx\n", alloc_top);
1496 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1497 prom_debug(" rmo_top : %lx\n", rmo_top);
1498 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001499
1500 return addr;
1501}
1502
1503/*
1504 * Allocates memory downward, either from top of RMO, or if highmem
1505 * is set, from the top of RAM. Note that this one doesn't handle
1506 * failures. It does claim memory if highmem is not set.
1507 */
1508static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1509 int highmem)
1510{
1511 unsigned long base, addr = 0;
1512
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001513 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001514 highmem ? "(high)" : "(low)");
1515 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001516 prom_panic("alloc_down() called with mem not initialized\n");
1517
1518 if (highmem) {
1519 /* Carve out storage for the TCE table. */
Christophe Leroye96d9042020-04-20 18:36:35 +00001520 addr = ALIGN_DOWN(alloc_top_high - size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001521 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001522 return 0;
1523 /* Will we bump into the RMO ? If yes, check out that we
1524 * didn't overlap existing allocations there, if we did,
1525 * we are dead, we must be the first in town !
1526 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001527 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001528 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001529 if (alloc_top == rmo_top)
1530 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001531 else
1532 return 0;
1533 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001534 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001535 goto bail;
1536 }
1537
Christophe Leroye96d9042020-04-20 18:36:35 +00001538 base = ALIGN_DOWN(alloc_top - size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001539 for (; base > alloc_bottom;
Christophe Leroye96d9042020-04-20 18:36:35 +00001540 base = ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001541 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001542 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001543 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001544 break;
1545 addr = 0;
1546 }
1547 if (addr == 0)
1548 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001549 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001550
1551 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001552 prom_debug(" -> %lx\n", addr);
1553 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1554 prom_debug(" alloc_top : %lx\n", alloc_top);
1555 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1556 prom_debug(" rmo_top : %lx\n", rmo_top);
1557 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001558
1559 return addr;
1560}
1561
1562/*
1563 * Parse a "reg" cell
1564 */
1565static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1566{
1567 cell_t *p = *cellp;
1568 unsigned long r = 0;
1569
1570 /* Ignore more than 2 cells */
1571 while (s > sizeof(unsigned long) / 4) {
1572 p++;
1573 s--;
1574 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001575 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001576#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001577 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001578 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001579 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001580 }
1581#endif
1582 *cellp = p;
1583 return r;
1584}
1585
1586/*
1587 * Very dumb function for adding to the memory reserve list, but
1588 * we don't need anything smarter at this point
1589 *
1590 * XXX Eventually check for collisions. They should NEVER happen.
1591 * If problems seem to show up, it would be a good start to track
1592 * them down.
1593 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001594static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001595{
Kumar Galacbbcf342006-01-11 17:57:13 -06001596 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001597 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001598
1599 if (size == 0)
1600 return;
1601
1602 /* We need to always keep one empty entry so that we
1603 * have our terminator with "size" set to 0 since we are
1604 * dumb and just copy this entire array to the boot params
1605 */
Christophe Leroye96d9042020-04-20 18:36:35 +00001606 base = ALIGN_DOWN(base, PAGE_SIZE);
Christophe Leroyb7115312020-04-20 18:36:36 +00001607 top = ALIGN(top, PAGE_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001608 size = top - base;
1609
1610 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1611 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001612 mem_reserve_map[cnt].base = cpu_to_be64(base);
1613 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001614 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001615}
1616
1617/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001618 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001619 * obtain that way the top of memory and RMO to setup out local allocator
1620 */
1621static void __init prom_init_mem(void)
1622{
1623 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001624 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001625 unsigned int plen;
1626 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001627 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001628 u32 rac, rsc;
1629
1630 /*
1631 * We iterate the memory nodes to find
1632 * 1) top of RMO (first node)
1633 * 2) top of memory
1634 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001635 val = cpu_to_be32(2);
1636 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1637 rac = be32_to_cpu(val);
1638 val = cpu_to_be32(1);
1639 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1640 rsc = be32_to_cpu(val);
1641 prom_debug("root_addr_cells: %x\n", rac);
1642 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001643
1644 prom_debug("scanning memory:\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001645
1646 for (node = 0; prom_next_node(&node); ) {
1647 type[0] = 0;
1648 prom_getprop(node, "device_type", type, sizeof(type));
1649
Paul Mackerrasc49888202005-10-26 21:52:53 +10001650 if (type[0] == 0) {
1651 /*
1652 * CHRP Longtrail machines have no device_type
1653 * on the memory node, so check the name instead...
1654 */
1655 prom_getprop(node, "name", type, sizeof(type));
1656 }
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001657 if (prom_strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001658 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001659
Anton Blanchard5827d412012-11-26 17:40:03 +00001660 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001661 if (plen > sizeof(regbuf)) {
1662 prom_printf("memory node too large for buffer !\n");
1663 plen = sizeof(regbuf);
1664 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001665 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001666 endp = p + (plen / sizeof(cell_t));
1667
1668#ifdef DEBUG_PROM
Mathieu Malaterrec806a6f2019-05-23 12:25:20 +02001669 memset(prom_scratch, 0, sizeof(prom_scratch));
1670 call_prom("package-to-path", 3, 1, node, prom_scratch,
1671 sizeof(prom_scratch) - 1);
1672 prom_debug(" node %s :\n", prom_scratch);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001673#endif /* DEBUG_PROM */
1674
1675 while ((endp - p) >= (rac + rsc)) {
1676 unsigned long base, size;
1677
1678 base = prom_next_cell(rac, &p);
1679 size = prom_next_cell(rsc, &p);
1680
1681 if (size == 0)
1682 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001683 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001684 if (base == 0 && (of_platform & PLATFORM_LPAR))
1685 rmo_top = size;
1686 if ((base + size) > ram_top)
1687 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001688 }
1689 }
1690
Anton Blanchard5827d412012-11-26 17:40:03 +00001691 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001692
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001693 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001694 * If prom_memory_limit is set we reduce the upper limits *except* for
1695 * alloc_top_high. This must be the real top of RAM so we can put
1696 * TCE's up there.
1697 */
1698
Anton Blanchard5827d412012-11-26 17:40:03 +00001699 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001700
Anton Blanchard5827d412012-11-26 17:40:03 +00001701 if (prom_memory_limit) {
1702 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001703 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1704 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001705 prom_memory_limit = 0;
1706 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001707 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1708 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001709 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001710 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001711 ram_top = prom_memory_limit;
1712 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001713 }
1714 }
1715
1716 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001717 * Setup our top alloc point, that is top of RMO or top of
1718 * segment 0 when running non-LPAR.
1719 * Some RS64 machines have buggy firmware where claims up at
1720 * 1GB fail. Cap at 768MB as a workaround.
1721 * Since 768MB is plenty of room, and we need to cap to something
1722 * reasonable on 32-bit, cap at 768MB on all machines.
1723 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001724 if (!rmo_top)
1725 rmo_top = ram_top;
1726 rmo_top = min(0x30000000ul, rmo_top);
1727 alloc_top = rmo_top;
1728 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001729
Paul Mackerras64968f62011-12-13 17:54:13 +00001730 /*
1731 * Check if we have an initrd after the kernel but still inside
1732 * the RMO. If we do move our bottom point to after it.
1733 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001734 if (prom_initrd_start &&
1735 prom_initrd_start < rmo_top &&
1736 prom_initrd_end > alloc_bottom)
1737 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001738
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001739 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001740 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1741 prom_memory_limit);
1742 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1743 prom_printf(" alloc_top : %lx\n", alloc_top);
1744 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1745 prom_printf(" rmo_top : %lx\n", rmo_top);
1746 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001747}
1748
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001749static void __init prom_close_stdin(void)
1750{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001751 __be32 val;
1752 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001753
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001754 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1755 stdin = be32_to_cpu(val);
1756 call_prom("close", 1, 0, stdin);
1757 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001758}
1759
Ram Pai6a9c9302019-08-19 23:13:14 -03001760#ifdef CONFIG_PPC_SVM
1761static int prom_rtas_hcall(uint64_t args)
1762{
1763 register uint64_t arg1 asm("r3") = H_RTAS;
1764 register uint64_t arg2 asm("r4") = args;
1765
1766 asm volatile("sc 1\n" : "=r" (arg1) :
1767 "r" (arg1),
1768 "r" (arg2) :);
1769 return arg1;
1770}
1771
1772static struct rtas_args __prombss os_term_args;
1773
1774static void __init prom_rtas_os_term(char *str)
1775{
1776 phandle rtas_node;
1777 __be32 val;
1778 u32 token;
1779
1780 prom_debug("%s: start...\n", __func__);
1781 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1782 prom_debug("rtas_node: %x\n", rtas_node);
1783 if (!PHANDLE_VALID(rtas_node))
1784 return;
1785
1786 val = 0;
1787 prom_getprop(rtas_node, "ibm,os-term", &val, sizeof(val));
1788 token = be32_to_cpu(val);
1789 prom_debug("ibm,os-term: %x\n", token);
1790 if (token == 0)
1791 prom_panic("Could not get token for ibm,os-term\n");
1792 os_term_args.token = cpu_to_be32(token);
Alexey Kardashevskiy74bb84e2020-03-12 18:44:04 +11001793 os_term_args.nargs = cpu_to_be32(1);
1794 os_term_args.nret = cpu_to_be32(1);
1795 os_term_args.args[0] = cpu_to_be32(__pa(str));
Ram Pai6a9c9302019-08-19 23:13:14 -03001796 prom_rtas_hcall((uint64_t)&os_term_args);
1797}
1798#endif /* CONFIG_PPC_SVM */
1799
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001800/*
1801 * Allocate room for and instantiate RTAS
1802 */
1803static void __init prom_instantiate_rtas(void)
1804{
1805 phandle rtas_node;
1806 ihandle rtas_inst;
1807 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001808 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001809 u32 size = 0;
1810
1811 prom_debug("prom_instantiate_rtas: start...\n");
1812
1813 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1814 prom_debug("rtas_node: %x\n", rtas_node);
1815 if (!PHANDLE_VALID(rtas_node))
1816 return;
1817
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001818 val = 0;
1819 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1820 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001821 if (size == 0)
1822 return;
1823
1824 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001825 if (base == 0)
1826 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001827
1828 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1829 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001830 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001831 return;
1832 }
1833
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001834 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001835
1836 if (call_prom_ret("call-method", 3, 2, &entry,
1837 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001838 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001839 || entry == 0) {
1840 prom_printf(" failed\n");
1841 return;
1842 }
1843 prom_printf(" done\n");
1844
1845 reserve_mem(base, size);
1846
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001847 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001848 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001849 &val, sizeof(val));
1850 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001851 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001852 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001853
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001854 /* Check if it supports "query-cpu-stopped-state" */
1855 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1856 &val, sizeof(val)) != PROM_ERROR)
1857 rtas_has_query_cpu_stopped = true;
1858
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001859 prom_debug("rtas base = 0x%x\n", base);
1860 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001861 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001862
1863 prom_debug("prom_instantiate_rtas: end...\n");
1864}
1865
1866#ifdef CONFIG_PPC64
1867/*
Ashley Lai4a727422012-08-14 18:34:57 -05001868 * Allocate room for and instantiate Stored Measurement Log (SML)
1869 */
1870static void __init prom_instantiate_sml(void)
1871{
1872 phandle ibmvtpm_node;
1873 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001874 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001875 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001876 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001877
1878 prom_debug("prom_instantiate_sml: start...\n");
1879
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001880 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001881 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1882 if (!PHANDLE_VALID(ibmvtpm_node))
1883 return;
1884
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001885 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001886 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1887 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1888 return;
1889 }
1890
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001891 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1892 &val, sizeof(val)) != PROM_ERROR) {
1893 if (call_prom_ret("call-method", 2, 2, &succ,
1894 ADDR("reformat-sml-to-efi-alignment"),
1895 ibmvtpm_inst) != 0 || succ == 0) {
1896 prom_printf("Reformat SML to EFI alignment failed\n");
1897 return;
1898 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001899
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001900 if (call_prom_ret("call-method", 2, 2, &size,
1901 ADDR("sml-get-allocated-size"),
1902 ibmvtpm_inst) != 0 || size == 0) {
1903 prom_printf("SML get allocated size failed\n");
1904 return;
1905 }
1906 } else {
1907 if (call_prom_ret("call-method", 2, 2, &size,
1908 ADDR("sml-get-handover-size"),
1909 ibmvtpm_inst) != 0 || size == 0) {
1910 prom_printf("SML get handover size failed\n");
1911 return;
1912 }
Ashley Lai4a727422012-08-14 18:34:57 -05001913 }
1914
1915 base = alloc_down(size, PAGE_SIZE, 0);
1916 if (base == 0)
1917 prom_panic("Could not allocate memory for sml\n");
1918
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001919 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001920
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001921 memset((void *)base, 0, size);
1922
Ashley Lai4a727422012-08-14 18:34:57 -05001923 if (call_prom_ret("call-method", 4, 2, &entry,
1924 ADDR("sml-handover"),
1925 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1926 prom_printf("SML handover failed\n");
1927 return;
1928 }
1929 prom_printf(" done\n");
1930
1931 reserve_mem(base, size);
1932
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001933 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001934 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001935 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001936 &size, sizeof(size));
1937
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001938 prom_debug("sml base = 0x%llx\n", base);
1939 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001940
1941 prom_debug("prom_instantiate_sml: end...\n");
1942}
1943
1944/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001945 * Allocate room for and initialize TCE tables
1946 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001947#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001948static void __init prom_initialize_tce_table(void)
1949{
1950 phandle node;
1951 ihandle phb_node;
1952 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001953 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001954 u64 base, align;
1955 u32 minalign, minsize;
1956 u64 tce_entry, *tce_entryp;
1957 u64 local_alloc_top, local_alloc_bottom;
1958 u64 i;
1959
Anton Blanchard5827d412012-11-26 17:40:03 +00001960 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001961 return;
1962
1963 prom_debug("starting prom_initialize_tce_table\n");
1964
1965 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001966 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001967 local_alloc_bottom = local_alloc_top;
1968
1969 /* Search all nodes looking for PHBs. */
1970 for (node = 0; prom_next_node(&node); ) {
1971 compatible[0] = 0;
1972 type[0] = 0;
1973 model[0] = 0;
1974 prom_getprop(node, "compatible",
1975 compatible, sizeof(compatible));
1976 prom_getprop(node, "device_type", type, sizeof(type));
1977 prom_getprop(node, "model", model, sizeof(model));
1978
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001979 if ((type[0] == 0) || (prom_strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001980 continue;
1981
Linas Vepstase788ff12007-09-07 03:45:21 +10001982 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001983 if (compatible[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001984 if ((prom_strstr(compatible, "python") == NULL) &&
1985 (prom_strstr(compatible, "Speedwagon") == NULL) &&
1986 (prom_strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001987 continue;
1988 } else if (model[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001989 if ((prom_strstr(model, "ython") == NULL) &&
1990 (prom_strstr(model, "peedwagon") == NULL) &&
1991 (prom_strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001992 continue;
1993 }
1994
1995 if (prom_getprop(node, "tce-table-minalign", &minalign,
1996 sizeof(minalign)) == PROM_ERROR)
1997 minalign = 0;
1998 if (prom_getprop(node, "tce-table-minsize", &minsize,
1999 sizeof(minsize)) == PROM_ERROR)
2000 minsize = 4UL << 20;
2001
2002 /*
2003 * Even though we read what OF wants, we just set the table
2004 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
2005 * By doing this, we avoid the pitfalls of trying to DMA to
2006 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002007 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10002008 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002009
2010 /* Align to the greater of the align or size */
2011 align = max(minalign, minsize);
2012 base = alloc_down(minsize, align, 1);
2013 if (base == 0)
2014 prom_panic("ERROR, cannot find space for TCE table.\n");
2015 if (base < local_alloc_bottom)
2016 local_alloc_bottom = base;
2017
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002018 /* It seems OF doesn't null-terminate the path :-( */
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002019 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002020 /* Call OF to setup the TCE hardware */
2021 if (call_prom("package-to-path", 3, 1, node,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002022 path, sizeof(prom_scratch) - 1) == PROM_ERROR) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002023 prom_printf("package-to-path failed\n");
2024 }
2025
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002026 /* Save away the TCE table attributes for later use. */
2027 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
2028 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
2029
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002030 prom_debug("TCE table: %s\n", path);
2031 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002032 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002033 prom_debug("\tsize = 0x%x\n", minsize);
2034
2035 /* Initialize the table to have a one-to-one mapping
2036 * over the allocated size.
2037 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00002038 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002039 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
2040 tce_entry = (i << PAGE_SHIFT);
2041 tce_entry |= 0x3;
2042 *tce_entryp = tce_entry;
2043 }
2044
2045 prom_printf("opening PHB %s", path);
2046 phb_node = call_prom("open", 1, 1, path);
2047 if (phb_node == 0)
2048 prom_printf("... failed\n");
2049 else
2050 prom_printf("... done\n");
2051
2052 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
2053 phb_node, -1, minsize,
2054 (u32) base, (u32) (base >> 32));
2055 call_prom("close", 1, 0, phb_node);
2056 }
2057
2058 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
2059
Michael Ellerman2babf5c2006-05-17 18:00:46 +10002060 /* These are only really needed if there is a memory limit in
2061 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00002062 prom_tce_alloc_start = local_alloc_bottom;
2063 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002064
2065 /* Flag the first invalid entry */
2066 prom_debug("ending prom_initialize_tce_table\n");
2067}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002068#endif /* __BIG_ENDIAN__ */
2069#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002070
2071/*
2072 * With CHRP SMP we need to use the OF to start the other processors.
2073 * We can't wait until smp_boot_cpus (the OF is trashed by then)
2074 * so we have to put the processors into a holding pattern controlled
2075 * by the kernel (not OF) before we destroy the OF.
2076 *
2077 * This uses a chunk of low memory, puts some holding pattern
2078 * code there and sends the other processors off to there until
2079 * smp_boot_cpus tells them to do something. The holding pattern
2080 * checks that address until its cpu # is there, when it is that
2081 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
2082 * of setting those values.
2083 *
2084 * We also use physical address 0x4 here to tell when a cpu
2085 * is in its holding pattern code.
2086 *
2087 * -- Cort
2088 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002089/*
2090 * We want to reference the copy of __secondary_hold_* in the
2091 * 0 - 0x100 address range
2092 */
2093#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
2094
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002095static void __init prom_hold_cpus(void)
2096{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002097 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002098 phandle node;
2099 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002100 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002101 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002102 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002103 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002104 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002105
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002106 /*
2107 * On pseries, if RTAS supports "query-cpu-stopped-state",
2108 * we skip this stage, the CPUs will be started by the
2109 * kernel using RTAS.
2110 */
2111 if ((of_platform == PLATFORM_PSERIES ||
2112 of_platform == PLATFORM_PSERIES_LPAR) &&
2113 rtas_has_query_cpu_stopped) {
2114 prom_printf("prom_hold_cpus: skipped\n");
2115 return;
2116 }
2117
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002118 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002119 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
2120 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
2121 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002122 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002123 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
2124 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002125
2126 /* Set the common spinloop variable, so all of the secondary cpus
2127 * will block when they are awakened from their OF spinloop.
2128 * This must occur for both SMP and non SMP kernels, since OF will
2129 * be trashed when we move the kernel.
2130 */
2131 *spinloop = 0;
2132
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002133 /* look for cpus */
2134 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002135 unsigned int cpu_no;
2136 __be32 reg;
2137
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002138 type[0] = 0;
2139 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002140 if (prom_strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002141 continue;
2142
2143 /* Skip non-configured cpus. */
2144 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002145 if (prom_strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002146 continue;
2147
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002148 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002149 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002150 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002151
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002152 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002153
2154 /* Init the acknowledge var which will be reset by
2155 * the secondary cpu when it awakens from its OF
2156 * spinloop.
2157 */
2158 *acknowledge = (unsigned long)-1;
2159
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002160 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002161 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002162 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002163 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002164 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002165
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002166 for (i = 0; (i < 100000000) &&
2167 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002168 mb();
2169
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002170 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002171 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002172 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002173 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002174 }
2175#ifdef CONFIG_SMP
2176 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002177 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002178#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002179 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002180
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002181 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002182}
2183
2184
2185static void __init prom_init_client_services(unsigned long pp)
2186{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002187 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00002188 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002189
2190 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00002191 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
2192 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002193 prom_panic("cannot find chosen"); /* msg won't be printed :( */
2194
2195 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00002196 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
2197 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002198 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002199
Anton Blanchard5827d412012-11-26 17:40:03 +00002200 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002201}
2202
Paul Mackerrasa575b802005-10-23 17:23:21 +10002203#ifdef CONFIG_PPC32
2204/*
2205 * For really old powermacs, we need to map things we claim.
2206 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002207 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10002208 */
2209static void __init prom_find_mmu(void)
2210{
Paul Mackerrasa575b802005-10-23 17:23:21 +10002211 phandle oprom;
2212 char version[64];
2213
2214 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
2215 if (!PHANDLE_VALID(oprom))
2216 return;
2217 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
2218 return;
2219 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002220 /* XXX might need to add other versions here */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002221 if (prom_strcmp(version, "Open Firmware, 1.0.5") == 0)
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002222 of_workarounds = OF_WA_CLAIM;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002223 else if (prom_strncmp(version, "FirmWorks,3.", 12) == 0) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002224 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2225 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2226 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002227 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002228 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2229 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2230 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002231 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002232 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002233 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002234}
2235#else
2236#define prom_find_mmu()
2237#endif
2238
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002239static void __init prom_init_stdout(void)
2240{
Anton Blanchard5827d412012-11-26 17:40:03 +00002241 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002242 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002243 phandle stdout_node;
2244 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002245
Anton Blanchard5827d412012-11-26 17:40:03 +00002246 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002247 prom_panic("cannot find stdout");
2248
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002249 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002250
2251 /* Get the full OF pathname of the stdout device */
2252 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002253 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002254 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2255 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002256 path, prom_strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002257
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002258 /* instance-to-package fails on PA-Semi */
2259 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2260 if (stdout_node != PROM_ERROR) {
2261 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002262
2263 /* If it's a display, note it */
2264 memset(type, 0, sizeof(type));
2265 prom_getprop(stdout_node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002266 if (prom_strcmp(type, "display") == 0)
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002267 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2268 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002269}
2270
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002271static int __init prom_find_machine_type(void)
2272{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002273 char compat[256];
2274 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002275#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002276 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002277 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002278#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002279
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002280 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002281 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002282 compat, sizeof(compat)-1);
2283 if (len > 0) {
2284 compat[len] = 0;
2285 while (i < len) {
2286 char *p = &compat[i];
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002287 int sl = prom_strlen(p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002288 if (sl == 0)
2289 break;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002290 if (prom_strstr(p, "Power Macintosh") ||
2291 prom_strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002292 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002293#ifdef CONFIG_PPC64
2294 /* We must make sure we don't detect the IBM Cell
2295 * blades as pSeries due to some firmware issues,
2296 * so we do it here.
2297 */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002298 if (prom_strstr(p, "IBM,CBEA") ||
2299 prom_strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002300 return PLATFORM_GENERIC;
2301#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002302 i += sl + 1;
2303 }
2304 }
2305#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002306 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002307 * PAPR compliant platform. We assume it is if :
2308 * - /device_type is "chrp" (please, do NOT use that for future
2309 * non-IBM designs !
2310 * - it has /rtas
2311 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002312 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002313 compat, sizeof(compat)-1);
2314 if (len <= 0)
2315 return PLATFORM_GENERIC;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002316 if (prom_strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002317 return PLATFORM_GENERIC;
2318
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002319 /* Default to pSeries. We need to know if we are running LPAR */
2320 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002321 if (!PHANDLE_VALID(rtas))
2322 return PLATFORM_GENERIC;
2323 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2324 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002325 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002326 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002327 }
2328 return PLATFORM_PSERIES;
2329#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002330 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002331#endif
2332}
2333
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002334static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2335{
2336 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2337}
2338
2339/*
2340 * If we have a display that we don't know how to drive,
2341 * we will want to try to execute OF's open method for it
2342 * later. However, OF will probably fall over if we do that
2343 * we've taken over the MMU.
2344 * So we check whether we will need to open the display,
2345 * and if so, open it now.
2346 */
2347static void __init prom_check_displays(void)
2348{
2349 char type[16], *path;
2350 phandle node;
2351 ihandle ih;
2352 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002353
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11002354 static const unsigned char default_colors[] __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002355 0x00, 0x00, 0x00,
2356 0x00, 0x00, 0xaa,
2357 0x00, 0xaa, 0x00,
2358 0x00, 0xaa, 0xaa,
2359 0xaa, 0x00, 0x00,
2360 0xaa, 0x00, 0xaa,
2361 0xaa, 0xaa, 0x00,
2362 0xaa, 0xaa, 0xaa,
2363 0x55, 0x55, 0x55,
2364 0x55, 0x55, 0xff,
2365 0x55, 0xff, 0x55,
2366 0x55, 0xff, 0xff,
2367 0xff, 0x55, 0x55,
2368 0xff, 0x55, 0xff,
2369 0xff, 0xff, 0x55,
2370 0xff, 0xff, 0xff
2371 };
2372 const unsigned char *clut;
2373
Anton Blanchard4da727a2009-03-31 20:06:14 +00002374 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002375 for (node = 0; prom_next_node(&node); ) {
2376 memset(type, 0, sizeof(type));
2377 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002378 if (prom_strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002379 continue;
2380
2381 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002382 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002383 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002384
2385 /*
2386 * leave some room at the end of the path for appending extra
2387 * arguments
2388 */
2389 if (call_prom("package-to-path", 3, 1, node, path,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002390 sizeof(prom_scratch) - 10) == PROM_ERROR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002391 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002392 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002393
2394 ih = call_prom("open", 1, 1, path);
2395 if (ih == 0) {
2396 prom_printf("failed\n");
2397 continue;
2398 }
2399
2400 /* Success */
2401 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002402 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002403
2404 /* Setup a usable color table when the appropriate
2405 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002406 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002407 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002408 if (prom_set_color(ih, i, clut[0], clut[1],
2409 clut[2]) != 0)
2410 break;
2411
2412#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002413 clut = PTRRELOC(logo_linux_clut224.clut);
2414 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002415 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2416 clut[2]) != 0)
2417 break;
2418#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002419
2420#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2421 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2422 PROM_ERROR) {
2423 u32 width, height, pitch, addr;
2424
2425 prom_printf("Setting btext !\n");
Michael Ellerman6c71cfc2020-08-21 20:34:07 +10002426
2427 if (prom_getprop(node, "width", &width, 4) == PROM_ERROR)
2428 return;
2429
2430 if (prom_getprop(node, "height", &height, 4) == PROM_ERROR)
2431 return;
2432
2433 if (prom_getprop(node, "linebytes", &pitch, 4) == PROM_ERROR)
2434 return;
2435
2436 if (prom_getprop(node, "address", &addr, 4) == PROM_ERROR)
2437 return;
2438
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002439 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2440 width, height, pitch, addr);
2441 btext_setup_display(width, height, 8, pitch, addr);
Christophe Leroyc21f5a92019-06-03 13:00:51 +00002442 btext_prepare_BAT();
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002443 }
2444#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002445 }
2446}
2447
2448
2449/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2450static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2451 unsigned long needed, unsigned long align)
2452{
2453 void *ret;
2454
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002455 *mem_start = ALIGN(*mem_start, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002456 while ((*mem_start + needed) > *mem_end) {
2457 unsigned long room, chunk;
2458
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002459 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002460 alloc_bottom);
2461 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002462 if (room > DEVTREE_CHUNK_SIZE)
2463 room = DEVTREE_CHUNK_SIZE;
2464 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002465 prom_panic("No memory for flatten_device_tree "
2466 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002467 chunk = alloc_up(room, 0);
2468 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002469 prom_panic("No memory for flatten_device_tree "
2470 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002471 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002472 }
2473
2474 ret = (void *)*mem_start;
2475 *mem_start += needed;
2476
2477 return ret;
2478}
2479
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002480#define dt_push_token(token, mem_start, mem_end) do { \
2481 void *room = make_room(mem_start, mem_end, 4, 4); \
2482 *(__be32 *)room = cpu_to_be32(token); \
2483 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002484
2485static unsigned long __init dt_find_string(char *str)
2486{
2487 char *s, *os;
2488
Anton Blanchard5827d412012-11-26 17:40:03 +00002489 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002490 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002491 while (s < (char *)dt_string_end) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002492 if (prom_strcmp(s, str) == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002493 return s - os;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002494 s += prom_strlen(s) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002495 }
2496 return 0;
2497}
2498
2499/*
2500 * The Open Firmware 1275 specification states properties must be 31 bytes or
2501 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2502 */
2503#define MAX_PROPERTY_NAME 64
2504
2505static void __init scan_dt_build_strings(phandle node,
2506 unsigned long *mem_start,
2507 unsigned long *mem_end)
2508{
2509 char *prev_name, *namep, *sstart;
2510 unsigned long soff;
2511 phandle child;
2512
Anton Blanchard5827d412012-11-26 17:40:03 +00002513 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002514
2515 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002516 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002517 for (;;) {
2518 /* 64 is max len of name including nul. */
2519 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2520 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2521 /* No more nodes: unwind alloc */
2522 *mem_start = (unsigned long)namep;
2523 break;
2524 }
2525
2526 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002527 if (prom_strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002528 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002529 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002530 continue;
2531 }
2532 /* get/create string entry */
2533 soff = dt_find_string(namep);
2534 if (soff != 0) {
2535 *mem_start = (unsigned long)namep;
2536 namep = sstart + soff;
2537 } else {
2538 /* Trim off some if we can */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002539 *mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002540 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002541 }
2542 prev_name = namep;
2543 }
2544
2545 /* do all our children */
2546 child = call_prom("child", 1, 1, node);
2547 while (child != 0) {
2548 scan_dt_build_strings(child, mem_start, mem_end);
2549 child = call_prom("peer", 1, 1, child);
2550 }
2551}
2552
2553static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2554 unsigned long *mem_end)
2555{
2556 phandle child;
2557 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2558 unsigned long soff;
2559 unsigned char *valp;
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +11002560 static char pname[MAX_PROPERTY_NAME] __prombss;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002561 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002562
2563 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2564
2565 /* get the node's full name */
2566 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002567 room = *mem_end - *mem_start;
2568 if (room > 255)
2569 room = 255;
2570 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002571 if (l >= 0) {
2572 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002573 if (l >= room) {
2574 if (l >= *mem_end - *mem_start)
2575 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002576 call_prom("package-to-path", 3, 1, node, namep, l);
2577 }
2578 namep[l] = '\0';
2579
2580 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002581 * middle of the path in some properties, and extract
2582 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002583 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002584 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002585 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002586 lp = namep;
2587 else if (*p != 0)
2588 *lp++ = *p;
2589 }
2590 *lp = 0;
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002591 *mem_start = ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002592 }
2593
2594 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002595 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002596 memset(path, 0, sizeof(prom_scratch));
2597 call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002598
2599 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002600 prev_name = "";
2601 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002602 for (;;) {
2603 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002604 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002605 break;
2606
2607 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002608 if (prom_strcmp(pname, "name") == 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002609 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002610 continue;
2611 }
2612
2613 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002614 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002615 if (soff == 0) {
2616 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002617 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002618 break;
2619 }
2620 prev_name = sstart + soff;
2621
2622 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002623 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002624
2625 /* sanity checks */
2626 if (l == PROM_ERROR)
2627 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002628
2629 /* push property head */
2630 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2631 dt_push_token(l, mem_start, mem_end);
2632 dt_push_token(soff, mem_start, mem_end);
2633
2634 /* push property content */
2635 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002636 call_prom("getprop", 4, 1, node, pname, valp, l);
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002637 *mem_start = ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002638
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002639 if (!prom_strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002640 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002641 }
2642
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002643 /* Add a "phandle" property if none already exist */
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002644 if (!has_phandle) {
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002645 soff = dt_find_string("phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002646 if (soff == 0)
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002647 prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002648 else {
2649 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2650 dt_push_token(4, mem_start, mem_end);
2651 dt_push_token(soff, mem_start, mem_end);
2652 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002653 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002654 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002655 }
2656
2657 /* do all our children */
2658 child = call_prom("child", 1, 1, node);
2659 while (child != 0) {
2660 scan_dt_build_struct(child, mem_start, mem_end);
2661 child = call_prom("peer", 1, 1, child);
2662 }
2663
2664 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2665}
2666
2667static void __init flatten_device_tree(void)
2668{
2669 phandle root;
2670 unsigned long mem_start, mem_end, room;
2671 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002672 char *namep;
2673 u64 *rsvmap;
2674
2675 /*
2676 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002677 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002678 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002679 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002680 if (room > DEVTREE_CHUNK_SIZE)
2681 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002682 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002683
2684 /* Now try to claim that */
2685 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2686 if (mem_start == 0)
2687 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002688 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002689
2690 /* Get root of tree */
2691 root = call_prom("peer", 1, 1, (phandle)0);
2692 if (root == (phandle)0)
2693 prom_panic ("couldn't get device tree root\n");
2694
2695 /* Build header and make room for mem rsv map */
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002696 mem_start = ALIGN(mem_start, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002697 hdr = make_room(&mem_start, &mem_end,
2698 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002699 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002700 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2701
2702 /* Start of strings */
2703 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002704 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002705 mem_start += 4; /* hole */
2706
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002707 /* Add "phandle" in there, we'll need it */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002708 namep = make_room(&mem_start, &mem_end, 16, 1);
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002709 prom_strcpy(namep, "phandle");
2710 mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002711
2712 /* Build string array */
2713 prom_printf("Building dt strings...\n");
2714 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002715 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002716
2717 /* Build structure */
2718 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002719 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002720 prom_printf("Building dt structure...\n");
2721 scan_dt_build_struct(root, &mem_start, &mem_end);
2722 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002723 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002724
2725 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002726 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2727 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2728 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2729 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2730 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2731 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2732 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2733 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002734 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002735 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002736
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002737 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002738 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002739
2740#ifdef DEBUG_PROM
2741 {
2742 int i;
2743 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002744 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002745 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002746 be64_to_cpu(mem_reserve_map[i].base),
2747 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002748 }
2749#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002750 /* Bump mem_reserve_cnt to cause further reservations to fail
2751 * since it's too late.
2752 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002753 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002754
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002755 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002756 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002757 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002758 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002759}
2760
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002761#ifdef CONFIG_PPC_MAPLE
2762/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2763 * The values are bad, and it doesn't even have the right number of cells. */
2764static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002765{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002766 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002767 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002768 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002769 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002770
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002771 name = "/ht@0/isa@4";
2772 isa = call_prom("finddevice", 1, 1, ADDR(name));
2773 if (!PHANDLE_VALID(isa)) {
2774 name = "/ht@0/isa@6";
2775 isa = call_prom("finddevice", 1, 1, ADDR(name));
2776 rloc = 0x01003000; /* IO space; PCI device = 6 */
2777 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002778 if (!PHANDLE_VALID(isa))
2779 return;
2780
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002781 if (prom_getproplen(isa, "ranges") != 12)
2782 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002783 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2784 == PROM_ERROR)
2785 return;
2786
2787 if (isa_ranges[0] != 0x1 ||
2788 isa_ranges[1] != 0xf4000000 ||
2789 isa_ranges[2] != 0x00010000)
2790 return;
2791
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002792 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002793
2794 isa_ranges[0] = 0x1;
2795 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002796 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002797 isa_ranges[3] = 0x0;
2798 isa_ranges[4] = 0x0;
2799 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002800 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002801 isa_ranges, sizeof(isa_ranges));
2802}
Harry Ciao8f101a052009-06-17 16:28:00 -07002803
2804#define CPC925_MC_START 0xf8000000
2805#define CPC925_MC_LENGTH 0x1000000
2806/* The values for memory-controller don't have right number of cells */
2807static void __init fixup_device_tree_maple_memory_controller(void)
2808{
2809 phandle mc;
2810 u32 mc_reg[4];
2811 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002812 u32 ac, sc;
2813
2814 mc = call_prom("finddevice", 1, 1, ADDR(name));
2815 if (!PHANDLE_VALID(mc))
2816 return;
2817
2818 if (prom_getproplen(mc, "reg") != 8)
2819 return;
2820
Anton Blanchard5827d412012-11-26 17:40:03 +00002821 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2822 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002823 if ((ac != 2) || (sc != 2))
2824 return;
2825
2826 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2827 return;
2828
2829 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2830 return;
2831
2832 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2833
2834 mc_reg[0] = 0x0;
2835 mc_reg[1] = CPC925_MC_START;
2836 mc_reg[2] = 0x0;
2837 mc_reg[3] = CPC925_MC_LENGTH;
2838 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2839}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002840#else
2841#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002842#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002843#endif
2844
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002845#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002846/*
2847 * Pegasos and BriQ lacks the "ranges" property in the isa node
2848 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf92007-08-18 04:27:17 +10002849 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002850 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002851static void __init fixup_device_tree_chrp(void)
2852{
Olaf Heringe4805922007-04-04 18:20:04 +02002853 phandle ph;
2854 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002855 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002856 char *name;
2857 int rc;
2858
2859 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002860 ph = call_prom("finddevice", 1, 1, ADDR(name));
2861 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002862 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002863 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002864 rloc = 0x01003000; /* IO space; PCI device = 6 */
2865 }
Olaf Heringe4805922007-04-04 18:20:04 +02002866 if (PHANDLE_VALID(ph)) {
2867 rc = prom_getproplen(ph, "ranges");
2868 if (rc == 0 || rc == PROM_ERROR) {
2869 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002870
Olaf Heringe4805922007-04-04 18:20:04 +02002871 prop[0] = 0x1;
2872 prop[1] = 0x0;
2873 prop[2] = rloc;
2874 prop[3] = 0x0;
2875 prop[4] = 0x0;
2876 prop[5] = 0x00010000;
2877 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2878 }
2879 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002880
Olaf Heringe4805922007-04-04 18:20:04 +02002881 name = "/pci@80000000/ide@C,1";
2882 ph = call_prom("finddevice", 1, 1, ADDR(name));
2883 if (PHANDLE_VALID(ph)) {
2884 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2885 prop[0] = 14;
2886 prop[1] = 0x0;
Olaf Hering556ecf92007-08-18 04:27:17 +10002887 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2888 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2889 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2890 if (rc == sizeof(u32)) {
2891 prop[0] &= ~0x5;
2892 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2893 }
Olaf Heringe4805922007-04-04 18:20:04 +02002894 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002895}
2896#else
2897#define fixup_device_tree_chrp()
2898#endif
2899
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002900#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002901static void __init fixup_device_tree_pmac(void)
2902{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002903 phandle u3, i2c, mpic;
2904 u32 u3_rev;
2905 u32 interrupts[2];
2906 u32 parent;
2907
2908 /* Some G5s have a missing interrupt definition, fix it up here */
2909 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2910 if (!PHANDLE_VALID(u3))
2911 return;
2912 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2913 if (!PHANDLE_VALID(i2c))
2914 return;
2915 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2916 if (!PHANDLE_VALID(mpic))
2917 return;
2918
2919 /* check if proper rev of u3 */
2920 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2921 == PROM_ERROR)
2922 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002923 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002924 return;
2925 /* does it need fixup ? */
2926 if (prom_getproplen(i2c, "interrupts") > 0)
2927 return;
2928
2929 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2930
2931 /* interrupt on this revision of u3 is number 0 and level */
2932 interrupts[0] = 0;
2933 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002934 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2935 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002936 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002937 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2938 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002939}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002940#else
2941#define fixup_device_tree_pmac()
2942#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002943
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002944#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002945/*
2946 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2947 * to talk to the phy. If the phy-handle property is missing, then this
2948 * function is called to add the appropriate nodes and link it to the
2949 * ethernet node.
2950 */
2951static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002952{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002953 u32 node;
2954 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002955 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002956
Grant Likely94d2dde2008-01-24 22:25:32 -07002957 /* Check if /builtin/ethernet exists - bail if it doesn't */
2958 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002959 if (!PHANDLE_VALID(node))
2960 return;
2961
Grant Likely94d2dde2008-01-24 22:25:32 -07002962 /* Check if the phy-handle property exists - bail if it does */
2963 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2964 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002965 return;
2966
Grant Likely94d2dde2008-01-24 22:25:32 -07002967 /*
2968 * At this point the ethernet device doesn't have a phy described.
2969 * Now we need to add the missing phy node and linkage
2970 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002971
Grant Likely94d2dde2008-01-24 22:25:32 -07002972 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002973 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2974 if (!PHANDLE_VALID(node)) {
2975 prom_printf("Adding Ethernet MDIO node\n");
2976 call_prom("interpret", 1, 1,
2977 " s\" /builtin\" find-device"
2978 " new-device"
2979 " 1 encode-int s\" #address-cells\" property"
2980 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002981 " s\" mdio\" device-name"
2982 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002983 " s\" compatible\" property"
2984 " 0xf0003000 0x400 reg"
2985 " 0x2 encode-int"
2986 " 0x5 encode-int encode+"
2987 " 0x3 encode-int encode+"
2988 " s\" interrupts\" property"
2989 " finish-device");
2990 };
2991
Grant Likely94d2dde2008-01-24 22:25:32 -07002992 /* Check for a PHY device node - if missing then create one and
2993 * give it's phandle to the ethernet node */
2994 node = call_prom("finddevice", 1, 1,
2995 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002996 if (!PHANDLE_VALID(node)) {
2997 prom_printf("Adding Ethernet PHY node\n");
2998 call_prom("interpret", 1, 1,
2999 " s\" /builtin/mdio\" find-device"
3000 " new-device"
3001 " s\" ethernet-phy\" device-name"
3002 " 0x10 encode-int s\" reg\" property"
3003 " my-self"
3004 " ihandle>phandle"
3005 " finish-device"
3006 " s\" /builtin/ethernet\" find-device"
3007 " encode-int"
3008 " s\" phy-handle\" property"
3009 " device-end");
3010 }
Grant Likely94d2dde2008-01-24 22:25:32 -07003011}
Olaf Hering6f4347c2008-01-10 01:06:08 +11003012
Grant Likely94d2dde2008-01-24 22:25:32 -07003013static void __init fixup_device_tree_efika(void)
3014{
3015 int sound_irq[3] = { 2, 2, 0 };
3016 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
3017 3,4,0, 3,5,0, 3,6,0, 3,7,0,
3018 3,8,0, 3,9,0, 3,10,0, 3,11,0,
3019 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
3020 u32 node;
3021 char prop[64];
3022 int rv, len;
3023
3024 /* Check if we're really running on a EFIKA */
3025 node = call_prom("finddevice", 1, 1, ADDR("/"));
3026 if (!PHANDLE_VALID(node))
3027 return;
3028
3029 rv = prom_getprop(node, "model", prop, sizeof(prop));
3030 if (rv == PROM_ERROR)
3031 return;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003032 if (prom_strcmp(prop, "EFIKA5K2"))
Grant Likely94d2dde2008-01-24 22:25:32 -07003033 return;
3034
3035 prom_printf("Applying EFIKA device tree fixups\n");
3036
3037 /* Claiming to be 'chrp' is death */
3038 node = call_prom("finddevice", 1, 1, ADDR("/"));
3039 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003040 if (rv != PROM_ERROR && (prom_strcmp(prop, "chrp") == 0))
Grant Likely94d2dde2008-01-24 22:25:32 -07003041 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
3042
David Woodhouse7f4392c2008-04-14 02:52:38 +10003043 /* CODEGEN,description is exposed in /proc/cpuinfo so
3044 fix that too */
3045 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003046 if (rv != PROM_ERROR && (prom_strstr(prop, "CHRP")))
David Woodhouse7f4392c2008-04-14 02:52:38 +10003047 prom_setprop(node, "/", "CODEGEN,description",
3048 "Efika 5200B PowerPC System",
3049 sizeof("Efika 5200B PowerPC System"));
3050
Grant Likely94d2dde2008-01-24 22:25:32 -07003051 /* Fixup bestcomm interrupts property */
3052 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
3053 if (PHANDLE_VALID(node)) {
3054 len = prom_getproplen(node, "interrupts");
3055 if (len == 12) {
3056 prom_printf("Fixing bestcomm interrupts property\n");
3057 prom_setprop(node, "/builtin/bestcom", "interrupts",
3058 bcomm_irq, sizeof(bcomm_irq));
3059 }
3060 }
3061
3062 /* Fixup sound interrupts property */
3063 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
3064 if (PHANDLE_VALID(node)) {
3065 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
3066 if (rv == PROM_ERROR) {
3067 prom_printf("Adding sound interrupts property\n");
3068 prom_setprop(node, "/builtin/sound", "interrupts",
3069 sound_irq, sizeof(sound_irq));
3070 }
3071 }
3072
3073 /* Make sure ethernet phy-handle property exists */
3074 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003075}
3076#else
3077#define fixup_device_tree_efika()
3078#endif
3079
Darren Stevens50246782016-08-31 13:24:40 +01003080#ifdef CONFIG_PPC_PASEMI_NEMO
3081/*
3082 * CFE supplied on Nemo is broken in several ways, biggest
3083 * problem is that it reassigns ISA interrupts to unused mpic ints.
3084 * Add an interrupt-controller property for the io-bridge to use
3085 * and correct the ints so we can attach them to an irq_domain
3086 */
3087static void __init fixup_device_tree_pasemi(void)
3088{
3089 u32 interrupts[2], parent, rval, val = 0;
3090 char *name, *pci_name;
3091 phandle iob, node;
3092
3093 /* Find the root pci node */
3094 name = "/pxp@0,e0000000";
3095 iob = call_prom("finddevice", 1, 1, ADDR(name));
3096 if (!PHANDLE_VALID(iob))
3097 return;
3098
3099 /* check if interrupt-controller node set yet */
3100 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
3101 return;
3102
3103 prom_printf("adding interrupt-controller property for SB600...\n");
3104
3105 prom_setprop(iob, name, "interrupt-controller", &val, 0);
3106
3107 pci_name = "/pxp@0,e0000000/pci@11";
3108 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
3109 parent = ADDR(iob);
3110
3111 for( ; prom_next_node(&node); ) {
3112 /* scan each node for one with an interrupt */
3113 if (!PHANDLE_VALID(node))
3114 continue;
3115
3116 rval = prom_getproplen(node, "interrupts");
3117 if (rval == 0 || rval == PROM_ERROR)
3118 continue;
3119
3120 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
3121 if ((interrupts[0] < 212) || (interrupts[0] > 222))
3122 continue;
3123
3124 /* found a node, update both interrupts and interrupt-parent */
3125 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
3126 interrupts[0] -= 203;
3127 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
3128 interrupts[0] -= 213;
3129 if (interrupts[0] == 221)
3130 interrupts[0] = 14;
3131 if (interrupts[0] == 222)
3132 interrupts[0] = 8;
3133
3134 prom_setprop(node, pci_name, "interrupts", interrupts,
3135 sizeof(interrupts));
3136 prom_setprop(node, pci_name, "interrupt-parent", &parent,
3137 sizeof(parent));
3138 }
Darren Stevens687e16b2016-08-31 13:24:45 +01003139
3140 /*
3141 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
3142 * so that generic isa-bridge code can add the SB600 and its on-board
3143 * peripherals.
3144 */
3145 name = "/pxp@0,e0000000/io-bridge@0";
3146 iob = call_prom("finddevice", 1, 1, ADDR(name));
3147 if (!PHANDLE_VALID(iob))
3148 return;
3149
3150 /* device_type is already set, just change it. */
3151
3152 prom_printf("Changing device_type of SB600 node...\n");
3153
3154 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01003155}
3156#else /* !CONFIG_PPC_PASEMI_NEMO */
3157static inline void fixup_device_tree_pasemi(void) { }
3158#endif
3159
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003160static void __init fixup_device_tree(void)
3161{
3162 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07003163 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10003164 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003165 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003166 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01003167 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003168}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003169
3170static void __init prom_find_boot_cpu(void)
3171{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003172 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003173 ihandle prom_cpu;
3174 phandle cpu_pkg;
3175
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003176 rval = 0;
3177 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10003178 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003179 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003180
3181 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
3182
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00003183 if (!PHANDLE_VALID(cpu_pkg))
3184 return;
3185
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003186 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
3187 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003188
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003189 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003190}
3191
3192static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
3193{
3194#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003195 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003196 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003197
Anton Blanchard5827d412012-11-26 17:40:03 +00003198 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
3199 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003200
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003201 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00003202 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003203 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003204 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00003205 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003206 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003207
Anton Blanchard5827d412012-11-26 17:40:03 +00003208 reserve_mem(prom_initrd_start,
3209 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003210
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003211 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
3212 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003213 }
3214#endif /* CONFIG_BLK_DEV_INITRD */
3215}
3216
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003217#ifdef CONFIG_PPC64
3218#ifdef CONFIG_RELOCATABLE
3219static void reloc_toc(void)
3220{
3221}
3222
3223static void unreloc_toc(void)
3224{
3225}
3226#else
Anton Blanchard16744002013-03-12 01:51:51 +00003227static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003228{
3229 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003230 unsigned long *toc_entry;
3231
3232 /* Get the start of the TOC by using r2 directly. */
3233 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003234
3235 for (i = 0; i < nr_entries; i++) {
3236 *toc_entry = *toc_entry + offset;
3237 toc_entry++;
3238 }
3239}
3240
3241static void reloc_toc(void)
3242{
3243 unsigned long offset = reloc_offset();
3244 unsigned long nr_entries =
3245 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3246
Anton Blanchard16744002013-03-12 01:51:51 +00003247 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003248
3249 mb();
3250}
3251
3252static void unreloc_toc(void)
3253{
3254 unsigned long offset = reloc_offset();
3255 unsigned long nr_entries =
3256 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3257
3258 mb();
3259
Anton Blanchard16744002013-03-12 01:51:51 +00003260 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003261}
3262#endif
3263#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003264
Ram Pai6a9c9302019-08-19 23:13:14 -03003265#ifdef CONFIG_PPC_SVM
3266/*
3267 * Perform the Enter Secure Mode ultracall.
3268 */
3269static int enter_secure_mode(unsigned long kbase, unsigned long fdt)
3270{
3271 register unsigned long r3 asm("r3") = UV_ESM;
3272 register unsigned long r4 asm("r4") = kbase;
3273 register unsigned long r5 asm("r5") = fdt;
3274
3275 asm volatile("sc 2" : "+r"(r3) : "r"(r4), "r"(r5));
3276
3277 return r3;
3278}
3279
3280/*
3281 * Call the Ultravisor to transfer us to secure memory if we have an ESM blob.
3282 */
Vladis Dronovaff77952020-07-29 15:37:41 +02003283static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
Ram Pai6a9c9302019-08-19 23:13:14 -03003284{
3285 int ret;
3286
3287 if (!prom_svm_enable)
3288 return;
3289
3290 /* Switch to secure mode. */
3291 prom_printf("Switching to secure mode.\n");
3292
Thiago Jung Bauermann05d9a952019-09-11 13:34:33 -03003293 /*
3294 * The ultravisor will do an integrity check of the kernel image but we
3295 * relocated it so the check will fail. Restore the original image by
3296 * relocating it back to the kernel virtual base address.
3297 */
3298 if (IS_ENABLED(CONFIG_RELOCATABLE))
3299 relocate(KERNELBASE);
3300
Ram Pai6a9c9302019-08-19 23:13:14 -03003301 ret = enter_secure_mode(kbase, fdt);
Thiago Jung Bauermann05d9a952019-09-11 13:34:33 -03003302
3303 /* Relocate the kernel again. */
3304 if (IS_ENABLED(CONFIG_RELOCATABLE))
3305 relocate(kbase);
3306
Ram Pai6a9c9302019-08-19 23:13:14 -03003307 if (ret != U_SUCCESS) {
3308 prom_printf("Returned %d from switching to secure mode.\n", ret);
3309 prom_rtas_os_term("Switch to secure mode failed.\n");
3310 }
3311}
3312#else
Vladis Dronovaff77952020-07-29 15:37:41 +02003313static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
Ram Pai6a9c9302019-08-19 23:13:14 -03003314{
3315}
3316#endif /* CONFIG_PPC_SVM */
3317
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003318/*
3319 * We enter here early on, when the Open Firmware prom is still
3320 * handling exceptions and the MMU hash table for us.
3321 */
3322
3323unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3324 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003325 unsigned long r6, unsigned long r7,
3326 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003327{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003328 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003329
3330#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003331 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003332 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003333#else
3334 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003335#endif
3336
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003337 /*
3338 * First zero the BSS
3339 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003340 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003341
3342 /*
3343 * Init interface to Open Firmware, get some node references,
3344 * like /chosen
3345 */
3346 prom_init_client_services(pp);
3347
3348 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003349 * See if this OF is old enough that we need to do explicit maps
3350 * and other workarounds
3351 */
3352 prom_find_mmu();
3353
3354 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003355 * Init prom stdout device
3356 */
3357 prom_init_stdout();
3358
Anton Blanchard5827d412012-11-26 17:40:03 +00003359 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003360
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003361 /*
3362 * Get default machine type. At this point, we do not differentiate
3363 * between pSeries SMP and pSeries LPAR
3364 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003365 of_platform = prom_find_machine_type();
3366 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003367
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003368#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003369 /* Bail if this is a kdump kernel. */
3370 if (PHYSICAL_START > 0)
3371 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003372#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003373
3374 /*
3375 * Check for an initrd
3376 */
3377 prom_check_initrd(r3, r4);
3378
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003379 /*
3380 * Do early parsing of command line
3381 */
3382 early_cmdline_parse();
3383
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003384#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003385 /*
3386 * On pSeries, inform the firmware about our capabilities
3387 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003388 if (of_platform == PLATFORM_PSERIES ||
3389 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003390 prom_send_capabilities();
3391#endif
3392
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003393 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003394 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003395 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003396 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003397 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003398
3399 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003400 * Initialize memory management within prom_init
3401 */
3402 prom_init_mem();
3403
3404 /*
3405 * Determine which cpu is actually running right _now_
3406 */
3407 prom_find_boot_cpu();
3408
3409 /*
3410 * Initialize display devices
3411 */
3412 prom_check_displays();
3413
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003414#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003415 /*
3416 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3417 * that uses the allocator, we need to make sure we get the top of memory
3418 * available for us here...
3419 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003420 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003421 prom_initialize_tce_table();
3422#endif
3423
3424 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003425 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3426 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003427 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003428 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003429 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003430
Ashley Lai4a727422012-08-14 18:34:57 -05003431#ifdef CONFIG_PPC64
3432 /* instantiate sml */
3433 prom_instantiate_sml();
3434#endif
3435
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003436 /*
3437 * On non-powermacs, put all CPUs in spin-loops.
3438 *
3439 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003440 *
3441 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003442 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003443 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003444 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003445
3446 /*
3447 * Fill in some infos for use by the kernel later on
3448 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003449 if (prom_memory_limit) {
3450 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003451 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003452 &val, sizeof(val));
3453 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003454#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003455 if (prom_iommu_off)
3456 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003457 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003458
Anton Blanchard5827d412012-11-26 17:40:03 +00003459 if (prom_iommu_force_on)
3460 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003461 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003462
Anton Blanchard5827d412012-11-26 17:40:03 +00003463 if (prom_tce_alloc_start) {
3464 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3465 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003466 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003467 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3468 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003469 sizeof(prom_tce_alloc_end));
3470 }
3471#endif
3472
3473 /*
3474 * Fixup any known bugs in the device-tree
3475 */
3476 fixup_device_tree();
3477
3478 /*
3479 * Now finally create the flattened device-tree
3480 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003481 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003482 flatten_device_tree();
3483
Paul Mackerras3825ac02005-11-08 22:48:08 +11003484 /*
3485 * in case stdin is USB and still active on IBM machines...
3486 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003487 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003488 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003489 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003490 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003491
3492 /*
3493 * Call OF "quiesce" method to shut down pending DMA's from
3494 * devices etc...
3495 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003496 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003497 call_prom("quiesce", 0, 0);
3498
3499 /*
3500 * And finally, call the kernel passing it the flattened device
3501 * tree and NULL as r5, thus triggering the new entry point which
3502 * is common to us and kexec
3503 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003504 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003505
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003506 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3507 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003508
3509#ifdef CONFIG_PPC32
3510 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003511#else
3512 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003513#endif
3514
Ram Pai6a9c9302019-08-19 23:13:14 -03003515 /* Move to secure memory if we're supposed to be secure guests. */
3516 setup_secure_guest(kbase, hdr);
3517
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003518 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003519
3520 return 0;
3521}