blob: ed446b7ea1643cd1278feab02867ac6464056f3a [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>
29#include <asm/prom.h>
30#include <asm/rtas.h>
31#include <asm/page.h>
32#include <asm/processor.h>
33#include <asm/irq.h>
34#include <asm/io.h>
35#include <asm/smp.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100036#include <asm/mmu.h>
37#include <asm/pgtable.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>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100043
Paul Mackerras9b6b5632005-10-06 12:06:20 +100044#include <linux/linux_logo.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100045
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110046/* All of prom_init bss lives here */
Benjamin Herrenschmidt5f69e382018-10-15 13:49:58 +110047#define __prombss __section(.bss.prominit)
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110048
Paul Mackerras9b6b5632005-10-06 12:06:20 +100049/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +100050 * Eventually bump that one up
51 */
52#define DEVTREE_CHUNK_SIZE 0x100000
53
54/*
55 * This is the size of the local memory reserve map that gets copied
56 * into the boot params passed to the kernel. That size is totally
57 * flexible as the kernel just reads the list until it encounters an
58 * entry with size 0, so it can be changed without breaking binary
59 * compatibility
60 */
61#define MEM_RESERVE_MAP_SIZE 8
62
63/*
64 * prom_init() is called very early on, before the kernel text
65 * and data have been mapped to KERNELBASE. At this point the code
66 * is running at whatever address it has been loaded at.
67 * On ppc32 we compile with -mrelocatable, which means that references
68 * to extern and static variables get relocated automatically.
Anton Blanchard5ac47f72012-11-26 17:39:03 +000069 * ppc64 objects are always relocatable, we just need to relocate the
70 * TOC.
Paul Mackerras9b6b5632005-10-06 12:06:20 +100071 *
72 * Because OF may have mapped I/O devices into the area starting at
73 * KERNELBASE, particularly on CHRP machines, we can't safely call
74 * OF once the kernel has been mapped to KERNELBASE. Therefore all
75 * OF calls must be done within prom_init().
76 *
77 * ADDR is used in calls to call_prom. The 4th and following
78 * arguments to call_prom should be 32-bit values.
79 * On ppc64, 64 bit values are truncated to 32 bits (and
80 * fortunately don't get interpreted as two arguments).
81 */
Anton Blanchard5ac47f72012-11-26 17:39:03 +000082#define ADDR(x) (u32)(unsigned long)(x)
83
Paul Mackerras9b6b5632005-10-06 12:06:20 +100084#ifdef CONFIG_PPC64
Paul Mackerrasa23414b2005-11-10 12:00:55 +110085#define OF_WORKAROUNDS 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +100086#else
Paul Mackerrasa23414b2005-11-10 12:00:55 +110087#define OF_WORKAROUNDS of_workarounds
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110088static int of_workarounds __prombss;
Paul Mackerras9b6b5632005-10-06 12:06:20 +100089#endif
90
Paul Mackerrasa23414b2005-11-10 12:00:55 +110091#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
92#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
93
Paul Mackerras9b6b5632005-10-06 12:06:20 +100094#define PROM_BUG() do { \
95 prom_printf("kernel BUG at %s line 0x%x!\n", \
Anton Blanchard5827d412012-11-26 17:40:03 +000096 __FILE__, __LINE__); \
Paul Mackerras9b6b5632005-10-06 12:06:20 +100097 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
98} while (0)
99
100#ifdef DEBUG_PROM
101#define prom_debug(x...) prom_printf(x)
102#else
Mathieu Malaterre85aa4b92018-04-23 21:36:38 +0200103#define prom_debug(x...) do { } while (0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000104#endif
105
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000106
107typedef u32 prom_arg_t;
108
109struct prom_args {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000110 __be32 service;
111 __be32 nargs;
112 __be32 nret;
113 __be32 args[10];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000114};
115
116struct prom_t {
117 ihandle root;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100118 phandle chosen;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000119 int cpu;
120 ihandle stdout;
Paul Mackerrasa575b802005-10-23 17:23:21 +1000121 ihandle mmumap;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100122 ihandle memory;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000123};
124
125struct mem_map_entry {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000126 __be64 base;
127 __be64 size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000128};
129
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000130typedef __be32 cell_t;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000131
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +0000132extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
133 unsigned long r6, unsigned long r7, unsigned long r8,
134 unsigned long r9);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000135
136#ifdef CONFIG_PPC64
Paul Mackerrasc49888202005-10-26 21:52:53 +1000137extern int enter_prom(struct prom_args *args, unsigned long entry);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000138#else
Paul Mackerrasc49888202005-10-26 21:52:53 +1000139static inline int enter_prom(struct prom_args *args, unsigned long entry)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000140{
Paul Mackerrasc49888202005-10-26 21:52:53 +1000141 return ((int (*)(struct prom_args *))entry)(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000142}
143#endif
144
145extern void copy_and_flush(unsigned long dest, unsigned long src,
146 unsigned long size, unsigned long offset);
147
148/* prom structure */
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100149static struct prom_t __prombss prom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000150
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100151static unsigned long __prombss prom_entry;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000152
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100153static char __prombss of_stdout_device[256];
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +0000154static char __prombss prom_scratch[256];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000155
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100156static unsigned long __prombss dt_header_start;
157static unsigned long __prombss dt_struct_start, dt_struct_end;
158static unsigned long __prombss dt_string_start, dt_string_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000159
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100160static unsigned long __prombss prom_initrd_start, prom_initrd_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000161
162#ifdef CONFIG_PPC64
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100163static int __prombss prom_iommu_force_on;
164static int __prombss prom_iommu_off;
165static unsigned long __prombss prom_tce_alloc_start;
166static unsigned long __prombss prom_tce_alloc_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000167#endif
168
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100169#ifdef CONFIG_PPC_PSERIES
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100170static bool __prombss prom_radix_disable;
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100171#endif
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100172
173struct platform_support {
174 bool hash_mmu;
175 bool radix_mmu;
176 bool radix_gtse;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +0200177 bool xive;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100178};
179
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100180/* Platforms codes are now obsolete in the kernel. Now only used within this
181 * file and ultimately gone too. Feel free to change them if you need, they
182 * are not shared with anything outside of this file anymore
183 */
184#define PLATFORM_PSERIES 0x0100
185#define PLATFORM_PSERIES_LPAR 0x0101
186#define PLATFORM_LPAR 0x0001
187#define PLATFORM_POWERMAC 0x0400
188#define PLATFORM_GENERIC 0x0500
189
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100190static int __prombss of_platform;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000191
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100192static char __prombss prom_cmd_line[COMMAND_LINE_SIZE];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000193
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100194static unsigned long __prombss prom_memory_limit;
Benjamin Krillcf687872009-07-27 22:02:39 +0000195
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100196static unsigned long __prombss alloc_top;
197static unsigned long __prombss alloc_top_high;
198static unsigned long __prombss alloc_bottom;
199static unsigned long __prombss rmo_top;
200static unsigned long __prombss ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000201
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100202static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE];
203static int __prombss mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000204
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100205static cell_t __prombss regbuf[1024];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000206
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100207static bool __prombss rtas_has_query_cpu_stopped;
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000208
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000209
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000210/*
211 * Error results ... some OF calls will return "-1" on error, some
212 * will return 0, some will return either. To simplify, here are
213 * macros to use with any ihandle or phandle return value to check if
214 * it is valid
215 */
216
217#define PROM_ERROR (-1u)
218#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
219#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
220
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000221/* Copied from lib/string.c and lib/kstrtox.c */
222
223static int __init prom_strcmp(const char *cs, const char *ct)
224{
225 unsigned char c1, c2;
226
227 while (1) {
228 c1 = *cs++;
229 c2 = *ct++;
230 if (c1 != c2)
231 return c1 < c2 ? -1 : 1;
232 if (!c1)
233 break;
234 }
235 return 0;
236}
237
238static char __init *prom_strcpy(char *dest, const char *src)
239{
240 char *tmp = dest;
241
242 while ((*dest++ = *src++) != '\0')
243 /* nothing */;
244 return tmp;
245}
246
247static int __init prom_strncmp(const char *cs, const char *ct, size_t count)
248{
249 unsigned char c1, c2;
250
251 while (count) {
252 c1 = *cs++;
253 c2 = *ct++;
254 if (c1 != c2)
255 return c1 < c2 ? -1 : 1;
256 if (!c1)
257 break;
258 count--;
259 }
260 return 0;
261}
262
263static size_t __init prom_strlen(const char *s)
264{
265 const char *sc;
266
267 for (sc = s; *sc != '\0'; ++sc)
268 /* nothing */;
269 return sc - s;
270}
271
272static int __init prom_memcmp(const void *cs, const void *ct, size_t count)
273{
274 const unsigned char *su1, *su2;
275 int res = 0;
276
277 for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
278 if ((res = *su1 - *su2) != 0)
279 break;
280 return res;
281}
282
283static char __init *prom_strstr(const char *s1, const char *s2)
284{
285 size_t l1, l2;
286
287 l2 = prom_strlen(s2);
288 if (!l2)
289 return (char *)s1;
290 l1 = prom_strlen(s1);
291 while (l1 >= l2) {
292 l1--;
293 if (!prom_memcmp(s1, s2, l2))
294 return (char *)s1;
295 s1++;
296 }
297 return NULL;
298}
299
300static size_t __init prom_strlcpy(char *dest, const char *src, size_t size)
301{
302 size_t ret = prom_strlen(src);
303
304 if (size) {
305 size_t len = (ret >= size) ? size - 1 : ret;
306 memcpy(dest, src, len);
307 dest[len] = '\0';
308 }
309 return ret;
310}
311
312#ifdef CONFIG_PPC_PSERIES
313static int __init prom_strtobool(const char *s, bool *res)
314{
315 if (!s)
316 return -EINVAL;
317
318 switch (s[0]) {
319 case 'y':
320 case 'Y':
321 case '1':
322 *res = true;
323 return 0;
324 case 'n':
325 case 'N':
326 case '0':
327 *res = false;
328 return 0;
329 case 'o':
330 case 'O':
331 switch (s[1]) {
332 case 'n':
333 case 'N':
334 *res = true;
335 return 0;
336 case 'f':
337 case 'F':
338 *res = false;
339 return 0;
340 default:
341 break;
342 }
343 default:
344 break;
345 }
346
347 return -EINVAL;
348}
349#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000350
351/* This is the one and *ONLY* place where we actually call open
352 * firmware.
353 */
354
355static int __init call_prom(const char *service, int nargs, int nret, ...)
356{
357 int i;
358 struct prom_args args;
359 va_list list;
360
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000361 args.service = cpu_to_be32(ADDR(service));
362 args.nargs = cpu_to_be32(nargs);
363 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000364
365 va_start(list, nret);
366 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000367 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000368 va_end(list);
369
370 for (i = 0; i < nret; i++)
371 args.args[nargs+i] = 0;
372
Anton Blanchard5827d412012-11-26 17:40:03 +0000373 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000374 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000375
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000376 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000377}
378
379static int __init call_prom_ret(const char *service, int nargs, int nret,
380 prom_arg_t *rets, ...)
381{
382 int i;
383 struct prom_args args;
384 va_list list;
385
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000386 args.service = cpu_to_be32(ADDR(service));
387 args.nargs = cpu_to_be32(nargs);
388 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000389
390 va_start(list, rets);
391 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000392 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000393 va_end(list);
394
395 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100396 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000397
Anton Blanchard5827d412012-11-26 17:40:03 +0000398 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000399 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000400
401 if (rets != NULL)
402 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000403 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000404
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000405 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000406}
407
408
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000409static void __init prom_print(const char *msg)
410{
411 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000412
Anton Blanchard5827d412012-11-26 17:40:03 +0000413 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000414 return;
415
416 for (p = msg; *p != 0; p = q) {
417 for (q = p; *q != 0 && *q != '\n'; ++q)
418 ;
419 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000420 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000421 if (*q == 0)
422 break;
423 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000424 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000425 }
426}
427
428
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200429/*
430 * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that
431 * we do not need __udivdi3 or __umoddi3 on 32bits.
432 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000433static void __init prom_print_hex(unsigned long val)
434{
435 int i, nibbles = sizeof(val)*2;
436 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000437
438 for (i = nibbles-1; i >= 0; i--) {
439 buf[i] = (val & 0xf) + '0';
440 if (buf[i] > '9')
441 buf[i] += ('a'-'0'-10);
442 val >>= 4;
443 }
444 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000445 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000446}
447
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000448/* max number of decimal digits in an unsigned long */
449#define UL_DIGITS 21
450static void __init prom_print_dec(unsigned long val)
451{
452 int i, size;
453 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000454
455 for (i = UL_DIGITS-1; i >= 0; i--) {
456 buf[i] = (val % 10) + '0';
457 val = val/10;
458 if (val == 0)
459 break;
460 }
461 /* shift stuff down */
462 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000463 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000464}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000465
Mathieu Malaterreeae5f702018-04-06 22:12:19 +0200466__printf(1, 2)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000467static void __init prom_printf(const char *format, ...)
468{
469 const char *p, *q, *s;
470 va_list args;
471 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000472 long vs;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200473 int n = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000474
475 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000476 for (p = format; *p != 0; p = q) {
477 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
478 ;
479 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000480 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000481 if (*q == 0)
482 break;
483 if (*q == '\n') {
484 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000485 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000486 ADDR("\r\n"), 2);
487 continue;
488 }
489 ++q;
490 if (*q == 0)
491 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200492 while (*q == 'l') {
493 ++q;
494 ++n;
495 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000496 switch (*q) {
497 case 's':
498 ++q;
499 s = va_arg(args, const char *);
500 prom_print(s);
501 break;
502 case 'x':
503 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200504 switch (n) {
505 case 0:
506 v = va_arg(args, unsigned int);
507 break;
508 case 1:
509 v = va_arg(args, unsigned long);
510 break;
511 case 2:
512 default:
513 v = va_arg(args, unsigned long long);
514 break;
515 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000516 prom_print_hex(v);
517 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200518 case 'u':
519 ++q;
520 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 }
532 prom_print_dec(v);
533 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000534 case 'd':
535 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200536 switch (n) {
537 case 0:
538 vs = va_arg(args, int);
539 break;
540 case 1:
541 vs = va_arg(args, long);
542 break;
543 case 2:
544 default:
545 vs = va_arg(args, long long);
546 break;
547 }
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000548 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000549 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000550 vs = -vs;
551 }
552 prom_print_dec(vs);
553 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000554 }
555 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100556 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000557}
558
559
Paul Mackerrasa575b802005-10-23 17:23:21 +1000560static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
561 unsigned long align)
562{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000563
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100564 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
565 /*
566 * Old OF requires we claim physical and virtual separately
567 * and then map explicitly (assuming virtual mode)
568 */
569 int ret;
570 prom_arg_t result;
571
572 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000573 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100574 align, size, virt);
575 if (ret != 0 || result == -1)
576 return -1;
577 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000578 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100579 align, size, virt);
580 if (ret != 0) {
581 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000582 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100583 return -1;
584 }
585 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000586 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000587 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100588 return virt;
589 }
590 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
591 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000592}
593
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000594static void __init __attribute__((noreturn)) prom_panic(const char *reason)
595{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000596 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100597 /* Do not call exit because it clears the screen on pmac
598 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000599 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100600 asm("trap\n");
601
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000602 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000603 call_prom("exit", 0, 0);
604
605 for (;;) /* should never get here */
606 ;
607}
608
609
610static int __init prom_next_node(phandle *nodep)
611{
612 phandle node;
613
614 if ((node = *nodep) != 0
615 && (*nodep = call_prom("child", 1, 1, node)) != 0)
616 return 1;
617 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
618 return 1;
619 for (;;) {
620 if ((node = call_prom("parent", 1, 1, node)) == 0)
621 return 0;
622 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
623 return 1;
624 }
625}
626
Masahiro Yamada480795a2019-05-14 15:42:14 -0700627static inline int __init prom_getprop(phandle node, const char *pname,
628 void *value, size_t valuelen)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000629{
630 return call_prom("getprop", 4, 1, node, ADDR(pname),
631 (u32)(unsigned long) value, (u32) valuelen);
632}
633
Masahiro Yamada480795a2019-05-14 15:42:14 -0700634static inline int __init prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000635{
636 return call_prom("getproplen", 2, 1, node, ADDR(pname));
637}
638
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100639static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000640{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100641 char *p = *str;
642
643 while (*q)
644 *p++ = *q++;
645 *p++ = ' ';
646 *str = p;
647}
648
649static char *tohex(unsigned int x)
650{
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100651 static const char digits[] __initconst = "0123456789abcdef";
652 static char result[9] __prombss;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100653 int i;
654
655 result[8] = 0;
656 i = 8;
657 do {
658 --i;
659 result[i] = digits[x & 0xf];
660 x >>= 4;
661 } while (x != 0 && i > 0);
662 return &result[i];
663}
664
665static int __init prom_setprop(phandle node, const char *nodename,
666 const char *pname, void *value, size_t valuelen)
667{
668 char cmd[256], *p;
669
670 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
671 return call_prom("setprop", 4, 1, node, ADDR(pname),
672 (u32)(unsigned long) value, (u32) valuelen);
673
674 /* gah... setprop doesn't work on longtrail, have to use interpret */
675 p = cmd;
676 add_string(&p, "dev");
677 add_string(&p, nodename);
678 add_string(&p, tohex((u32)(unsigned long) value));
679 add_string(&p, tohex(valuelen));
680 add_string(&p, tohex(ADDR(pname)));
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000681 add_string(&p, tohex(prom_strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100682 add_string(&p, "property");
683 *p = 0;
684 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000685}
686
Anton Blanchard5827d412012-11-26 17:40:03 +0000687/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000688#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
689 || ('a' <= (c) && (c) <= 'f') \
690 || ('A' <= (c) && (c) <= 'F'))
691
692#define isdigit(c) ('0' <= (c) && (c) <= '9')
693#define islower(c) ('a' <= (c) && (c) <= 'z')
694#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
695
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000696static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000697{
698 unsigned long result = 0, base = 10, value;
699
700 if (*cp == '0') {
701 base = 8;
702 cp++;
703 if (toupper(*cp) == 'X') {
704 cp++;
705 base = 16;
706 }
707 }
708
709 while (isxdigit(*cp) &&
710 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
711 result = result * base + value;
712 cp++;
713 }
714
715 if (endp)
716 *endp = cp;
717
718 return result;
719}
720
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000721static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000722{
723 unsigned long ret = prom_strtoul(ptr, retptr);
724 int shift = 0;
725
726 /*
727 * We can't use a switch here because GCC *may* generate a
728 * jump table which won't work, because we're not running at
729 * the address we're linked at.
730 */
731 if ('G' == **retptr || 'g' == **retptr)
732 shift = 30;
733
734 if ('M' == **retptr || 'm' == **retptr)
735 shift = 20;
736
737 if ('K' == **retptr || 'k' == **retptr)
738 shift = 10;
739
740 if (shift) {
741 ret <<= shift;
742 (*retptr)++;
743 }
744
745 return ret;
746}
747
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000748/*
749 * Early parsing of the command line passed to the kernel, used for
750 * "mem=x" and the options that affect the iommu
751 */
752static void __init early_cmdline_parse(void)
753{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100754 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000755
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100756 char *p;
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000757 int l = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000758
Anton Blanchard5827d412012-11-26 17:40:03 +0000759 prom_cmd_line[0] = 0;
760 p = prom_cmd_line;
761 if ((long)prom.chosen > 0)
762 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000763 if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && (l <= 0 || p[0] == '\0')) /* dbl check */
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000764 prom_strlcpy(prom_cmd_line, CONFIG_CMDLINE, sizeof(prom_cmd_line));
Anton Blanchard5827d412012-11-26 17:40:03 +0000765 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000766
767#ifdef CONFIG_PPC64
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000768 opt = prom_strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000769 if (opt) {
770 prom_printf("iommu opt is: %s\n", opt);
771 opt += 6;
772 while (*opt && *opt == ' ')
773 opt++;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000774 if (!prom_strncmp(opt, "off", 3))
Anton Blanchard5827d412012-11-26 17:40:03 +0000775 prom_iommu_off = 1;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000776 else if (!prom_strncmp(opt, "force", 5))
Anton Blanchard5827d412012-11-26 17:40:03 +0000777 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000778 }
779#endif
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000780 opt = prom_strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000781 if (opt) {
782 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000783 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000784#ifdef CONFIG_PPC64
785 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000786 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000787#endif
788 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100789
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100790#ifdef CONFIG_PPC_PSERIES
791 prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000792 opt = prom_strstr(prom_cmd_line, "disable_radix");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100793 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530794 opt += 13;
795 if (*opt && *opt == '=') {
796 bool val;
797
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000798 if (prom_strtobool(++opt, &val))
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530799 prom_radix_disable = false;
800 else
801 prom_radix_disable = val;
802 } else
803 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100804 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530805 if (prom_radix_disable)
806 prom_debug("Radix disabled from cmdline\n");
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100807#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000808}
809
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +1100810#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000811/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000812 * The architecture vector has an array of PVR mask/value pairs,
813 * followed by # option vectors - 1, followed by the option vectors.
814 *
815 * See prom.h for the definition of the bits specified in the
816 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000817 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000818
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000819/* Firmware expects the value to be n - 1, where n is the # of vectors */
820#define NUM_VECTORS(n) ((n) - 1)
821
822/*
823 * Firmware expects 1 + n - 2, where n is the length of the option vector in
824 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
825 */
826#define VECTOR_LENGTH(n) (1 + (n) - 2)
827
Michael Ellermand03d1d62016-11-18 23:15:41 +1100828struct option_vector1 {
829 u8 byte1;
830 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100831 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100832} __packed;
833
834struct option_vector2 {
835 u8 byte1;
836 __be16 reserved;
837 __be32 real_base;
838 __be32 real_size;
839 __be32 virt_base;
840 __be32 virt_size;
841 __be32 load_base;
842 __be32 min_rma;
843 __be32 min_load;
844 u8 min_rma_percent;
845 u8 max_pft_size;
846} __packed;
847
848struct option_vector3 {
849 u8 byte1;
850 u8 byte2;
851} __packed;
852
853struct option_vector4 {
854 u8 byte1;
855 u8 min_vp_cap;
856} __packed;
857
858struct option_vector5 {
859 u8 byte1;
860 u8 byte2;
861 u8 byte3;
862 u8 cmo;
863 u8 associativity;
864 u8 bin_opts;
865 u8 micro_checkpoint;
866 u8 reserved0;
867 __be32 max_cpus;
868 __be16 papr_level;
869 __be16 reserved1;
870 u8 platform_facilities;
871 u8 reserved2;
872 __be16 reserved3;
873 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100874 u8 byte22;
875 u8 intarch;
876 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100877 u8 hash_ext;
878 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100879} __packed;
880
881struct option_vector6 {
882 u8 reserved;
883 u8 secondary_pteg;
884 u8 os_name;
885} __packed;
886
Michael Ellerman76ffb572016-11-18 23:15:42 +1100887struct ibm_arch_vec {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100888 struct { u32 mask, val; } pvrs[12];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100889
890 u8 num_vectors;
891
892 u8 vec1_len;
893 struct option_vector1 vec1;
894
895 u8 vec2_len;
896 struct option_vector2 vec2;
897
898 u8 vec3_len;
899 struct option_vector3 vec3;
900
901 u8 vec4_len;
902 struct option_vector4 vec4;
903
904 u8 vec5_len;
905 struct option_vector5 vec5;
906
907 u8 vec6_len;
908 struct option_vector6 vec6;
909} __packed;
910
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +1100911static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100912 .pvrs = {
913 {
914 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
915 .val = cpu_to_be32(0x003a0000),
916 },
917 {
918 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
919 .val = cpu_to_be32(0x003e0000),
920 },
921 {
922 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
923 .val = cpu_to_be32(0x003f0000),
924 },
925 {
926 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
927 .val = cpu_to_be32(0x004b0000),
928 },
929 {
930 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
931 .val = cpu_to_be32(0x004c0000),
932 },
933 {
934 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
935 .val = cpu_to_be32(0x004d0000),
936 },
937 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100938 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
939 .val = cpu_to_be32(0x004e0000),
940 },
941 {
942 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
943 .val = cpu_to_be32(0x0f000005),
944 },
945 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100946 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
947 .val = cpu_to_be32(0x0f000004),
948 },
949 {
950 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
951 .val = cpu_to_be32(0x0f000003),
952 },
953 {
954 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
955 .val = cpu_to_be32(0x0f000002),
956 },
957 {
958 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
959 .val = cpu_to_be32(0x0f000001),
960 },
961 },
962
963 .num_vectors = NUM_VECTORS(6),
964
965 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
966 .vec1 = {
967 .byte1 = 0,
968 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
969 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100970 .arch_versions3 = OV1_PPC_3_00,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100971 },
972
973 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
974 /* option vector 2: Open Firmware options supported */
975 .vec2 = {
976 .byte1 = OV2_REAL_MODE,
977 .reserved = 0,
978 .real_base = cpu_to_be32(0xffffffff),
979 .real_size = cpu_to_be32(0xffffffff),
980 .virt_base = cpu_to_be32(0xffffffff),
981 .virt_size = cpu_to_be32(0xffffffff),
982 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -0400983 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +1100984 .min_load = cpu_to_be32(0xffffffff), /* full client load */
985 .min_rma_percent = 0, /* min RMA percentage of total RAM */
986 .max_pft_size = 48, /* max log_2(hash table size) */
987 },
988
989 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
990 /* option vector 3: processor options supported */
991 .vec3 = {
992 .byte1 = 0, /* don't ignore, don't halt */
993 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
994 },
995
996 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
997 /* option vector 4: IBM PAPR implementation */
998 .vec4 = {
999 .byte1 = 0, /* don't halt */
1000 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
1001 },
1002
1003 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
1004 /* option vector 5: PAPR/OF options */
1005 .vec5 = {
1006 .byte1 = 0, /* don't ignore, don't halt */
1007 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
1008 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
1009#ifdef CONFIG_PCI_MSI
1010 /* PCIe/MSI support. Without MSI full PCIe is not supported */
1011 OV5_FEAT(OV5_MSI),
1012#else
1013 0,
1014#endif
1015 .byte3 = 0,
1016 .cmo =
1017#ifdef CONFIG_PPC_SMLPAR
1018 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
1019#else
1020 0,
1021#endif
1022 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -06001023 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +11001024 .micro_checkpoint = 0,
1025 .reserved0 = 0,
1026 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
1027 .papr_level = 0,
1028 .reserved1 = 0,
1029 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
1030 .reserved2 = 0,
1031 .reserved3 = 0,
1032 .subprocessors = 1,
Nathan Fontenot0c38ed62017-12-01 10:48:03 -06001033 .byte22 = OV5_FEAT(OV5_DRMEM_V2),
Paul Mackerrascc3d2942017-01-30 21:21:36 +11001034 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001035 .mmu = 0,
1036 .hash_ext = 0,
1037 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001038 },
1039
1040 /* option vector 6: IBM PAPR hints */
1041 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
1042 .vec6 = {
1043 .reserved = 0,
1044 .secondary_pteg = 0,
1045 .os_name = OV6_LINUX,
1046 },
1047};
1048
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001049static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned;
1050
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001051/* Old method - ELF header with PT_NOTE sections only works on BE */
1052#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +10001053static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001054 Elf32_Ehdr elfhdr;
1055 Elf32_Phdr phdr[2];
1056 struct chrpnote {
1057 u32 namesz;
1058 u32 descsz;
1059 u32 type;
1060 char name[8]; /* "PowerPC" */
1061 struct chrpdesc {
1062 u32 real_mode;
1063 u32 real_base;
1064 u32 real_size;
1065 u32 virt_base;
1066 u32 virt_size;
1067 u32 load_base;
1068 } chrpdesc;
1069 } chrpnote;
1070 struct rpanote {
1071 u32 namesz;
1072 u32 descsz;
1073 u32 type;
1074 char name[24]; /* "IBM,RPA-Client-Config" */
1075 struct rpadesc {
1076 u32 lpar_affinity;
1077 u32 min_rmo_size;
1078 u32 min_rmo_percent;
1079 u32 max_pft_size;
1080 u32 splpar;
1081 u32 min_load;
1082 u32 new_mem_def;
1083 u32 ignore_me;
1084 } rpadesc;
1085 } rpanote;
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11001086} fake_elf __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001087 .elfhdr = {
1088 .e_ident = { 0x7f, 'E', 'L', 'F',
1089 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
1090 .e_type = ET_EXEC, /* yeah right */
1091 .e_machine = EM_PPC,
1092 .e_version = EV_CURRENT,
1093 .e_phoff = offsetof(struct fake_elf, phdr),
1094 .e_phentsize = sizeof(Elf32_Phdr),
1095 .e_phnum = 2
1096 },
1097 .phdr = {
1098 [0] = {
1099 .p_type = PT_NOTE,
1100 .p_offset = offsetof(struct fake_elf, chrpnote),
1101 .p_filesz = sizeof(struct chrpnote)
1102 }, [1] = {
1103 .p_type = PT_NOTE,
1104 .p_offset = offsetof(struct fake_elf, rpanote),
1105 .p_filesz = sizeof(struct rpanote)
1106 }
1107 },
1108 .chrpnote = {
1109 .namesz = sizeof("PowerPC"),
1110 .descsz = sizeof(struct chrpdesc),
1111 .type = 0x1275,
1112 .name = "PowerPC",
1113 .chrpdesc = {
1114 .real_mode = ~0U, /* ~0 means "don't care" */
1115 .real_base = ~0U,
1116 .real_size = ~0U,
1117 .virt_base = ~0U,
1118 .virt_size = ~0U,
1119 .load_base = ~0U
1120 },
1121 },
1122 .rpanote = {
1123 .namesz = sizeof("IBM,RPA-Client-Config"),
1124 .descsz = sizeof(struct rpadesc),
1125 .type = 0x12759999,
1126 .name = "IBM,RPA-Client-Config",
1127 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001128 .lpar_affinity = 0,
1129 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001130 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001131 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001132 .splpar = 1,
1133 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001134 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001135 }
1136 }
1137};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001138#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001139
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001140static int __init prom_count_smt_threads(void)
1141{
1142 phandle node;
1143 char type[64];
1144 unsigned int plen;
1145
1146 /* Pick up th first CPU node we can find */
1147 for (node = 0; prom_next_node(&node); ) {
1148 type[0] = 0;
1149 prom_getprop(node, "device_type", type, sizeof(type));
1150
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001151 if (prom_strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001152 continue;
1153 /*
1154 * There is an entry for each smt thread, each entry being
1155 * 4 bytes long. All cpus should have the same number of
1156 * smt threads, so return after finding the first.
1157 */
1158 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1159 if (plen == PROM_ERROR)
1160 break;
1161 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001162 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001163
1164 /* Sanity check */
1165 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001166 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001167 (unsigned long)plen);
1168 return 1;
1169 }
1170 return plen;
1171 }
1172 prom_debug("No threads found, assuming 1 per core\n");
1173
1174 return 1;
1175
1176}
1177
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001178static void __init prom_parse_mmu_model(u8 val,
1179 struct platform_support *support)
1180{
1181 switch (val) {
1182 case OV5_FEAT(OV5_MMU_DYNAMIC):
1183 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1184 prom_debug("MMU - either supported\n");
1185 support->radix_mmu = !prom_radix_disable;
1186 support->hash_mmu = true;
1187 break;
1188 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1189 prom_debug("MMU - radix only\n");
1190 if (prom_radix_disable) {
1191 /*
1192 * If we __have__ to do radix, we're better off ignoring
1193 * the command line rather than not booting.
1194 */
1195 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1196 }
1197 support->radix_mmu = true;
1198 break;
1199 case OV5_FEAT(OV5_MMU_HASH):
1200 prom_debug("MMU - hash only\n");
1201 support->hash_mmu = true;
1202 break;
1203 default:
1204 prom_debug("Unknown mmu support option: 0x%x\n", val);
1205 break;
1206 }
1207}
1208
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001209static void __init prom_parse_xive_model(u8 val,
1210 struct platform_support *support)
1211{
1212 switch (val) {
1213 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1214 prom_debug("XIVE - either mode supported\n");
1215 support->xive = true;
1216 break;
1217 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1218 prom_debug("XIVE - exploitation mode supported\n");
1219 support->xive = true;
1220 break;
1221 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1222 prom_debug("XIVE - legacy mode supported\n");
1223 break;
1224 default:
1225 prom_debug("Unknown xive support option: 0x%x\n", val);
1226 break;
1227 }
1228}
1229
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001230static void __init prom_parse_platform_support(u8 index, u8 val,
1231 struct platform_support *support)
1232{
1233 switch (index) {
1234 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1235 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1236 break;
1237 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
1238 if (val & OV5_FEAT(OV5_RADIX_GTSE)) {
1239 prom_debug("Radix - GTSE supported\n");
1240 support->radix_gtse = true;
1241 }
1242 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001243 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1244 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1245 support);
1246 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001247 }
1248}
1249
1250static void __init prom_check_platform_support(void)
1251{
1252 struct platform_support supported = {
1253 .hash_mmu = false,
1254 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001255 .radix_gtse = false,
1256 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001257 };
1258 int prop_len = prom_getproplen(prom.chosen,
1259 "ibm,arch-vec-5-platform-support");
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001260
Christophe Leroyadcf5912019-04-26 16:23:29 +00001261 /*
1262 * First copy the architecture vec template
1263 *
1264 * use memcpy() instead of *vec = *vec_template so that GCC replaces it
1265 * by __memcpy() when KASAN is active
1266 */
1267 memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template,
1268 sizeof(ibm_architecture_vec));
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001269
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001270 if (prop_len > 1) {
1271 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001272 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001273 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1274 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001275 if (prop_len > sizeof(vec))
1276 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1277 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001278 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1279 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001280 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001281 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1282 , vec[i]
1283 , vec[i + 1]);
1284 prom_parse_platform_support(vec[i], vec[i + 1],
1285 &supported);
1286 }
1287 }
1288
Alexey Kardashevskiy79b46862018-01-09 16:45:20 +11001289 if (supported.radix_mmu && supported.radix_gtse &&
1290 IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001291 /* Radix preferred - but we require GTSE for now */
1292 prom_debug("Asking for radix with GTSE\n");
1293 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
1294 ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE);
1295 } else if (supported.hash_mmu) {
1296 /* Default to hash mmu (if we can) */
1297 prom_debug("Asking for hash\n");
1298 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1299 } else {
1300 /* We're probably on a legacy hypervisor */
1301 prom_debug("Assuming legacy hash support\n");
1302 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001303
1304 if (supported.xive) {
1305 prom_debug("Asking for XIVE\n");
1306 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1307 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001308}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001309
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001310static void __init prom_send_capabilities(void)
1311{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001312 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001313 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001314 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001315
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001316 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1317 prom_check_platform_support();
1318
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001319 root = call_prom("open", 1, 1, ADDR("/"));
1320 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001321 /* We need to tell the FW about the number of cores we support.
1322 *
1323 * To do that, we count the number of threads on the first core
1324 * (we assume this is the same for all cores) and use it to
1325 * divide NR_CPUS.
1326 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001327
Michael Ellerman76ffb572016-11-18 23:15:42 +11001328 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001329 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001330 cores, NR_CPUS);
1331
1332 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001333
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001334 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001335 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001336 if (call_prom_ret("call-method", 3, 2, &ret,
1337 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001338 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001339 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001340 /* the call exists... */
1341 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001342 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001343 "-support call FAILED!\n");
1344 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001345 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001346 return;
1347 }
1348 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001349 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001350 }
1351
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001352#ifdef __BIG_ENDIAN__
1353 {
1354 ihandle elfloader;
1355
1356 /* no ibm,client-architecture-support call, try the old way */
1357 elfloader = call_prom("open", 1, 1,
1358 ADDR("/packages/elf-loader"));
1359 if (elfloader == 0) {
1360 prom_printf("couldn't open /packages/elf-loader\n");
1361 return;
1362 }
1363 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1364 elfloader, ADDR(&fake_elf));
1365 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001366 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001367#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001368}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001369#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001370
1371/*
1372 * Memory allocation strategy... our layout is normally:
1373 *
1374 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1375 * rare cases, initrd might end up being before the kernel though.
1376 * We assume this won't override the final kernel at 0, we have no
1377 * provision to handle that in this version, but it should hopefully
1378 * never happen.
1379 *
1380 * alloc_top is set to the top of RMO, eventually shrink down if the
1381 * TCEs overlap
1382 *
1383 * alloc_bottom is set to the top of kernel/initrd
1384 *
1385 * from there, allocations are done this way : rtas is allocated
1386 * topmost, and the device-tree is allocated from the bottom. We try
1387 * to grow the device-tree allocation as we progress. If we can't,
1388 * then we fail, we don't currently have a facility to restart
1389 * elsewhere, but that shouldn't be necessary.
1390 *
1391 * Note that calls to reserve_mem have to be done explicitly, memory
1392 * allocated with either alloc_up or alloc_down isn't automatically
1393 * reserved.
1394 */
1395
1396
1397/*
1398 * Allocates memory in the RMO upward from the kernel/initrd
1399 *
1400 * When align is 0, this is a special case, it means to allocate in place
1401 * at the current location of alloc_bottom or fail (that is basically
1402 * extending the previous allocation). Used for the device-tree flattening
1403 */
1404static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1405{
Anton Blanchard5827d412012-11-26 17:40:03 +00001406 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001407 unsigned long addr = 0;
1408
Paul Mackerrasc49888202005-10-26 21:52:53 +10001409 if (align)
1410 base = _ALIGN_UP(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001411 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001412 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001413 prom_panic("alloc_up() called with mem not initialized\n");
1414
1415 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +00001416 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001417 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001418 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001419
Anton Blanchard5827d412012-11-26 17:40:03 +00001420 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001421 base = _ALIGN_UP(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001422 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001423 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001424 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001425 break;
1426 addr = 0;
1427 if (align == 0)
1428 break;
1429 }
1430 if (addr == 0)
1431 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001432 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001433
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001434 prom_debug(" -> %lx\n", addr);
1435 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1436 prom_debug(" alloc_top : %lx\n", alloc_top);
1437 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1438 prom_debug(" rmo_top : %lx\n", rmo_top);
1439 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001440
1441 return addr;
1442}
1443
1444/*
1445 * Allocates memory downward, either from top of RMO, or if highmem
1446 * is set, from the top of RAM. Note that this one doesn't handle
1447 * failures. It does claim memory if highmem is not set.
1448 */
1449static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1450 int highmem)
1451{
1452 unsigned long base, addr = 0;
1453
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001454 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001455 highmem ? "(high)" : "(low)");
1456 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001457 prom_panic("alloc_down() called with mem not initialized\n");
1458
1459 if (highmem) {
1460 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001461 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1462 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001463 return 0;
1464 /* Will we bump into the RMO ? If yes, check out that we
1465 * didn't overlap existing allocations there, if we did,
1466 * we are dead, we must be the first in town !
1467 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001468 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001469 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001470 if (alloc_top == rmo_top)
1471 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001472 else
1473 return 0;
1474 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001475 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001476 goto bail;
1477 }
1478
Anton Blanchard5827d412012-11-26 17:40:03 +00001479 base = _ALIGN_DOWN(alloc_top - size, align);
1480 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001481 base = _ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001482 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001483 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001484 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001485 break;
1486 addr = 0;
1487 }
1488 if (addr == 0)
1489 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001490 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001491
1492 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001493 prom_debug(" -> %lx\n", addr);
1494 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1495 prom_debug(" alloc_top : %lx\n", alloc_top);
1496 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1497 prom_debug(" rmo_top : %lx\n", rmo_top);
1498 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001499
1500 return addr;
1501}
1502
1503/*
1504 * Parse a "reg" cell
1505 */
1506static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1507{
1508 cell_t *p = *cellp;
1509 unsigned long r = 0;
1510
1511 /* Ignore more than 2 cells */
1512 while (s > sizeof(unsigned long) / 4) {
1513 p++;
1514 s--;
1515 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001516 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001517#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001518 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001519 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001520 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001521 }
1522#endif
1523 *cellp = p;
1524 return r;
1525}
1526
1527/*
1528 * Very dumb function for adding to the memory reserve list, but
1529 * we don't need anything smarter at this point
1530 *
1531 * XXX Eventually check for collisions. They should NEVER happen.
1532 * If problems seem to show up, it would be a good start to track
1533 * them down.
1534 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001535static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001536{
Kumar Galacbbcf342006-01-11 17:57:13 -06001537 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001538 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001539
1540 if (size == 0)
1541 return;
1542
1543 /* We need to always keep one empty entry so that we
1544 * have our terminator with "size" set to 0 since we are
1545 * dumb and just copy this entire array to the boot params
1546 */
1547 base = _ALIGN_DOWN(base, PAGE_SIZE);
1548 top = _ALIGN_UP(top, PAGE_SIZE);
1549 size = top - base;
1550
1551 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1552 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001553 mem_reserve_map[cnt].base = cpu_to_be64(base);
1554 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001555 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001556}
1557
1558/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001559 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001560 * obtain that way the top of memory and RMO to setup out local allocator
1561 */
1562static void __init prom_init_mem(void)
1563{
1564 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001565#ifdef DEBUG_PROM
1566 char *path;
1567#endif
1568 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001569 unsigned int plen;
1570 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001571 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001572 u32 rac, rsc;
1573
1574 /*
1575 * We iterate the memory nodes to find
1576 * 1) top of RMO (first node)
1577 * 2) top of memory
1578 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001579 val = cpu_to_be32(2);
1580 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1581 rac = be32_to_cpu(val);
1582 val = cpu_to_be32(1);
1583 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1584 rsc = be32_to_cpu(val);
1585 prom_debug("root_addr_cells: %x\n", rac);
1586 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001587
1588 prom_debug("scanning memory:\n");
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001589#ifdef DEBUG_PROM
Anton Blanchard5827d412012-11-26 17:40:03 +00001590 path = prom_scratch;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001591#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001592
1593 for (node = 0; prom_next_node(&node); ) {
1594 type[0] = 0;
1595 prom_getprop(node, "device_type", type, sizeof(type));
1596
Paul Mackerrasc49888202005-10-26 21:52:53 +10001597 if (type[0] == 0) {
1598 /*
1599 * CHRP Longtrail machines have no device_type
1600 * on the memory node, so check the name instead...
1601 */
1602 prom_getprop(node, "name", type, sizeof(type));
1603 }
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001604 if (prom_strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001605 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001606
Anton Blanchard5827d412012-11-26 17:40:03 +00001607 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001608 if (plen > sizeof(regbuf)) {
1609 prom_printf("memory node too large for buffer !\n");
1610 plen = sizeof(regbuf);
1611 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001612 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001613 endp = p + (plen / sizeof(cell_t));
1614
1615#ifdef DEBUG_PROM
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00001616 memset(path, 0, sizeof(prom_scratch));
1617 call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001618 prom_debug(" node %s :\n", path);
1619#endif /* DEBUG_PROM */
1620
1621 while ((endp - p) >= (rac + rsc)) {
1622 unsigned long base, size;
1623
1624 base = prom_next_cell(rac, &p);
1625 size = prom_next_cell(rsc, &p);
1626
1627 if (size == 0)
1628 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001629 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001630 if (base == 0 && (of_platform & PLATFORM_LPAR))
1631 rmo_top = size;
1632 if ((base + size) > ram_top)
1633 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001634 }
1635 }
1636
Anton Blanchard5827d412012-11-26 17:40:03 +00001637 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001638
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001639 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001640 * If prom_memory_limit is set we reduce the upper limits *except* for
1641 * alloc_top_high. This must be the real top of RAM so we can put
1642 * TCE's up there.
1643 */
1644
Anton Blanchard5827d412012-11-26 17:40:03 +00001645 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001646
Anton Blanchard5827d412012-11-26 17:40:03 +00001647 if (prom_memory_limit) {
1648 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001649 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1650 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001651 prom_memory_limit = 0;
1652 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001653 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1654 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001655 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001656 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001657 ram_top = prom_memory_limit;
1658 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001659 }
1660 }
1661
1662 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001663 * Setup our top alloc point, that is top of RMO or top of
1664 * segment 0 when running non-LPAR.
1665 * Some RS64 machines have buggy firmware where claims up at
1666 * 1GB fail. Cap at 768MB as a workaround.
1667 * Since 768MB is plenty of room, and we need to cap to something
1668 * reasonable on 32-bit, cap at 768MB on all machines.
1669 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001670 if (!rmo_top)
1671 rmo_top = ram_top;
1672 rmo_top = min(0x30000000ul, rmo_top);
1673 alloc_top = rmo_top;
1674 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001675
Paul Mackerras64968f62011-12-13 17:54:13 +00001676 /*
1677 * Check if we have an initrd after the kernel but still inside
1678 * the RMO. If we do move our bottom point to after it.
1679 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001680 if (prom_initrd_start &&
1681 prom_initrd_start < rmo_top &&
1682 prom_initrd_end > alloc_bottom)
1683 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001684
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001685 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001686 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1687 prom_memory_limit);
1688 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1689 prom_printf(" alloc_top : %lx\n", alloc_top);
1690 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1691 prom_printf(" rmo_top : %lx\n", rmo_top);
1692 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001693}
1694
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001695static void __init prom_close_stdin(void)
1696{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001697 __be32 val;
1698 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001699
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001700 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1701 stdin = be32_to_cpu(val);
1702 call_prom("close", 1, 0, stdin);
1703 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001704}
1705
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001706/*
1707 * Allocate room for and instantiate RTAS
1708 */
1709static void __init prom_instantiate_rtas(void)
1710{
1711 phandle rtas_node;
1712 ihandle rtas_inst;
1713 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001714 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001715 u32 size = 0;
1716
1717 prom_debug("prom_instantiate_rtas: start...\n");
1718
1719 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1720 prom_debug("rtas_node: %x\n", rtas_node);
1721 if (!PHANDLE_VALID(rtas_node))
1722 return;
1723
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001724 val = 0;
1725 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1726 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001727 if (size == 0)
1728 return;
1729
1730 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001731 if (base == 0)
1732 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001733
1734 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1735 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001736 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001737 return;
1738 }
1739
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001740 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001741
1742 if (call_prom_ret("call-method", 3, 2, &entry,
1743 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001744 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001745 || entry == 0) {
1746 prom_printf(" failed\n");
1747 return;
1748 }
1749 prom_printf(" done\n");
1750
1751 reserve_mem(base, size);
1752
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001753 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001754 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001755 &val, sizeof(val));
1756 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001757 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001758 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001759
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001760 /* Check if it supports "query-cpu-stopped-state" */
1761 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1762 &val, sizeof(val)) != PROM_ERROR)
1763 rtas_has_query_cpu_stopped = true;
1764
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001765 prom_debug("rtas base = 0x%x\n", base);
1766 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001767 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001768
1769 prom_debug("prom_instantiate_rtas: end...\n");
1770}
1771
1772#ifdef CONFIG_PPC64
1773/*
Ashley Lai4a727422012-08-14 18:34:57 -05001774 * Allocate room for and instantiate Stored Measurement Log (SML)
1775 */
1776static void __init prom_instantiate_sml(void)
1777{
1778 phandle ibmvtpm_node;
1779 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001780 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001781 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001782 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001783
1784 prom_debug("prom_instantiate_sml: start...\n");
1785
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001786 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001787 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1788 if (!PHANDLE_VALID(ibmvtpm_node))
1789 return;
1790
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001791 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001792 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1793 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1794 return;
1795 }
1796
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001797 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1798 &val, sizeof(val)) != PROM_ERROR) {
1799 if (call_prom_ret("call-method", 2, 2, &succ,
1800 ADDR("reformat-sml-to-efi-alignment"),
1801 ibmvtpm_inst) != 0 || succ == 0) {
1802 prom_printf("Reformat SML to EFI alignment failed\n");
1803 return;
1804 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001805
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001806 if (call_prom_ret("call-method", 2, 2, &size,
1807 ADDR("sml-get-allocated-size"),
1808 ibmvtpm_inst) != 0 || size == 0) {
1809 prom_printf("SML get allocated size failed\n");
1810 return;
1811 }
1812 } else {
1813 if (call_prom_ret("call-method", 2, 2, &size,
1814 ADDR("sml-get-handover-size"),
1815 ibmvtpm_inst) != 0 || size == 0) {
1816 prom_printf("SML get handover size failed\n");
1817 return;
1818 }
Ashley Lai4a727422012-08-14 18:34:57 -05001819 }
1820
1821 base = alloc_down(size, PAGE_SIZE, 0);
1822 if (base == 0)
1823 prom_panic("Could not allocate memory for sml\n");
1824
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001825 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001826
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001827 memset((void *)base, 0, size);
1828
Ashley Lai4a727422012-08-14 18:34:57 -05001829 if (call_prom_ret("call-method", 4, 2, &entry,
1830 ADDR("sml-handover"),
1831 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1832 prom_printf("SML handover failed\n");
1833 return;
1834 }
1835 prom_printf(" done\n");
1836
1837 reserve_mem(base, size);
1838
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001839 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001840 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001841 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001842 &size, sizeof(size));
1843
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001844 prom_debug("sml base = 0x%llx\n", base);
1845 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001846
1847 prom_debug("prom_instantiate_sml: end...\n");
1848}
1849
1850/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001851 * Allocate room for and initialize TCE tables
1852 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001853#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001854static void __init prom_initialize_tce_table(void)
1855{
1856 phandle node;
1857 ihandle phb_node;
1858 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001859 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001860 u64 base, align;
1861 u32 minalign, minsize;
1862 u64 tce_entry, *tce_entryp;
1863 u64 local_alloc_top, local_alloc_bottom;
1864 u64 i;
1865
Anton Blanchard5827d412012-11-26 17:40:03 +00001866 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001867 return;
1868
1869 prom_debug("starting prom_initialize_tce_table\n");
1870
1871 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001872 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001873 local_alloc_bottom = local_alloc_top;
1874
1875 /* Search all nodes looking for PHBs. */
1876 for (node = 0; prom_next_node(&node); ) {
1877 compatible[0] = 0;
1878 type[0] = 0;
1879 model[0] = 0;
1880 prom_getprop(node, "compatible",
1881 compatible, sizeof(compatible));
1882 prom_getprop(node, "device_type", type, sizeof(type));
1883 prom_getprop(node, "model", model, sizeof(model));
1884
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001885 if ((type[0] == 0) || (prom_strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001886 continue;
1887
Linas Vepstase788ff12007-09-07 03:45:21 +10001888 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001889 if (compatible[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001890 if ((prom_strstr(compatible, "python") == NULL) &&
1891 (prom_strstr(compatible, "Speedwagon") == NULL) &&
1892 (prom_strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001893 continue;
1894 } else if (model[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001895 if ((prom_strstr(model, "ython") == NULL) &&
1896 (prom_strstr(model, "peedwagon") == NULL) &&
1897 (prom_strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001898 continue;
1899 }
1900
1901 if (prom_getprop(node, "tce-table-minalign", &minalign,
1902 sizeof(minalign)) == PROM_ERROR)
1903 minalign = 0;
1904 if (prom_getprop(node, "tce-table-minsize", &minsize,
1905 sizeof(minsize)) == PROM_ERROR)
1906 minsize = 4UL << 20;
1907
1908 /*
1909 * Even though we read what OF wants, we just set the table
1910 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1911 * By doing this, we avoid the pitfalls of trying to DMA to
1912 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001913 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10001914 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001915
1916 /* Align to the greater of the align or size */
1917 align = max(minalign, minsize);
1918 base = alloc_down(minsize, align, 1);
1919 if (base == 0)
1920 prom_panic("ERROR, cannot find space for TCE table.\n");
1921 if (base < local_alloc_bottom)
1922 local_alloc_bottom = base;
1923
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001924 /* It seems OF doesn't null-terminate the path :-( */
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00001925 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001926 /* Call OF to setup the TCE hardware */
1927 if (call_prom("package-to-path", 3, 1, node,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00001928 path, sizeof(prom_scratch) - 1) == PROM_ERROR) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001929 prom_printf("package-to-path failed\n");
1930 }
1931
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001932 /* Save away the TCE table attributes for later use. */
1933 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1934 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1935
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001936 prom_debug("TCE table: %s\n", path);
1937 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001938 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001939 prom_debug("\tsize = 0x%x\n", minsize);
1940
1941 /* Initialize the table to have a one-to-one mapping
1942 * over the allocated size.
1943 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001944 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001945 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1946 tce_entry = (i << PAGE_SHIFT);
1947 tce_entry |= 0x3;
1948 *tce_entryp = tce_entry;
1949 }
1950
1951 prom_printf("opening PHB %s", path);
1952 phb_node = call_prom("open", 1, 1, path);
1953 if (phb_node == 0)
1954 prom_printf("... failed\n");
1955 else
1956 prom_printf("... done\n");
1957
1958 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1959 phb_node, -1, minsize,
1960 (u32) base, (u32) (base >> 32));
1961 call_prom("close", 1, 0, phb_node);
1962 }
1963
1964 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1965
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001966 /* These are only really needed if there is a memory limit in
1967 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001968 prom_tce_alloc_start = local_alloc_bottom;
1969 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001970
1971 /* Flag the first invalid entry */
1972 prom_debug("ending prom_initialize_tce_table\n");
1973}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001974#endif /* __BIG_ENDIAN__ */
1975#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001976
1977/*
1978 * With CHRP SMP we need to use the OF to start the other processors.
1979 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1980 * so we have to put the processors into a holding pattern controlled
1981 * by the kernel (not OF) before we destroy the OF.
1982 *
1983 * This uses a chunk of low memory, puts some holding pattern
1984 * code there and sends the other processors off to there until
1985 * smp_boot_cpus tells them to do something. The holding pattern
1986 * checks that address until its cpu # is there, when it is that
1987 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1988 * of setting those values.
1989 *
1990 * We also use physical address 0x4 here to tell when a cpu
1991 * is in its holding pattern code.
1992 *
1993 * -- Cort
1994 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001995/*
1996 * We want to reference the copy of __secondary_hold_* in the
1997 * 0 - 0x100 address range
1998 */
1999#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
2000
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002001static void __init prom_hold_cpus(void)
2002{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002003 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002004 phandle node;
2005 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002006 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002007 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002008 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002009 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002010 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002011
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002012 /*
2013 * On pseries, if RTAS supports "query-cpu-stopped-state",
2014 * we skip this stage, the CPUs will be started by the
2015 * kernel using RTAS.
2016 */
2017 if ((of_platform == PLATFORM_PSERIES ||
2018 of_platform == PLATFORM_PSERIES_LPAR) &&
2019 rtas_has_query_cpu_stopped) {
2020 prom_printf("prom_hold_cpus: skipped\n");
2021 return;
2022 }
2023
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002024 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002025 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
2026 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
2027 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002028 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002029 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
2030 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002031
2032 /* Set the common spinloop variable, so all of the secondary cpus
2033 * will block when they are awakened from their OF spinloop.
2034 * This must occur for both SMP and non SMP kernels, since OF will
2035 * be trashed when we move the kernel.
2036 */
2037 *spinloop = 0;
2038
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002039 /* look for cpus */
2040 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002041 unsigned int cpu_no;
2042 __be32 reg;
2043
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002044 type[0] = 0;
2045 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002046 if (prom_strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002047 continue;
2048
2049 /* Skip non-configured cpus. */
2050 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002051 if (prom_strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002052 continue;
2053
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002054 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002055 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002056 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002057
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002058 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002059
2060 /* Init the acknowledge var which will be reset by
2061 * the secondary cpu when it awakens from its OF
2062 * spinloop.
2063 */
2064 *acknowledge = (unsigned long)-1;
2065
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002066 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002067 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002068 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002069 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002070 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002071
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002072 for (i = 0; (i < 100000000) &&
2073 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002074 mb();
2075
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002076 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002077 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002078 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002079 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002080 }
2081#ifdef CONFIG_SMP
2082 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002083 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002084#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002085 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002086
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002087 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002088}
2089
2090
2091static void __init prom_init_client_services(unsigned long pp)
2092{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002093 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00002094 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002095
2096 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00002097 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
2098 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002099 prom_panic("cannot find chosen"); /* msg won't be printed :( */
2100
2101 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00002102 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
2103 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002104 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002105
Anton Blanchard5827d412012-11-26 17:40:03 +00002106 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002107}
2108
Paul Mackerrasa575b802005-10-23 17:23:21 +10002109#ifdef CONFIG_PPC32
2110/*
2111 * For really old powermacs, we need to map things we claim.
2112 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002113 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10002114 */
2115static void __init prom_find_mmu(void)
2116{
Paul Mackerrasa575b802005-10-23 17:23:21 +10002117 phandle oprom;
2118 char version[64];
2119
2120 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
2121 if (!PHANDLE_VALID(oprom))
2122 return;
2123 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
2124 return;
2125 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002126 /* XXX might need to add other versions here */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002127 if (prom_strcmp(version, "Open Firmware, 1.0.5") == 0)
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002128 of_workarounds = OF_WA_CLAIM;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002129 else if (prom_strncmp(version, "FirmWorks,3.", 12) == 0) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002130 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2131 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2132 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002133 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002134 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2135 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2136 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002137 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002138 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002139 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002140}
2141#else
2142#define prom_find_mmu()
2143#endif
2144
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002145static void __init prom_init_stdout(void)
2146{
Anton Blanchard5827d412012-11-26 17:40:03 +00002147 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002148 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002149 phandle stdout_node;
2150 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002151
Anton Blanchard5827d412012-11-26 17:40:03 +00002152 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002153 prom_panic("cannot find stdout");
2154
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002155 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002156
2157 /* Get the full OF pathname of the stdout device */
2158 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002159 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002160 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2161 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002162 path, prom_strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002163
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002164 /* instance-to-package fails on PA-Semi */
2165 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2166 if (stdout_node != PROM_ERROR) {
2167 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002168
2169 /* If it's a display, note it */
2170 memset(type, 0, sizeof(type));
2171 prom_getprop(stdout_node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002172 if (prom_strcmp(type, "display") == 0)
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002173 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2174 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002175}
2176
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002177static int __init prom_find_machine_type(void)
2178{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002179 char compat[256];
2180 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002181#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002182 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002183 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002184#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002185
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002186 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002187 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188 compat, sizeof(compat)-1);
2189 if (len > 0) {
2190 compat[len] = 0;
2191 while (i < len) {
2192 char *p = &compat[i];
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002193 int sl = prom_strlen(p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002194 if (sl == 0)
2195 break;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002196 if (prom_strstr(p, "Power Macintosh") ||
2197 prom_strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002198 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002199#ifdef CONFIG_PPC64
2200 /* We must make sure we don't detect the IBM Cell
2201 * blades as pSeries due to some firmware issues,
2202 * so we do it here.
2203 */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002204 if (prom_strstr(p, "IBM,CBEA") ||
2205 prom_strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002206 return PLATFORM_GENERIC;
2207#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002208 i += sl + 1;
2209 }
2210 }
2211#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002212 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002213 * PAPR compliant platform. We assume it is if :
2214 * - /device_type is "chrp" (please, do NOT use that for future
2215 * non-IBM designs !
2216 * - it has /rtas
2217 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002218 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002219 compat, sizeof(compat)-1);
2220 if (len <= 0)
2221 return PLATFORM_GENERIC;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002222 if (prom_strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002223 return PLATFORM_GENERIC;
2224
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002225 /* Default to pSeries. We need to know if we are running LPAR */
2226 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002227 if (!PHANDLE_VALID(rtas))
2228 return PLATFORM_GENERIC;
2229 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2230 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002231 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002232 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002233 }
2234 return PLATFORM_PSERIES;
2235#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002236 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002237#endif
2238}
2239
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002240static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2241{
2242 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2243}
2244
2245/*
2246 * If we have a display that we don't know how to drive,
2247 * we will want to try to execute OF's open method for it
2248 * later. However, OF will probably fall over if we do that
2249 * we've taken over the MMU.
2250 * So we check whether we will need to open the display,
2251 * and if so, open it now.
2252 */
2253static void __init prom_check_displays(void)
2254{
2255 char type[16], *path;
2256 phandle node;
2257 ihandle ih;
2258 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002259
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11002260 static const unsigned char default_colors[] __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002261 0x00, 0x00, 0x00,
2262 0x00, 0x00, 0xaa,
2263 0x00, 0xaa, 0x00,
2264 0x00, 0xaa, 0xaa,
2265 0xaa, 0x00, 0x00,
2266 0xaa, 0x00, 0xaa,
2267 0xaa, 0xaa, 0x00,
2268 0xaa, 0xaa, 0xaa,
2269 0x55, 0x55, 0x55,
2270 0x55, 0x55, 0xff,
2271 0x55, 0xff, 0x55,
2272 0x55, 0xff, 0xff,
2273 0xff, 0x55, 0x55,
2274 0xff, 0x55, 0xff,
2275 0xff, 0xff, 0x55,
2276 0xff, 0xff, 0xff
2277 };
2278 const unsigned char *clut;
2279
Anton Blanchard4da727a2009-03-31 20:06:14 +00002280 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002281 for (node = 0; prom_next_node(&node); ) {
2282 memset(type, 0, sizeof(type));
2283 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002284 if (prom_strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002285 continue;
2286
2287 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002288 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002289 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002290
2291 /*
2292 * leave some room at the end of the path for appending extra
2293 * arguments
2294 */
2295 if (call_prom("package-to-path", 3, 1, node, path,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002296 sizeof(prom_scratch) - 10) == PROM_ERROR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002297 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002298 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002299
2300 ih = call_prom("open", 1, 1, path);
2301 if (ih == 0) {
2302 prom_printf("failed\n");
2303 continue;
2304 }
2305
2306 /* Success */
2307 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002308 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002309
2310 /* Setup a usable color table when the appropriate
2311 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002312 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002313 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002314 if (prom_set_color(ih, i, clut[0], clut[1],
2315 clut[2]) != 0)
2316 break;
2317
2318#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002319 clut = PTRRELOC(logo_linux_clut224.clut);
2320 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002321 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2322 clut[2]) != 0)
2323 break;
2324#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002325
2326#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2327 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2328 PROM_ERROR) {
2329 u32 width, height, pitch, addr;
2330
2331 prom_printf("Setting btext !\n");
2332 prom_getprop(node, "width", &width, 4);
2333 prom_getprop(node, "height", &height, 4);
2334 prom_getprop(node, "linebytes", &pitch, 4);
2335 prom_getprop(node, "address", &addr, 4);
2336 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2337 width, height, pitch, addr);
2338 btext_setup_display(width, height, 8, pitch, addr);
Christophe Leroyc21f5a92019-06-03 13:00:51 +00002339 btext_prepare_BAT();
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002340 }
2341#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002342 }
2343}
2344
2345
2346/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2347static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2348 unsigned long needed, unsigned long align)
2349{
2350 void *ret;
2351
2352 *mem_start = _ALIGN(*mem_start, align);
2353 while ((*mem_start + needed) > *mem_end) {
2354 unsigned long room, chunk;
2355
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002356 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002357 alloc_bottom);
2358 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002359 if (room > DEVTREE_CHUNK_SIZE)
2360 room = DEVTREE_CHUNK_SIZE;
2361 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002362 prom_panic("No memory for flatten_device_tree "
2363 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002364 chunk = alloc_up(room, 0);
2365 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002366 prom_panic("No memory for flatten_device_tree "
2367 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002368 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002369 }
2370
2371 ret = (void *)*mem_start;
2372 *mem_start += needed;
2373
2374 return ret;
2375}
2376
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002377#define dt_push_token(token, mem_start, mem_end) do { \
2378 void *room = make_room(mem_start, mem_end, 4, 4); \
2379 *(__be32 *)room = cpu_to_be32(token); \
2380 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002381
2382static unsigned long __init dt_find_string(char *str)
2383{
2384 char *s, *os;
2385
Anton Blanchard5827d412012-11-26 17:40:03 +00002386 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002387 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002388 while (s < (char *)dt_string_end) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002389 if (prom_strcmp(s, str) == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002390 return s - os;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002391 s += prom_strlen(s) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002392 }
2393 return 0;
2394}
2395
2396/*
2397 * The Open Firmware 1275 specification states properties must be 31 bytes or
2398 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2399 */
2400#define MAX_PROPERTY_NAME 64
2401
2402static void __init scan_dt_build_strings(phandle node,
2403 unsigned long *mem_start,
2404 unsigned long *mem_end)
2405{
2406 char *prev_name, *namep, *sstart;
2407 unsigned long soff;
2408 phandle child;
2409
Anton Blanchard5827d412012-11-26 17:40:03 +00002410 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002411
2412 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002413 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002414 for (;;) {
2415 /* 64 is max len of name including nul. */
2416 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2417 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2418 /* No more nodes: unwind alloc */
2419 *mem_start = (unsigned long)namep;
2420 break;
2421 }
2422
2423 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002424 if (prom_strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002425 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002426 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002427 continue;
2428 }
2429 /* get/create string entry */
2430 soff = dt_find_string(namep);
2431 if (soff != 0) {
2432 *mem_start = (unsigned long)namep;
2433 namep = sstart + soff;
2434 } else {
2435 /* Trim off some if we can */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002436 *mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002437 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002438 }
2439 prev_name = namep;
2440 }
2441
2442 /* do all our children */
2443 child = call_prom("child", 1, 1, node);
2444 while (child != 0) {
2445 scan_dt_build_strings(child, mem_start, mem_end);
2446 child = call_prom("peer", 1, 1, child);
2447 }
2448}
2449
2450static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2451 unsigned long *mem_end)
2452{
2453 phandle child;
2454 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2455 unsigned long soff;
2456 unsigned char *valp;
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +11002457 static char pname[MAX_PROPERTY_NAME] __prombss;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002458 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002459
2460 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2461
2462 /* get the node's full name */
2463 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002464 room = *mem_end - *mem_start;
2465 if (room > 255)
2466 room = 255;
2467 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002468 if (l >= 0) {
2469 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002470 if (l >= room) {
2471 if (l >= *mem_end - *mem_start)
2472 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002473 call_prom("package-to-path", 3, 1, node, namep, l);
2474 }
2475 namep[l] = '\0';
2476
2477 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002478 * middle of the path in some properties, and extract
2479 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002480 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002481 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002482 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002483 lp = namep;
2484 else if (*p != 0)
2485 *lp++ = *p;
2486 }
2487 *lp = 0;
2488 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002489 }
2490
2491 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002492 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002493 memset(path, 0, sizeof(prom_scratch));
2494 call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002495
2496 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002497 prev_name = "";
2498 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002499 for (;;) {
2500 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002501 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002502 break;
2503
2504 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002505 if (prom_strcmp(pname, "name") == 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002506 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002507 continue;
2508 }
2509
2510 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002511 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002512 if (soff == 0) {
2513 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002514 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002515 break;
2516 }
2517 prev_name = sstart + soff;
2518
2519 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002520 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002521
2522 /* sanity checks */
2523 if (l == PROM_ERROR)
2524 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002525
2526 /* push property head */
2527 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2528 dt_push_token(l, mem_start, mem_end);
2529 dt_push_token(soff, mem_start, mem_end);
2530
2531 /* push property content */
2532 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002533 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002534 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002535
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002536 if (!prom_strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002537 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002538 }
2539
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002540 /* Add a "phandle" property if none already exist */
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002541 if (!has_phandle) {
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002542 soff = dt_find_string("phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002543 if (soff == 0)
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002544 prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002545 else {
2546 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2547 dt_push_token(4, mem_start, mem_end);
2548 dt_push_token(soff, mem_start, mem_end);
2549 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002550 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002551 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002552 }
2553
2554 /* do all our children */
2555 child = call_prom("child", 1, 1, node);
2556 while (child != 0) {
2557 scan_dt_build_struct(child, mem_start, mem_end);
2558 child = call_prom("peer", 1, 1, child);
2559 }
2560
2561 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2562}
2563
2564static void __init flatten_device_tree(void)
2565{
2566 phandle root;
2567 unsigned long mem_start, mem_end, room;
2568 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002569 char *namep;
2570 u64 *rsvmap;
2571
2572 /*
2573 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002574 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002575 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002576 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002577 if (room > DEVTREE_CHUNK_SIZE)
2578 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002579 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002580
2581 /* Now try to claim that */
2582 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2583 if (mem_start == 0)
2584 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002585 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002586
2587 /* Get root of tree */
2588 root = call_prom("peer", 1, 1, (phandle)0);
2589 if (root == (phandle)0)
2590 prom_panic ("couldn't get device tree root\n");
2591
2592 /* Build header and make room for mem rsv map */
2593 mem_start = _ALIGN(mem_start, 4);
2594 hdr = make_room(&mem_start, &mem_end,
2595 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002596 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002597 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2598
2599 /* Start of strings */
2600 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002601 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002602 mem_start += 4; /* hole */
2603
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002604 /* Add "phandle" in there, we'll need it */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002605 namep = make_room(&mem_start, &mem_end, 16, 1);
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002606 prom_strcpy(namep, "phandle");
2607 mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002608
2609 /* Build string array */
2610 prom_printf("Building dt strings...\n");
2611 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002612 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002613
2614 /* Build structure */
2615 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002616 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002617 prom_printf("Building dt structure...\n");
2618 scan_dt_build_struct(root, &mem_start, &mem_end);
2619 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002620 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002621
2622 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002623 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2624 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2625 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2626 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2627 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2628 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2629 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2630 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002631 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002632 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002633
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002634 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002635 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002636
2637#ifdef DEBUG_PROM
2638 {
2639 int i;
2640 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002641 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002642 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002643 be64_to_cpu(mem_reserve_map[i].base),
2644 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002645 }
2646#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002647 /* Bump mem_reserve_cnt to cause further reservations to fail
2648 * since it's too late.
2649 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002650 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002651
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002652 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002653 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002654 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002655 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002656}
2657
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002658#ifdef CONFIG_PPC_MAPLE
2659/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2660 * The values are bad, and it doesn't even have the right number of cells. */
2661static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002662{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002663 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002664 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002665 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002666 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002667
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002668 name = "/ht@0/isa@4";
2669 isa = call_prom("finddevice", 1, 1, ADDR(name));
2670 if (!PHANDLE_VALID(isa)) {
2671 name = "/ht@0/isa@6";
2672 isa = call_prom("finddevice", 1, 1, ADDR(name));
2673 rloc = 0x01003000; /* IO space; PCI device = 6 */
2674 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002675 if (!PHANDLE_VALID(isa))
2676 return;
2677
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002678 if (prom_getproplen(isa, "ranges") != 12)
2679 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002680 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2681 == PROM_ERROR)
2682 return;
2683
2684 if (isa_ranges[0] != 0x1 ||
2685 isa_ranges[1] != 0xf4000000 ||
2686 isa_ranges[2] != 0x00010000)
2687 return;
2688
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002689 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002690
2691 isa_ranges[0] = 0x1;
2692 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002693 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002694 isa_ranges[3] = 0x0;
2695 isa_ranges[4] = 0x0;
2696 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002697 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002698 isa_ranges, sizeof(isa_ranges));
2699}
Harry Ciao8f101a052009-06-17 16:28:00 -07002700
2701#define CPC925_MC_START 0xf8000000
2702#define CPC925_MC_LENGTH 0x1000000
2703/* The values for memory-controller don't have right number of cells */
2704static void __init fixup_device_tree_maple_memory_controller(void)
2705{
2706 phandle mc;
2707 u32 mc_reg[4];
2708 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002709 u32 ac, sc;
2710
2711 mc = call_prom("finddevice", 1, 1, ADDR(name));
2712 if (!PHANDLE_VALID(mc))
2713 return;
2714
2715 if (prom_getproplen(mc, "reg") != 8)
2716 return;
2717
Anton Blanchard5827d412012-11-26 17:40:03 +00002718 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2719 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002720 if ((ac != 2) || (sc != 2))
2721 return;
2722
2723 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2724 return;
2725
2726 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2727 return;
2728
2729 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2730
2731 mc_reg[0] = 0x0;
2732 mc_reg[1] = CPC925_MC_START;
2733 mc_reg[2] = 0x0;
2734 mc_reg[3] = CPC925_MC_LENGTH;
2735 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2736}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002737#else
2738#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002739#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002740#endif
2741
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002742#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002743/*
2744 * Pegasos and BriQ lacks the "ranges" property in the isa node
2745 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002746 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002747 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002748static void __init fixup_device_tree_chrp(void)
2749{
Olaf Heringe4805922007-04-04 18:20:04 +02002750 phandle ph;
2751 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002752 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002753 char *name;
2754 int rc;
2755
2756 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002757 ph = call_prom("finddevice", 1, 1, ADDR(name));
2758 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002759 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002760 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002761 rloc = 0x01003000; /* IO space; PCI device = 6 */
2762 }
Olaf Heringe4805922007-04-04 18:20:04 +02002763 if (PHANDLE_VALID(ph)) {
2764 rc = prom_getproplen(ph, "ranges");
2765 if (rc == 0 || rc == PROM_ERROR) {
2766 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002767
Olaf Heringe4805922007-04-04 18:20:04 +02002768 prop[0] = 0x1;
2769 prop[1] = 0x0;
2770 prop[2] = rloc;
2771 prop[3] = 0x0;
2772 prop[4] = 0x0;
2773 prop[5] = 0x00010000;
2774 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2775 }
2776 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002777
Olaf Heringe4805922007-04-04 18:20:04 +02002778 name = "/pci@80000000/ide@C,1";
2779 ph = call_prom("finddevice", 1, 1, ADDR(name));
2780 if (PHANDLE_VALID(ph)) {
2781 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2782 prop[0] = 14;
2783 prop[1] = 0x0;
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002784 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2785 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2786 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2787 if (rc == sizeof(u32)) {
2788 prop[0] &= ~0x5;
2789 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2790 }
Olaf Heringe4805922007-04-04 18:20:04 +02002791 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002792}
2793#else
2794#define fixup_device_tree_chrp()
2795#endif
2796
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002797#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002798static void __init fixup_device_tree_pmac(void)
2799{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002800 phandle u3, i2c, mpic;
2801 u32 u3_rev;
2802 u32 interrupts[2];
2803 u32 parent;
2804
2805 /* Some G5s have a missing interrupt definition, fix it up here */
2806 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2807 if (!PHANDLE_VALID(u3))
2808 return;
2809 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2810 if (!PHANDLE_VALID(i2c))
2811 return;
2812 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2813 if (!PHANDLE_VALID(mpic))
2814 return;
2815
2816 /* check if proper rev of u3 */
2817 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2818 == PROM_ERROR)
2819 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002820 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002821 return;
2822 /* does it need fixup ? */
2823 if (prom_getproplen(i2c, "interrupts") > 0)
2824 return;
2825
2826 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2827
2828 /* interrupt on this revision of u3 is number 0 and level */
2829 interrupts[0] = 0;
2830 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002831 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2832 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002833 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002834 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2835 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002836}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002837#else
2838#define fixup_device_tree_pmac()
2839#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002840
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002841#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002842/*
2843 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2844 * to talk to the phy. If the phy-handle property is missing, then this
2845 * function is called to add the appropriate nodes and link it to the
2846 * ethernet node.
2847 */
2848static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002849{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002850 u32 node;
2851 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002852 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002853
Grant Likely94d2dde2008-01-24 22:25:32 -07002854 /* Check if /builtin/ethernet exists - bail if it doesn't */
2855 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002856 if (!PHANDLE_VALID(node))
2857 return;
2858
Grant Likely94d2dde2008-01-24 22:25:32 -07002859 /* Check if the phy-handle property exists - bail if it does */
2860 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2861 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002862 return;
2863
Grant Likely94d2dde2008-01-24 22:25:32 -07002864 /*
2865 * At this point the ethernet device doesn't have a phy described.
2866 * Now we need to add the missing phy node and linkage
2867 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002868
Grant Likely94d2dde2008-01-24 22:25:32 -07002869 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002870 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2871 if (!PHANDLE_VALID(node)) {
2872 prom_printf("Adding Ethernet MDIO node\n");
2873 call_prom("interpret", 1, 1,
2874 " s\" /builtin\" find-device"
2875 " new-device"
2876 " 1 encode-int s\" #address-cells\" property"
2877 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002878 " s\" mdio\" device-name"
2879 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002880 " s\" compatible\" property"
2881 " 0xf0003000 0x400 reg"
2882 " 0x2 encode-int"
2883 " 0x5 encode-int encode+"
2884 " 0x3 encode-int encode+"
2885 " s\" interrupts\" property"
2886 " finish-device");
2887 };
2888
Grant Likely94d2dde2008-01-24 22:25:32 -07002889 /* Check for a PHY device node - if missing then create one and
2890 * give it's phandle to the ethernet node */
2891 node = call_prom("finddevice", 1, 1,
2892 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002893 if (!PHANDLE_VALID(node)) {
2894 prom_printf("Adding Ethernet PHY node\n");
2895 call_prom("interpret", 1, 1,
2896 " s\" /builtin/mdio\" find-device"
2897 " new-device"
2898 " s\" ethernet-phy\" device-name"
2899 " 0x10 encode-int s\" reg\" property"
2900 " my-self"
2901 " ihandle>phandle"
2902 " finish-device"
2903 " s\" /builtin/ethernet\" find-device"
2904 " encode-int"
2905 " s\" phy-handle\" property"
2906 " device-end");
2907 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002908}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002909
Grant Likely94d2dde2008-01-24 22:25:32 -07002910static void __init fixup_device_tree_efika(void)
2911{
2912 int sound_irq[3] = { 2, 2, 0 };
2913 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2914 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2915 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2916 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2917 u32 node;
2918 char prop[64];
2919 int rv, len;
2920
2921 /* Check if we're really running on a EFIKA */
2922 node = call_prom("finddevice", 1, 1, ADDR("/"));
2923 if (!PHANDLE_VALID(node))
2924 return;
2925
2926 rv = prom_getprop(node, "model", prop, sizeof(prop));
2927 if (rv == PROM_ERROR)
2928 return;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002929 if (prom_strcmp(prop, "EFIKA5K2"))
Grant Likely94d2dde2008-01-24 22:25:32 -07002930 return;
2931
2932 prom_printf("Applying EFIKA device tree fixups\n");
2933
2934 /* Claiming to be 'chrp' is death */
2935 node = call_prom("finddevice", 1, 1, ADDR("/"));
2936 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002937 if (rv != PROM_ERROR && (prom_strcmp(prop, "chrp") == 0))
Grant Likely94d2dde2008-01-24 22:25:32 -07002938 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2939
David Woodhouse7f4392c2008-04-14 02:52:38 +10002940 /* CODEGEN,description is exposed in /proc/cpuinfo so
2941 fix that too */
2942 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002943 if (rv != PROM_ERROR && (prom_strstr(prop, "CHRP")))
David Woodhouse7f4392c2008-04-14 02:52:38 +10002944 prom_setprop(node, "/", "CODEGEN,description",
2945 "Efika 5200B PowerPC System",
2946 sizeof("Efika 5200B PowerPC System"));
2947
Grant Likely94d2dde2008-01-24 22:25:32 -07002948 /* Fixup bestcomm interrupts property */
2949 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2950 if (PHANDLE_VALID(node)) {
2951 len = prom_getproplen(node, "interrupts");
2952 if (len == 12) {
2953 prom_printf("Fixing bestcomm interrupts property\n");
2954 prom_setprop(node, "/builtin/bestcom", "interrupts",
2955 bcomm_irq, sizeof(bcomm_irq));
2956 }
2957 }
2958
2959 /* Fixup sound interrupts property */
2960 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2961 if (PHANDLE_VALID(node)) {
2962 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2963 if (rv == PROM_ERROR) {
2964 prom_printf("Adding sound interrupts property\n");
2965 prom_setprop(node, "/builtin/sound", "interrupts",
2966 sound_irq, sizeof(sound_irq));
2967 }
2968 }
2969
2970 /* Make sure ethernet phy-handle property exists */
2971 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002972}
2973#else
2974#define fixup_device_tree_efika()
2975#endif
2976
Darren Stevens50246782016-08-31 13:24:40 +01002977#ifdef CONFIG_PPC_PASEMI_NEMO
2978/*
2979 * CFE supplied on Nemo is broken in several ways, biggest
2980 * problem is that it reassigns ISA interrupts to unused mpic ints.
2981 * Add an interrupt-controller property for the io-bridge to use
2982 * and correct the ints so we can attach them to an irq_domain
2983 */
2984static void __init fixup_device_tree_pasemi(void)
2985{
2986 u32 interrupts[2], parent, rval, val = 0;
2987 char *name, *pci_name;
2988 phandle iob, node;
2989
2990 /* Find the root pci node */
2991 name = "/pxp@0,e0000000";
2992 iob = call_prom("finddevice", 1, 1, ADDR(name));
2993 if (!PHANDLE_VALID(iob))
2994 return;
2995
2996 /* check if interrupt-controller node set yet */
2997 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
2998 return;
2999
3000 prom_printf("adding interrupt-controller property for SB600...\n");
3001
3002 prom_setprop(iob, name, "interrupt-controller", &val, 0);
3003
3004 pci_name = "/pxp@0,e0000000/pci@11";
3005 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
3006 parent = ADDR(iob);
3007
3008 for( ; prom_next_node(&node); ) {
3009 /* scan each node for one with an interrupt */
3010 if (!PHANDLE_VALID(node))
3011 continue;
3012
3013 rval = prom_getproplen(node, "interrupts");
3014 if (rval == 0 || rval == PROM_ERROR)
3015 continue;
3016
3017 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
3018 if ((interrupts[0] < 212) || (interrupts[0] > 222))
3019 continue;
3020
3021 /* found a node, update both interrupts and interrupt-parent */
3022 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
3023 interrupts[0] -= 203;
3024 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
3025 interrupts[0] -= 213;
3026 if (interrupts[0] == 221)
3027 interrupts[0] = 14;
3028 if (interrupts[0] == 222)
3029 interrupts[0] = 8;
3030
3031 prom_setprop(node, pci_name, "interrupts", interrupts,
3032 sizeof(interrupts));
3033 prom_setprop(node, pci_name, "interrupt-parent", &parent,
3034 sizeof(parent));
3035 }
Darren Stevens687e16b2016-08-31 13:24:45 +01003036
3037 /*
3038 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
3039 * so that generic isa-bridge code can add the SB600 and its on-board
3040 * peripherals.
3041 */
3042 name = "/pxp@0,e0000000/io-bridge@0";
3043 iob = call_prom("finddevice", 1, 1, ADDR(name));
3044 if (!PHANDLE_VALID(iob))
3045 return;
3046
3047 /* device_type is already set, just change it. */
3048
3049 prom_printf("Changing device_type of SB600 node...\n");
3050
3051 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01003052}
3053#else /* !CONFIG_PPC_PASEMI_NEMO */
3054static inline void fixup_device_tree_pasemi(void) { }
3055#endif
3056
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003057static void __init fixup_device_tree(void)
3058{
3059 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07003060 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10003061 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003062 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003063 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01003064 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003065}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003066
3067static void __init prom_find_boot_cpu(void)
3068{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003069 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003070 ihandle prom_cpu;
3071 phandle cpu_pkg;
3072
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003073 rval = 0;
3074 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10003075 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003076 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003077
3078 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
3079
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00003080 if (!PHANDLE_VALID(cpu_pkg))
3081 return;
3082
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003083 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
3084 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003085
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003086 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003087}
3088
3089static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
3090{
3091#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003092 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003093 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003094
Anton Blanchard5827d412012-11-26 17:40:03 +00003095 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
3096 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003097
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003098 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00003099 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003100 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003101 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00003102 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003103 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003104
Anton Blanchard5827d412012-11-26 17:40:03 +00003105 reserve_mem(prom_initrd_start,
3106 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003107
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003108 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
3109 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003110 }
3111#endif /* CONFIG_BLK_DEV_INITRD */
3112}
3113
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003114#ifdef CONFIG_PPC64
3115#ifdef CONFIG_RELOCATABLE
3116static void reloc_toc(void)
3117{
3118}
3119
3120static void unreloc_toc(void)
3121{
3122}
3123#else
Anton Blanchard16744002013-03-12 01:51:51 +00003124static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003125{
3126 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003127 unsigned long *toc_entry;
3128
3129 /* Get the start of the TOC by using r2 directly. */
3130 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003131
3132 for (i = 0; i < nr_entries; i++) {
3133 *toc_entry = *toc_entry + offset;
3134 toc_entry++;
3135 }
3136}
3137
3138static void reloc_toc(void)
3139{
3140 unsigned long offset = reloc_offset();
3141 unsigned long nr_entries =
3142 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3143
Anton Blanchard16744002013-03-12 01:51:51 +00003144 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003145
3146 mb();
3147}
3148
3149static void unreloc_toc(void)
3150{
3151 unsigned long offset = reloc_offset();
3152 unsigned long nr_entries =
3153 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3154
3155 mb();
3156
Anton Blanchard16744002013-03-12 01:51:51 +00003157 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003158}
3159#endif
3160#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003161
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003162/*
3163 * We enter here early on, when the Open Firmware prom is still
3164 * handling exceptions and the MMU hash table for us.
3165 */
3166
3167unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3168 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003169 unsigned long r6, unsigned long r7,
3170 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003171{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003172 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003173
3174#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003175 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003176 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003177#else
3178 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003179#endif
3180
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003181 /*
3182 * First zero the BSS
3183 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003184 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003185
3186 /*
3187 * Init interface to Open Firmware, get some node references,
3188 * like /chosen
3189 */
3190 prom_init_client_services(pp);
3191
3192 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003193 * See if this OF is old enough that we need to do explicit maps
3194 * and other workarounds
3195 */
3196 prom_find_mmu();
3197
3198 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003199 * Init prom stdout device
3200 */
3201 prom_init_stdout();
3202
Anton Blanchard5827d412012-11-26 17:40:03 +00003203 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003204
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003205 /*
3206 * Get default machine type. At this point, we do not differentiate
3207 * between pSeries SMP and pSeries LPAR
3208 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003209 of_platform = prom_find_machine_type();
3210 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003211
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003212#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003213 /* Bail if this is a kdump kernel. */
3214 if (PHYSICAL_START > 0)
3215 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003216#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003217
3218 /*
3219 * Check for an initrd
3220 */
3221 prom_check_initrd(r3, r4);
3222
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003223 /*
3224 * Do early parsing of command line
3225 */
3226 early_cmdline_parse();
3227
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003228#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003229 /*
3230 * On pSeries, inform the firmware about our capabilities
3231 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003232 if (of_platform == PLATFORM_PSERIES ||
3233 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003234 prom_send_capabilities();
3235#endif
3236
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003237 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003238 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003239 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003240 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003241 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003242
3243 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003244 * Initialize memory management within prom_init
3245 */
3246 prom_init_mem();
3247
3248 /*
3249 * Determine which cpu is actually running right _now_
3250 */
3251 prom_find_boot_cpu();
3252
3253 /*
3254 * Initialize display devices
3255 */
3256 prom_check_displays();
3257
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003258#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003259 /*
3260 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3261 * that uses the allocator, we need to make sure we get the top of memory
3262 * available for us here...
3263 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003264 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003265 prom_initialize_tce_table();
3266#endif
3267
3268 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003269 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3270 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003271 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003272 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003273 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003274
Ashley Lai4a727422012-08-14 18:34:57 -05003275#ifdef CONFIG_PPC64
3276 /* instantiate sml */
3277 prom_instantiate_sml();
3278#endif
3279
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003280 /*
3281 * On non-powermacs, put all CPUs in spin-loops.
3282 *
3283 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003284 *
3285 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003286 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003287 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003288 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003289
3290 /*
3291 * Fill in some infos for use by the kernel later on
3292 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003293 if (prom_memory_limit) {
3294 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003295 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003296 &val, sizeof(val));
3297 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003298#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003299 if (prom_iommu_off)
3300 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003301 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003302
Anton Blanchard5827d412012-11-26 17:40:03 +00003303 if (prom_iommu_force_on)
3304 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003305 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003306
Anton Blanchard5827d412012-11-26 17:40:03 +00003307 if (prom_tce_alloc_start) {
3308 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3309 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003310 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003311 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3312 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003313 sizeof(prom_tce_alloc_end));
3314 }
3315#endif
3316
3317 /*
3318 * Fixup any known bugs in the device-tree
3319 */
3320 fixup_device_tree();
3321
3322 /*
3323 * Now finally create the flattened device-tree
3324 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003325 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003326 flatten_device_tree();
3327
Paul Mackerras3825ac02005-11-08 22:48:08 +11003328 /*
3329 * in case stdin is USB and still active on IBM machines...
3330 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003331 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003332 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003333 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003334 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003335
3336 /*
3337 * Call OF "quiesce" method to shut down pending DMA's from
3338 * devices etc...
3339 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003340 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003341 call_prom("quiesce", 0, 0);
3342
3343 /*
3344 * And finally, call the kernel passing it the flattened device
3345 * tree and NULL as r5, thus triggering the new entry point which
3346 * is common to us and kexec
3347 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003348 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003349
3350 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003351 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3352 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003353
3354#ifdef CONFIG_PPC32
3355 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003356#else
3357 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003358#endif
3359
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003360 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003361
3362 return 0;
3363}