blob: 523b31685c4cbadf8741233ac38a8b62ff6e744b [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. */
Andy Shevchenko4cfdd922021-05-10 17:49:25 +0300704#define prom_isxdigit(c) \
705 (('0' <= (c) && (c) <= '9') || ('a' <= (c) && (c) <= 'f') || ('A' <= (c) && (c) <= 'F'))
Benjamin Krillcf687872009-07-27 22:02:39 +0000706
Andy Shevchenko4cfdd922021-05-10 17:49:25 +0300707#define prom_isdigit(c) ('0' <= (c) && (c) <= '9')
708#define prom_islower(c) ('a' <= (c) && (c) <= 'z')
709#define prom_toupper(c) (prom_islower(c) ? ((c) - 'a' + 'A') : (c))
Benjamin Krillcf687872009-07-27 22:02:39 +0000710
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000711static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000712{
713 unsigned long result = 0, base = 10, value;
714
715 if (*cp == '0') {
716 base = 8;
717 cp++;
Andy Shevchenko4cfdd922021-05-10 17:49:25 +0300718 if (prom_toupper(*cp) == 'X') {
Benjamin Krillcf687872009-07-27 22:02:39 +0000719 cp++;
720 base = 16;
721 }
722 }
723
Andy Shevchenko4cfdd922021-05-10 17:49:25 +0300724 while (prom_isxdigit(*cp) &&
725 (value = prom_isdigit(*cp) ? *cp - '0' : prom_toupper(*cp) - 'A' + 10) < base) {
Benjamin Krillcf687872009-07-27 22:02:39 +0000726 result = result * base + value;
727 cp++;
728 }
729
730 if (endp)
731 *endp = cp;
732
733 return result;
734}
735
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000736static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000737{
738 unsigned long ret = prom_strtoul(ptr, retptr);
739 int shift = 0;
740
741 /*
742 * We can't use a switch here because GCC *may* generate a
743 * jump table which won't work, because we're not running at
744 * the address we're linked at.
745 */
746 if ('G' == **retptr || 'g' == **retptr)
747 shift = 30;
748
749 if ('M' == **retptr || 'm' == **retptr)
750 shift = 20;
751
752 if ('K' == **retptr || 'k' == **retptr)
753 shift = 10;
754
755 if (shift) {
756 ret <<= shift;
757 (*retptr)++;
758 }
759
760 return ret;
761}
762
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000763/*
764 * Early parsing of the command line passed to the kernel, used for
765 * "mem=x" and the options that affect the iommu
766 */
767static void __init early_cmdline_parse(void)
768{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100769 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000770
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100771 char *p;
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000772 int l = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000773
Anton Blanchard5827d412012-11-26 17:40:03 +0000774 prom_cmd_line[0] = 0;
775 p = prom_cmd_line;
Chris Packhamd79fbb32019-08-02 10:50:06 +1200776
777 if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && (long)prom.chosen > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +0000778 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Chris Packhamd79fbb32019-08-02 10:50:06 +1200779
780 if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || l <= 0 || p[0] == '\0')
781 prom_strlcat(prom_cmd_line, " " CONFIG_CMDLINE,
782 sizeof(prom_cmd_line));
783
Anton Blanchard5827d412012-11-26 17:40:03 +0000784 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000785
786#ifdef CONFIG_PPC64
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000787 opt = prom_strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000788 if (opt) {
789 prom_printf("iommu opt is: %s\n", opt);
790 opt += 6;
791 while (*opt && *opt == ' ')
792 opt++;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000793 if (!prom_strncmp(opt, "off", 3))
Anton Blanchard5827d412012-11-26 17:40:03 +0000794 prom_iommu_off = 1;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000795 else if (!prom_strncmp(opt, "force", 5))
Anton Blanchard5827d412012-11-26 17:40:03 +0000796 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000797 }
798#endif
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000799 opt = prom_strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000800 if (opt) {
801 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000802 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000803#ifdef CONFIG_PPC64
804 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000805 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000806#endif
807 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100808
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100809#ifdef CONFIG_PPC_PSERIES
810 prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000811 opt = prom_strstr(prom_cmd_line, "disable_radix");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100812 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530813 opt += 13;
814 if (*opt && *opt == '=') {
815 bool val;
816
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000817 if (prom_strtobool(++opt, &val))
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530818 prom_radix_disable = false;
819 else
820 prom_radix_disable = val;
821 } else
822 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100823 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530824 if (prom_radix_disable)
825 prom_debug("Radix disabled from cmdline\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200826
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +0530827 opt = prom_strstr(prom_cmd_line, "radix_hcall_invalidate=on");
828 if (opt) {
829 prom_radix_gtse_disable = true;
830 prom_debug("Radix GTSE disabled from cmdline\n");
831 }
832
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200833 opt = prom_strstr(prom_cmd_line, "xive=off");
834 if (opt) {
835 prom_xive_disable = true;
836 prom_debug("XIVE disabled from cmdline\n");
837 }
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100838#endif /* CONFIG_PPC_PSERIES */
Ram Pai6a9c9302019-08-19 23:13:14 -0300839
840#ifdef CONFIG_PPC_SVM
841 opt = prom_strstr(prom_cmd_line, "svm=");
842 if (opt) {
843 bool val;
844
845 opt += sizeof("svm=") - 1;
846 if (!prom_strtobool(opt, &val))
847 prom_svm_enable = val;
848 }
849#endif /* CONFIG_PPC_SVM */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000850}
851
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +1100852#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000853/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000854 * The architecture vector has an array of PVR mask/value pairs,
855 * followed by # option vectors - 1, followed by the option vectors.
856 *
857 * See prom.h for the definition of the bits specified in the
858 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000859 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000860
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000861/* Firmware expects the value to be n - 1, where n is the # of vectors */
862#define NUM_VECTORS(n) ((n) - 1)
863
864/*
865 * Firmware expects 1 + n - 2, where n is the length of the option vector in
866 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
867 */
868#define VECTOR_LENGTH(n) (1 + (n) - 2)
869
Michael Ellermand03d1d62016-11-18 23:15:41 +1100870struct option_vector1 {
871 u8 byte1;
872 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100873 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100874} __packed;
875
876struct option_vector2 {
877 u8 byte1;
878 __be16 reserved;
879 __be32 real_base;
880 __be32 real_size;
881 __be32 virt_base;
882 __be32 virt_size;
883 __be32 load_base;
884 __be32 min_rma;
885 __be32 min_load;
886 u8 min_rma_percent;
887 u8 max_pft_size;
888} __packed;
889
890struct option_vector3 {
891 u8 byte1;
892 u8 byte2;
893} __packed;
894
895struct option_vector4 {
896 u8 byte1;
897 u8 min_vp_cap;
898} __packed;
899
900struct option_vector5 {
901 u8 byte1;
902 u8 byte2;
903 u8 byte3;
904 u8 cmo;
905 u8 associativity;
906 u8 bin_opts;
907 u8 micro_checkpoint;
908 u8 reserved0;
909 __be32 max_cpus;
910 __be16 papr_level;
911 __be16 reserved1;
912 u8 platform_facilities;
913 u8 reserved2;
914 __be16 reserved3;
915 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100916 u8 byte22;
917 u8 intarch;
918 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100919 u8 hash_ext;
920 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100921} __packed;
922
923struct option_vector6 {
924 u8 reserved;
925 u8 secondary_pteg;
926 u8 os_name;
927} __packed;
928
Michael Ellerman76ffb572016-11-18 23:15:42 +1100929struct ibm_arch_vec {
Alistair Popplea3ea40d2020-05-21 11:43:41 +1000930 struct { u32 mask, val; } pvrs[14];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100931
932 u8 num_vectors;
933
934 u8 vec1_len;
935 struct option_vector1 vec1;
936
937 u8 vec2_len;
938 struct option_vector2 vec2;
939
940 u8 vec3_len;
941 struct option_vector3 vec3;
942
943 u8 vec4_len;
944 struct option_vector4 vec4;
945
946 u8 vec5_len;
947 struct option_vector5 vec5;
948
949 u8 vec6_len;
950 struct option_vector6 vec6;
951} __packed;
952
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +1100953static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100954 .pvrs = {
955 {
956 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
957 .val = cpu_to_be32(0x003a0000),
958 },
959 {
960 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
961 .val = cpu_to_be32(0x003e0000),
962 },
963 {
964 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
965 .val = cpu_to_be32(0x003f0000),
966 },
967 {
968 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
969 .val = cpu_to_be32(0x004b0000),
970 },
971 {
972 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
973 .val = cpu_to_be32(0x004c0000),
974 },
975 {
976 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
977 .val = cpu_to_be32(0x004d0000),
978 },
979 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100980 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
981 .val = cpu_to_be32(0x004e0000),
982 },
983 {
Alistair Popplea3ea40d2020-05-21 11:43:41 +1000984 .mask = cpu_to_be32(0xffff0000), /* POWER10 */
985 .val = cpu_to_be32(0x00800000),
986 },
987 {
988 .mask = cpu_to_be32(0xffffffff), /* all 3.1-compliant */
989 .val = cpu_to_be32(0x0f000006),
990 },
991 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100992 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
993 .val = cpu_to_be32(0x0f000005),
994 },
995 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100996 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
997 .val = cpu_to_be32(0x0f000004),
998 },
999 {
1000 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
1001 .val = cpu_to_be32(0x0f000003),
1002 },
1003 {
1004 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
1005 .val = cpu_to_be32(0x0f000002),
1006 },
1007 {
1008 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
1009 .val = cpu_to_be32(0x0f000001),
1010 },
1011 },
1012
1013 .num_vectors = NUM_VECTORS(6),
1014
1015 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
1016 .vec1 = {
1017 .byte1 = 0,
1018 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
1019 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Alistair Popplea3ea40d2020-05-21 11:43:41 +10001020 .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001021 },
1022
1023 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
1024 /* option vector 2: Open Firmware options supported */
1025 .vec2 = {
1026 .byte1 = OV2_REAL_MODE,
1027 .reserved = 0,
1028 .real_base = cpu_to_be32(0xffffffff),
1029 .real_size = cpu_to_be32(0xffffffff),
1030 .virt_base = cpu_to_be32(0xffffffff),
1031 .virt_size = cpu_to_be32(0xffffffff),
1032 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -04001033 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +11001034 .min_load = cpu_to_be32(0xffffffff), /* full client load */
1035 .min_rma_percent = 0, /* min RMA percentage of total RAM */
1036 .max_pft_size = 48, /* max log_2(hash table size) */
1037 },
1038
1039 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
1040 /* option vector 3: processor options supported */
1041 .vec3 = {
1042 .byte1 = 0, /* don't ignore, don't halt */
1043 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
1044 },
1045
1046 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
1047 /* option vector 4: IBM PAPR implementation */
1048 .vec4 = {
1049 .byte1 = 0, /* don't halt */
1050 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
1051 },
1052
1053 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
1054 /* option vector 5: PAPR/OF options */
1055 .vec5 = {
1056 .byte1 = 0, /* don't ignore, don't halt */
1057 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
1058 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
1059#ifdef CONFIG_PCI_MSI
1060 /* PCIe/MSI support. Without MSI full PCIe is not supported */
1061 OV5_FEAT(OV5_MSI),
1062#else
1063 0,
1064#endif
1065 .byte3 = 0,
1066 .cmo =
1067#ifdef CONFIG_PPC_SMLPAR
1068 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
1069#else
1070 0,
1071#endif
1072 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -06001073 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +11001074 .micro_checkpoint = 0,
1075 .reserved0 = 0,
1076 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
1077 .papr_level = 0,
1078 .reserved1 = 0,
1079 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
1080 .reserved2 = 0,
1081 .reserved3 = 0,
1082 .subprocessors = 1,
Tyrel Datwyler0a87ccd2019-11-10 23:21:37 -06001083 .byte22 = OV5_FEAT(OV5_DRMEM_V2) | OV5_FEAT(OV5_DRC_INFO),
Paul Mackerrascc3d2942017-01-30 21:21:36 +11001084 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001085 .mmu = 0,
1086 .hash_ext = 0,
1087 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001088 },
1089
1090 /* option vector 6: IBM PAPR hints */
1091 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
1092 .vec6 = {
1093 .reserved = 0,
1094 .secondary_pteg = 0,
1095 .os_name = OV6_LINUX,
1096 },
1097};
1098
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001099static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned;
1100
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001101/* Old method - ELF header with PT_NOTE sections only works on BE */
1102#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +10001103static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001104 Elf32_Ehdr elfhdr;
1105 Elf32_Phdr phdr[2];
1106 struct chrpnote {
1107 u32 namesz;
1108 u32 descsz;
1109 u32 type;
1110 char name[8]; /* "PowerPC" */
1111 struct chrpdesc {
1112 u32 real_mode;
1113 u32 real_base;
1114 u32 real_size;
1115 u32 virt_base;
1116 u32 virt_size;
1117 u32 load_base;
1118 } chrpdesc;
1119 } chrpnote;
1120 struct rpanote {
1121 u32 namesz;
1122 u32 descsz;
1123 u32 type;
1124 char name[24]; /* "IBM,RPA-Client-Config" */
1125 struct rpadesc {
1126 u32 lpar_affinity;
1127 u32 min_rmo_size;
1128 u32 min_rmo_percent;
1129 u32 max_pft_size;
1130 u32 splpar;
1131 u32 min_load;
1132 u32 new_mem_def;
1133 u32 ignore_me;
1134 } rpadesc;
1135 } rpanote;
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11001136} fake_elf __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001137 .elfhdr = {
1138 .e_ident = { 0x7f, 'E', 'L', 'F',
1139 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
1140 .e_type = ET_EXEC, /* yeah right */
1141 .e_machine = EM_PPC,
1142 .e_version = EV_CURRENT,
1143 .e_phoff = offsetof(struct fake_elf, phdr),
1144 .e_phentsize = sizeof(Elf32_Phdr),
1145 .e_phnum = 2
1146 },
1147 .phdr = {
1148 [0] = {
1149 .p_type = PT_NOTE,
1150 .p_offset = offsetof(struct fake_elf, chrpnote),
1151 .p_filesz = sizeof(struct chrpnote)
1152 }, [1] = {
1153 .p_type = PT_NOTE,
1154 .p_offset = offsetof(struct fake_elf, rpanote),
1155 .p_filesz = sizeof(struct rpanote)
1156 }
1157 },
1158 .chrpnote = {
1159 .namesz = sizeof("PowerPC"),
1160 .descsz = sizeof(struct chrpdesc),
1161 .type = 0x1275,
1162 .name = "PowerPC",
1163 .chrpdesc = {
1164 .real_mode = ~0U, /* ~0 means "don't care" */
1165 .real_base = ~0U,
1166 .real_size = ~0U,
1167 .virt_base = ~0U,
1168 .virt_size = ~0U,
1169 .load_base = ~0U
1170 },
1171 },
1172 .rpanote = {
1173 .namesz = sizeof("IBM,RPA-Client-Config"),
1174 .descsz = sizeof(struct rpadesc),
1175 .type = 0x12759999,
1176 .name = "IBM,RPA-Client-Config",
1177 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001178 .lpar_affinity = 0,
1179 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001180 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001181 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001182 .splpar = 1,
1183 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001184 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001185 }
1186 }
1187};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001188#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001189
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001190static int __init prom_count_smt_threads(void)
1191{
1192 phandle node;
1193 char type[64];
1194 unsigned int plen;
1195
1196 /* Pick up th first CPU node we can find */
1197 for (node = 0; prom_next_node(&node); ) {
1198 type[0] = 0;
1199 prom_getprop(node, "device_type", type, sizeof(type));
1200
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001201 if (prom_strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001202 continue;
1203 /*
1204 * There is an entry for each smt thread, each entry being
1205 * 4 bytes long. All cpus should have the same number of
1206 * smt threads, so return after finding the first.
1207 */
1208 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1209 if (plen == PROM_ERROR)
1210 break;
1211 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001212 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001213
1214 /* Sanity check */
1215 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001216 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001217 (unsigned long)plen);
1218 return 1;
1219 }
1220 return plen;
1221 }
1222 prom_debug("No threads found, assuming 1 per core\n");
1223
1224 return 1;
1225
1226}
1227
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001228static void __init prom_parse_mmu_model(u8 val,
1229 struct platform_support *support)
1230{
1231 switch (val) {
1232 case OV5_FEAT(OV5_MMU_DYNAMIC):
1233 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1234 prom_debug("MMU - either supported\n");
1235 support->radix_mmu = !prom_radix_disable;
1236 support->hash_mmu = true;
1237 break;
1238 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1239 prom_debug("MMU - radix only\n");
1240 if (prom_radix_disable) {
1241 /*
1242 * If we __have__ to do radix, we're better off ignoring
1243 * the command line rather than not booting.
1244 */
1245 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1246 }
1247 support->radix_mmu = true;
1248 break;
1249 case OV5_FEAT(OV5_MMU_HASH):
1250 prom_debug("MMU - hash only\n");
1251 support->hash_mmu = true;
1252 break;
1253 default:
1254 prom_debug("Unknown mmu support option: 0x%x\n", val);
1255 break;
1256 }
1257}
1258
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001259static void __init prom_parse_xive_model(u8 val,
1260 struct platform_support *support)
1261{
1262 switch (val) {
1263 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1264 prom_debug("XIVE - either mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001265 support->xive = !prom_xive_disable;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001266 break;
1267 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1268 prom_debug("XIVE - exploitation mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001269 if (prom_xive_disable) {
1270 /*
1271 * If we __have__ to do XIVE, we're better off ignoring
1272 * the command line rather than not booting.
1273 */
1274 prom_printf("WARNING: Ignoring cmdline option xive=off\n");
1275 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001276 support->xive = true;
1277 break;
1278 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1279 prom_debug("XIVE - legacy mode supported\n");
1280 break;
1281 default:
1282 prom_debug("Unknown xive support option: 0x%x\n", val);
1283 break;
1284 }
1285}
1286
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001287static void __init prom_parse_platform_support(u8 index, u8 val,
1288 struct platform_support *support)
1289{
1290 switch (index) {
1291 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1292 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1293 break;
1294 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +05301295 if (val & OV5_FEAT(OV5_RADIX_GTSE))
1296 support->radix_gtse = !prom_radix_gtse_disable;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001297 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001298 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1299 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1300 support);
1301 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001302 }
1303}
1304
1305static void __init prom_check_platform_support(void)
1306{
1307 struct platform_support supported = {
1308 .hash_mmu = false,
1309 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001310 .radix_gtse = false,
1311 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001312 };
1313 int prop_len = prom_getproplen(prom.chosen,
1314 "ibm,arch-vec-5-platform-support");
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001315
Christophe Leroyadcf5912019-04-26 16:23:29 +00001316 /*
1317 * First copy the architecture vec template
1318 *
1319 * use memcpy() instead of *vec = *vec_template so that GCC replaces it
1320 * by __memcpy() when KASAN is active
1321 */
1322 memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template,
1323 sizeof(ibm_architecture_vec));
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001324
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001325 if (prop_len > 1) {
1326 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001327 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001328 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1329 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001330 if (prop_len > sizeof(vec))
1331 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1332 prop_len);
Cédric Le Goatered5b00a2021-01-22 08:50:29 +01001333 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", &vec, sizeof(vec));
1334 for (i = 0; i < prop_len; i += 2) {
1335 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2, vec[i], vec[i + 1]);
1336 prom_parse_platform_support(vec[i], vec[i + 1], &supported);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001337 }
1338 }
1339
Bharata B Rao029ab302020-07-03 11:06:06 +05301340 if (supported.radix_mmu && IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
1341 /* Radix preferred - Check if GTSE is also supported */
1342 prom_debug("Asking for radix\n");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001343 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
Bharata B Rao029ab302020-07-03 11:06:06 +05301344 if (supported.radix_gtse)
1345 ibm_architecture_vec.vec5.radix_ext =
1346 OV5_FEAT(OV5_RADIX_GTSE);
1347 else
1348 prom_debug("Radix GTSE isn't supported\n");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001349 } else if (supported.hash_mmu) {
1350 /* Default to hash mmu (if we can) */
1351 prom_debug("Asking for hash\n");
1352 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1353 } else {
1354 /* We're probably on a legacy hypervisor */
1355 prom_debug("Assuming legacy hash support\n");
1356 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001357
1358 if (supported.xive) {
1359 prom_debug("Asking for XIVE\n");
1360 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1361 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001362}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001363
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001364static void __init prom_send_capabilities(void)
1365{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001366 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001367 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001368 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001369
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001370 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1371 prom_check_platform_support();
1372
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001373 root = call_prom("open", 1, 1, ADDR("/"));
1374 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001375 /* We need to tell the FW about the number of cores we support.
1376 *
1377 * To do that, we count the number of threads on the first core
1378 * (we assume this is the same for all cores) and use it to
1379 * divide NR_CPUS.
1380 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001381
Michael Ellerman76ffb572016-11-18 23:15:42 +11001382 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001383 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001384 cores, NR_CPUS);
1385
1386 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001387
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001388 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001389 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001390 if (call_prom_ret("call-method", 3, 2, &ret,
1391 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001392 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001393 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001394 /* the call exists... */
1395 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001396 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001397 "-support call FAILED!\n");
1398 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001399 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001400 return;
1401 }
1402 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001403 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001404 }
1405
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001406#ifdef __BIG_ENDIAN__
1407 {
1408 ihandle elfloader;
1409
1410 /* no ibm,client-architecture-support call, try the old way */
1411 elfloader = call_prom("open", 1, 1,
1412 ADDR("/packages/elf-loader"));
1413 if (elfloader == 0) {
1414 prom_printf("couldn't open /packages/elf-loader\n");
1415 return;
1416 }
1417 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1418 elfloader, ADDR(&fake_elf));
1419 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001420 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001421#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001422}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001423#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001424
1425/*
1426 * Memory allocation strategy... our layout is normally:
1427 *
1428 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1429 * rare cases, initrd might end up being before the kernel though.
1430 * We assume this won't override the final kernel at 0, we have no
1431 * provision to handle that in this version, but it should hopefully
1432 * never happen.
1433 *
1434 * alloc_top is set to the top of RMO, eventually shrink down if the
1435 * TCEs overlap
1436 *
1437 * alloc_bottom is set to the top of kernel/initrd
1438 *
1439 * from there, allocations are done this way : rtas is allocated
1440 * topmost, and the device-tree is allocated from the bottom. We try
1441 * to grow the device-tree allocation as we progress. If we can't,
1442 * then we fail, we don't currently have a facility to restart
1443 * elsewhere, but that shouldn't be necessary.
1444 *
1445 * Note that calls to reserve_mem have to be done explicitly, memory
1446 * allocated with either alloc_up or alloc_down isn't automatically
1447 * reserved.
1448 */
1449
1450
1451/*
1452 * Allocates memory in the RMO upward from the kernel/initrd
1453 *
1454 * When align is 0, this is a special case, it means to allocate in place
1455 * at the current location of alloc_bottom or fail (that is basically
1456 * extending the previous allocation). Used for the device-tree flattening
1457 */
1458static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1459{
Anton Blanchard5827d412012-11-26 17:40:03 +00001460 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001461 unsigned long addr = 0;
1462
Paul Mackerrasc49888202005-10-26 21:52:53 +10001463 if (align)
Christophe Leroyb7115312020-04-20 18:36:36 +00001464 base = ALIGN(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001465 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001466 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001467 prom_panic("alloc_up() called with mem not initialized\n");
1468
1469 if (align)
Christophe Leroyb7115312020-04-20 18:36:36 +00001470 base = ALIGN(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001471 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001472 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001473
Anton Blanchard5827d412012-11-26 17:40:03 +00001474 for(; (base + size) <= alloc_top;
Christophe Leroyb7115312020-04-20 18:36:36 +00001475 base = ALIGN(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001476 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001477 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001478 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001479 break;
1480 addr = 0;
1481 if (align == 0)
1482 break;
1483 }
1484 if (addr == 0)
1485 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001486 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001487
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001488 prom_debug(" -> %lx\n", addr);
1489 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1490 prom_debug(" alloc_top : %lx\n", alloc_top);
1491 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1492 prom_debug(" rmo_top : %lx\n", rmo_top);
1493 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001494
1495 return addr;
1496}
1497
1498/*
1499 * Allocates memory downward, either from top of RMO, or if highmem
1500 * is set, from the top of RAM. Note that this one doesn't handle
1501 * failures. It does claim memory if highmem is not set.
1502 */
1503static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1504 int highmem)
1505{
1506 unsigned long base, addr = 0;
1507
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001508 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001509 highmem ? "(high)" : "(low)");
1510 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001511 prom_panic("alloc_down() called with mem not initialized\n");
1512
1513 if (highmem) {
1514 /* Carve out storage for the TCE table. */
Christophe Leroye96d9042020-04-20 18:36:35 +00001515 addr = ALIGN_DOWN(alloc_top_high - size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001516 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001517 return 0;
1518 /* Will we bump into the RMO ? If yes, check out that we
1519 * didn't overlap existing allocations there, if we did,
1520 * we are dead, we must be the first in town !
1521 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001522 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001523 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001524 if (alloc_top == rmo_top)
1525 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001526 else
1527 return 0;
1528 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001529 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001530 goto bail;
1531 }
1532
Christophe Leroye96d9042020-04-20 18:36:35 +00001533 base = ALIGN_DOWN(alloc_top - size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001534 for (; base > alloc_bottom;
Christophe Leroye96d9042020-04-20 18:36:35 +00001535 base = ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001536 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001537 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001538 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001539 break;
1540 addr = 0;
1541 }
1542 if (addr == 0)
1543 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001544 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001545
1546 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001547 prom_debug(" -> %lx\n", addr);
1548 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1549 prom_debug(" alloc_top : %lx\n", alloc_top);
1550 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1551 prom_debug(" rmo_top : %lx\n", rmo_top);
1552 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001553
1554 return addr;
1555}
1556
1557/*
1558 * Parse a "reg" cell
1559 */
1560static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1561{
1562 cell_t *p = *cellp;
1563 unsigned long r = 0;
1564
1565 /* Ignore more than 2 cells */
1566 while (s > sizeof(unsigned long) / 4) {
1567 p++;
1568 s--;
1569 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001570 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001571#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001572 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001573 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001574 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001575 }
1576#endif
1577 *cellp = p;
1578 return r;
1579}
1580
1581/*
1582 * Very dumb function for adding to the memory reserve list, but
1583 * we don't need anything smarter at this point
1584 *
1585 * XXX Eventually check for collisions. They should NEVER happen.
1586 * If problems seem to show up, it would be a good start to track
1587 * them down.
1588 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001589static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001590{
Kumar Galacbbcf342006-01-11 17:57:13 -06001591 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001592 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001593
1594 if (size == 0)
1595 return;
1596
1597 /* We need to always keep one empty entry so that we
1598 * have our terminator with "size" set to 0 since we are
1599 * dumb and just copy this entire array to the boot params
1600 */
Christophe Leroye96d9042020-04-20 18:36:35 +00001601 base = ALIGN_DOWN(base, PAGE_SIZE);
Christophe Leroyb7115312020-04-20 18:36:36 +00001602 top = ALIGN(top, PAGE_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001603 size = top - base;
1604
1605 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1606 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001607 mem_reserve_map[cnt].base = cpu_to_be64(base);
1608 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001609 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001610}
1611
1612/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001613 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001614 * obtain that way the top of memory and RMO to setup out local allocator
1615 */
1616static void __init prom_init_mem(void)
1617{
1618 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001619 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001620 unsigned int plen;
1621 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001622 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001623 u32 rac, rsc;
1624
1625 /*
1626 * We iterate the memory nodes to find
1627 * 1) top of RMO (first node)
1628 * 2) top of memory
1629 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001630 val = cpu_to_be32(2);
1631 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1632 rac = be32_to_cpu(val);
1633 val = cpu_to_be32(1);
1634 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1635 rsc = be32_to_cpu(val);
1636 prom_debug("root_addr_cells: %x\n", rac);
1637 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001638
1639 prom_debug("scanning memory:\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001640
1641 for (node = 0; prom_next_node(&node); ) {
1642 type[0] = 0;
1643 prom_getprop(node, "device_type", type, sizeof(type));
1644
Paul Mackerrasc49888202005-10-26 21:52:53 +10001645 if (type[0] == 0) {
1646 /*
1647 * CHRP Longtrail machines have no device_type
1648 * on the memory node, so check the name instead...
1649 */
1650 prom_getprop(node, "name", type, sizeof(type));
1651 }
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001652 if (prom_strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001653 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001654
Anton Blanchard5827d412012-11-26 17:40:03 +00001655 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001656 if (plen > sizeof(regbuf)) {
1657 prom_printf("memory node too large for buffer !\n");
1658 plen = sizeof(regbuf);
1659 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001660 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001661 endp = p + (plen / sizeof(cell_t));
1662
1663#ifdef DEBUG_PROM
Mathieu Malaterrec806a6f2019-05-23 12:25:20 +02001664 memset(prom_scratch, 0, sizeof(prom_scratch));
1665 call_prom("package-to-path", 3, 1, node, prom_scratch,
1666 sizeof(prom_scratch) - 1);
1667 prom_debug(" node %s :\n", prom_scratch);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001668#endif /* DEBUG_PROM */
1669
1670 while ((endp - p) >= (rac + rsc)) {
1671 unsigned long base, size;
1672
1673 base = prom_next_cell(rac, &p);
1674 size = prom_next_cell(rsc, &p);
1675
1676 if (size == 0)
1677 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001678 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001679 if (base == 0 && (of_platform & PLATFORM_LPAR))
1680 rmo_top = size;
1681 if ((base + size) > ram_top)
1682 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001683 }
1684 }
1685
Anton Blanchard5827d412012-11-26 17:40:03 +00001686 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001687
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001688 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001689 * If prom_memory_limit is set we reduce the upper limits *except* for
1690 * alloc_top_high. This must be the real top of RAM so we can put
1691 * TCE's up there.
1692 */
1693
Anton Blanchard5827d412012-11-26 17:40:03 +00001694 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001695
Anton Blanchard5827d412012-11-26 17:40:03 +00001696 if (prom_memory_limit) {
1697 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001698 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1699 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001700 prom_memory_limit = 0;
1701 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001702 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1703 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001704 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001705 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001706 ram_top = prom_memory_limit;
1707 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001708 }
1709 }
1710
1711 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001712 * Setup our top alloc point, that is top of RMO or top of
1713 * segment 0 when running non-LPAR.
1714 * Some RS64 machines have buggy firmware where claims up at
1715 * 1GB fail. Cap at 768MB as a workaround.
1716 * Since 768MB is plenty of room, and we need to cap to something
1717 * reasonable on 32-bit, cap at 768MB on all machines.
1718 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001719 if (!rmo_top)
1720 rmo_top = ram_top;
1721 rmo_top = min(0x30000000ul, rmo_top);
1722 alloc_top = rmo_top;
1723 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001724
Paul Mackerras64968f62011-12-13 17:54:13 +00001725 /*
1726 * Check if we have an initrd after the kernel but still inside
1727 * the RMO. If we do move our bottom point to after it.
1728 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001729 if (prom_initrd_start &&
1730 prom_initrd_start < rmo_top &&
1731 prom_initrd_end > alloc_bottom)
1732 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001733
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001734 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001735 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1736 prom_memory_limit);
1737 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1738 prom_printf(" alloc_top : %lx\n", alloc_top);
1739 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1740 prom_printf(" rmo_top : %lx\n", rmo_top);
1741 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001742}
1743
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001744static void __init prom_close_stdin(void)
1745{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001746 __be32 val;
1747 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001748
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001749 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1750 stdin = be32_to_cpu(val);
1751 call_prom("close", 1, 0, stdin);
1752 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001753}
1754
Ram Pai6a9c9302019-08-19 23:13:14 -03001755#ifdef CONFIG_PPC_SVM
1756static int prom_rtas_hcall(uint64_t args)
1757{
1758 register uint64_t arg1 asm("r3") = H_RTAS;
1759 register uint64_t arg2 asm("r4") = args;
1760
1761 asm volatile("sc 1\n" : "=r" (arg1) :
1762 "r" (arg1),
1763 "r" (arg2) :);
1764 return arg1;
1765}
1766
1767static struct rtas_args __prombss os_term_args;
1768
1769static void __init prom_rtas_os_term(char *str)
1770{
1771 phandle rtas_node;
1772 __be32 val;
1773 u32 token;
1774
1775 prom_debug("%s: start...\n", __func__);
1776 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1777 prom_debug("rtas_node: %x\n", rtas_node);
1778 if (!PHANDLE_VALID(rtas_node))
1779 return;
1780
1781 val = 0;
1782 prom_getprop(rtas_node, "ibm,os-term", &val, sizeof(val));
1783 token = be32_to_cpu(val);
1784 prom_debug("ibm,os-term: %x\n", token);
1785 if (token == 0)
1786 prom_panic("Could not get token for ibm,os-term\n");
1787 os_term_args.token = cpu_to_be32(token);
Alexey Kardashevskiy74bb84e2020-03-12 18:44:04 +11001788 os_term_args.nargs = cpu_to_be32(1);
1789 os_term_args.nret = cpu_to_be32(1);
1790 os_term_args.args[0] = cpu_to_be32(__pa(str));
Ram Pai6a9c9302019-08-19 23:13:14 -03001791 prom_rtas_hcall((uint64_t)&os_term_args);
1792}
1793#endif /* CONFIG_PPC_SVM */
1794
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001795/*
1796 * Allocate room for and instantiate RTAS
1797 */
1798static void __init prom_instantiate_rtas(void)
1799{
1800 phandle rtas_node;
1801 ihandle rtas_inst;
1802 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001803 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001804 u32 size = 0;
1805
1806 prom_debug("prom_instantiate_rtas: start...\n");
1807
1808 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1809 prom_debug("rtas_node: %x\n", rtas_node);
1810 if (!PHANDLE_VALID(rtas_node))
1811 return;
1812
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001813 val = 0;
1814 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1815 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001816 if (size == 0)
1817 return;
1818
1819 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001820 if (base == 0)
1821 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001822
1823 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1824 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001825 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001826 return;
1827 }
1828
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001829 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001830
1831 if (call_prom_ret("call-method", 3, 2, &entry,
1832 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001833 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001834 || entry == 0) {
1835 prom_printf(" failed\n");
1836 return;
1837 }
1838 prom_printf(" done\n");
1839
1840 reserve_mem(base, size);
1841
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001842 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001843 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001844 &val, sizeof(val));
1845 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001846 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001847 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001848
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001849 /* Check if it supports "query-cpu-stopped-state" */
1850 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1851 &val, sizeof(val)) != PROM_ERROR)
1852 rtas_has_query_cpu_stopped = true;
1853
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001854 prom_debug("rtas base = 0x%x\n", base);
1855 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001856 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001857
1858 prom_debug("prom_instantiate_rtas: end...\n");
1859}
1860
1861#ifdef CONFIG_PPC64
1862/*
Ashley Lai4a727422012-08-14 18:34:57 -05001863 * Allocate room for and instantiate Stored Measurement Log (SML)
1864 */
1865static void __init prom_instantiate_sml(void)
1866{
1867 phandle ibmvtpm_node;
1868 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001869 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001870 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001871 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001872
1873 prom_debug("prom_instantiate_sml: start...\n");
1874
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001875 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001876 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1877 if (!PHANDLE_VALID(ibmvtpm_node))
1878 return;
1879
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001880 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001881 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1882 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1883 return;
1884 }
1885
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001886 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1887 &val, sizeof(val)) != PROM_ERROR) {
1888 if (call_prom_ret("call-method", 2, 2, &succ,
1889 ADDR("reformat-sml-to-efi-alignment"),
1890 ibmvtpm_inst) != 0 || succ == 0) {
1891 prom_printf("Reformat SML to EFI alignment failed\n");
1892 return;
1893 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001894
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001895 if (call_prom_ret("call-method", 2, 2, &size,
1896 ADDR("sml-get-allocated-size"),
1897 ibmvtpm_inst) != 0 || size == 0) {
1898 prom_printf("SML get allocated size failed\n");
1899 return;
1900 }
1901 } else {
1902 if (call_prom_ret("call-method", 2, 2, &size,
1903 ADDR("sml-get-handover-size"),
1904 ibmvtpm_inst) != 0 || size == 0) {
1905 prom_printf("SML get handover size failed\n");
1906 return;
1907 }
Ashley Lai4a727422012-08-14 18:34:57 -05001908 }
1909
1910 base = alloc_down(size, PAGE_SIZE, 0);
1911 if (base == 0)
1912 prom_panic("Could not allocate memory for sml\n");
1913
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001914 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001915
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001916 memset((void *)base, 0, size);
1917
Ashley Lai4a727422012-08-14 18:34:57 -05001918 if (call_prom_ret("call-method", 4, 2, &entry,
1919 ADDR("sml-handover"),
1920 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1921 prom_printf("SML handover failed\n");
1922 return;
1923 }
1924 prom_printf(" done\n");
1925
1926 reserve_mem(base, size);
1927
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001928 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001929 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001930 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001931 &size, sizeof(size));
1932
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001933 prom_debug("sml base = 0x%llx\n", base);
1934 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001935
1936 prom_debug("prom_instantiate_sml: end...\n");
1937}
1938
1939/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001940 * Allocate room for and initialize TCE tables
1941 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001942#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001943static void __init prom_initialize_tce_table(void)
1944{
1945 phandle node;
1946 ihandle phb_node;
1947 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001948 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001949 u64 base, align;
1950 u32 minalign, minsize;
1951 u64 tce_entry, *tce_entryp;
1952 u64 local_alloc_top, local_alloc_bottom;
1953 u64 i;
1954
Anton Blanchard5827d412012-11-26 17:40:03 +00001955 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001956 return;
1957
1958 prom_debug("starting prom_initialize_tce_table\n");
1959
1960 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001961 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001962 local_alloc_bottom = local_alloc_top;
1963
1964 /* Search all nodes looking for PHBs. */
1965 for (node = 0; prom_next_node(&node); ) {
1966 compatible[0] = 0;
1967 type[0] = 0;
1968 model[0] = 0;
1969 prom_getprop(node, "compatible",
1970 compatible, sizeof(compatible));
1971 prom_getprop(node, "device_type", type, sizeof(type));
1972 prom_getprop(node, "model", model, sizeof(model));
1973
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001974 if ((type[0] == 0) || (prom_strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001975 continue;
1976
Linas Vepstase788ff12007-09-07 03:45:21 +10001977 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001978 if (compatible[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001979 if ((prom_strstr(compatible, "python") == NULL) &&
1980 (prom_strstr(compatible, "Speedwagon") == NULL) &&
1981 (prom_strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001982 continue;
1983 } else if (model[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001984 if ((prom_strstr(model, "ython") == NULL) &&
1985 (prom_strstr(model, "peedwagon") == NULL) &&
1986 (prom_strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001987 continue;
1988 }
1989
1990 if (prom_getprop(node, "tce-table-minalign", &minalign,
1991 sizeof(minalign)) == PROM_ERROR)
1992 minalign = 0;
1993 if (prom_getprop(node, "tce-table-minsize", &minsize,
1994 sizeof(minsize)) == PROM_ERROR)
1995 minsize = 4UL << 20;
1996
1997 /*
1998 * Even though we read what OF wants, we just set the table
1999 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
2000 * By doing this, we avoid the pitfalls of trying to DMA to
2001 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002002 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10002003 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002004
2005 /* Align to the greater of the align or size */
2006 align = max(minalign, minsize);
2007 base = alloc_down(minsize, align, 1);
2008 if (base == 0)
2009 prom_panic("ERROR, cannot find space for TCE table.\n");
2010 if (base < local_alloc_bottom)
2011 local_alloc_bottom = base;
2012
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002013 /* It seems OF doesn't null-terminate the path :-( */
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002014 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002015 /* Call OF to setup the TCE hardware */
2016 if (call_prom("package-to-path", 3, 1, node,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002017 path, sizeof(prom_scratch) - 1) == PROM_ERROR) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002018 prom_printf("package-to-path failed\n");
2019 }
2020
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002021 /* Save away the TCE table attributes for later use. */
2022 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
2023 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
2024
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002025 prom_debug("TCE table: %s\n", path);
2026 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002027 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002028 prom_debug("\tsize = 0x%x\n", minsize);
2029
2030 /* Initialize the table to have a one-to-one mapping
2031 * over the allocated size.
2032 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00002033 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002034 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
2035 tce_entry = (i << PAGE_SHIFT);
2036 tce_entry |= 0x3;
2037 *tce_entryp = tce_entry;
2038 }
2039
2040 prom_printf("opening PHB %s", path);
2041 phb_node = call_prom("open", 1, 1, path);
2042 if (phb_node == 0)
2043 prom_printf("... failed\n");
2044 else
2045 prom_printf("... done\n");
2046
2047 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
2048 phb_node, -1, minsize,
2049 (u32) base, (u32) (base >> 32));
2050 call_prom("close", 1, 0, phb_node);
2051 }
2052
2053 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
2054
Michael Ellerman2babf5c2006-05-17 18:00:46 +10002055 /* These are only really needed if there is a memory limit in
2056 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00002057 prom_tce_alloc_start = local_alloc_bottom;
2058 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002059
2060 /* Flag the first invalid entry */
2061 prom_debug("ending prom_initialize_tce_table\n");
2062}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002063#endif /* __BIG_ENDIAN__ */
2064#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002065
2066/*
2067 * With CHRP SMP we need to use the OF to start the other processors.
2068 * We can't wait until smp_boot_cpus (the OF is trashed by then)
2069 * so we have to put the processors into a holding pattern controlled
2070 * by the kernel (not OF) before we destroy the OF.
2071 *
2072 * This uses a chunk of low memory, puts some holding pattern
2073 * code there and sends the other processors off to there until
2074 * smp_boot_cpus tells them to do something. The holding pattern
2075 * checks that address until its cpu # is there, when it is that
2076 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
2077 * of setting those values.
2078 *
2079 * We also use physical address 0x4 here to tell when a cpu
2080 * is in its holding pattern code.
2081 *
2082 * -- Cort
2083 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002084/*
2085 * We want to reference the copy of __secondary_hold_* in the
2086 * 0 - 0x100 address range
2087 */
2088#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
2089
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002090static void __init prom_hold_cpus(void)
2091{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002092 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002093 phandle node;
2094 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002095 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002096 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002097 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002098 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002099 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002100
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002101 /*
2102 * On pseries, if RTAS supports "query-cpu-stopped-state",
2103 * we skip this stage, the CPUs will be started by the
2104 * kernel using RTAS.
2105 */
2106 if ((of_platform == PLATFORM_PSERIES ||
2107 of_platform == PLATFORM_PSERIES_LPAR) &&
2108 rtas_has_query_cpu_stopped) {
2109 prom_printf("prom_hold_cpus: skipped\n");
2110 return;
2111 }
2112
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002113 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002114 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
2115 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
2116 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002117 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002118 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
2119 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002120
2121 /* Set the common spinloop variable, so all of the secondary cpus
2122 * will block when they are awakened from their OF spinloop.
2123 * This must occur for both SMP and non SMP kernels, since OF will
2124 * be trashed when we move the kernel.
2125 */
2126 *spinloop = 0;
2127
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002128 /* look for cpus */
2129 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002130 unsigned int cpu_no;
2131 __be32 reg;
2132
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002133 type[0] = 0;
2134 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002135 if (prom_strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002136 continue;
2137
2138 /* Skip non-configured cpus. */
2139 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002140 if (prom_strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002141 continue;
2142
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002143 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002144 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002145 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002146
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002147 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002148
2149 /* Init the acknowledge var which will be reset by
2150 * the secondary cpu when it awakens from its OF
2151 * spinloop.
2152 */
2153 *acknowledge = (unsigned long)-1;
2154
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002155 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002156 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002157 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002158 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002159 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002160
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002161 for (i = 0; (i < 100000000) &&
2162 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002163 mb();
2164
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002165 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002166 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002167 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002168 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002169 }
2170#ifdef CONFIG_SMP
2171 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002172 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002173#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002174 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002175
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002176 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002177}
2178
2179
2180static void __init prom_init_client_services(unsigned long pp)
2181{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002182 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00002183 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002184
2185 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00002186 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
2187 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188 prom_panic("cannot find chosen"); /* msg won't be printed :( */
2189
2190 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00002191 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
2192 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002193 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002194
Anton Blanchard5827d412012-11-26 17:40:03 +00002195 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002196}
2197
Paul Mackerrasa575b802005-10-23 17:23:21 +10002198#ifdef CONFIG_PPC32
2199/*
2200 * For really old powermacs, we need to map things we claim.
2201 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002202 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10002203 */
2204static void __init prom_find_mmu(void)
2205{
Paul Mackerrasa575b802005-10-23 17:23:21 +10002206 phandle oprom;
2207 char version[64];
2208
2209 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
2210 if (!PHANDLE_VALID(oprom))
2211 return;
2212 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
2213 return;
2214 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002215 /* XXX might need to add other versions here */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002216 if (prom_strcmp(version, "Open Firmware, 1.0.5") == 0)
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002217 of_workarounds = OF_WA_CLAIM;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002218 else if (prom_strncmp(version, "FirmWorks,3.", 12) == 0) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002219 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2220 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2221 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002222 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002223 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2224 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2225 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002226 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002227 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002228 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002229}
2230#else
2231#define prom_find_mmu()
2232#endif
2233
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002234static void __init prom_init_stdout(void)
2235{
Anton Blanchard5827d412012-11-26 17:40:03 +00002236 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002237 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002238 phandle stdout_node;
2239 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002240
Anton Blanchard5827d412012-11-26 17:40:03 +00002241 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002242 prom_panic("cannot find stdout");
2243
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002244 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002245
2246 /* Get the full OF pathname of the stdout device */
2247 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002248 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002249 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2250 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002251 path, prom_strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002252
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002253 /* instance-to-package fails on PA-Semi */
2254 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2255 if (stdout_node != PROM_ERROR) {
2256 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002257
2258 /* If it's a display, note it */
2259 memset(type, 0, sizeof(type));
2260 prom_getprop(stdout_node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002261 if (prom_strcmp(type, "display") == 0)
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002262 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2263 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002264}
2265
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002266static int __init prom_find_machine_type(void)
2267{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002268 char compat[256];
2269 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002270#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002271 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002272 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002273#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002274
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002275 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002276 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002277 compat, sizeof(compat)-1);
2278 if (len > 0) {
2279 compat[len] = 0;
2280 while (i < len) {
2281 char *p = &compat[i];
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002282 int sl = prom_strlen(p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002283 if (sl == 0)
2284 break;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002285 if (prom_strstr(p, "Power Macintosh") ||
2286 prom_strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002287 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002288#ifdef CONFIG_PPC64
2289 /* We must make sure we don't detect the IBM Cell
2290 * blades as pSeries due to some firmware issues,
2291 * so we do it here.
2292 */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002293 if (prom_strstr(p, "IBM,CBEA") ||
2294 prom_strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002295 return PLATFORM_GENERIC;
2296#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002297 i += sl + 1;
2298 }
2299 }
2300#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002301 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002302 * PAPR compliant platform. We assume it is if :
2303 * - /device_type is "chrp" (please, do NOT use that for future
2304 * non-IBM designs !
2305 * - it has /rtas
2306 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002307 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002308 compat, sizeof(compat)-1);
2309 if (len <= 0)
2310 return PLATFORM_GENERIC;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002311 if (prom_strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002312 return PLATFORM_GENERIC;
2313
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002314 /* Default to pSeries. We need to know if we are running LPAR */
2315 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002316 if (!PHANDLE_VALID(rtas))
2317 return PLATFORM_GENERIC;
2318 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2319 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002320 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002321 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002322 }
2323 return PLATFORM_PSERIES;
2324#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002325 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002326#endif
2327}
2328
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002329static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2330{
2331 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2332}
2333
2334/*
2335 * If we have a display that we don't know how to drive,
2336 * we will want to try to execute OF's open method for it
2337 * later. However, OF will probably fall over if we do that
2338 * we've taken over the MMU.
2339 * So we check whether we will need to open the display,
2340 * and if so, open it now.
2341 */
2342static void __init prom_check_displays(void)
2343{
2344 char type[16], *path;
2345 phandle node;
2346 ihandle ih;
2347 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002348
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11002349 static const unsigned char default_colors[] __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002350 0x00, 0x00, 0x00,
2351 0x00, 0x00, 0xaa,
2352 0x00, 0xaa, 0x00,
2353 0x00, 0xaa, 0xaa,
2354 0xaa, 0x00, 0x00,
2355 0xaa, 0x00, 0xaa,
2356 0xaa, 0xaa, 0x00,
2357 0xaa, 0xaa, 0xaa,
2358 0x55, 0x55, 0x55,
2359 0x55, 0x55, 0xff,
2360 0x55, 0xff, 0x55,
2361 0x55, 0xff, 0xff,
2362 0xff, 0x55, 0x55,
2363 0xff, 0x55, 0xff,
2364 0xff, 0xff, 0x55,
2365 0xff, 0xff, 0xff
2366 };
2367 const unsigned char *clut;
2368
Anton Blanchard4da727a2009-03-31 20:06:14 +00002369 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002370 for (node = 0; prom_next_node(&node); ) {
2371 memset(type, 0, sizeof(type));
2372 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002373 if (prom_strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002374 continue;
2375
2376 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002377 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002378 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002379
2380 /*
2381 * leave some room at the end of the path for appending extra
2382 * arguments
2383 */
2384 if (call_prom("package-to-path", 3, 1, node, path,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002385 sizeof(prom_scratch) - 10) == PROM_ERROR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002386 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002387 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002388
2389 ih = call_prom("open", 1, 1, path);
2390 if (ih == 0) {
2391 prom_printf("failed\n");
2392 continue;
2393 }
2394
2395 /* Success */
2396 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002397 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002398
2399 /* Setup a usable color table when the appropriate
2400 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002401 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002402 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002403 if (prom_set_color(ih, i, clut[0], clut[1],
2404 clut[2]) != 0)
2405 break;
2406
2407#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002408 clut = PTRRELOC(logo_linux_clut224.clut);
2409 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002410 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2411 clut[2]) != 0)
2412 break;
2413#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002414
2415#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2416 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2417 PROM_ERROR) {
2418 u32 width, height, pitch, addr;
2419
2420 prom_printf("Setting btext !\n");
Michael Ellerman6c71cfc2020-08-21 20:34:07 +10002421
2422 if (prom_getprop(node, "width", &width, 4) == PROM_ERROR)
2423 return;
2424
2425 if (prom_getprop(node, "height", &height, 4) == PROM_ERROR)
2426 return;
2427
2428 if (prom_getprop(node, "linebytes", &pitch, 4) == PROM_ERROR)
2429 return;
2430
2431 if (prom_getprop(node, "address", &addr, 4) == PROM_ERROR)
2432 return;
2433
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002434 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2435 width, height, pitch, addr);
2436 btext_setup_display(width, height, 8, pitch, addr);
Christophe Leroyc21f5a92019-06-03 13:00:51 +00002437 btext_prepare_BAT();
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002438 }
2439#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002440 }
2441}
2442
2443
2444/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2445static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2446 unsigned long needed, unsigned long align)
2447{
2448 void *ret;
2449
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002450 *mem_start = ALIGN(*mem_start, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002451 while ((*mem_start + needed) > *mem_end) {
2452 unsigned long room, chunk;
2453
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002454 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002455 alloc_bottom);
2456 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002457 if (room > DEVTREE_CHUNK_SIZE)
2458 room = DEVTREE_CHUNK_SIZE;
2459 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002460 prom_panic("No memory for flatten_device_tree "
2461 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002462 chunk = alloc_up(room, 0);
2463 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002464 prom_panic("No memory for flatten_device_tree "
2465 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002466 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002467 }
2468
2469 ret = (void *)*mem_start;
2470 *mem_start += needed;
2471
2472 return ret;
2473}
2474
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002475#define dt_push_token(token, mem_start, mem_end) do { \
2476 void *room = make_room(mem_start, mem_end, 4, 4); \
2477 *(__be32 *)room = cpu_to_be32(token); \
2478 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002479
2480static unsigned long __init dt_find_string(char *str)
2481{
2482 char *s, *os;
2483
Anton Blanchard5827d412012-11-26 17:40:03 +00002484 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002485 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002486 while (s < (char *)dt_string_end) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002487 if (prom_strcmp(s, str) == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002488 return s - os;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002489 s += prom_strlen(s) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002490 }
2491 return 0;
2492}
2493
2494/*
2495 * The Open Firmware 1275 specification states properties must be 31 bytes or
2496 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2497 */
2498#define MAX_PROPERTY_NAME 64
2499
2500static void __init scan_dt_build_strings(phandle node,
2501 unsigned long *mem_start,
2502 unsigned long *mem_end)
2503{
2504 char *prev_name, *namep, *sstart;
2505 unsigned long soff;
2506 phandle child;
2507
Anton Blanchard5827d412012-11-26 17:40:03 +00002508 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002509
2510 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002511 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002512 for (;;) {
2513 /* 64 is max len of name including nul. */
2514 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2515 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2516 /* No more nodes: unwind alloc */
2517 *mem_start = (unsigned long)namep;
2518 break;
2519 }
2520
2521 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002522 if (prom_strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002523 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002524 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002525 continue;
2526 }
2527 /* get/create string entry */
2528 soff = dt_find_string(namep);
2529 if (soff != 0) {
2530 *mem_start = (unsigned long)namep;
2531 namep = sstart + soff;
2532 } else {
2533 /* Trim off some if we can */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002534 *mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002535 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002536 }
2537 prev_name = namep;
2538 }
2539
2540 /* do all our children */
2541 child = call_prom("child", 1, 1, node);
2542 while (child != 0) {
2543 scan_dt_build_strings(child, mem_start, mem_end);
2544 child = call_prom("peer", 1, 1, child);
2545 }
2546}
2547
2548static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2549 unsigned long *mem_end)
2550{
2551 phandle child;
2552 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2553 unsigned long soff;
2554 unsigned char *valp;
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +11002555 static char pname[MAX_PROPERTY_NAME] __prombss;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002556 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002557
2558 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2559
2560 /* get the node's full name */
2561 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002562 room = *mem_end - *mem_start;
2563 if (room > 255)
2564 room = 255;
2565 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002566 if (l >= 0) {
2567 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002568 if (l >= room) {
2569 if (l >= *mem_end - *mem_start)
2570 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002571 call_prom("package-to-path", 3, 1, node, namep, l);
2572 }
2573 namep[l] = '\0';
2574
2575 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002576 * middle of the path in some properties, and extract
2577 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002578 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002579 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002580 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002581 lp = namep;
2582 else if (*p != 0)
2583 *lp++ = *p;
2584 }
2585 *lp = 0;
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002586 *mem_start = ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002587 }
2588
2589 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002590 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002591 memset(path, 0, sizeof(prom_scratch));
2592 call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002593
2594 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002595 prev_name = "";
2596 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002597 for (;;) {
2598 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002599 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002600 break;
2601
2602 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002603 if (prom_strcmp(pname, "name") == 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002604 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002605 continue;
2606 }
2607
2608 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002609 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002610 if (soff == 0) {
2611 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002612 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002613 break;
2614 }
2615 prev_name = sstart + soff;
2616
2617 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002618 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002619
2620 /* sanity checks */
2621 if (l == PROM_ERROR)
2622 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002623
2624 /* push property head */
2625 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2626 dt_push_token(l, mem_start, mem_end);
2627 dt_push_token(soff, mem_start, mem_end);
2628
2629 /* push property content */
2630 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002631 call_prom("getprop", 4, 1, node, pname, valp, l);
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002632 *mem_start = ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002633
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002634 if (!prom_strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002635 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002636 }
2637
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002638 /* Add a "phandle" property if none already exist */
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002639 if (!has_phandle) {
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002640 soff = dt_find_string("phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002641 if (soff == 0)
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002642 prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002643 else {
2644 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2645 dt_push_token(4, mem_start, mem_end);
2646 dt_push_token(soff, mem_start, mem_end);
2647 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002648 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002649 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002650 }
2651
2652 /* do all our children */
2653 child = call_prom("child", 1, 1, node);
2654 while (child != 0) {
2655 scan_dt_build_struct(child, mem_start, mem_end);
2656 child = call_prom("peer", 1, 1, child);
2657 }
2658
2659 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2660}
2661
2662static void __init flatten_device_tree(void)
2663{
2664 phandle root;
2665 unsigned long mem_start, mem_end, room;
2666 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002667 char *namep;
2668 u64 *rsvmap;
2669
2670 /*
2671 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002672 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002673 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002674 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002675 if (room > DEVTREE_CHUNK_SIZE)
2676 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002677 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002678
2679 /* Now try to claim that */
2680 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2681 if (mem_start == 0)
2682 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002683 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002684
2685 /* Get root of tree */
2686 root = call_prom("peer", 1, 1, (phandle)0);
2687 if (root == (phandle)0)
2688 prom_panic ("couldn't get device tree root\n");
2689
2690 /* Build header and make room for mem rsv map */
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002691 mem_start = ALIGN(mem_start, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002692 hdr = make_room(&mem_start, &mem_end,
2693 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002694 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002695 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2696
2697 /* Start of strings */
2698 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002699 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002700 mem_start += 4; /* hole */
2701
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002702 /* Add "phandle" in there, we'll need it */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002703 namep = make_room(&mem_start, &mem_end, 16, 1);
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002704 prom_strcpy(namep, "phandle");
2705 mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002706
2707 /* Build string array */
2708 prom_printf("Building dt strings...\n");
2709 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002710 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002711
2712 /* Build structure */
2713 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002714 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002715 prom_printf("Building dt structure...\n");
2716 scan_dt_build_struct(root, &mem_start, &mem_end);
2717 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002718 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002719
2720 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002721 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2722 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2723 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2724 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2725 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2726 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2727 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2728 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002729 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002730 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002731
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002732 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002733 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002734
2735#ifdef DEBUG_PROM
2736 {
2737 int i;
2738 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002739 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002740 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002741 be64_to_cpu(mem_reserve_map[i].base),
2742 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002743 }
2744#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002745 /* Bump mem_reserve_cnt to cause further reservations to fail
2746 * since it's too late.
2747 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002748 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002749
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002750 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002751 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002752 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002753 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002754}
2755
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002756#ifdef CONFIG_PPC_MAPLE
2757/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2758 * The values are bad, and it doesn't even have the right number of cells. */
2759static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002760{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002761 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002762 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002763 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002764 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002765
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002766 name = "/ht@0/isa@4";
2767 isa = call_prom("finddevice", 1, 1, ADDR(name));
2768 if (!PHANDLE_VALID(isa)) {
2769 name = "/ht@0/isa@6";
2770 isa = call_prom("finddevice", 1, 1, ADDR(name));
2771 rloc = 0x01003000; /* IO space; PCI device = 6 */
2772 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002773 if (!PHANDLE_VALID(isa))
2774 return;
2775
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002776 if (prom_getproplen(isa, "ranges") != 12)
2777 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002778 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2779 == PROM_ERROR)
2780 return;
2781
2782 if (isa_ranges[0] != 0x1 ||
2783 isa_ranges[1] != 0xf4000000 ||
2784 isa_ranges[2] != 0x00010000)
2785 return;
2786
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002787 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002788
2789 isa_ranges[0] = 0x1;
2790 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002791 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002792 isa_ranges[3] = 0x0;
2793 isa_ranges[4] = 0x0;
2794 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002795 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002796 isa_ranges, sizeof(isa_ranges));
2797}
Harry Ciao8f101a052009-06-17 16:28:00 -07002798
2799#define CPC925_MC_START 0xf8000000
2800#define CPC925_MC_LENGTH 0x1000000
2801/* The values for memory-controller don't have right number of cells */
2802static void __init fixup_device_tree_maple_memory_controller(void)
2803{
2804 phandle mc;
2805 u32 mc_reg[4];
2806 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002807 u32 ac, sc;
2808
2809 mc = call_prom("finddevice", 1, 1, ADDR(name));
2810 if (!PHANDLE_VALID(mc))
2811 return;
2812
2813 if (prom_getproplen(mc, "reg") != 8)
2814 return;
2815
Anton Blanchard5827d412012-11-26 17:40:03 +00002816 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2817 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002818 if ((ac != 2) || (sc != 2))
2819 return;
2820
2821 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2822 return;
2823
2824 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2825 return;
2826
2827 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2828
2829 mc_reg[0] = 0x0;
2830 mc_reg[1] = CPC925_MC_START;
2831 mc_reg[2] = 0x0;
2832 mc_reg[3] = CPC925_MC_LENGTH;
2833 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2834}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002835#else
2836#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002837#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002838#endif
2839
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002840#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002841/*
2842 * Pegasos and BriQ lacks the "ranges" property in the isa node
2843 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf92007-08-18 04:27:17 +10002844 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002845 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002846static void __init fixup_device_tree_chrp(void)
2847{
Olaf Heringe4805922007-04-04 18:20:04 +02002848 phandle ph;
2849 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002850 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002851 char *name;
2852 int rc;
2853
2854 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002855 ph = call_prom("finddevice", 1, 1, ADDR(name));
2856 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002857 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002858 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002859 rloc = 0x01003000; /* IO space; PCI device = 6 */
2860 }
Olaf Heringe4805922007-04-04 18:20:04 +02002861 if (PHANDLE_VALID(ph)) {
2862 rc = prom_getproplen(ph, "ranges");
2863 if (rc == 0 || rc == PROM_ERROR) {
2864 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002865
Olaf Heringe4805922007-04-04 18:20:04 +02002866 prop[0] = 0x1;
2867 prop[1] = 0x0;
2868 prop[2] = rloc;
2869 prop[3] = 0x0;
2870 prop[4] = 0x0;
2871 prop[5] = 0x00010000;
2872 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2873 }
2874 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002875
Olaf Heringe4805922007-04-04 18:20:04 +02002876 name = "/pci@80000000/ide@C,1";
2877 ph = call_prom("finddevice", 1, 1, ADDR(name));
2878 if (PHANDLE_VALID(ph)) {
2879 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2880 prop[0] = 14;
2881 prop[1] = 0x0;
Olaf Hering556ecf92007-08-18 04:27:17 +10002882 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2883 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2884 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2885 if (rc == sizeof(u32)) {
2886 prop[0] &= ~0x5;
2887 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2888 }
Olaf Heringe4805922007-04-04 18:20:04 +02002889 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002890}
2891#else
2892#define fixup_device_tree_chrp()
2893#endif
2894
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002895#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002896static void __init fixup_device_tree_pmac(void)
2897{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002898 phandle u3, i2c, mpic;
2899 u32 u3_rev;
2900 u32 interrupts[2];
2901 u32 parent;
2902
2903 /* Some G5s have a missing interrupt definition, fix it up here */
2904 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2905 if (!PHANDLE_VALID(u3))
2906 return;
2907 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2908 if (!PHANDLE_VALID(i2c))
2909 return;
2910 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2911 if (!PHANDLE_VALID(mpic))
2912 return;
2913
2914 /* check if proper rev of u3 */
2915 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2916 == PROM_ERROR)
2917 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002918 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002919 return;
2920 /* does it need fixup ? */
2921 if (prom_getproplen(i2c, "interrupts") > 0)
2922 return;
2923
2924 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2925
2926 /* interrupt on this revision of u3 is number 0 and level */
2927 interrupts[0] = 0;
2928 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002929 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2930 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002931 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002932 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2933 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002934}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002935#else
2936#define fixup_device_tree_pmac()
2937#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002938
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002939#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002940/*
2941 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2942 * to talk to the phy. If the phy-handle property is missing, then this
2943 * function is called to add the appropriate nodes and link it to the
2944 * ethernet node.
2945 */
2946static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002947{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002948 u32 node;
2949 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002950 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002951
Grant Likely94d2dde2008-01-24 22:25:32 -07002952 /* Check if /builtin/ethernet exists - bail if it doesn't */
2953 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002954 if (!PHANDLE_VALID(node))
2955 return;
2956
Grant Likely94d2dde2008-01-24 22:25:32 -07002957 /* Check if the phy-handle property exists - bail if it does */
2958 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2959 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002960 return;
2961
Grant Likely94d2dde2008-01-24 22:25:32 -07002962 /*
2963 * At this point the ethernet device doesn't have a phy described.
2964 * Now we need to add the missing phy node and linkage
2965 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002966
Grant Likely94d2dde2008-01-24 22:25:32 -07002967 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002968 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2969 if (!PHANDLE_VALID(node)) {
2970 prom_printf("Adding Ethernet MDIO node\n");
2971 call_prom("interpret", 1, 1,
2972 " s\" /builtin\" find-device"
2973 " new-device"
2974 " 1 encode-int s\" #address-cells\" property"
2975 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002976 " s\" mdio\" device-name"
2977 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002978 " s\" compatible\" property"
2979 " 0xf0003000 0x400 reg"
2980 " 0x2 encode-int"
2981 " 0x5 encode-int encode+"
2982 " 0x3 encode-int encode+"
2983 " s\" interrupts\" property"
2984 " finish-device");
Jiapeng Chong4f46d572021-02-24 15:29:21 +08002985 }
Olaf Hering6f4347c2008-01-10 01:06:08 +11002986
Grant Likely94d2dde2008-01-24 22:25:32 -07002987 /* Check for a PHY device node - if missing then create one and
2988 * give it's phandle to the ethernet node */
2989 node = call_prom("finddevice", 1, 1,
2990 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002991 if (!PHANDLE_VALID(node)) {
2992 prom_printf("Adding Ethernet PHY node\n");
2993 call_prom("interpret", 1, 1,
2994 " s\" /builtin/mdio\" find-device"
2995 " new-device"
2996 " s\" ethernet-phy\" device-name"
2997 " 0x10 encode-int s\" reg\" property"
2998 " my-self"
2999 " ihandle>phandle"
3000 " finish-device"
3001 " s\" /builtin/ethernet\" find-device"
3002 " encode-int"
3003 " s\" phy-handle\" property"
3004 " device-end");
3005 }
Grant Likely94d2dde2008-01-24 22:25:32 -07003006}
Olaf Hering6f4347c2008-01-10 01:06:08 +11003007
Grant Likely94d2dde2008-01-24 22:25:32 -07003008static void __init fixup_device_tree_efika(void)
3009{
3010 int sound_irq[3] = { 2, 2, 0 };
3011 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
3012 3,4,0, 3,5,0, 3,6,0, 3,7,0,
3013 3,8,0, 3,9,0, 3,10,0, 3,11,0,
3014 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
3015 u32 node;
3016 char prop[64];
3017 int rv, len;
3018
3019 /* Check if we're really running on a EFIKA */
3020 node = call_prom("finddevice", 1, 1, ADDR("/"));
3021 if (!PHANDLE_VALID(node))
3022 return;
3023
3024 rv = prom_getprop(node, "model", prop, sizeof(prop));
3025 if (rv == PROM_ERROR)
3026 return;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003027 if (prom_strcmp(prop, "EFIKA5K2"))
Grant Likely94d2dde2008-01-24 22:25:32 -07003028 return;
3029
3030 prom_printf("Applying EFIKA device tree fixups\n");
3031
3032 /* Claiming to be 'chrp' is death */
3033 node = call_prom("finddevice", 1, 1, ADDR("/"));
3034 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003035 if (rv != PROM_ERROR && (prom_strcmp(prop, "chrp") == 0))
Grant Likely94d2dde2008-01-24 22:25:32 -07003036 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
3037
David Woodhouse7f4392c2008-04-14 02:52:38 +10003038 /* CODEGEN,description is exposed in /proc/cpuinfo so
3039 fix that too */
3040 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003041 if (rv != PROM_ERROR && (prom_strstr(prop, "CHRP")))
David Woodhouse7f4392c2008-04-14 02:52:38 +10003042 prom_setprop(node, "/", "CODEGEN,description",
3043 "Efika 5200B PowerPC System",
3044 sizeof("Efika 5200B PowerPC System"));
3045
Grant Likely94d2dde2008-01-24 22:25:32 -07003046 /* Fixup bestcomm interrupts property */
3047 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
3048 if (PHANDLE_VALID(node)) {
3049 len = prom_getproplen(node, "interrupts");
3050 if (len == 12) {
3051 prom_printf("Fixing bestcomm interrupts property\n");
3052 prom_setprop(node, "/builtin/bestcom", "interrupts",
3053 bcomm_irq, sizeof(bcomm_irq));
3054 }
3055 }
3056
3057 /* Fixup sound interrupts property */
3058 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
3059 if (PHANDLE_VALID(node)) {
3060 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
3061 if (rv == PROM_ERROR) {
3062 prom_printf("Adding sound interrupts property\n");
3063 prom_setprop(node, "/builtin/sound", "interrupts",
3064 sound_irq, sizeof(sound_irq));
3065 }
3066 }
3067
3068 /* Make sure ethernet phy-handle property exists */
3069 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003070}
3071#else
3072#define fixup_device_tree_efika()
3073#endif
3074
Darren Stevens50246782016-08-31 13:24:40 +01003075#ifdef CONFIG_PPC_PASEMI_NEMO
3076/*
3077 * CFE supplied on Nemo is broken in several ways, biggest
3078 * problem is that it reassigns ISA interrupts to unused mpic ints.
3079 * Add an interrupt-controller property for the io-bridge to use
3080 * and correct the ints so we can attach them to an irq_domain
3081 */
3082static void __init fixup_device_tree_pasemi(void)
3083{
3084 u32 interrupts[2], parent, rval, val = 0;
3085 char *name, *pci_name;
3086 phandle iob, node;
3087
3088 /* Find the root pci node */
3089 name = "/pxp@0,e0000000";
3090 iob = call_prom("finddevice", 1, 1, ADDR(name));
3091 if (!PHANDLE_VALID(iob))
3092 return;
3093
3094 /* check if interrupt-controller node set yet */
3095 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
3096 return;
3097
3098 prom_printf("adding interrupt-controller property for SB600...\n");
3099
3100 prom_setprop(iob, name, "interrupt-controller", &val, 0);
3101
3102 pci_name = "/pxp@0,e0000000/pci@11";
3103 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
3104 parent = ADDR(iob);
3105
3106 for( ; prom_next_node(&node); ) {
3107 /* scan each node for one with an interrupt */
3108 if (!PHANDLE_VALID(node))
3109 continue;
3110
3111 rval = prom_getproplen(node, "interrupts");
3112 if (rval == 0 || rval == PROM_ERROR)
3113 continue;
3114
3115 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
3116 if ((interrupts[0] < 212) || (interrupts[0] > 222))
3117 continue;
3118
3119 /* found a node, update both interrupts and interrupt-parent */
3120 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
3121 interrupts[0] -= 203;
3122 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
3123 interrupts[0] -= 213;
3124 if (interrupts[0] == 221)
3125 interrupts[0] = 14;
3126 if (interrupts[0] == 222)
3127 interrupts[0] = 8;
3128
3129 prom_setprop(node, pci_name, "interrupts", interrupts,
3130 sizeof(interrupts));
3131 prom_setprop(node, pci_name, "interrupt-parent", &parent,
3132 sizeof(parent));
3133 }
Darren Stevens687e16b2016-08-31 13:24:45 +01003134
3135 /*
3136 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
3137 * so that generic isa-bridge code can add the SB600 and its on-board
3138 * peripherals.
3139 */
3140 name = "/pxp@0,e0000000/io-bridge@0";
3141 iob = call_prom("finddevice", 1, 1, ADDR(name));
3142 if (!PHANDLE_VALID(iob))
3143 return;
3144
3145 /* device_type is already set, just change it. */
3146
3147 prom_printf("Changing device_type of SB600 node...\n");
3148
3149 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01003150}
3151#else /* !CONFIG_PPC_PASEMI_NEMO */
3152static inline void fixup_device_tree_pasemi(void) { }
3153#endif
3154
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003155static void __init fixup_device_tree(void)
3156{
3157 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07003158 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10003159 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003160 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003161 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01003162 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003163}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003164
3165static void __init prom_find_boot_cpu(void)
3166{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003167 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003168 ihandle prom_cpu;
3169 phandle cpu_pkg;
3170
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003171 rval = 0;
3172 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10003173 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003174 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003175
3176 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
3177
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00003178 if (!PHANDLE_VALID(cpu_pkg))
3179 return;
3180
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003181 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
3182 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003183
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003184 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003185}
3186
3187static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
3188{
3189#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003190 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003191 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003192
Anton Blanchard5827d412012-11-26 17:40:03 +00003193 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
3194 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003195
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003196 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00003197 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003198 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003199 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00003200 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003201 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003202
Anton Blanchard5827d412012-11-26 17:40:03 +00003203 reserve_mem(prom_initrd_start,
3204 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003205
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003206 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
3207 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003208 }
3209#endif /* CONFIG_BLK_DEV_INITRD */
3210}
3211
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003212#ifdef CONFIG_PPC64
3213#ifdef CONFIG_RELOCATABLE
3214static void reloc_toc(void)
3215{
3216}
3217
3218static void unreloc_toc(void)
3219{
3220}
3221#else
Anton Blanchard16744002013-03-12 01:51:51 +00003222static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003223{
3224 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003225 unsigned long *toc_entry;
3226
3227 /* Get the start of the TOC by using r2 directly. */
3228 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003229
3230 for (i = 0; i < nr_entries; i++) {
3231 *toc_entry = *toc_entry + offset;
3232 toc_entry++;
3233 }
3234}
3235
3236static void reloc_toc(void)
3237{
3238 unsigned long offset = reloc_offset();
3239 unsigned long nr_entries =
3240 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3241
Anton Blanchard16744002013-03-12 01:51:51 +00003242 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003243
3244 mb();
3245}
3246
3247static void unreloc_toc(void)
3248{
3249 unsigned long offset = reloc_offset();
3250 unsigned long nr_entries =
3251 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3252
3253 mb();
3254
Anton Blanchard16744002013-03-12 01:51:51 +00003255 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003256}
3257#endif
3258#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003259
Ram Pai6a9c9302019-08-19 23:13:14 -03003260#ifdef CONFIG_PPC_SVM
3261/*
3262 * Perform the Enter Secure Mode ultracall.
3263 */
3264static int enter_secure_mode(unsigned long kbase, unsigned long fdt)
3265{
3266 register unsigned long r3 asm("r3") = UV_ESM;
3267 register unsigned long r4 asm("r4") = kbase;
3268 register unsigned long r5 asm("r5") = fdt;
3269
3270 asm volatile("sc 2" : "+r"(r3) : "r"(r4), "r"(r5));
3271
3272 return r3;
3273}
3274
3275/*
3276 * Call the Ultravisor to transfer us to secure memory if we have an ESM blob.
3277 */
Vladis Dronovaff77952020-07-29 15:37:41 +02003278static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
Ram Pai6a9c9302019-08-19 23:13:14 -03003279{
3280 int ret;
3281
3282 if (!prom_svm_enable)
3283 return;
3284
3285 /* Switch to secure mode. */
3286 prom_printf("Switching to secure mode.\n");
3287
Thiago Jung Bauermann05d9a952019-09-11 13:34:33 -03003288 /*
3289 * The ultravisor will do an integrity check of the kernel image but we
3290 * relocated it so the check will fail. Restore the original image by
3291 * relocating it back to the kernel virtual base address.
3292 */
3293 if (IS_ENABLED(CONFIG_RELOCATABLE))
3294 relocate(KERNELBASE);
3295
Ram Pai6a9c9302019-08-19 23:13:14 -03003296 ret = enter_secure_mode(kbase, fdt);
Thiago Jung Bauermann05d9a952019-09-11 13:34:33 -03003297
3298 /* Relocate the kernel again. */
3299 if (IS_ENABLED(CONFIG_RELOCATABLE))
3300 relocate(kbase);
3301
Ram Pai6a9c9302019-08-19 23:13:14 -03003302 if (ret != U_SUCCESS) {
3303 prom_printf("Returned %d from switching to secure mode.\n", ret);
3304 prom_rtas_os_term("Switch to secure mode failed.\n");
3305 }
3306}
3307#else
Vladis Dronovaff77952020-07-29 15:37:41 +02003308static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
Ram Pai6a9c9302019-08-19 23:13:14 -03003309{
3310}
3311#endif /* CONFIG_PPC_SVM */
3312
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003313/*
3314 * We enter here early on, when the Open Firmware prom is still
3315 * handling exceptions and the MMU hash table for us.
3316 */
3317
3318unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3319 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003320 unsigned long r6, unsigned long r7,
3321 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003322{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003323 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003324
3325#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003326 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003327 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003328#else
3329 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003330#endif
3331
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003332 /*
3333 * First zero the BSS
3334 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003335 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003336
3337 /*
3338 * Init interface to Open Firmware, get some node references,
3339 * like /chosen
3340 */
3341 prom_init_client_services(pp);
3342
3343 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003344 * See if this OF is old enough that we need to do explicit maps
3345 * and other workarounds
3346 */
3347 prom_find_mmu();
3348
3349 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003350 * Init prom stdout device
3351 */
3352 prom_init_stdout();
3353
Anton Blanchard5827d412012-11-26 17:40:03 +00003354 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003355
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003356 /*
3357 * Get default machine type. At this point, we do not differentiate
3358 * between pSeries SMP and pSeries LPAR
3359 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003360 of_platform = prom_find_machine_type();
3361 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003362
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003363#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003364 /* Bail if this is a kdump kernel. */
3365 if (PHYSICAL_START > 0)
3366 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003367#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003368
3369 /*
3370 * Check for an initrd
3371 */
3372 prom_check_initrd(r3, r4);
3373
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003374 /*
3375 * Do early parsing of command line
3376 */
3377 early_cmdline_parse();
3378
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003379#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003380 /*
3381 * On pSeries, inform the firmware about our capabilities
3382 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003383 if (of_platform == PLATFORM_PSERIES ||
3384 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003385 prom_send_capabilities();
3386#endif
3387
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003388 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003389 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003390 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003391 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003392 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003393
3394 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003395 * Initialize memory management within prom_init
3396 */
3397 prom_init_mem();
3398
3399 /*
3400 * Determine which cpu is actually running right _now_
3401 */
3402 prom_find_boot_cpu();
3403
3404 /*
3405 * Initialize display devices
3406 */
3407 prom_check_displays();
3408
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003409#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003410 /*
3411 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3412 * that uses the allocator, we need to make sure we get the top of memory
3413 * available for us here...
3414 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003415 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003416 prom_initialize_tce_table();
3417#endif
3418
3419 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003420 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3421 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003422 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003423 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003424 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003425
Ashley Lai4a727422012-08-14 18:34:57 -05003426#ifdef CONFIG_PPC64
3427 /* instantiate sml */
3428 prom_instantiate_sml();
3429#endif
3430
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003431 /*
3432 * On non-powermacs, put all CPUs in spin-loops.
3433 *
3434 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003435 *
3436 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003437 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003438 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003439 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003440
3441 /*
3442 * Fill in some infos for use by the kernel later on
3443 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003444 if (prom_memory_limit) {
3445 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003446 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003447 &val, sizeof(val));
3448 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003449#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003450 if (prom_iommu_off)
3451 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003452 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003453
Anton Blanchard5827d412012-11-26 17:40:03 +00003454 if (prom_iommu_force_on)
3455 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003456 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003457
Anton Blanchard5827d412012-11-26 17:40:03 +00003458 if (prom_tce_alloc_start) {
3459 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3460 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003461 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003462 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3463 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003464 sizeof(prom_tce_alloc_end));
3465 }
3466#endif
3467
3468 /*
3469 * Fixup any known bugs in the device-tree
3470 */
3471 fixup_device_tree();
3472
3473 /*
3474 * Now finally create the flattened device-tree
3475 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003476 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003477 flatten_device_tree();
3478
Paul Mackerras3825ac02005-11-08 22:48:08 +11003479 /*
3480 * in case stdin is USB and still active on IBM machines...
3481 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003482 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003483 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003484 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003485 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003486
3487 /*
3488 * Call OF "quiesce" method to shut down pending DMA's from
3489 * devices etc...
3490 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003491 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003492 call_prom("quiesce", 0, 0);
3493
3494 /*
3495 * And finally, call the kernel passing it the flattened device
3496 * tree and NULL as r5, thus triggering the new entry point which
3497 * is common to us and kexec
3498 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003499 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003500
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003501 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3502 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003503
3504#ifdef CONFIG_PPC32
3505 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003506#else
3507 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003508#endif
3509
Ram Pai6a9c9302019-08-19 23:13:14 -03003510 /* Move to secure memory if we're supposed to be secure guests. */
3511 setup_secure_guest(kbase, hdr);
3512
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003513 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003514
3515 return 0;
3516}