blob: bf3966d125650509388d966f26a66d0ca61d6ffe [file] [log] [blame]
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001/*
2 * Procedures for interfacing to Open Firmware.
3 *
4 * Paul Mackerras August 1996.
5 * Copyright (C) 1996-2005 Paul Mackerras.
6 *
7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
8 * {engebret|bergner}@us.ibm.com
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#undef DEBUG_PROM
17
18#include <stdarg.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100019#include <linux/kernel.h>
20#include <linux/string.h>
21#include <linux/init.h>
22#include <linux/threads.h>
23#include <linux/spinlock.h>
24#include <linux/types.h>
25#include <linux/pci.h>
26#include <linux/proc_fs.h>
27#include <linux/stringify.h>
28#include <linux/delay.h>
29#include <linux/initrd.h>
30#include <linux/bitops.h>
31#include <asm/prom.h>
32#include <asm/rtas.h>
33#include <asm/page.h>
34#include <asm/processor.h>
35#include <asm/irq.h>
36#include <asm/io.h>
37#include <asm/smp.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100038#include <asm/mmu.h>
39#include <asm/pgtable.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100040#include <asm/iommu.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100041#include <asm/btext.h>
42#include <asm/sections.h>
43#include <asm/machdep.h>
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +000044#include <asm/opal.h>
Daniel Axtens0545d542016-09-06 15:32:43 +100045#include <asm/asm-prototypes.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100046
Paul Mackerras9b6b5632005-10-06 12:06:20 +100047#include <linux/linux_logo.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100048
49/*
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
88int of_workarounds;
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
103#define prom_debug(x...)
104#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 */
149static struct prom_t __initdata prom;
150
151static unsigned long prom_entry __initdata;
152
153#define PROM_SCRATCH_SIZE 256
154
155static char __initdata of_stdout_device[256];
156static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
157
158static unsigned long __initdata dt_header_start;
159static unsigned long __initdata dt_struct_start, dt_struct_end;
160static unsigned long __initdata dt_string_start, dt_string_end;
161
162static unsigned long __initdata prom_initrd_start, prom_initrd_end;
163
164#ifdef CONFIG_PPC64
Jeremy Kerr165785e2006-11-11 17:25:18 +1100165static int __initdata prom_iommu_force_on;
166static int __initdata prom_iommu_off;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000167static unsigned long __initdata prom_tce_alloc_start;
168static unsigned long __initdata prom_tce_alloc_end;
169#endif
170
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100171/* Platforms codes are now obsolete in the kernel. Now only used within this
172 * file and ultimately gone too. Feel free to change them if you need, they
173 * are not shared with anything outside of this file anymore
174 */
175#define PLATFORM_PSERIES 0x0100
176#define PLATFORM_PSERIES_LPAR 0x0101
177#define PLATFORM_LPAR 0x0001
178#define PLATFORM_POWERMAC 0x0400
179#define PLATFORM_GENERIC 0x0500
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000180#define PLATFORM_OPAL 0x0600
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100181
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000182static int __initdata of_platform;
183
184static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
185
Benjamin Krillcf687872009-07-27 22:02:39 +0000186static unsigned long __initdata prom_memory_limit;
187
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000188static unsigned long __initdata alloc_top;
189static unsigned long __initdata alloc_top_high;
190static unsigned long __initdata alloc_bottom;
191static unsigned long __initdata rmo_top;
192static unsigned long __initdata ram_top;
193
194static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
195static int __initdata mem_reserve_cnt;
196
197static cell_t __initdata regbuf[1024];
198
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000199static bool rtas_has_query_cpu_stopped;
200
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000201
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000202/*
203 * Error results ... some OF calls will return "-1" on error, some
204 * will return 0, some will return either. To simplify, here are
205 * macros to use with any ihandle or phandle return value to check if
206 * it is valid
207 */
208
209#define PROM_ERROR (-1u)
210#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
211#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
212
213
214/* This is the one and *ONLY* place where we actually call open
215 * firmware.
216 */
217
218static int __init call_prom(const char *service, int nargs, int nret, ...)
219{
220 int i;
221 struct prom_args args;
222 va_list list;
223
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000224 args.service = cpu_to_be32(ADDR(service));
225 args.nargs = cpu_to_be32(nargs);
226 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000227
228 va_start(list, nret);
229 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000230 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000231 va_end(list);
232
233 for (i = 0; i < nret; i++)
234 args.args[nargs+i] = 0;
235
Anton Blanchard5827d412012-11-26 17:40:03 +0000236 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000237 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000238
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000239 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000240}
241
242static int __init call_prom_ret(const char *service, int nargs, int nret,
243 prom_arg_t *rets, ...)
244{
245 int i;
246 struct prom_args args;
247 va_list list;
248
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000249 args.service = cpu_to_be32(ADDR(service));
250 args.nargs = cpu_to_be32(nargs);
251 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000252
253 va_start(list, rets);
254 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000255 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000256 va_end(list);
257
258 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100259 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000260
Anton Blanchard5827d412012-11-26 17:40:03 +0000261 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000262 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000263
264 if (rets != NULL)
265 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000266 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000267
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000268 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000269}
270
271
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000272static void __init prom_print(const char *msg)
273{
274 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000275
Anton Blanchard5827d412012-11-26 17:40:03 +0000276 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000277 return;
278
279 for (p = msg; *p != 0; p = q) {
280 for (q = p; *q != 0 && *q != '\n'; ++q)
281 ;
282 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000283 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000284 if (*q == 0)
285 break;
286 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000287 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000288 }
289}
290
291
292static void __init prom_print_hex(unsigned long val)
293{
294 int i, nibbles = sizeof(val)*2;
295 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000296
297 for (i = nibbles-1; i >= 0; i--) {
298 buf[i] = (val & 0xf) + '0';
299 if (buf[i] > '9')
300 buf[i] += ('a'-'0'-10);
301 val >>= 4;
302 }
303 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000304 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000305}
306
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000307/* max number of decimal digits in an unsigned long */
308#define UL_DIGITS 21
309static void __init prom_print_dec(unsigned long val)
310{
311 int i, size;
312 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000313
314 for (i = UL_DIGITS-1; i >= 0; i--) {
315 buf[i] = (val % 10) + '0';
316 val = val/10;
317 if (val == 0)
318 break;
319 }
320 /* shift stuff down */
321 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000322 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000323}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000324
325static void __init prom_printf(const char *format, ...)
326{
327 const char *p, *q, *s;
328 va_list args;
329 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000330 long vs;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000331
332 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000333 for (p = format; *p != 0; p = q) {
334 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
335 ;
336 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000337 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000338 if (*q == 0)
339 break;
340 if (*q == '\n') {
341 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000342 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000343 ADDR("\r\n"), 2);
344 continue;
345 }
346 ++q;
347 if (*q == 0)
348 break;
349 switch (*q) {
350 case 's':
351 ++q;
352 s = va_arg(args, const char *);
353 prom_print(s);
354 break;
355 case 'x':
356 ++q;
357 v = va_arg(args, unsigned long);
358 prom_print_hex(v);
359 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000360 case 'd':
361 ++q;
362 vs = va_arg(args, int);
363 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000364 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000365 vs = -vs;
366 }
367 prom_print_dec(vs);
368 break;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000369 case 'l':
370 ++q;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000371 if (*q == 0)
372 break;
373 else if (*q == 'x') {
374 ++q;
375 v = va_arg(args, unsigned long);
376 prom_print_hex(v);
377 } else if (*q == 'u') { /* '%lu' */
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000378 ++q;
379 v = va_arg(args, unsigned long);
380 prom_print_dec(v);
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000381 } else if (*q == 'd') { /* %ld */
382 ++q;
383 vs = va_arg(args, long);
384 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000385 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000386 vs = -vs;
387 }
388 prom_print_dec(vs);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000389 }
390 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000391 }
392 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100393 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000394}
395
396
Paul Mackerrasa575b802005-10-23 17:23:21 +1000397static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
398 unsigned long align)
399{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000400
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100401 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
402 /*
403 * Old OF requires we claim physical and virtual separately
404 * and then map explicitly (assuming virtual mode)
405 */
406 int ret;
407 prom_arg_t result;
408
409 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000410 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100411 align, size, virt);
412 if (ret != 0 || result == -1)
413 return -1;
414 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000415 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100416 align, size, virt);
417 if (ret != 0) {
418 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000419 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100420 return -1;
421 }
422 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000423 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000424 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100425 return virt;
426 }
427 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
428 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000429}
430
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000431static void __init __attribute__((noreturn)) prom_panic(const char *reason)
432{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000433 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100434 /* Do not call exit because it clears the screen on pmac
435 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000436 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100437 asm("trap\n");
438
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000439 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000440 call_prom("exit", 0, 0);
441
442 for (;;) /* should never get here */
443 ;
444}
445
446
447static int __init prom_next_node(phandle *nodep)
448{
449 phandle node;
450
451 if ((node = *nodep) != 0
452 && (*nodep = call_prom("child", 1, 1, node)) != 0)
453 return 1;
454 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
455 return 1;
456 for (;;) {
457 if ((node = call_prom("parent", 1, 1, node)) == 0)
458 return 0;
459 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
460 return 1;
461 }
462}
463
Tobias Klauser60d862e2016-11-17 17:20:24 +0100464static inline int prom_getprop(phandle node, const char *pname,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000465 void *value, size_t valuelen)
466{
467 return call_prom("getprop", 4, 1, node, ADDR(pname),
468 (u32)(unsigned long) value, (u32) valuelen);
469}
470
Tobias Klauser60d862e2016-11-17 17:20:24 +0100471static inline int prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000472{
473 return call_prom("getproplen", 2, 1, node, ADDR(pname));
474}
475
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100476static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000477{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100478 char *p = *str;
479
480 while (*q)
481 *p++ = *q++;
482 *p++ = ' ';
483 *str = p;
484}
485
486static char *tohex(unsigned int x)
487{
488 static char digits[] = "0123456789abcdef";
489 static char result[9];
490 int i;
491
492 result[8] = 0;
493 i = 8;
494 do {
495 --i;
496 result[i] = digits[x & 0xf];
497 x >>= 4;
498 } while (x != 0 && i > 0);
499 return &result[i];
500}
501
502static int __init prom_setprop(phandle node, const char *nodename,
503 const char *pname, void *value, size_t valuelen)
504{
505 char cmd[256], *p;
506
507 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
508 return call_prom("setprop", 4, 1, node, ADDR(pname),
509 (u32)(unsigned long) value, (u32) valuelen);
510
511 /* gah... setprop doesn't work on longtrail, have to use interpret */
512 p = cmd;
513 add_string(&p, "dev");
514 add_string(&p, nodename);
515 add_string(&p, tohex((u32)(unsigned long) value));
516 add_string(&p, tohex(valuelen));
517 add_string(&p, tohex(ADDR(pname)));
Anton Blanchard5827d412012-11-26 17:40:03 +0000518 add_string(&p, tohex(strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100519 add_string(&p, "property");
520 *p = 0;
521 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000522}
523
Anton Blanchard5827d412012-11-26 17:40:03 +0000524/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000525#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
526 || ('a' <= (c) && (c) <= 'f') \
527 || ('A' <= (c) && (c) <= 'F'))
528
529#define isdigit(c) ('0' <= (c) && (c) <= '9')
530#define islower(c) ('a' <= (c) && (c) <= 'z')
531#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
532
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000533static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000534{
535 unsigned long result = 0, base = 10, value;
536
537 if (*cp == '0') {
538 base = 8;
539 cp++;
540 if (toupper(*cp) == 'X') {
541 cp++;
542 base = 16;
543 }
544 }
545
546 while (isxdigit(*cp) &&
547 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
548 result = result * base + value;
549 cp++;
550 }
551
552 if (endp)
553 *endp = cp;
554
555 return result;
556}
557
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000558static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000559{
560 unsigned long ret = prom_strtoul(ptr, retptr);
561 int shift = 0;
562
563 /*
564 * We can't use a switch here because GCC *may* generate a
565 * jump table which won't work, because we're not running at
566 * the address we're linked at.
567 */
568 if ('G' == **retptr || 'g' == **retptr)
569 shift = 30;
570
571 if ('M' == **retptr || 'm' == **retptr)
572 shift = 20;
573
574 if ('K' == **retptr || 'k' == **retptr)
575 shift = 10;
576
577 if (shift) {
578 ret <<= shift;
579 (*retptr)++;
580 }
581
582 return ret;
583}
584
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000585/*
586 * Early parsing of the command line passed to the kernel, used for
587 * "mem=x" and the options that affect the iommu
588 */
589static void __init early_cmdline_parse(void)
590{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100591 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000592
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100593 char *p;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000594 int l = 0;
595
Anton Blanchard5827d412012-11-26 17:40:03 +0000596 prom_cmd_line[0] = 0;
597 p = prom_cmd_line;
598 if ((long)prom.chosen > 0)
599 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000600#ifdef CONFIG_CMDLINE
Amos Waterland0e4aa9c2006-06-12 23:45:02 -0400601 if (l <= 0 || p[0] == '\0') /* dbl check */
Anton Blanchard5827d412012-11-26 17:40:03 +0000602 strlcpy(prom_cmd_line,
603 CONFIG_CMDLINE, sizeof(prom_cmd_line));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000604#endif /* CONFIG_CMDLINE */
Anton Blanchard5827d412012-11-26 17:40:03 +0000605 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000606
607#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +0000608 opt = strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000609 if (opt) {
610 prom_printf("iommu opt is: %s\n", opt);
611 opt += 6;
612 while (*opt && *opt == ' ')
613 opt++;
Anton Blanchard5827d412012-11-26 17:40:03 +0000614 if (!strncmp(opt, "off", 3))
615 prom_iommu_off = 1;
616 else if (!strncmp(opt, "force", 5))
617 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000618 }
619#endif
Anton Blanchard5827d412012-11-26 17:40:03 +0000620 opt = strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000621 if (opt) {
622 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000623 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000624#ifdef CONFIG_PPC64
625 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000626 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000627#endif
628 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000629}
630
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000631#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000632/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000633 * The architecture vector has an array of PVR mask/value pairs,
634 * followed by # option vectors - 1, followed by the option vectors.
635 *
636 * See prom.h for the definition of the bits specified in the
637 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000638 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000639
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000640/* Firmware expects the value to be n - 1, where n is the # of vectors */
641#define NUM_VECTORS(n) ((n) - 1)
642
643/*
644 * Firmware expects 1 + n - 2, where n is the length of the option vector in
645 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
646 */
647#define VECTOR_LENGTH(n) (1 + (n) - 2)
648
Michael Ellermand03d1d62016-11-18 23:15:41 +1100649struct option_vector1 {
650 u8 byte1;
651 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100652 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100653} __packed;
654
655struct option_vector2 {
656 u8 byte1;
657 __be16 reserved;
658 __be32 real_base;
659 __be32 real_size;
660 __be32 virt_base;
661 __be32 virt_size;
662 __be32 load_base;
663 __be32 min_rma;
664 __be32 min_load;
665 u8 min_rma_percent;
666 u8 max_pft_size;
667} __packed;
668
669struct option_vector3 {
670 u8 byte1;
671 u8 byte2;
672} __packed;
673
674struct option_vector4 {
675 u8 byte1;
676 u8 min_vp_cap;
677} __packed;
678
679struct option_vector5 {
680 u8 byte1;
681 u8 byte2;
682 u8 byte3;
683 u8 cmo;
684 u8 associativity;
685 u8 bin_opts;
686 u8 micro_checkpoint;
687 u8 reserved0;
688 __be32 max_cpus;
689 __be16 papr_level;
690 __be16 reserved1;
691 u8 platform_facilities;
692 u8 reserved2;
693 __be16 reserved3;
694 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100695 u8 byte22;
696 u8 intarch;
697 u8 mmu;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100698} __packed;
699
700struct option_vector6 {
701 u8 reserved;
702 u8 secondary_pteg;
703 u8 os_name;
704} __packed;
705
Michael Ellerman76ffb572016-11-18 23:15:42 +1100706struct ibm_arch_vec {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100707 struct { u32 mask, val; } pvrs[12];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100708
709 u8 num_vectors;
710
711 u8 vec1_len;
712 struct option_vector1 vec1;
713
714 u8 vec2_len;
715 struct option_vector2 vec2;
716
717 u8 vec3_len;
718 struct option_vector3 vec3;
719
720 u8 vec4_len;
721 struct option_vector4 vec4;
722
723 u8 vec5_len;
724 struct option_vector5 vec5;
725
726 u8 vec6_len;
727 struct option_vector6 vec6;
728} __packed;
729
730struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
731 .pvrs = {
732 {
733 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
734 .val = cpu_to_be32(0x003a0000),
735 },
736 {
737 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
738 .val = cpu_to_be32(0x003e0000),
739 },
740 {
741 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
742 .val = cpu_to_be32(0x003f0000),
743 },
744 {
745 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
746 .val = cpu_to_be32(0x004b0000),
747 },
748 {
749 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
750 .val = cpu_to_be32(0x004c0000),
751 },
752 {
753 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
754 .val = cpu_to_be32(0x004d0000),
755 },
756 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100757 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
758 .val = cpu_to_be32(0x004e0000),
759 },
760 {
761 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
762 .val = cpu_to_be32(0x0f000005),
763 },
764 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100765 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
766 .val = cpu_to_be32(0x0f000004),
767 },
768 {
769 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
770 .val = cpu_to_be32(0x0f000003),
771 },
772 {
773 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
774 .val = cpu_to_be32(0x0f000002),
775 },
776 {
777 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
778 .val = cpu_to_be32(0x0f000001),
779 },
780 },
781
782 .num_vectors = NUM_VECTORS(6),
783
784 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
785 .vec1 = {
786 .byte1 = 0,
787 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
788 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100789 .arch_versions3 = OV1_PPC_3_00,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100790 },
791
792 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
793 /* option vector 2: Open Firmware options supported */
794 .vec2 = {
795 .byte1 = OV2_REAL_MODE,
796 .reserved = 0,
797 .real_base = cpu_to_be32(0xffffffff),
798 .real_size = cpu_to_be32(0xffffffff),
799 .virt_base = cpu_to_be32(0xffffffff),
800 .virt_size = cpu_to_be32(0xffffffff),
801 .load_base = cpu_to_be32(0xffffffff),
802 .min_rma = cpu_to_be32(256), /* 256MB min RMA */
803 .min_load = cpu_to_be32(0xffffffff), /* full client load */
804 .min_rma_percent = 0, /* min RMA percentage of total RAM */
805 .max_pft_size = 48, /* max log_2(hash table size) */
806 },
807
808 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
809 /* option vector 3: processor options supported */
810 .vec3 = {
811 .byte1 = 0, /* don't ignore, don't halt */
812 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
813 },
814
815 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
816 /* option vector 4: IBM PAPR implementation */
817 .vec4 = {
818 .byte1 = 0, /* don't halt */
819 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
820 },
821
822 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
823 /* option vector 5: PAPR/OF options */
824 .vec5 = {
825 .byte1 = 0, /* don't ignore, don't halt */
826 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
827 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
828#ifdef CONFIG_PCI_MSI
829 /* PCIe/MSI support. Without MSI full PCIe is not supported */
830 OV5_FEAT(OV5_MSI),
831#else
832 0,
833#endif
834 .byte3 = 0,
835 .cmo =
836#ifdef CONFIG_PPC_SMLPAR
837 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
838#else
839 0,
840#endif
841 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -0600842 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +1100843 .micro_checkpoint = 0,
844 .reserved0 = 0,
845 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
846 .papr_level = 0,
847 .reserved1 = 0,
848 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
849 .reserved2 = 0,
850 .reserved3 = 0,
851 .subprocessors = 1,
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100852 .intarch = 0,
853 .mmu = OV5_FEAT(OV5_MMU_RADIX_300) | OV5_FEAT(OV5_MMU_HASH_300) |
854 OV5_FEAT(OV5_MMU_PROC_TBL) | OV5_FEAT(OV5_MMU_GTSE),
Michael Ellerman76ffb572016-11-18 23:15:42 +1100855 },
856
857 /* option vector 6: IBM PAPR hints */
858 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
859 .vec6 = {
860 .reserved = 0,
861 .secondary_pteg = 0,
862 .os_name = OV6_LINUX,
863 },
864};
865
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000866/* Old method - ELF header with PT_NOTE sections only works on BE */
867#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000868static struct fake_elf {
869 Elf32_Ehdr elfhdr;
870 Elf32_Phdr phdr[2];
871 struct chrpnote {
872 u32 namesz;
873 u32 descsz;
874 u32 type;
875 char name[8]; /* "PowerPC" */
876 struct chrpdesc {
877 u32 real_mode;
878 u32 real_base;
879 u32 real_size;
880 u32 virt_base;
881 u32 virt_size;
882 u32 load_base;
883 } chrpdesc;
884 } chrpnote;
885 struct rpanote {
886 u32 namesz;
887 u32 descsz;
888 u32 type;
889 char name[24]; /* "IBM,RPA-Client-Config" */
890 struct rpadesc {
891 u32 lpar_affinity;
892 u32 min_rmo_size;
893 u32 min_rmo_percent;
894 u32 max_pft_size;
895 u32 splpar;
896 u32 min_load;
897 u32 new_mem_def;
898 u32 ignore_me;
899 } rpadesc;
900 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100901} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000902 .elfhdr = {
903 .e_ident = { 0x7f, 'E', 'L', 'F',
904 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
905 .e_type = ET_EXEC, /* yeah right */
906 .e_machine = EM_PPC,
907 .e_version = EV_CURRENT,
908 .e_phoff = offsetof(struct fake_elf, phdr),
909 .e_phentsize = sizeof(Elf32_Phdr),
910 .e_phnum = 2
911 },
912 .phdr = {
913 [0] = {
914 .p_type = PT_NOTE,
915 .p_offset = offsetof(struct fake_elf, chrpnote),
916 .p_filesz = sizeof(struct chrpnote)
917 }, [1] = {
918 .p_type = PT_NOTE,
919 .p_offset = offsetof(struct fake_elf, rpanote),
920 .p_filesz = sizeof(struct rpanote)
921 }
922 },
923 .chrpnote = {
924 .namesz = sizeof("PowerPC"),
925 .descsz = sizeof(struct chrpdesc),
926 .type = 0x1275,
927 .name = "PowerPC",
928 .chrpdesc = {
929 .real_mode = ~0U, /* ~0 means "don't care" */
930 .real_base = ~0U,
931 .real_size = ~0U,
932 .virt_base = ~0U,
933 .virt_size = ~0U,
934 .load_base = ~0U
935 },
936 },
937 .rpanote = {
938 .namesz = sizeof("IBM,RPA-Client-Config"),
939 .descsz = sizeof(struct rpadesc),
940 .type = 0x12759999,
941 .name = "IBM,RPA-Client-Config",
942 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +1100943 .lpar_affinity = 0,
944 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000945 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +1100946 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000947 .splpar = 1,
948 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +1100949 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000950 }
951 }
952};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000953#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000954
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100955static int __init prom_count_smt_threads(void)
956{
957 phandle node;
958 char type[64];
959 unsigned int plen;
960
961 /* Pick up th first CPU node we can find */
962 for (node = 0; prom_next_node(&node); ) {
963 type[0] = 0;
964 prom_getprop(node, "device_type", type, sizeof(type));
965
Anton Blanchard5827d412012-11-26 17:40:03 +0000966 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100967 continue;
968 /*
969 * There is an entry for each smt thread, each entry being
970 * 4 bytes long. All cpus should have the same number of
971 * smt threads, so return after finding the first.
972 */
973 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
974 if (plen == PROM_ERROR)
975 break;
976 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000977 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100978
979 /* Sanity check */
980 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000981 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100982 (unsigned long)plen);
983 return 1;
984 }
985 return plen;
986 }
987 prom_debug("No threads found, assuming 1 per core\n");
988
989 return 1;
990
991}
992
993
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000994static void __init prom_send_capabilities(void)
995{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000996 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000997 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200998 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000999
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001000 root = call_prom("open", 1, 1, ADDR("/"));
1001 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001002 /* We need to tell the FW about the number of cores we support.
1003 *
1004 * To do that, we count the number of threads on the first core
1005 * (we assume this is the same for all cores) and use it to
1006 * divide NR_CPUS.
1007 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001008
Michael Ellerman76ffb572016-11-18 23:15:42 +11001009 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
1010 prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
1011 cores, NR_CPUS);
1012
1013 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001014
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001015 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001016 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001017 if (call_prom_ret("call-method", 3, 2, &ret,
1018 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001019 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001020 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001021 /* the call exists... */
1022 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001023 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001024 "-support call FAILED!\n");
1025 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001026 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001027 return;
1028 }
1029 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001030 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001031 }
1032
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001033#ifdef __BIG_ENDIAN__
1034 {
1035 ihandle elfloader;
1036
1037 /* no ibm,client-architecture-support call, try the old way */
1038 elfloader = call_prom("open", 1, 1,
1039 ADDR("/packages/elf-loader"));
1040 if (elfloader == 0) {
1041 prom_printf("couldn't open /packages/elf-loader\n");
1042 return;
1043 }
1044 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1045 elfloader, ADDR(&fake_elf));
1046 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001047 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001048#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001049}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001050#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001051
1052/*
1053 * Memory allocation strategy... our layout is normally:
1054 *
1055 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1056 * rare cases, initrd might end up being before the kernel though.
1057 * We assume this won't override the final kernel at 0, we have no
1058 * provision to handle that in this version, but it should hopefully
1059 * never happen.
1060 *
1061 * alloc_top is set to the top of RMO, eventually shrink down if the
1062 * TCEs overlap
1063 *
1064 * alloc_bottom is set to the top of kernel/initrd
1065 *
1066 * from there, allocations are done this way : rtas is allocated
1067 * topmost, and the device-tree is allocated from the bottom. We try
1068 * to grow the device-tree allocation as we progress. If we can't,
1069 * then we fail, we don't currently have a facility to restart
1070 * elsewhere, but that shouldn't be necessary.
1071 *
1072 * Note that calls to reserve_mem have to be done explicitly, memory
1073 * allocated with either alloc_up or alloc_down isn't automatically
1074 * reserved.
1075 */
1076
1077
1078/*
1079 * Allocates memory in the RMO upward from the kernel/initrd
1080 *
1081 * When align is 0, this is a special case, it means to allocate in place
1082 * at the current location of alloc_bottom or fail (that is basically
1083 * extending the previous allocation). Used for the device-tree flattening
1084 */
1085static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1086{
Anton Blanchard5827d412012-11-26 17:40:03 +00001087 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001088 unsigned long addr = 0;
1089
Paul Mackerrasc49888202005-10-26 21:52:53 +10001090 if (align)
1091 base = _ALIGN_UP(base, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001092 prom_debug("alloc_up(%x, %x)\n", size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001093 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001094 prom_panic("alloc_up() called with mem not initialized\n");
1095
1096 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +00001097 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001098 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001099 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001100
Anton Blanchard5827d412012-11-26 17:40:03 +00001101 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001102 base = _ALIGN_UP(base + 0x100000, align)) {
1103 prom_debug(" trying: 0x%x\n\r", base);
1104 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001105 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001106 break;
1107 addr = 0;
1108 if (align == 0)
1109 break;
1110 }
1111 if (addr == 0)
1112 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001113 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001114
1115 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001116 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1117 prom_debug(" alloc_top : %x\n", alloc_top);
1118 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1119 prom_debug(" rmo_top : %x\n", rmo_top);
1120 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001121
1122 return addr;
1123}
1124
1125/*
1126 * Allocates memory downward, either from top of RMO, or if highmem
1127 * is set, from the top of RAM. Note that this one doesn't handle
1128 * failures. It does claim memory if highmem is not set.
1129 */
1130static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1131 int highmem)
1132{
1133 unsigned long base, addr = 0;
1134
1135 prom_debug("alloc_down(%x, %x, %s)\n", size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001136 highmem ? "(high)" : "(low)");
1137 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001138 prom_panic("alloc_down() called with mem not initialized\n");
1139
1140 if (highmem) {
1141 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001142 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1143 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001144 return 0;
1145 /* Will we bump into the RMO ? If yes, check out that we
1146 * didn't overlap existing allocations there, if we did,
1147 * we are dead, we must be the first in town !
1148 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001149 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001150 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001151 if (alloc_top == rmo_top)
1152 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001153 else
1154 return 0;
1155 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001156 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001157 goto bail;
1158 }
1159
Anton Blanchard5827d412012-11-26 17:40:03 +00001160 base = _ALIGN_DOWN(alloc_top - size, align);
1161 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001162 base = _ALIGN_DOWN(base - 0x100000, align)) {
1163 prom_debug(" trying: 0x%x\n\r", base);
1164 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001165 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001166 break;
1167 addr = 0;
1168 }
1169 if (addr == 0)
1170 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001171 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001172
1173 bail:
1174 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001175 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1176 prom_debug(" alloc_top : %x\n", alloc_top);
1177 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1178 prom_debug(" rmo_top : %x\n", rmo_top);
1179 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001180
1181 return addr;
1182}
1183
1184/*
1185 * Parse a "reg" cell
1186 */
1187static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1188{
1189 cell_t *p = *cellp;
1190 unsigned long r = 0;
1191
1192 /* Ignore more than 2 cells */
1193 while (s > sizeof(unsigned long) / 4) {
1194 p++;
1195 s--;
1196 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001197 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001198#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001199 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001200 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001201 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001202 }
1203#endif
1204 *cellp = p;
1205 return r;
1206}
1207
1208/*
1209 * Very dumb function for adding to the memory reserve list, but
1210 * we don't need anything smarter at this point
1211 *
1212 * XXX Eventually check for collisions. They should NEVER happen.
1213 * If problems seem to show up, it would be a good start to track
1214 * them down.
1215 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001216static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001217{
Kumar Galacbbcf342006-01-11 17:57:13 -06001218 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001219 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001220
1221 if (size == 0)
1222 return;
1223
1224 /* We need to always keep one empty entry so that we
1225 * have our terminator with "size" set to 0 since we are
1226 * dumb and just copy this entire array to the boot params
1227 */
1228 base = _ALIGN_DOWN(base, PAGE_SIZE);
1229 top = _ALIGN_UP(top, PAGE_SIZE);
1230 size = top - base;
1231
1232 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1233 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001234 mem_reserve_map[cnt].base = cpu_to_be64(base);
1235 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001236 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001237}
1238
1239/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001240 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001241 * obtain that way the top of memory and RMO to setup out local allocator
1242 */
1243static void __init prom_init_mem(void)
1244{
1245 phandle node;
1246 char *path, type[64];
1247 unsigned int plen;
1248 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001249 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001250 u32 rac, rsc;
1251
1252 /*
1253 * We iterate the memory nodes to find
1254 * 1) top of RMO (first node)
1255 * 2) top of memory
1256 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001257 val = cpu_to_be32(2);
1258 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1259 rac = be32_to_cpu(val);
1260 val = cpu_to_be32(1);
1261 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1262 rsc = be32_to_cpu(val);
1263 prom_debug("root_addr_cells: %x\n", rac);
1264 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001265
1266 prom_debug("scanning memory:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001267 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001268
1269 for (node = 0; prom_next_node(&node); ) {
1270 type[0] = 0;
1271 prom_getprop(node, "device_type", type, sizeof(type));
1272
Paul Mackerrasc49888202005-10-26 21:52:53 +10001273 if (type[0] == 0) {
1274 /*
1275 * CHRP Longtrail machines have no device_type
1276 * on the memory node, so check the name instead...
1277 */
1278 prom_getprop(node, "name", type, sizeof(type));
1279 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001280 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001281 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001282
Anton Blanchard5827d412012-11-26 17:40:03 +00001283 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001284 if (plen > sizeof(regbuf)) {
1285 prom_printf("memory node too large for buffer !\n");
1286 plen = sizeof(regbuf);
1287 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001288 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001289 endp = p + (plen / sizeof(cell_t));
1290
1291#ifdef DEBUG_PROM
1292 memset(path, 0, PROM_SCRATCH_SIZE);
1293 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1294 prom_debug(" node %s :\n", path);
1295#endif /* DEBUG_PROM */
1296
1297 while ((endp - p) >= (rac + rsc)) {
1298 unsigned long base, size;
1299
1300 base = prom_next_cell(rac, &p);
1301 size = prom_next_cell(rsc, &p);
1302
1303 if (size == 0)
1304 continue;
1305 prom_debug(" %x %x\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001306 if (base == 0 && (of_platform & PLATFORM_LPAR))
1307 rmo_top = size;
1308 if ((base + size) > ram_top)
1309 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001310 }
1311 }
1312
Anton Blanchard5827d412012-11-26 17:40:03 +00001313 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001314
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001315 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001316 * If prom_memory_limit is set we reduce the upper limits *except* for
1317 * alloc_top_high. This must be the real top of RAM so we can put
1318 * TCE's up there.
1319 */
1320
Anton Blanchard5827d412012-11-26 17:40:03 +00001321 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001322
Anton Blanchard5827d412012-11-26 17:40:03 +00001323 if (prom_memory_limit) {
1324 if (prom_memory_limit <= alloc_bottom) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001325 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001326 prom_memory_limit);
1327 prom_memory_limit = 0;
1328 } else if (prom_memory_limit >= ram_top) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001329 prom_printf("Ignoring mem=%x >= ram_top.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001330 prom_memory_limit);
1331 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001332 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001333 ram_top = prom_memory_limit;
1334 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001335 }
1336 }
1337
1338 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001339 * Setup our top alloc point, that is top of RMO or top of
1340 * segment 0 when running non-LPAR.
1341 * Some RS64 machines have buggy firmware where claims up at
1342 * 1GB fail. Cap at 768MB as a workaround.
1343 * Since 768MB is plenty of room, and we need to cap to something
1344 * reasonable on 32-bit, cap at 768MB on all machines.
1345 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001346 if (!rmo_top)
1347 rmo_top = ram_top;
1348 rmo_top = min(0x30000000ul, rmo_top);
1349 alloc_top = rmo_top;
1350 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001351
Paul Mackerras64968f62011-12-13 17:54:13 +00001352 /*
1353 * Check if we have an initrd after the kernel but still inside
1354 * the RMO. If we do move our bottom point to after it.
1355 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001356 if (prom_initrd_start &&
1357 prom_initrd_start < rmo_top &&
1358 prom_initrd_end > alloc_bottom)
1359 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001360
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001361 prom_printf("memory layout at init:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001362 prom_printf(" memory_limit : %x (16 MB aligned)\n", prom_memory_limit);
1363 prom_printf(" alloc_bottom : %x\n", alloc_bottom);
1364 prom_printf(" alloc_top : %x\n", alloc_top);
1365 prom_printf(" alloc_top_hi : %x\n", alloc_top_high);
1366 prom_printf(" rmo_top : %x\n", rmo_top);
1367 prom_printf(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001368}
1369
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001370static void __init prom_close_stdin(void)
1371{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001372 __be32 val;
1373 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001374
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001375 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1376 stdin = be32_to_cpu(val);
1377 call_prom("close", 1, 0, stdin);
1378 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001379}
1380
1381#ifdef CONFIG_PPC_POWERNV
1382
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001383#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1384static u64 __initdata prom_opal_base;
1385static u64 __initdata prom_opal_entry;
1386#endif
1387
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001388/*
1389 * Allocate room for and instantiate OPAL
1390 */
1391static void __init prom_instantiate_opal(void)
1392{
1393 phandle opal_node;
1394 ihandle opal_inst;
1395 u64 base, entry;
1396 u64 size = 0, align = 0x10000;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001397 __be64 val64;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001398 u32 rets[2];
1399
1400 prom_debug("prom_instantiate_opal: start...\n");
1401
1402 opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
1403 prom_debug("opal_node: %x\n", opal_node);
1404 if (!PHANDLE_VALID(opal_node))
1405 return;
1406
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001407 val64 = 0;
1408 prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64));
1409 size = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001410 if (size == 0)
1411 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001412 val64 = 0;
1413 prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64));
1414 align = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001415
1416 base = alloc_down(size, align, 0);
1417 if (base == 0) {
1418 prom_printf("OPAL allocation failed !\n");
1419 return;
1420 }
1421
1422 opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
1423 if (!IHANDLE_VALID(opal_inst)) {
1424 prom_printf("opening opal package failed (%x)\n", opal_inst);
1425 return;
1426 }
1427
1428 prom_printf("instantiating opal at 0x%x...", base);
1429
1430 if (call_prom_ret("call-method", 4, 3, rets,
1431 ADDR("load-opal-runtime"),
1432 opal_inst,
1433 base >> 32, base & 0xffffffff) != 0
1434 || (rets[0] == 0 && rets[1] == 0)) {
1435 prom_printf(" failed\n");
1436 return;
1437 }
1438 entry = (((u64)rets[0]) << 32) | rets[1];
1439
1440 prom_printf(" done\n");
1441
1442 reserve_mem(base, size);
1443
1444 prom_debug("opal base = 0x%x\n", base);
1445 prom_debug("opal align = 0x%x\n", align);
1446 prom_debug("opal entry = 0x%x\n", entry);
1447 prom_debug("opal size = 0x%x\n", (long)size);
1448
1449 prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
1450 &base, sizeof(base));
1451 prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
1452 &entry, sizeof(entry));
1453
1454#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
Anton Blanchard5827d412012-11-26 17:40:03 +00001455 prom_opal_base = base;
1456 prom_opal_entry = entry;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001457#endif
1458 prom_debug("prom_instantiate_opal: end...\n");
1459}
1460
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001461#endif /* CONFIG_PPC_POWERNV */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001462
1463/*
1464 * Allocate room for and instantiate RTAS
1465 */
1466static void __init prom_instantiate_rtas(void)
1467{
1468 phandle rtas_node;
1469 ihandle rtas_inst;
1470 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001471 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001472 u32 size = 0;
1473
1474 prom_debug("prom_instantiate_rtas: start...\n");
1475
1476 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1477 prom_debug("rtas_node: %x\n", rtas_node);
1478 if (!PHANDLE_VALID(rtas_node))
1479 return;
1480
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001481 val = 0;
1482 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1483 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001484 if (size == 0)
1485 return;
1486
1487 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001488 if (base == 0)
1489 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001490
1491 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1492 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001493 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001494 return;
1495 }
1496
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001497 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001498
1499 if (call_prom_ret("call-method", 3, 2, &entry,
1500 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001501 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001502 || entry == 0) {
1503 prom_printf(" failed\n");
1504 return;
1505 }
1506 prom_printf(" done\n");
1507
1508 reserve_mem(base, size);
1509
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001510 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001511 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001512 &val, sizeof(val));
1513 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001514 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001515 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001516
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001517 /* Check if it supports "query-cpu-stopped-state" */
1518 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1519 &val, sizeof(val)) != PROM_ERROR)
1520 rtas_has_query_cpu_stopped = true;
1521
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001522 prom_debug("rtas base = 0x%x\n", base);
1523 prom_debug("rtas entry = 0x%x\n", entry);
1524 prom_debug("rtas size = 0x%x\n", (long)size);
1525
1526 prom_debug("prom_instantiate_rtas: end...\n");
1527}
1528
1529#ifdef CONFIG_PPC64
1530/*
Ashley Lai4a727422012-08-14 18:34:57 -05001531 * Allocate room for and instantiate Stored Measurement Log (SML)
1532 */
1533static void __init prom_instantiate_sml(void)
1534{
1535 phandle ibmvtpm_node;
1536 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001537 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001538 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001539 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001540
1541 prom_debug("prom_instantiate_sml: start...\n");
1542
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001543 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001544 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1545 if (!PHANDLE_VALID(ibmvtpm_node))
1546 return;
1547
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001548 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001549 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1550 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1551 return;
1552 }
1553
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001554 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1555 &val, sizeof(val)) != PROM_ERROR) {
1556 if (call_prom_ret("call-method", 2, 2, &succ,
1557 ADDR("reformat-sml-to-efi-alignment"),
1558 ibmvtpm_inst) != 0 || succ == 0) {
1559 prom_printf("Reformat SML to EFI alignment failed\n");
1560 return;
1561 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001562
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001563 if (call_prom_ret("call-method", 2, 2, &size,
1564 ADDR("sml-get-allocated-size"),
1565 ibmvtpm_inst) != 0 || size == 0) {
1566 prom_printf("SML get allocated size failed\n");
1567 return;
1568 }
1569 } else {
1570 if (call_prom_ret("call-method", 2, 2, &size,
1571 ADDR("sml-get-handover-size"),
1572 ibmvtpm_inst) != 0 || size == 0) {
1573 prom_printf("SML get handover size failed\n");
1574 return;
1575 }
Ashley Lai4a727422012-08-14 18:34:57 -05001576 }
1577
1578 base = alloc_down(size, PAGE_SIZE, 0);
1579 if (base == 0)
1580 prom_panic("Could not allocate memory for sml\n");
1581
1582 prom_printf("instantiating sml at 0x%x...", base);
1583
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001584 memset((void *)base, 0, size);
1585
Ashley Lai4a727422012-08-14 18:34:57 -05001586 if (call_prom_ret("call-method", 4, 2, &entry,
1587 ADDR("sml-handover"),
1588 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1589 prom_printf("SML handover failed\n");
1590 return;
1591 }
1592 prom_printf(" done\n");
1593
1594 reserve_mem(base, size);
1595
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001596 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001597 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001598 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001599 &size, sizeof(size));
1600
1601 prom_debug("sml base = 0x%x\n", base);
1602 prom_debug("sml size = 0x%x\n", (long)size);
1603
1604 prom_debug("prom_instantiate_sml: end...\n");
1605}
1606
1607/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001608 * Allocate room for and initialize TCE tables
1609 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001610#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001611static void __init prom_initialize_tce_table(void)
1612{
1613 phandle node;
1614 ihandle phb_node;
1615 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001616 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001617 u64 base, align;
1618 u32 minalign, minsize;
1619 u64 tce_entry, *tce_entryp;
1620 u64 local_alloc_top, local_alloc_bottom;
1621 u64 i;
1622
Anton Blanchard5827d412012-11-26 17:40:03 +00001623 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001624 return;
1625
1626 prom_debug("starting prom_initialize_tce_table\n");
1627
1628 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001629 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001630 local_alloc_bottom = local_alloc_top;
1631
1632 /* Search all nodes looking for PHBs. */
1633 for (node = 0; prom_next_node(&node); ) {
1634 compatible[0] = 0;
1635 type[0] = 0;
1636 model[0] = 0;
1637 prom_getprop(node, "compatible",
1638 compatible, sizeof(compatible));
1639 prom_getprop(node, "device_type", type, sizeof(type));
1640 prom_getprop(node, "model", model, sizeof(model));
1641
Anton Blanchard5827d412012-11-26 17:40:03 +00001642 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001643 continue;
1644
Linas Vepstase788ff12007-09-07 03:45:21 +10001645 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001646 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001647 if ((strstr(compatible, "python") == NULL) &&
1648 (strstr(compatible, "Speedwagon") == NULL) &&
1649 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001650 continue;
1651 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001652 if ((strstr(model, "ython") == NULL) &&
1653 (strstr(model, "peedwagon") == NULL) &&
1654 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001655 continue;
1656 }
1657
1658 if (prom_getprop(node, "tce-table-minalign", &minalign,
1659 sizeof(minalign)) == PROM_ERROR)
1660 minalign = 0;
1661 if (prom_getprop(node, "tce-table-minsize", &minsize,
1662 sizeof(minsize)) == PROM_ERROR)
1663 minsize = 4UL << 20;
1664
1665 /*
1666 * Even though we read what OF wants, we just set the table
1667 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1668 * By doing this, we avoid the pitfalls of trying to DMA to
1669 * MMIO space and the DMA alias hole.
1670 *
1671 * On POWER4, firmware sets the TCE region by assuming
1672 * each TCE table is 8MB. Using this memory for anything
1673 * else will impact performance, so we always allocate 8MB.
1674 * Anton
1675 */
Michael Ellermand3dbeef2012-08-19 21:44:01 +00001676 if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001677 minsize = 8UL << 20;
1678 else
1679 minsize = 4UL << 20;
1680
1681 /* Align to the greater of the align or size */
1682 align = max(minalign, minsize);
1683 base = alloc_down(minsize, align, 1);
1684 if (base == 0)
1685 prom_panic("ERROR, cannot find space for TCE table.\n");
1686 if (base < local_alloc_bottom)
1687 local_alloc_bottom = base;
1688
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001689 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001690 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001691 /* Call OF to setup the TCE hardware */
1692 if (call_prom("package-to-path", 3, 1, node,
1693 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1694 prom_printf("package-to-path failed\n");
1695 }
1696
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001697 /* Save away the TCE table attributes for later use. */
1698 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1699 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1700
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001701 prom_debug("TCE table: %s\n", path);
1702 prom_debug("\tnode = 0x%x\n", node);
1703 prom_debug("\tbase = 0x%x\n", base);
1704 prom_debug("\tsize = 0x%x\n", minsize);
1705
1706 /* Initialize the table to have a one-to-one mapping
1707 * over the allocated size.
1708 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001709 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001710 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1711 tce_entry = (i << PAGE_SHIFT);
1712 tce_entry |= 0x3;
1713 *tce_entryp = tce_entry;
1714 }
1715
1716 prom_printf("opening PHB %s", path);
1717 phb_node = call_prom("open", 1, 1, path);
1718 if (phb_node == 0)
1719 prom_printf("... failed\n");
1720 else
1721 prom_printf("... done\n");
1722
1723 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1724 phb_node, -1, minsize,
1725 (u32) base, (u32) (base >> 32));
1726 call_prom("close", 1, 0, phb_node);
1727 }
1728
1729 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1730
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001731 /* These are only really needed if there is a memory limit in
1732 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001733 prom_tce_alloc_start = local_alloc_bottom;
1734 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001735
1736 /* Flag the first invalid entry */
1737 prom_debug("ending prom_initialize_tce_table\n");
1738}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001739#endif /* __BIG_ENDIAN__ */
1740#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001741
1742/*
1743 * With CHRP SMP we need to use the OF to start the other processors.
1744 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1745 * so we have to put the processors into a holding pattern controlled
1746 * by the kernel (not OF) before we destroy the OF.
1747 *
1748 * This uses a chunk of low memory, puts some holding pattern
1749 * code there and sends the other processors off to there until
1750 * smp_boot_cpus tells them to do something. The holding pattern
1751 * checks that address until its cpu # is there, when it is that
1752 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1753 * of setting those values.
1754 *
1755 * We also use physical address 0x4 here to tell when a cpu
1756 * is in its holding pattern code.
1757 *
1758 * -- Cort
1759 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001760/*
1761 * We want to reference the copy of __secondary_hold_* in the
1762 * 0 - 0x100 address range
1763 */
1764#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1765
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001766static void __init prom_hold_cpus(void)
1767{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001768 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001769 phandle node;
1770 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001771 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001772 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001773 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001774 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001775 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001776
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001777 /*
1778 * On pseries, if RTAS supports "query-cpu-stopped-state",
1779 * we skip this stage, the CPUs will be started by the
1780 * kernel using RTAS.
1781 */
1782 if ((of_platform == PLATFORM_PSERIES ||
1783 of_platform == PLATFORM_PSERIES_LPAR) &&
1784 rtas_has_query_cpu_stopped) {
1785 prom_printf("prom_hold_cpus: skipped\n");
1786 return;
1787 }
1788
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001789 prom_debug("prom_hold_cpus: start...\n");
1790 prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
1791 prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
1792 prom_debug(" 1) acknowledge = 0x%x\n",
1793 (unsigned long)acknowledge);
1794 prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
1795 prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
1796
1797 /* Set the common spinloop variable, so all of the secondary cpus
1798 * will block when they are awakened from their OF spinloop.
1799 * This must occur for both SMP and non SMP kernels, since OF will
1800 * be trashed when we move the kernel.
1801 */
1802 *spinloop = 0;
1803
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001804 /* look for cpus */
1805 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001806 unsigned int cpu_no;
1807 __be32 reg;
1808
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001809 type[0] = 0;
1810 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001811 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001812 continue;
1813
1814 /* Skip non-configured cpus. */
1815 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001816 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001817 continue;
1818
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001819 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001820 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001821 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001822
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001823 prom_debug("cpu hw idx = %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001824
1825 /* Init the acknowledge var which will be reset by
1826 * the secondary cpu when it awakens from its OF
1827 * spinloop.
1828 */
1829 *acknowledge = (unsigned long)-1;
1830
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001831 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001832 /* Primary Thread of non-boot cpu or any thread */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001833 prom_printf("starting cpu hw idx %lu... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001834 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001835 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001836
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001837 for (i = 0; (i < 100000000) &&
1838 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001839 mb();
1840
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001841 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001842 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001843 else
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001844 prom_printf("failed: %x\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001845 }
1846#ifdef CONFIG_SMP
1847 else
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001848 prom_printf("boot cpu hw idx %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001849#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001850 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001851
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001852 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001853}
1854
1855
1856static void __init prom_init_client_services(unsigned long pp)
1857{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001858 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00001859 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001860
1861 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00001862 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1863 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001864 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1865
1866 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00001867 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
1868 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001869 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001870
Anton Blanchard5827d412012-11-26 17:40:03 +00001871 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001872}
1873
Paul Mackerrasa575b802005-10-23 17:23:21 +10001874#ifdef CONFIG_PPC32
1875/*
1876 * For really old powermacs, we need to map things we claim.
1877 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001878 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10001879 */
1880static void __init prom_find_mmu(void)
1881{
Paul Mackerrasa575b802005-10-23 17:23:21 +10001882 phandle oprom;
1883 char version[64];
1884
1885 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1886 if (!PHANDLE_VALID(oprom))
1887 return;
1888 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1889 return;
1890 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10001891 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001892 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
1893 of_workarounds = OF_WA_CLAIM;
1894 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
1895 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
1896 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
1897 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10001898 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00001899 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
1900 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
1901 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001902 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00001903 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001904 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001905}
1906#else
1907#define prom_find_mmu()
1908#endif
1909
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001910static void __init prom_init_stdout(void)
1911{
Anton Blanchard5827d412012-11-26 17:40:03 +00001912 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001913 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001914 phandle stdout_node;
1915 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001916
Anton Blanchard5827d412012-11-26 17:40:03 +00001917 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001918 prom_panic("cannot find stdout");
1919
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001920 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001921
1922 /* Get the full OF pathname of the stdout device */
1923 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00001924 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00001925 prom_printf("OF stdout device is: %s\n", of_stdout_device);
1926 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001927 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001928
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11001929 /* instance-to-package fails on PA-Semi */
1930 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
1931 if (stdout_node != PROM_ERROR) {
1932 val = cpu_to_be32(stdout_node);
1933 prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
1934 &val, sizeof(val));
1935
1936 /* If it's a display, note it */
1937 memset(type, 0, sizeof(type));
1938 prom_getprop(stdout_node, "device_type", type, sizeof(type));
1939 if (strcmp(type, "display") == 0)
1940 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
1941 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001942}
1943
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001944static int __init prom_find_machine_type(void)
1945{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001946 char compat[256];
1947 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001948#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001949 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001950 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001951#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001952
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001953 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00001954 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001955 compat, sizeof(compat)-1);
1956 if (len > 0) {
1957 compat[len] = 0;
1958 while (i < len) {
1959 char *p = &compat[i];
1960 int sl = strlen(p);
1961 if (sl == 0)
1962 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00001963 if (strstr(p, "Power Macintosh") ||
1964 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001965 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10001966#ifdef CONFIG_PPC64
1967 /* We must make sure we don't detect the IBM Cell
1968 * blades as pSeries due to some firmware issues,
1969 * so we do it here.
1970 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001971 if (strstr(p, "IBM,CBEA") ||
1972 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10001973 return PLATFORM_GENERIC;
1974#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001975 i += sl + 1;
1976 }
1977 }
1978#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001979 /* Try to detect OPAL */
1980 if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
1981 return PLATFORM_OPAL;
1982
1983 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001984 * PAPR compliant platform. We assume it is if :
1985 * - /device_type is "chrp" (please, do NOT use that for future
1986 * non-IBM designs !
1987 * - it has /rtas
1988 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001989 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001990 compat, sizeof(compat)-1);
1991 if (len <= 0)
1992 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00001993 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001994 return PLATFORM_GENERIC;
1995
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001996 /* Default to pSeries. We need to know if we are running LPAR */
1997 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001998 if (!PHANDLE_VALID(rtas))
1999 return PLATFORM_GENERIC;
2000 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2001 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002002 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002003 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002004 }
2005 return PLATFORM_PSERIES;
2006#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002007 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002008#endif
2009}
2010
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002011static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2012{
2013 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2014}
2015
2016/*
2017 * If we have a display that we don't know how to drive,
2018 * we will want to try to execute OF's open method for it
2019 * later. However, OF will probably fall over if we do that
2020 * we've taken over the MMU.
2021 * So we check whether we will need to open the display,
2022 * and if so, open it now.
2023 */
2024static void __init prom_check_displays(void)
2025{
2026 char type[16], *path;
2027 phandle node;
2028 ihandle ih;
2029 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002030
2031 static unsigned char default_colors[] = {
2032 0x00, 0x00, 0x00,
2033 0x00, 0x00, 0xaa,
2034 0x00, 0xaa, 0x00,
2035 0x00, 0xaa, 0xaa,
2036 0xaa, 0x00, 0x00,
2037 0xaa, 0x00, 0xaa,
2038 0xaa, 0xaa, 0x00,
2039 0xaa, 0xaa, 0xaa,
2040 0x55, 0x55, 0x55,
2041 0x55, 0x55, 0xff,
2042 0x55, 0xff, 0x55,
2043 0x55, 0xff, 0xff,
2044 0xff, 0x55, 0x55,
2045 0xff, 0x55, 0xff,
2046 0xff, 0xff, 0x55,
2047 0xff, 0xff, 0xff
2048 };
2049 const unsigned char *clut;
2050
Anton Blanchard4da727a2009-03-31 20:06:14 +00002051 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002052 for (node = 0; prom_next_node(&node); ) {
2053 memset(type, 0, sizeof(type));
2054 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00002055 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002056 continue;
2057
2058 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002059 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002060 memset(path, 0, PROM_SCRATCH_SIZE);
2061
2062 /*
2063 * leave some room at the end of the path for appending extra
2064 * arguments
2065 */
2066 if (call_prom("package-to-path", 3, 1, node, path,
2067 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
2068 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002069 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002070
2071 ih = call_prom("open", 1, 1, path);
2072 if (ih == 0) {
2073 prom_printf("failed\n");
2074 continue;
2075 }
2076
2077 /* Success */
2078 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002079 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002080
2081 /* Setup a usable color table when the appropriate
2082 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002083 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002084 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002085 if (prom_set_color(ih, i, clut[0], clut[1],
2086 clut[2]) != 0)
2087 break;
2088
2089#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002090 clut = PTRRELOC(logo_linux_clut224.clut);
2091 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002092 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2093 clut[2]) != 0)
2094 break;
2095#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002096
2097#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2098 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2099 PROM_ERROR) {
2100 u32 width, height, pitch, addr;
2101
2102 prom_printf("Setting btext !\n");
2103 prom_getprop(node, "width", &width, 4);
2104 prom_getprop(node, "height", &height, 4);
2105 prom_getprop(node, "linebytes", &pitch, 4);
2106 prom_getprop(node, "address", &addr, 4);
2107 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2108 width, height, pitch, addr);
2109 btext_setup_display(width, height, 8, pitch, addr);
2110 }
2111#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002112 }
2113}
2114
2115
2116/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2117static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2118 unsigned long needed, unsigned long align)
2119{
2120 void *ret;
2121
2122 *mem_start = _ALIGN(*mem_start, align);
2123 while ((*mem_start + needed) > *mem_end) {
2124 unsigned long room, chunk;
2125
2126 prom_debug("Chunk exhausted, claiming more at %x...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002127 alloc_bottom);
2128 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002129 if (room > DEVTREE_CHUNK_SIZE)
2130 room = DEVTREE_CHUNK_SIZE;
2131 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002132 prom_panic("No memory for flatten_device_tree "
2133 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002134 chunk = alloc_up(room, 0);
2135 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002136 prom_panic("No memory for flatten_device_tree "
2137 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002138 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002139 }
2140
2141 ret = (void *)*mem_start;
2142 *mem_start += needed;
2143
2144 return ret;
2145}
2146
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002147#define dt_push_token(token, mem_start, mem_end) do { \
2148 void *room = make_room(mem_start, mem_end, 4, 4); \
2149 *(__be32 *)room = cpu_to_be32(token); \
2150 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002151
2152static unsigned long __init dt_find_string(char *str)
2153{
2154 char *s, *os;
2155
Anton Blanchard5827d412012-11-26 17:40:03 +00002156 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002157 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002158 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002159 if (strcmp(s, str) == 0)
2160 return s - os;
2161 s += strlen(s) + 1;
2162 }
2163 return 0;
2164}
2165
2166/*
2167 * The Open Firmware 1275 specification states properties must be 31 bytes or
2168 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2169 */
2170#define MAX_PROPERTY_NAME 64
2171
2172static void __init scan_dt_build_strings(phandle node,
2173 unsigned long *mem_start,
2174 unsigned long *mem_end)
2175{
2176 char *prev_name, *namep, *sstart;
2177 unsigned long soff;
2178 phandle child;
2179
Anton Blanchard5827d412012-11-26 17:40:03 +00002180 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002181
2182 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002183 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002184 for (;;) {
2185 /* 64 is max len of name including nul. */
2186 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2187 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2188 /* No more nodes: unwind alloc */
2189 *mem_start = (unsigned long)namep;
2190 break;
2191 }
2192
2193 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002194 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002195 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002196 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002197 continue;
2198 }
2199 /* get/create string entry */
2200 soff = dt_find_string(namep);
2201 if (soff != 0) {
2202 *mem_start = (unsigned long)namep;
2203 namep = sstart + soff;
2204 } else {
2205 /* Trim off some if we can */
2206 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002207 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002208 }
2209 prev_name = namep;
2210 }
2211
2212 /* do all our children */
2213 child = call_prom("child", 1, 1, node);
2214 while (child != 0) {
2215 scan_dt_build_strings(child, mem_start, mem_end);
2216 child = call_prom("peer", 1, 1, child);
2217 }
2218}
2219
2220static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2221 unsigned long *mem_end)
2222{
2223 phandle child;
2224 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2225 unsigned long soff;
2226 unsigned char *valp;
2227 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002228 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002229
2230 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2231
2232 /* get the node's full name */
2233 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002234 room = *mem_end - *mem_start;
2235 if (room > 255)
2236 room = 255;
2237 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002238 if (l >= 0) {
2239 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002240 if (l >= room) {
2241 if (l >= *mem_end - *mem_start)
2242 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002243 call_prom("package-to-path", 3, 1, node, namep, l);
2244 }
2245 namep[l] = '\0';
2246
2247 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002248 * middle of the path in some properties, and extract
2249 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002250 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002251 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002252 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002253 lp = namep;
2254 else if (*p != 0)
2255 *lp++ = *p;
2256 }
2257 *lp = 0;
2258 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002259 }
2260
2261 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002262 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002263 memset(path, 0, PROM_SCRATCH_SIZE);
2264 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2265
2266 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002267 prev_name = "";
2268 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002269 for (;;) {
2270 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002271 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002272 break;
2273
2274 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002275 if (strcmp(pname, "name") == 0) {
2276 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002277 continue;
2278 }
2279
2280 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002281 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002282 if (soff == 0) {
2283 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002284 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002285 break;
2286 }
2287 prev_name = sstart + soff;
2288
2289 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002290 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002291
2292 /* sanity checks */
2293 if (l == PROM_ERROR)
2294 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002295
2296 /* push property head */
2297 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2298 dt_push_token(l, mem_start, mem_end);
2299 dt_push_token(soff, mem_start, mem_end);
2300
2301 /* push property content */
2302 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002303 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002304 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002305
Anton Blanchard5827d412012-11-26 17:40:03 +00002306 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002307 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002308 }
2309
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002310 /* Add a "linux,phandle" property if no "phandle" property already
2311 * existed (can happen with OPAL)
2312 */
2313 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002314 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002315 if (soff == 0)
2316 prom_printf("WARNING: Can't find string index for"
2317 " <linux-phandle> node %s\n", path);
2318 else {
2319 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2320 dt_push_token(4, mem_start, mem_end);
2321 dt_push_token(soff, mem_start, mem_end);
2322 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002323 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002324 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002325 }
2326
2327 /* do all our children */
2328 child = call_prom("child", 1, 1, node);
2329 while (child != 0) {
2330 scan_dt_build_struct(child, mem_start, mem_end);
2331 child = call_prom("peer", 1, 1, child);
2332 }
2333
2334 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2335}
2336
2337static void __init flatten_device_tree(void)
2338{
2339 phandle root;
2340 unsigned long mem_start, mem_end, room;
2341 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002342 char *namep;
2343 u64 *rsvmap;
2344
2345 /*
2346 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002347 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002348 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002349 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002350 if (room > DEVTREE_CHUNK_SIZE)
2351 room = DEVTREE_CHUNK_SIZE;
Anton Blanchard5827d412012-11-26 17:40:03 +00002352 prom_debug("starting device tree allocs at %x\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002353
2354 /* Now try to claim that */
2355 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2356 if (mem_start == 0)
2357 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002358 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002359
2360 /* Get root of tree */
2361 root = call_prom("peer", 1, 1, (phandle)0);
2362 if (root == (phandle)0)
2363 prom_panic ("couldn't get device tree root\n");
2364
2365 /* Build header and make room for mem rsv map */
2366 mem_start = _ALIGN(mem_start, 4);
2367 hdr = make_room(&mem_start, &mem_end,
2368 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002369 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002370 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2371
2372 /* Start of strings */
2373 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002374 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002375 mem_start += 4; /* hole */
2376
2377 /* Add "linux,phandle" in there, we'll need it */
2378 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002379 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002380 mem_start = (unsigned long)namep + strlen(namep) + 1;
2381
2382 /* Build string array */
2383 prom_printf("Building dt strings...\n");
2384 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002385 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002386
2387 /* Build structure */
2388 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002389 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002390 prom_printf("Building dt structure...\n");
2391 scan_dt_build_struct(root, &mem_start, &mem_end);
2392 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002393 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002394
2395 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002396 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2397 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2398 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2399 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2400 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2401 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2402 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2403 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002404 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002405 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002406
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002407 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002408 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002409
2410#ifdef DEBUG_PROM
2411 {
2412 int i;
2413 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002414 for (i = 0; i < mem_reserve_cnt; i++)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002415 prom_printf(" %x - %x\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002416 be64_to_cpu(mem_reserve_map[i].base),
2417 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002418 }
2419#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002420 /* Bump mem_reserve_cnt to cause further reservations to fail
2421 * since it's too late.
2422 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002423 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002424
2425 prom_printf("Device tree strings 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002426 dt_string_start, dt_string_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002427 prom_printf("Device tree struct 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002428 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002429}
2430
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002431#ifdef CONFIG_PPC_MAPLE
2432/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2433 * The values are bad, and it doesn't even have the right number of cells. */
2434static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002435{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002436 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002437 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002438 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002439 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002440
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002441 name = "/ht@0/isa@4";
2442 isa = call_prom("finddevice", 1, 1, ADDR(name));
2443 if (!PHANDLE_VALID(isa)) {
2444 name = "/ht@0/isa@6";
2445 isa = call_prom("finddevice", 1, 1, ADDR(name));
2446 rloc = 0x01003000; /* IO space; PCI device = 6 */
2447 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002448 if (!PHANDLE_VALID(isa))
2449 return;
2450
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002451 if (prom_getproplen(isa, "ranges") != 12)
2452 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002453 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2454 == PROM_ERROR)
2455 return;
2456
2457 if (isa_ranges[0] != 0x1 ||
2458 isa_ranges[1] != 0xf4000000 ||
2459 isa_ranges[2] != 0x00010000)
2460 return;
2461
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002462 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002463
2464 isa_ranges[0] = 0x1;
2465 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002466 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002467 isa_ranges[3] = 0x0;
2468 isa_ranges[4] = 0x0;
2469 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002470 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002471 isa_ranges, sizeof(isa_ranges));
2472}
Harry Ciao8f101a052009-06-17 16:28:00 -07002473
2474#define CPC925_MC_START 0xf8000000
2475#define CPC925_MC_LENGTH 0x1000000
2476/* The values for memory-controller don't have right number of cells */
2477static void __init fixup_device_tree_maple_memory_controller(void)
2478{
2479 phandle mc;
2480 u32 mc_reg[4];
2481 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002482 u32 ac, sc;
2483
2484 mc = call_prom("finddevice", 1, 1, ADDR(name));
2485 if (!PHANDLE_VALID(mc))
2486 return;
2487
2488 if (prom_getproplen(mc, "reg") != 8)
2489 return;
2490
Anton Blanchard5827d412012-11-26 17:40:03 +00002491 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2492 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002493 if ((ac != 2) || (sc != 2))
2494 return;
2495
2496 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2497 return;
2498
2499 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2500 return;
2501
2502 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2503
2504 mc_reg[0] = 0x0;
2505 mc_reg[1] = CPC925_MC_START;
2506 mc_reg[2] = 0x0;
2507 mc_reg[3] = CPC925_MC_LENGTH;
2508 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2509}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002510#else
2511#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002512#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002513#endif
2514
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002515#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002516/*
2517 * Pegasos and BriQ lacks the "ranges" property in the isa node
2518 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002519 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002520 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002521static void __init fixup_device_tree_chrp(void)
2522{
Olaf Heringe4805922007-04-04 18:20:04 +02002523 phandle ph;
2524 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002525 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002526 char *name;
2527 int rc;
2528
2529 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002530 ph = call_prom("finddevice", 1, 1, ADDR(name));
2531 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002532 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002533 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002534 rloc = 0x01003000; /* IO space; PCI device = 6 */
2535 }
Olaf Heringe4805922007-04-04 18:20:04 +02002536 if (PHANDLE_VALID(ph)) {
2537 rc = prom_getproplen(ph, "ranges");
2538 if (rc == 0 || rc == PROM_ERROR) {
2539 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002540
Olaf Heringe4805922007-04-04 18:20:04 +02002541 prop[0] = 0x1;
2542 prop[1] = 0x0;
2543 prop[2] = rloc;
2544 prop[3] = 0x0;
2545 prop[4] = 0x0;
2546 prop[5] = 0x00010000;
2547 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2548 }
2549 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002550
Olaf Heringe4805922007-04-04 18:20:04 +02002551 name = "/pci@80000000/ide@C,1";
2552 ph = call_prom("finddevice", 1, 1, ADDR(name));
2553 if (PHANDLE_VALID(ph)) {
2554 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2555 prop[0] = 14;
2556 prop[1] = 0x0;
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002557 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2558 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2559 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2560 if (rc == sizeof(u32)) {
2561 prop[0] &= ~0x5;
2562 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2563 }
Olaf Heringe4805922007-04-04 18:20:04 +02002564 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002565}
2566#else
2567#define fixup_device_tree_chrp()
2568#endif
2569
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002570#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002571static void __init fixup_device_tree_pmac(void)
2572{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002573 phandle u3, i2c, mpic;
2574 u32 u3_rev;
2575 u32 interrupts[2];
2576 u32 parent;
2577
2578 /* Some G5s have a missing interrupt definition, fix it up here */
2579 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2580 if (!PHANDLE_VALID(u3))
2581 return;
2582 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2583 if (!PHANDLE_VALID(i2c))
2584 return;
2585 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2586 if (!PHANDLE_VALID(mpic))
2587 return;
2588
2589 /* check if proper rev of u3 */
2590 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2591 == PROM_ERROR)
2592 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002593 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002594 return;
2595 /* does it need fixup ? */
2596 if (prom_getproplen(i2c, "interrupts") > 0)
2597 return;
2598
2599 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2600
2601 /* interrupt on this revision of u3 is number 0 and level */
2602 interrupts[0] = 0;
2603 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002604 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2605 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002606 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002607 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2608 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002609}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002610#else
2611#define fixup_device_tree_pmac()
2612#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002613
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002614#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002615/*
2616 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2617 * to talk to the phy. If the phy-handle property is missing, then this
2618 * function is called to add the appropriate nodes and link it to the
2619 * ethernet node.
2620 */
2621static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002622{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002623 u32 node;
2624 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002625 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002626
Grant Likely94d2dde2008-01-24 22:25:32 -07002627 /* Check if /builtin/ethernet exists - bail if it doesn't */
2628 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002629 if (!PHANDLE_VALID(node))
2630 return;
2631
Grant Likely94d2dde2008-01-24 22:25:32 -07002632 /* Check if the phy-handle property exists - bail if it does */
2633 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2634 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002635 return;
2636
Grant Likely94d2dde2008-01-24 22:25:32 -07002637 /*
2638 * At this point the ethernet device doesn't have a phy described.
2639 * Now we need to add the missing phy node and linkage
2640 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002641
Grant Likely94d2dde2008-01-24 22:25:32 -07002642 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002643 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2644 if (!PHANDLE_VALID(node)) {
2645 prom_printf("Adding Ethernet MDIO node\n");
2646 call_prom("interpret", 1, 1,
2647 " s\" /builtin\" find-device"
2648 " new-device"
2649 " 1 encode-int s\" #address-cells\" property"
2650 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002651 " s\" mdio\" device-name"
2652 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002653 " s\" compatible\" property"
2654 " 0xf0003000 0x400 reg"
2655 " 0x2 encode-int"
2656 " 0x5 encode-int encode+"
2657 " 0x3 encode-int encode+"
2658 " s\" interrupts\" property"
2659 " finish-device");
2660 };
2661
Grant Likely94d2dde2008-01-24 22:25:32 -07002662 /* Check for a PHY device node - if missing then create one and
2663 * give it's phandle to the ethernet node */
2664 node = call_prom("finddevice", 1, 1,
2665 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002666 if (!PHANDLE_VALID(node)) {
2667 prom_printf("Adding Ethernet PHY node\n");
2668 call_prom("interpret", 1, 1,
2669 " s\" /builtin/mdio\" find-device"
2670 " new-device"
2671 " s\" ethernet-phy\" device-name"
2672 " 0x10 encode-int s\" reg\" property"
2673 " my-self"
2674 " ihandle>phandle"
2675 " finish-device"
2676 " s\" /builtin/ethernet\" find-device"
2677 " encode-int"
2678 " s\" phy-handle\" property"
2679 " device-end");
2680 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002681}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002682
Grant Likely94d2dde2008-01-24 22:25:32 -07002683static void __init fixup_device_tree_efika(void)
2684{
2685 int sound_irq[3] = { 2, 2, 0 };
2686 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2687 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2688 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2689 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2690 u32 node;
2691 char prop[64];
2692 int rv, len;
2693
2694 /* Check if we're really running on a EFIKA */
2695 node = call_prom("finddevice", 1, 1, ADDR("/"));
2696 if (!PHANDLE_VALID(node))
2697 return;
2698
2699 rv = prom_getprop(node, "model", prop, sizeof(prop));
2700 if (rv == PROM_ERROR)
2701 return;
2702 if (strcmp(prop, "EFIKA5K2"))
2703 return;
2704
2705 prom_printf("Applying EFIKA device tree fixups\n");
2706
2707 /* Claiming to be 'chrp' is death */
2708 node = call_prom("finddevice", 1, 1, ADDR("/"));
2709 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2710 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2711 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2712
David Woodhouse7f4392c2008-04-14 02:52:38 +10002713 /* CODEGEN,description is exposed in /proc/cpuinfo so
2714 fix that too */
2715 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2716 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2717 prom_setprop(node, "/", "CODEGEN,description",
2718 "Efika 5200B PowerPC System",
2719 sizeof("Efika 5200B PowerPC System"));
2720
Grant Likely94d2dde2008-01-24 22:25:32 -07002721 /* Fixup bestcomm interrupts property */
2722 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2723 if (PHANDLE_VALID(node)) {
2724 len = prom_getproplen(node, "interrupts");
2725 if (len == 12) {
2726 prom_printf("Fixing bestcomm interrupts property\n");
2727 prom_setprop(node, "/builtin/bestcom", "interrupts",
2728 bcomm_irq, sizeof(bcomm_irq));
2729 }
2730 }
2731
2732 /* Fixup sound interrupts property */
2733 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2734 if (PHANDLE_VALID(node)) {
2735 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2736 if (rv == PROM_ERROR) {
2737 prom_printf("Adding sound interrupts property\n");
2738 prom_setprop(node, "/builtin/sound", "interrupts",
2739 sound_irq, sizeof(sound_irq));
2740 }
2741 }
2742
2743 /* Make sure ethernet phy-handle property exists */
2744 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002745}
2746#else
2747#define fixup_device_tree_efika()
2748#endif
2749
Darren Stevens50246782016-08-31 13:24:40 +01002750#ifdef CONFIG_PPC_PASEMI_NEMO
2751/*
2752 * CFE supplied on Nemo is broken in several ways, biggest
2753 * problem is that it reassigns ISA interrupts to unused mpic ints.
2754 * Add an interrupt-controller property for the io-bridge to use
2755 * and correct the ints so we can attach them to an irq_domain
2756 */
2757static void __init fixup_device_tree_pasemi(void)
2758{
2759 u32 interrupts[2], parent, rval, val = 0;
2760 char *name, *pci_name;
2761 phandle iob, node;
2762
2763 /* Find the root pci node */
2764 name = "/pxp@0,e0000000";
2765 iob = call_prom("finddevice", 1, 1, ADDR(name));
2766 if (!PHANDLE_VALID(iob))
2767 return;
2768
2769 /* check if interrupt-controller node set yet */
2770 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
2771 return;
2772
2773 prom_printf("adding interrupt-controller property for SB600...\n");
2774
2775 prom_setprop(iob, name, "interrupt-controller", &val, 0);
2776
2777 pci_name = "/pxp@0,e0000000/pci@11";
2778 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
2779 parent = ADDR(iob);
2780
2781 for( ; prom_next_node(&node); ) {
2782 /* scan each node for one with an interrupt */
2783 if (!PHANDLE_VALID(node))
2784 continue;
2785
2786 rval = prom_getproplen(node, "interrupts");
2787 if (rval == 0 || rval == PROM_ERROR)
2788 continue;
2789
2790 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
2791 if ((interrupts[0] < 212) || (interrupts[0] > 222))
2792 continue;
2793
2794 /* found a node, update both interrupts and interrupt-parent */
2795 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
2796 interrupts[0] -= 203;
2797 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
2798 interrupts[0] -= 213;
2799 if (interrupts[0] == 221)
2800 interrupts[0] = 14;
2801 if (interrupts[0] == 222)
2802 interrupts[0] = 8;
2803
2804 prom_setprop(node, pci_name, "interrupts", interrupts,
2805 sizeof(interrupts));
2806 prom_setprop(node, pci_name, "interrupt-parent", &parent,
2807 sizeof(parent));
2808 }
Darren Stevens687e16b2016-08-31 13:24:45 +01002809
2810 /*
2811 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
2812 * so that generic isa-bridge code can add the SB600 and its on-board
2813 * peripherals.
2814 */
2815 name = "/pxp@0,e0000000/io-bridge@0";
2816 iob = call_prom("finddevice", 1, 1, ADDR(name));
2817 if (!PHANDLE_VALID(iob))
2818 return;
2819
2820 /* device_type is already set, just change it. */
2821
2822 prom_printf("Changing device_type of SB600 node...\n");
2823
2824 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01002825}
2826#else /* !CONFIG_PPC_PASEMI_NEMO */
2827static inline void fixup_device_tree_pasemi(void) { }
2828#endif
2829
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002830static void __init fixup_device_tree(void)
2831{
2832 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07002833 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002834 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002835 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002836 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01002837 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002838}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002839
2840static void __init prom_find_boot_cpu(void)
2841{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002842 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002843 ihandle prom_cpu;
2844 phandle cpu_pkg;
2845
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002846 rval = 0;
2847 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10002848 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002849 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002850
2851 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
2852
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00002853 if (!PHANDLE_VALID(cpu_pkg))
2854 return;
2855
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002856 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
2857 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002858
Anton Blanchard5827d412012-11-26 17:40:03 +00002859 prom_debug("Booting CPU hw index = %lu\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002860}
2861
2862static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2863{
2864#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002865 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002866 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002867
Anton Blanchard5827d412012-11-26 17:40:03 +00002868 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
2869 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002870
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002871 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002872 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002873 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002874 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002875 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002876 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002877
Anton Blanchard5827d412012-11-26 17:40:03 +00002878 reserve_mem(prom_initrd_start,
2879 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002880
Anton Blanchard5827d412012-11-26 17:40:03 +00002881 prom_debug("initrd_start=0x%x\n", prom_initrd_start);
2882 prom_debug("initrd_end=0x%x\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002883 }
2884#endif /* CONFIG_BLK_DEV_INITRD */
2885}
2886
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002887#ifdef CONFIG_PPC64
2888#ifdef CONFIG_RELOCATABLE
2889static void reloc_toc(void)
2890{
2891}
2892
2893static void unreloc_toc(void)
2894{
2895}
2896#else
Anton Blanchard16744002013-03-12 01:51:51 +00002897static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002898{
2899 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00002900 unsigned long *toc_entry;
2901
2902 /* Get the start of the TOC by using r2 directly. */
2903 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002904
2905 for (i = 0; i < nr_entries; i++) {
2906 *toc_entry = *toc_entry + offset;
2907 toc_entry++;
2908 }
2909}
2910
2911static void reloc_toc(void)
2912{
2913 unsigned long offset = reloc_offset();
2914 unsigned long nr_entries =
2915 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2916
Anton Blanchard16744002013-03-12 01:51:51 +00002917 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002918
2919 mb();
2920}
2921
2922static void unreloc_toc(void)
2923{
2924 unsigned long offset = reloc_offset();
2925 unsigned long nr_entries =
2926 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2927
2928 mb();
2929
Anton Blanchard16744002013-03-12 01:51:51 +00002930 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002931}
2932#endif
2933#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002934
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002935/*
2936 * We enter here early on, when the Open Firmware prom is still
2937 * handling exceptions and the MMU hash table for us.
2938 */
2939
2940unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2941 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10002942 unsigned long r6, unsigned long r7,
2943 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002944{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002945 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002946
2947#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10002948 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002949 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002950#else
2951 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002952#endif
2953
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002954 /*
2955 * First zero the BSS
2956 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002957 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002958
2959 /*
2960 * Init interface to Open Firmware, get some node references,
2961 * like /chosen
2962 */
2963 prom_init_client_services(pp);
2964
2965 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002966 * See if this OF is old enough that we need to do explicit maps
2967 * and other workarounds
2968 */
2969 prom_find_mmu();
2970
2971 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002972 * Init prom stdout device
2973 */
2974 prom_init_stdout();
2975
Anton Blanchard5827d412012-11-26 17:40:03 +00002976 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00002977
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002978 /*
2979 * Get default machine type. At this point, we do not differentiate
2980 * between pSeries SMP and pSeries LPAR
2981 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002982 of_platform = prom_find_machine_type();
2983 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002984
Suzuki Poulose0f890c82011-12-14 22:57:15 +00002985#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01002986 /* Bail if this is a kdump kernel. */
2987 if (PHYSICAL_START > 0)
2988 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10002989#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01002990
2991 /*
2992 * Check for an initrd
2993 */
2994 prom_check_initrd(r3, r4);
2995
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11002996 /*
2997 * Do early parsing of command line
2998 */
2999 early_cmdline_parse();
3000
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003001#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003002 /*
3003 * On pSeries, inform the firmware about our capabilities
3004 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003005 if (of_platform == PLATFORM_PSERIES ||
3006 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003007 prom_send_capabilities();
3008#endif
3009
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003010 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003011 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003012 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003013 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003014 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003015
3016 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003017 * Initialize memory management within prom_init
3018 */
3019 prom_init_mem();
3020
3021 /*
3022 * Determine which cpu is actually running right _now_
3023 */
3024 prom_find_boot_cpu();
3025
3026 /*
3027 * Initialize display devices
3028 */
3029 prom_check_displays();
3030
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003031#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003032 /*
3033 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3034 * that uses the allocator, we need to make sure we get the top of memory
3035 * available for us here...
3036 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003037 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003038 prom_initialize_tce_table();
3039#endif
3040
3041 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003042 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3043 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003044 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003045 if (of_platform != PLATFORM_POWERMAC &&
3046 of_platform != PLATFORM_OPAL)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003047 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003048
3049#ifdef CONFIG_PPC_POWERNV
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003050 if (of_platform == PLATFORM_OPAL)
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003051 prom_instantiate_opal();
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003052#endif /* CONFIG_PPC_POWERNV */
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003053
Ashley Lai4a727422012-08-14 18:34:57 -05003054#ifdef CONFIG_PPC64
3055 /* instantiate sml */
3056 prom_instantiate_sml();
3057#endif
3058
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003059 /*
3060 * On non-powermacs, put all CPUs in spin-loops.
3061 *
3062 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003063 *
3064 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003065 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003066 if (of_platform != PLATFORM_POWERMAC &&
3067 of_platform != PLATFORM_OPAL)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003068 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003069
3070 /*
3071 * Fill in some infos for use by the kernel later on
3072 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003073 if (prom_memory_limit) {
3074 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003075 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003076 &val, sizeof(val));
3077 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003078#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003079 if (prom_iommu_off)
3080 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003081 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003082
Anton Blanchard5827d412012-11-26 17:40:03 +00003083 if (prom_iommu_force_on)
3084 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003085 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003086
Anton Blanchard5827d412012-11-26 17:40:03 +00003087 if (prom_tce_alloc_start) {
3088 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3089 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003090 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003091 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3092 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003093 sizeof(prom_tce_alloc_end));
3094 }
3095#endif
3096
3097 /*
3098 * Fixup any known bugs in the device-tree
3099 */
3100 fixup_device_tree();
3101
3102 /*
3103 * Now finally create the flattened device-tree
3104 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003105 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003106 flatten_device_tree();
3107
Paul Mackerras3825ac02005-11-08 22:48:08 +11003108 /*
3109 * in case stdin is USB and still active on IBM machines...
3110 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003111 * closed stdin already (in particular the powerbook 101). It
3112 * appears that the OPAL version of OFW doesn't like it either.
Paul Mackerras3825ac02005-11-08 22:48:08 +11003113 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003114 if (of_platform != PLATFORM_POWERMAC &&
3115 of_platform != PLATFORM_OPAL)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003116 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003117
3118 /*
3119 * Call OF "quiesce" method to shut down pending DMA's from
3120 * devices etc...
3121 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003122 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003123 call_prom("quiesce", 0, 0);
3124
3125 /*
3126 * And finally, call the kernel passing it the flattened device
3127 * tree and NULL as r5, thus triggering the new entry point which
3128 * is common to us and kexec
3129 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003130 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003131
3132 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Anton Blanchard5827d412012-11-26 17:40:03 +00003133 if (of_platform != PLATFORM_OPAL) {
Benjamin Herrenschmidt7d70c632016-08-10 17:29:29 +10003134 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003135 prom_debug("->dt_header_start=0x%x\n", hdr);
3136 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003137
3138#ifdef CONFIG_PPC32
3139 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003140#else
3141 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003142#endif
3143
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003144#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
3145 /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
3146 __start(hdr, kbase, 0, 0, 0,
Anton Blanchard5827d412012-11-26 17:40:03 +00003147 prom_opal_base, prom_opal_entry);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003148#else
3149 __start(hdr, kbase, 0, 0, 0, 0, 0);
3150#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003151
3152 return 0;
3153}