blob: 7b6391b68fb882b20abdf59703e6addd64ac27fc [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>
40#include <asm/pci.h>
41#include <asm/iommu.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100042#include <asm/btext.h>
43#include <asm/sections.h>
44#include <asm/machdep.h>
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +000045#include <asm/opal.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
199
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000200/*
201 * Error results ... some OF calls will return "-1" on error, some
202 * will return 0, some will return either. To simplify, here are
203 * macros to use with any ihandle or phandle return value to check if
204 * it is valid
205 */
206
207#define PROM_ERROR (-1u)
208#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
209#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
210
211
212/* This is the one and *ONLY* place where we actually call open
213 * firmware.
214 */
215
216static int __init call_prom(const char *service, int nargs, int nret, ...)
217{
218 int i;
219 struct prom_args args;
220 va_list list;
221
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000222 args.service = cpu_to_be32(ADDR(service));
223 args.nargs = cpu_to_be32(nargs);
224 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000225
226 va_start(list, nret);
227 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000228 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000229 va_end(list);
230
231 for (i = 0; i < nret; i++)
232 args.args[nargs+i] = 0;
233
Anton Blanchard5827d412012-11-26 17:40:03 +0000234 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000235 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000236
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000237 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000238}
239
240static int __init call_prom_ret(const char *service, int nargs, int nret,
241 prom_arg_t *rets, ...)
242{
243 int i;
244 struct prom_args args;
245 va_list list;
246
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000247 args.service = cpu_to_be32(ADDR(service));
248 args.nargs = cpu_to_be32(nargs);
249 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000250
251 va_start(list, rets);
252 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000253 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000254 va_end(list);
255
256 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100257 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000258
Anton Blanchard5827d412012-11-26 17:40:03 +0000259 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000260 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000261
262 if (rets != NULL)
263 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000264 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000265
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000266 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000267}
268
269
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000270static void __init prom_print(const char *msg)
271{
272 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000273
Anton Blanchard5827d412012-11-26 17:40:03 +0000274 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000275 return;
276
277 for (p = msg; *p != 0; p = q) {
278 for (q = p; *q != 0 && *q != '\n'; ++q)
279 ;
280 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000281 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000282 if (*q == 0)
283 break;
284 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000285 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000286 }
287}
288
289
290static void __init prom_print_hex(unsigned long val)
291{
292 int i, nibbles = sizeof(val)*2;
293 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000294
295 for (i = nibbles-1; i >= 0; i--) {
296 buf[i] = (val & 0xf) + '0';
297 if (buf[i] > '9')
298 buf[i] += ('a'-'0'-10);
299 val >>= 4;
300 }
301 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000302 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000303}
304
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000305/* max number of decimal digits in an unsigned long */
306#define UL_DIGITS 21
307static void __init prom_print_dec(unsigned long val)
308{
309 int i, size;
310 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000311
312 for (i = UL_DIGITS-1; i >= 0; i--) {
313 buf[i] = (val % 10) + '0';
314 val = val/10;
315 if (val == 0)
316 break;
317 }
318 /* shift stuff down */
319 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000320 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000321}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000322
323static void __init prom_printf(const char *format, ...)
324{
325 const char *p, *q, *s;
326 va_list args;
327 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000328 long vs;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000329
330 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000331 for (p = format; *p != 0; p = q) {
332 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
333 ;
334 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000335 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000336 if (*q == 0)
337 break;
338 if (*q == '\n') {
339 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000340 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000341 ADDR("\r\n"), 2);
342 continue;
343 }
344 ++q;
345 if (*q == 0)
346 break;
347 switch (*q) {
348 case 's':
349 ++q;
350 s = va_arg(args, const char *);
351 prom_print(s);
352 break;
353 case 'x':
354 ++q;
355 v = va_arg(args, unsigned long);
356 prom_print_hex(v);
357 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000358 case 'd':
359 ++q;
360 vs = va_arg(args, int);
361 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000362 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000363 vs = -vs;
364 }
365 prom_print_dec(vs);
366 break;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000367 case 'l':
368 ++q;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000369 if (*q == 0)
370 break;
371 else if (*q == 'x') {
372 ++q;
373 v = va_arg(args, unsigned long);
374 prom_print_hex(v);
375 } else if (*q == 'u') { /* '%lu' */
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000376 ++q;
377 v = va_arg(args, unsigned long);
378 prom_print_dec(v);
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000379 } else if (*q == 'd') { /* %ld */
380 ++q;
381 vs = va_arg(args, long);
382 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000383 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000384 vs = -vs;
385 }
386 prom_print_dec(vs);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000387 }
388 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000389 }
390 }
391}
392
393
Paul Mackerrasa575b802005-10-23 17:23:21 +1000394static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
395 unsigned long align)
396{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000397
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100398 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
399 /*
400 * Old OF requires we claim physical and virtual separately
401 * and then map explicitly (assuming virtual mode)
402 */
403 int ret;
404 prom_arg_t result;
405
406 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000407 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100408 align, size, virt);
409 if (ret != 0 || result == -1)
410 return -1;
411 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000412 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100413 align, size, virt);
414 if (ret != 0) {
415 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000416 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100417 return -1;
418 }
419 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000420 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000421 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100422 return virt;
423 }
424 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
425 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000426}
427
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000428static void __init __attribute__((noreturn)) prom_panic(const char *reason)
429{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000430 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100431 /* Do not call exit because it clears the screen on pmac
432 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000433 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100434 asm("trap\n");
435
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000436 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000437 call_prom("exit", 0, 0);
438
439 for (;;) /* should never get here */
440 ;
441}
442
443
444static int __init prom_next_node(phandle *nodep)
445{
446 phandle node;
447
448 if ((node = *nodep) != 0
449 && (*nodep = call_prom("child", 1, 1, node)) != 0)
450 return 1;
451 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
452 return 1;
453 for (;;) {
454 if ((node = call_prom("parent", 1, 1, node)) == 0)
455 return 0;
456 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
457 return 1;
458 }
459}
460
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +1100461static int inline prom_getprop(phandle node, const char *pname,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000462 void *value, size_t valuelen)
463{
464 return call_prom("getprop", 4, 1, node, ADDR(pname),
465 (u32)(unsigned long) value, (u32) valuelen);
466}
467
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +1100468static int inline prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000469{
470 return call_prom("getproplen", 2, 1, node, ADDR(pname));
471}
472
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100473static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000474{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100475 char *p = *str;
476
477 while (*q)
478 *p++ = *q++;
479 *p++ = ' ';
480 *str = p;
481}
482
483static char *tohex(unsigned int x)
484{
485 static char digits[] = "0123456789abcdef";
486 static char result[9];
487 int i;
488
489 result[8] = 0;
490 i = 8;
491 do {
492 --i;
493 result[i] = digits[x & 0xf];
494 x >>= 4;
495 } while (x != 0 && i > 0);
496 return &result[i];
497}
498
499static int __init prom_setprop(phandle node, const char *nodename,
500 const char *pname, void *value, size_t valuelen)
501{
502 char cmd[256], *p;
503
504 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
505 return call_prom("setprop", 4, 1, node, ADDR(pname),
506 (u32)(unsigned long) value, (u32) valuelen);
507
508 /* gah... setprop doesn't work on longtrail, have to use interpret */
509 p = cmd;
510 add_string(&p, "dev");
511 add_string(&p, nodename);
512 add_string(&p, tohex((u32)(unsigned long) value));
513 add_string(&p, tohex(valuelen));
514 add_string(&p, tohex(ADDR(pname)));
Anton Blanchard5827d412012-11-26 17:40:03 +0000515 add_string(&p, tohex(strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100516 add_string(&p, "property");
517 *p = 0;
518 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000519}
520
Anton Blanchard5827d412012-11-26 17:40:03 +0000521/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000522#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
523 || ('a' <= (c) && (c) <= 'f') \
524 || ('A' <= (c) && (c) <= 'F'))
525
526#define isdigit(c) ('0' <= (c) && (c) <= '9')
527#define islower(c) ('a' <= (c) && (c) <= 'z')
528#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
529
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000530static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000531{
532 unsigned long result = 0, base = 10, value;
533
534 if (*cp == '0') {
535 base = 8;
536 cp++;
537 if (toupper(*cp) == 'X') {
538 cp++;
539 base = 16;
540 }
541 }
542
543 while (isxdigit(*cp) &&
544 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
545 result = result * base + value;
546 cp++;
547 }
548
549 if (endp)
550 *endp = cp;
551
552 return result;
553}
554
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000555static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000556{
557 unsigned long ret = prom_strtoul(ptr, retptr);
558 int shift = 0;
559
560 /*
561 * We can't use a switch here because GCC *may* generate a
562 * jump table which won't work, because we're not running at
563 * the address we're linked at.
564 */
565 if ('G' == **retptr || 'g' == **retptr)
566 shift = 30;
567
568 if ('M' == **retptr || 'm' == **retptr)
569 shift = 20;
570
571 if ('K' == **retptr || 'k' == **retptr)
572 shift = 10;
573
574 if (shift) {
575 ret <<= shift;
576 (*retptr)++;
577 }
578
579 return ret;
580}
581
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000582/*
583 * Early parsing of the command line passed to the kernel, used for
584 * "mem=x" and the options that affect the iommu
585 */
586static void __init early_cmdline_parse(void)
587{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100588 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000589
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100590 char *p;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000591 int l = 0;
592
Anton Blanchard5827d412012-11-26 17:40:03 +0000593 prom_cmd_line[0] = 0;
594 p = prom_cmd_line;
595 if ((long)prom.chosen > 0)
596 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000597#ifdef CONFIG_CMDLINE
Amos Waterland0e4aa9c2006-06-12 23:45:02 -0400598 if (l <= 0 || p[0] == '\0') /* dbl check */
Anton Blanchard5827d412012-11-26 17:40:03 +0000599 strlcpy(prom_cmd_line,
600 CONFIG_CMDLINE, sizeof(prom_cmd_line));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000601#endif /* CONFIG_CMDLINE */
Anton Blanchard5827d412012-11-26 17:40:03 +0000602 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000603
604#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +0000605 opt = strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000606 if (opt) {
607 prom_printf("iommu opt is: %s\n", opt);
608 opt += 6;
609 while (*opt && *opt == ' ')
610 opt++;
Anton Blanchard5827d412012-11-26 17:40:03 +0000611 if (!strncmp(opt, "off", 3))
612 prom_iommu_off = 1;
613 else if (!strncmp(opt, "force", 5))
614 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000615 }
616#endif
Anton Blanchard5827d412012-11-26 17:40:03 +0000617 opt = strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000618 if (opt) {
619 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000620 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000621#ifdef CONFIG_PPC64
622 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000623 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000624#endif
625 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000626}
627
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000628#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000629/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000630 * The architecture vector has an array of PVR mask/value pairs,
631 * followed by # option vectors - 1, followed by the option vectors.
632 *
633 * See prom.h for the definition of the bits specified in the
634 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000635 *
636 * Because the description vector contains a mix of byte and word
637 * values, we declare it as an unsigned char array, and use this
638 * macro to put word values in.
639 */
640#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
641 ((x) >> 8) & 0xff, (x) & 0xff
642
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000643unsigned char ibm_architecture_vec[] = {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000644 W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
Anton Blanchard03054d52006-04-29 09:51:06 +1000645 W(0xffff0000), W(0x003e0000), /* POWER6 */
Michael Neulinge952e6c2008-06-18 10:47:26 +1000646 W(0xffff0000), W(0x003f0000), /* POWER7 */
Michael Neuling33959f82013-07-18 11:31:51 +1000647 W(0xffff0000), W(0x004b0000), /* POWER8E */
648 W(0xffff0000), W(0x004d0000), /* POWER8 */
Michael Neulingdf77c792012-11-08 20:23:11 +0000649 W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
Joel Schopp0cb99012008-06-19 06:23:23 +1000650 W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
Paul Mackerras0efbc182006-11-29 22:31:47 +1100651 W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000652 W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000653 6 - 1, /* 6 option vectors */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000654
655 /* option vector 1: processor architectures supported */
Will Schmidt11e9ed42006-08-25 15:46:59 -0500656 3 - 2, /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000657 0, /* don't ignore, don't halt */
658 OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
Michael Neulingdf77c792012-11-08 20:23:11 +0000659 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000660
661 /* option vector 2: Open Firmware options supported */
Will Schmidt11e9ed42006-08-25 15:46:59 -0500662 34 - 2, /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000663 OV2_REAL_MODE,
664 0, 0,
665 W(0xffffffff), /* real_base */
666 W(0xffffffff), /* real_size */
667 W(0xffffffff), /* virt_base */
668 W(0xffffffff), /* virt_size */
669 W(0xffffffff), /* load_base */
Anton Blanchard33392642011-12-04 13:13:58 +0000670 W(256), /* 256MB min RMA */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000671 W(0xffffffff), /* full client load */
672 0, /* min RMA percentage of total RAM */
673 48, /* max log_2(hash table size) */
674
675 /* option vector 3: processor options supported */
Will Schmidt11e9ed42006-08-25 15:46:59 -0500676 3 - 2, /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000677 0, /* don't ignore, don't halt */
Paul Mackerras974a76f2006-11-10 20:38:53 +1100678 OV3_FP | OV3_VMX | OV3_DFP,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000679
680 /* option vector 4: IBM PAPR implementation */
Robert Jennings404e32e2012-05-10 08:55:49 +0000681 3 - 2, /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000682 0, /* don't halt */
Robert Jennings404e32e2012-05-10 08:55:49 +0000683 OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000684
685 /* option vector 5: PAPR/OF options */
Michael Neulingdf77c792012-11-08 20:23:11 +0000686 19 - 2, /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000687 0, /* don't ignore, don't halt */
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000688 OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
689 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
690#ifdef CONFIG_PCI_MSI
691 /* PCIe/MSI support. Without MSI full PCIe is not supported */
692 OV5_FEAT(OV5_MSI),
693#else
Nathan Fontenot8391e422008-07-24 04:36:38 +1000694 0,
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000695#endif
696 0,
697#ifdef CONFIG_PPC_SMLPAR
698 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
699#else
700 0,
701#endif
Nathan Fontenot1b1218d2013-04-24 06:06:17 +0000702 OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000703 0,
704 0,
705 0,
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100706 /* WARNING: The offset of the "number of cores" field below
707 * must match by the macro below. Update the definition if
708 * the structure layout changes.
709 */
Michael Neuling33959f82013-07-18 11:31:51 +1000710#define IBM_ARCH_VEC_NRCORES_OFFSET 125
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100711 W(NR_CPUS), /* number of cores supported */
Kent Yoder828d2b52012-04-12 05:17:51 +0000712 0,
713 0,
714 0,
715 0,
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000716 OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
717 OV5_FEAT(OV5_PFO_HW_842),
718 OV5_FEAT(OV5_SUB_PROCESSORS),
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000719 /* option vector 6: IBM PAPR hints */
720 4 - 2, /* length */
721 0,
722 0,
723 OV6_LINUX,
724
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000725};
726
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000727/* Old method - ELF header with PT_NOTE sections only works on BE */
728#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000729static struct fake_elf {
730 Elf32_Ehdr elfhdr;
731 Elf32_Phdr phdr[2];
732 struct chrpnote {
733 u32 namesz;
734 u32 descsz;
735 u32 type;
736 char name[8]; /* "PowerPC" */
737 struct chrpdesc {
738 u32 real_mode;
739 u32 real_base;
740 u32 real_size;
741 u32 virt_base;
742 u32 virt_size;
743 u32 load_base;
744 } chrpdesc;
745 } chrpnote;
746 struct rpanote {
747 u32 namesz;
748 u32 descsz;
749 u32 type;
750 char name[24]; /* "IBM,RPA-Client-Config" */
751 struct rpadesc {
752 u32 lpar_affinity;
753 u32 min_rmo_size;
754 u32 min_rmo_percent;
755 u32 max_pft_size;
756 u32 splpar;
757 u32 min_load;
758 u32 new_mem_def;
759 u32 ignore_me;
760 } rpadesc;
761 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100762} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000763 .elfhdr = {
764 .e_ident = { 0x7f, 'E', 'L', 'F',
765 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
766 .e_type = ET_EXEC, /* yeah right */
767 .e_machine = EM_PPC,
768 .e_version = EV_CURRENT,
769 .e_phoff = offsetof(struct fake_elf, phdr),
770 .e_phentsize = sizeof(Elf32_Phdr),
771 .e_phnum = 2
772 },
773 .phdr = {
774 [0] = {
775 .p_type = PT_NOTE,
776 .p_offset = offsetof(struct fake_elf, chrpnote),
777 .p_filesz = sizeof(struct chrpnote)
778 }, [1] = {
779 .p_type = PT_NOTE,
780 .p_offset = offsetof(struct fake_elf, rpanote),
781 .p_filesz = sizeof(struct rpanote)
782 }
783 },
784 .chrpnote = {
785 .namesz = sizeof("PowerPC"),
786 .descsz = sizeof(struct chrpdesc),
787 .type = 0x1275,
788 .name = "PowerPC",
789 .chrpdesc = {
790 .real_mode = ~0U, /* ~0 means "don't care" */
791 .real_base = ~0U,
792 .real_size = ~0U,
793 .virt_base = ~0U,
794 .virt_size = ~0U,
795 .load_base = ~0U
796 },
797 },
798 .rpanote = {
799 .namesz = sizeof("IBM,RPA-Client-Config"),
800 .descsz = sizeof(struct rpadesc),
801 .type = 0x12759999,
802 .name = "IBM,RPA-Client-Config",
803 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +1100804 .lpar_affinity = 0,
805 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000806 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +1100807 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000808 .splpar = 1,
809 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +1100810 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000811 }
812 }
813};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000814#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000815
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100816static int __init prom_count_smt_threads(void)
817{
818 phandle node;
819 char type[64];
820 unsigned int plen;
821
822 /* Pick up th first CPU node we can find */
823 for (node = 0; prom_next_node(&node); ) {
824 type[0] = 0;
825 prom_getprop(node, "device_type", type, sizeof(type));
826
Anton Blanchard5827d412012-11-26 17:40:03 +0000827 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100828 continue;
829 /*
830 * There is an entry for each smt thread, each entry being
831 * 4 bytes long. All cpus should have the same number of
832 * smt threads, so return after finding the first.
833 */
834 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
835 if (plen == PROM_ERROR)
836 break;
837 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000838 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100839
840 /* Sanity check */
841 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000842 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100843 (unsigned long)plen);
844 return 1;
845 }
846 return plen;
847 }
848 prom_debug("No threads found, assuming 1 per core\n");
849
850 return 1;
851
852}
853
854
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000855static void __init prom_send_capabilities(void)
856{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000857 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000858 prom_arg_t ret;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000859 __be32 *cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000860
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000861 root = call_prom("open", 1, 1, ADDR("/"));
862 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100863 /* We need to tell the FW about the number of cores we support.
864 *
865 * To do that, we count the number of threads on the first core
866 * (we assume this is the same for all cores) and use it to
867 * divide NR_CPUS.
868 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000869 cores = (__be32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
870 if (be32_to_cpup(cores) != NR_CPUS) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100871 prom_printf("WARNING ! "
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000872 "ibm_architecture_vec structure inconsistent: %lu!\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000873 be32_to_cpup(cores));
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100874 } else {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000875 *cores = cpu_to_be32(DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()));
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000876 prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000877 be32_to_cpup(cores), NR_CPUS);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100878 }
879
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000880 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +0000881 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000882 if (call_prom_ret("call-method", 3, 2, &ret,
883 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +1000884 root,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000885 ADDR(ibm_architecture_vec)) == 0) {
886 /* the call exists... */
887 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +0000888 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000889 "-support call FAILED!\n");
890 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +0000891 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000892 return;
893 }
894 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +0000895 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000896 }
897
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000898#ifdef __BIG_ENDIAN__
899 {
900 ihandle elfloader;
901
902 /* no ibm,client-architecture-support call, try the old way */
903 elfloader = call_prom("open", 1, 1,
904 ADDR("/packages/elf-loader"));
905 if (elfloader == 0) {
906 prom_printf("couldn't open /packages/elf-loader\n");
907 return;
908 }
909 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
910 elfloader, ADDR(&fake_elf));
911 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000912 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000913#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000914}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000915#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000916
917/*
918 * Memory allocation strategy... our layout is normally:
919 *
920 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
921 * rare cases, initrd might end up being before the kernel though.
922 * We assume this won't override the final kernel at 0, we have no
923 * provision to handle that in this version, but it should hopefully
924 * never happen.
925 *
926 * alloc_top is set to the top of RMO, eventually shrink down if the
927 * TCEs overlap
928 *
929 * alloc_bottom is set to the top of kernel/initrd
930 *
931 * from there, allocations are done this way : rtas is allocated
932 * topmost, and the device-tree is allocated from the bottom. We try
933 * to grow the device-tree allocation as we progress. If we can't,
934 * then we fail, we don't currently have a facility to restart
935 * elsewhere, but that shouldn't be necessary.
936 *
937 * Note that calls to reserve_mem have to be done explicitly, memory
938 * allocated with either alloc_up or alloc_down isn't automatically
939 * reserved.
940 */
941
942
943/*
944 * Allocates memory in the RMO upward from the kernel/initrd
945 *
946 * When align is 0, this is a special case, it means to allocate in place
947 * at the current location of alloc_bottom or fail (that is basically
948 * extending the previous allocation). Used for the device-tree flattening
949 */
950static unsigned long __init alloc_up(unsigned long size, unsigned long align)
951{
Anton Blanchard5827d412012-11-26 17:40:03 +0000952 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000953 unsigned long addr = 0;
954
Paul Mackerrasc49888202005-10-26 21:52:53 +1000955 if (align)
956 base = _ALIGN_UP(base, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000957 prom_debug("alloc_up(%x, %x)\n", size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +0000958 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000959 prom_panic("alloc_up() called with mem not initialized\n");
960
961 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +0000962 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000963 else
Anton Blanchard5827d412012-11-26 17:40:03 +0000964 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000965
Anton Blanchard5827d412012-11-26 17:40:03 +0000966 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000967 base = _ALIGN_UP(base + 0x100000, align)) {
968 prom_debug(" trying: 0x%x\n\r", base);
969 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +1000970 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000971 break;
972 addr = 0;
973 if (align == 0)
974 break;
975 }
976 if (addr == 0)
977 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +0000978 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000979
980 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +0000981 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
982 prom_debug(" alloc_top : %x\n", alloc_top);
983 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
984 prom_debug(" rmo_top : %x\n", rmo_top);
985 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000986
987 return addr;
988}
989
990/*
991 * Allocates memory downward, either from top of RMO, or if highmem
992 * is set, from the top of RAM. Note that this one doesn't handle
993 * failures. It does claim memory if highmem is not set.
994 */
995static unsigned long __init alloc_down(unsigned long size, unsigned long align,
996 int highmem)
997{
998 unsigned long base, addr = 0;
999
1000 prom_debug("alloc_down(%x, %x, %s)\n", size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001001 highmem ? "(high)" : "(low)");
1002 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001003 prom_panic("alloc_down() called with mem not initialized\n");
1004
1005 if (highmem) {
1006 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001007 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1008 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001009 return 0;
1010 /* Will we bump into the RMO ? If yes, check out that we
1011 * didn't overlap existing allocations there, if we did,
1012 * we are dead, we must be the first in town !
1013 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001014 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001015 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001016 if (alloc_top == rmo_top)
1017 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001018 else
1019 return 0;
1020 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001021 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001022 goto bail;
1023 }
1024
Anton Blanchard5827d412012-11-26 17:40:03 +00001025 base = _ALIGN_DOWN(alloc_top - size, align);
1026 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001027 base = _ALIGN_DOWN(base - 0x100000, align)) {
1028 prom_debug(" trying: 0x%x\n\r", base);
1029 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001030 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001031 break;
1032 addr = 0;
1033 }
1034 if (addr == 0)
1035 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001036 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001037
1038 bail:
1039 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001040 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1041 prom_debug(" alloc_top : %x\n", alloc_top);
1042 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1043 prom_debug(" rmo_top : %x\n", rmo_top);
1044 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001045
1046 return addr;
1047}
1048
1049/*
1050 * Parse a "reg" cell
1051 */
1052static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1053{
1054 cell_t *p = *cellp;
1055 unsigned long r = 0;
1056
1057 /* Ignore more than 2 cells */
1058 while (s > sizeof(unsigned long) / 4) {
1059 p++;
1060 s--;
1061 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001062 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001063#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001064 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001065 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001066 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001067 }
1068#endif
1069 *cellp = p;
1070 return r;
1071}
1072
1073/*
1074 * Very dumb function for adding to the memory reserve list, but
1075 * we don't need anything smarter at this point
1076 *
1077 * XXX Eventually check for collisions. They should NEVER happen.
1078 * If problems seem to show up, it would be a good start to track
1079 * them down.
1080 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001081static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001082{
Kumar Galacbbcf342006-01-11 17:57:13 -06001083 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001084 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001085
1086 if (size == 0)
1087 return;
1088
1089 /* We need to always keep one empty entry so that we
1090 * have our terminator with "size" set to 0 since we are
1091 * dumb and just copy this entire array to the boot params
1092 */
1093 base = _ALIGN_DOWN(base, PAGE_SIZE);
1094 top = _ALIGN_UP(top, PAGE_SIZE);
1095 size = top - base;
1096
1097 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1098 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001099 mem_reserve_map[cnt].base = cpu_to_be64(base);
1100 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001101 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001102}
1103
1104/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001105 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001106 * obtain that way the top of memory and RMO to setup out local allocator
1107 */
1108static void __init prom_init_mem(void)
1109{
1110 phandle node;
1111 char *path, type[64];
1112 unsigned int plen;
1113 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001114 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001115 u32 rac, rsc;
1116
1117 /*
1118 * We iterate the memory nodes to find
1119 * 1) top of RMO (first node)
1120 * 2) top of memory
1121 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001122 val = cpu_to_be32(2);
1123 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1124 rac = be32_to_cpu(val);
1125 val = cpu_to_be32(1);
1126 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1127 rsc = be32_to_cpu(val);
1128 prom_debug("root_addr_cells: %x\n", rac);
1129 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001130
1131 prom_debug("scanning memory:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001132 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001133
1134 for (node = 0; prom_next_node(&node); ) {
1135 type[0] = 0;
1136 prom_getprop(node, "device_type", type, sizeof(type));
1137
Paul Mackerrasc49888202005-10-26 21:52:53 +10001138 if (type[0] == 0) {
1139 /*
1140 * CHRP Longtrail machines have no device_type
1141 * on the memory node, so check the name instead...
1142 */
1143 prom_getprop(node, "name", type, sizeof(type));
1144 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001145 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001146 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001147
Anton Blanchard5827d412012-11-26 17:40:03 +00001148 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001149 if (plen > sizeof(regbuf)) {
1150 prom_printf("memory node too large for buffer !\n");
1151 plen = sizeof(regbuf);
1152 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001153 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001154 endp = p + (plen / sizeof(cell_t));
1155
1156#ifdef DEBUG_PROM
1157 memset(path, 0, PROM_SCRATCH_SIZE);
1158 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1159 prom_debug(" node %s :\n", path);
1160#endif /* DEBUG_PROM */
1161
1162 while ((endp - p) >= (rac + rsc)) {
1163 unsigned long base, size;
1164
1165 base = prom_next_cell(rac, &p);
1166 size = prom_next_cell(rsc, &p);
1167
1168 if (size == 0)
1169 continue;
1170 prom_debug(" %x %x\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001171 if (base == 0 && (of_platform & PLATFORM_LPAR))
1172 rmo_top = size;
1173 if ((base + size) > ram_top)
1174 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001175 }
1176 }
1177
Anton Blanchard5827d412012-11-26 17:40:03 +00001178 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001179
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001180 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001181 * If prom_memory_limit is set we reduce the upper limits *except* for
1182 * alloc_top_high. This must be the real top of RAM so we can put
1183 * TCE's up there.
1184 */
1185
Anton Blanchard5827d412012-11-26 17:40:03 +00001186 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001187
Anton Blanchard5827d412012-11-26 17:40:03 +00001188 if (prom_memory_limit) {
1189 if (prom_memory_limit <= alloc_bottom) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001190 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001191 prom_memory_limit);
1192 prom_memory_limit = 0;
1193 } else if (prom_memory_limit >= ram_top) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001194 prom_printf("Ignoring mem=%x >= ram_top.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001195 prom_memory_limit);
1196 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001197 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001198 ram_top = prom_memory_limit;
1199 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001200 }
1201 }
1202
1203 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001204 * Setup our top alloc point, that is top of RMO or top of
1205 * segment 0 when running non-LPAR.
1206 * Some RS64 machines have buggy firmware where claims up at
1207 * 1GB fail. Cap at 768MB as a workaround.
1208 * Since 768MB is plenty of room, and we need to cap to something
1209 * reasonable on 32-bit, cap at 768MB on all machines.
1210 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001211 if (!rmo_top)
1212 rmo_top = ram_top;
1213 rmo_top = min(0x30000000ul, rmo_top);
1214 alloc_top = rmo_top;
1215 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001216
Paul Mackerras64968f62011-12-13 17:54:13 +00001217 /*
1218 * Check if we have an initrd after the kernel but still inside
1219 * the RMO. If we do move our bottom point to after it.
1220 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001221 if (prom_initrd_start &&
1222 prom_initrd_start < rmo_top &&
1223 prom_initrd_end > alloc_bottom)
1224 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001225
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001226 prom_printf("memory layout at init:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001227 prom_printf(" memory_limit : %x (16 MB aligned)\n", prom_memory_limit);
1228 prom_printf(" alloc_bottom : %x\n", alloc_bottom);
1229 prom_printf(" alloc_top : %x\n", alloc_top);
1230 prom_printf(" alloc_top_hi : %x\n", alloc_top_high);
1231 prom_printf(" rmo_top : %x\n", rmo_top);
1232 prom_printf(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001233}
1234
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001235static void __init prom_close_stdin(void)
1236{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001237 __be32 val;
1238 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001239
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001240 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1241 stdin = be32_to_cpu(val);
1242 call_prom("close", 1, 0, stdin);
1243 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001244}
1245
1246#ifdef CONFIG_PPC_POWERNV
1247
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001248#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1249static u64 __initdata prom_opal_base;
1250static u64 __initdata prom_opal_entry;
1251#endif
1252
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001253#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001254/* XXX Don't change this structure without updating opal-takeover.S */
1255static struct opal_secondary_data {
1256 s64 ack; /* 0 */
1257 u64 go; /* 8 */
1258 struct opal_takeover_args args; /* 16 */
1259} opal_secondary_data;
1260
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001261static u64 __initdata prom_opal_align;
1262static u64 __initdata prom_opal_size;
1263static int __initdata prom_rtas_start_cpu;
1264static u64 __initdata prom_rtas_data;
1265static u64 __initdata prom_rtas_entry;
1266
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001267extern char opal_secondary_entry;
1268
Li Zhong2cb387a2012-06-07 17:44:23 +00001269static void __init prom_query_opal(void)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001270{
1271 long rc;
1272
Benjamin Herrenschmidt76800572011-09-28 20:51:46 +00001273 /* We must not query for OPAL presence on a machine that
1274 * supports TNK takeover (970 blades), as this uses the same
1275 * h-call with different arguments and will crash
1276 */
1277 if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
1278 ADDR("/tnk-memory-map")))) {
1279 prom_printf("TNK takeover detected, skipping OPAL check\n");
1280 return;
1281 }
1282
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001283 prom_printf("Querying for OPAL presence... ");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001284
Anton Blanchard5827d412012-11-26 17:40:03 +00001285 rc = opal_query_takeover(&prom_opal_size,
1286 &prom_opal_align);
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001287 prom_debug("(rc = %ld) ", rc);
1288 if (rc != 0) {
1289 prom_printf("not there.\n");
1290 return;
1291 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001292 of_platform = PLATFORM_OPAL;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001293 prom_printf(" there !\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001294 prom_debug(" opal_size = 0x%lx\n", prom_opal_size);
1295 prom_debug(" opal_align = 0x%lx\n", prom_opal_align);
1296 if (prom_opal_align < 0x10000)
1297 prom_opal_align = 0x10000;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001298}
1299
1300static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
1301{
1302 struct rtas_args rtas_args;
1303 va_list list;
1304 int i;
1305
1306 rtas_args.token = token;
1307 rtas_args.nargs = nargs;
1308 rtas_args.nret = nret;
1309 rtas_args.rets = (rtas_arg_t *)&(rtas_args.args[nargs]);
1310 va_start(list, outputs);
1311 for (i = 0; i < nargs; ++i)
1312 rtas_args.args[i] = va_arg(list, rtas_arg_t);
1313 va_end(list);
1314
1315 for (i = 0; i < nret; ++i)
1316 rtas_args.rets[i] = 0;
1317
Anton Blanchard5827d412012-11-26 17:40:03 +00001318 opal_enter_rtas(&rtas_args, prom_rtas_data,
1319 prom_rtas_entry);
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001320
1321 if (nret > 1 && outputs != NULL)
1322 for (i = 0; i < nret-1; ++i)
1323 outputs[i] = rtas_args.rets[i+1];
1324 return (nret > 0)? rtas_args.rets[0]: 0;
1325}
1326
1327static void __init prom_opal_hold_cpus(void)
1328{
1329 int i, cnt, cpu, rc;
1330 long j;
1331 phandle node;
1332 char type[64];
1333 u32 servers[8];
Anton Blanchard5827d412012-11-26 17:40:03 +00001334 void *entry = (unsigned long *)&opal_secondary_entry;
1335 struct opal_secondary_data *data = &opal_secondary_data;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001336
1337 prom_debug("prom_opal_hold_cpus: start...\n");
1338 prom_debug(" - entry = 0x%x\n", entry);
1339 prom_debug(" - data = 0x%x\n", data);
1340
1341 data->ack = -1;
1342 data->go = 0;
1343
1344 /* look for cpus */
1345 for (node = 0; prom_next_node(&node); ) {
1346 type[0] = 0;
1347 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001348 if (strcmp(type, "cpu") != 0)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001349 continue;
1350
1351 /* Skip non-configured cpus. */
1352 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001353 if (strcmp(type, "okay") != 0)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001354 continue;
1355
1356 cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
1357 sizeof(servers));
1358 if (cnt == PROM_ERROR)
1359 break;
1360 cnt >>= 2;
1361 for (i = 0; i < cnt; i++) {
1362 cpu = servers[i];
1363 prom_debug("CPU %d ... ", cpu);
Anton Blanchard5827d412012-11-26 17:40:03 +00001364 if (cpu == prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001365 prom_debug("booted !\n");
1366 continue;
1367 }
1368 prom_debug("starting ... ");
1369
1370 /* Init the acknowledge var which will be reset by
1371 * the secondary cpu when it awakens from its OF
1372 * spinloop.
1373 */
1374 data->ack = -1;
Anton Blanchard5827d412012-11-26 17:40:03 +00001375 rc = prom_rtas_call(prom_rtas_start_cpu, 3, 1,
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001376 NULL, cpu, entry, data);
1377 prom_debug("rtas rc=%d ...", rc);
1378
1379 for (j = 0; j < 100000000 && data->ack == -1; j++) {
1380 HMT_low();
1381 mb();
1382 }
1383 HMT_medium();
1384 if (data->ack != -1)
1385 prom_debug("done, PIR=0x%x\n", data->ack);
1386 else
1387 prom_debug("timeout !\n");
1388 }
1389 }
1390 prom_debug("prom_opal_hold_cpus: end...\n");
1391}
1392
Li Zhong2cb387a2012-06-07 17:44:23 +00001393static void __init prom_opal_takeover(void)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001394{
Anton Blanchard5827d412012-11-26 17:40:03 +00001395 struct opal_secondary_data *data = &opal_secondary_data;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001396 struct opal_takeover_args *args = &data->args;
Anton Blanchard5827d412012-11-26 17:40:03 +00001397 u64 align = prom_opal_align;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001398 u64 top_addr, opal_addr;
1399
Anton Blanchard5827d412012-11-26 17:40:03 +00001400 args->k_image = (u64)_stext;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001401 args->k_size = _end - _stext;
1402 args->k_entry = 0;
1403 args->k_entry2 = 0x60;
1404
1405 top_addr = _ALIGN_UP(args->k_size, align);
1406
Anton Blanchard5827d412012-11-26 17:40:03 +00001407 if (prom_initrd_start != 0) {
1408 args->rd_image = prom_initrd_start;
1409 args->rd_size = prom_initrd_end - args->rd_image;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001410 args->rd_loc = top_addr;
1411 top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
1412 }
1413
1414 /* Pickup an address for the HAL. We want to go really high
1415 * up to avoid problem with future kexecs. On the other hand
1416 * we don't want to be all over the TCEs on P5IOC2 machines
1417 * which are going to be up there too. We assume the machine
1418 * has plenty of memory, and we ask for the HAL for now to
1419 * be just below the 1G point, or above the initrd
1420 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001421 opal_addr = _ALIGN_DOWN(0x40000000 - prom_opal_size, align);
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001422 if (opal_addr < top_addr)
1423 opal_addr = top_addr;
1424 args->hal_addr = opal_addr;
1425
Benjamin Herrenschmidt817c21a2011-09-19 17:44:56 +00001426 /* Copy the command line to the kernel image */
Anton Blanchard5827d412012-11-26 17:40:03 +00001427 strlcpy(boot_command_line, prom_cmd_line,
Benjamin Herrenschmidt817c21a2011-09-19 17:44:56 +00001428 COMMAND_LINE_SIZE);
1429
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001430 prom_debug(" k_image = 0x%lx\n", args->k_image);
1431 prom_debug(" k_size = 0x%lx\n", args->k_size);
1432 prom_debug(" k_entry = 0x%lx\n", args->k_entry);
1433 prom_debug(" k_entry2 = 0x%lx\n", args->k_entry2);
1434 prom_debug(" hal_addr = 0x%lx\n", args->hal_addr);
1435 prom_debug(" rd_image = 0x%lx\n", args->rd_image);
1436 prom_debug(" rd_size = 0x%lx\n", args->rd_size);
1437 prom_debug(" rd_loc = 0x%lx\n", args->rd_loc);
1438 prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
1439 prom_close_stdin();
1440 mb();
1441 data->go = 1;
1442 for (;;)
1443 opal_do_takeover(args);
1444}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001445#endif /* __BIG_ENDIAN__ */
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001446
1447/*
1448 * Allocate room for and instantiate OPAL
1449 */
1450static void __init prom_instantiate_opal(void)
1451{
1452 phandle opal_node;
1453 ihandle opal_inst;
1454 u64 base, entry;
1455 u64 size = 0, align = 0x10000;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001456 __be64 val64;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001457 u32 rets[2];
1458
1459 prom_debug("prom_instantiate_opal: start...\n");
1460
1461 opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
1462 prom_debug("opal_node: %x\n", opal_node);
1463 if (!PHANDLE_VALID(opal_node))
1464 return;
1465
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001466 val64 = 0;
1467 prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64));
1468 size = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001469 if (size == 0)
1470 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001471 val64 = 0;
1472 prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64));
1473 align = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001474
1475 base = alloc_down(size, align, 0);
1476 if (base == 0) {
1477 prom_printf("OPAL allocation failed !\n");
1478 return;
1479 }
1480
1481 opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
1482 if (!IHANDLE_VALID(opal_inst)) {
1483 prom_printf("opening opal package failed (%x)\n", opal_inst);
1484 return;
1485 }
1486
1487 prom_printf("instantiating opal at 0x%x...", base);
1488
1489 if (call_prom_ret("call-method", 4, 3, rets,
1490 ADDR("load-opal-runtime"),
1491 opal_inst,
1492 base >> 32, base & 0xffffffff) != 0
1493 || (rets[0] == 0 && rets[1] == 0)) {
1494 prom_printf(" failed\n");
1495 return;
1496 }
1497 entry = (((u64)rets[0]) << 32) | rets[1];
1498
1499 prom_printf(" done\n");
1500
1501 reserve_mem(base, size);
1502
1503 prom_debug("opal base = 0x%x\n", base);
1504 prom_debug("opal align = 0x%x\n", align);
1505 prom_debug("opal entry = 0x%x\n", entry);
1506 prom_debug("opal size = 0x%x\n", (long)size);
1507
1508 prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
1509 &base, sizeof(base));
1510 prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
1511 &entry, sizeof(entry));
1512
1513#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
Anton Blanchard5827d412012-11-26 17:40:03 +00001514 prom_opal_base = base;
1515 prom_opal_entry = entry;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001516#endif
1517 prom_debug("prom_instantiate_opal: end...\n");
1518}
1519
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001520#endif /* CONFIG_PPC_POWERNV */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001521
1522/*
1523 * Allocate room for and instantiate RTAS
1524 */
1525static void __init prom_instantiate_rtas(void)
1526{
1527 phandle rtas_node;
1528 ihandle rtas_inst;
1529 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001530 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001531 u32 size = 0;
1532
1533 prom_debug("prom_instantiate_rtas: start...\n");
1534
1535 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1536 prom_debug("rtas_node: %x\n", rtas_node);
1537 if (!PHANDLE_VALID(rtas_node))
1538 return;
1539
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001540 val = 0;
1541 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1542 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001543 if (size == 0)
1544 return;
1545
1546 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001547 if (base == 0)
1548 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001549
1550 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1551 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001552 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001553 return;
1554 }
1555
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001556 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001557
1558 if (call_prom_ret("call-method", 3, 2, &entry,
1559 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001560 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001561 || entry == 0) {
1562 prom_printf(" failed\n");
1563 return;
1564 }
1565 prom_printf(" done\n");
1566
1567 reserve_mem(base, size);
1568
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001569 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001570 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001571 &val, sizeof(val));
1572 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001573 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001574 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001575
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001576#if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001577 /* PowerVN takeover hack */
Anton Blanchard5827d412012-11-26 17:40:03 +00001578 prom_rtas_data = base;
1579 prom_rtas_entry = entry;
1580 prom_getprop(rtas_node, "start-cpu", &prom_rtas_start_cpu, 4);
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001581#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001582 prom_debug("rtas base = 0x%x\n", base);
1583 prom_debug("rtas entry = 0x%x\n", entry);
1584 prom_debug("rtas size = 0x%x\n", (long)size);
1585
1586 prom_debug("prom_instantiate_rtas: end...\n");
1587}
1588
1589#ifdef CONFIG_PPC64
1590/*
Ashley Lai4a727422012-08-14 18:34:57 -05001591 * Allocate room for and instantiate Stored Measurement Log (SML)
1592 */
1593static void __init prom_instantiate_sml(void)
1594{
1595 phandle ibmvtpm_node;
1596 ihandle ibmvtpm_inst;
1597 u32 entry = 0, size = 0;
1598 u64 base;
1599
1600 prom_debug("prom_instantiate_sml: start...\n");
1601
1602 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/ibm,vtpm"));
1603 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1604 if (!PHANDLE_VALID(ibmvtpm_node))
1605 return;
1606
1607 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/ibm,vtpm"));
1608 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1609 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1610 return;
1611 }
1612
1613 if (call_prom_ret("call-method", 2, 2, &size,
1614 ADDR("sml-get-handover-size"),
1615 ibmvtpm_inst) != 0 || size == 0) {
1616 prom_printf("SML get handover size failed\n");
1617 return;
1618 }
1619
1620 base = alloc_down(size, PAGE_SIZE, 0);
1621 if (base == 0)
1622 prom_panic("Could not allocate memory for sml\n");
1623
1624 prom_printf("instantiating sml at 0x%x...", base);
1625
1626 if (call_prom_ret("call-method", 4, 2, &entry,
1627 ADDR("sml-handover"),
1628 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1629 prom_printf("SML handover failed\n");
1630 return;
1631 }
1632 prom_printf(" done\n");
1633
1634 reserve_mem(base, size);
1635
1636 prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-base",
1637 &base, sizeof(base));
1638 prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-size",
1639 &size, sizeof(size));
1640
1641 prom_debug("sml base = 0x%x\n", base);
1642 prom_debug("sml size = 0x%x\n", (long)size);
1643
1644 prom_debug("prom_instantiate_sml: end...\n");
1645}
1646
1647/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001648 * Allocate room for and initialize TCE tables
1649 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001650#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001651static void __init prom_initialize_tce_table(void)
1652{
1653 phandle node;
1654 ihandle phb_node;
1655 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001656 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001657 u64 base, align;
1658 u32 minalign, minsize;
1659 u64 tce_entry, *tce_entryp;
1660 u64 local_alloc_top, local_alloc_bottom;
1661 u64 i;
1662
Anton Blanchard5827d412012-11-26 17:40:03 +00001663 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001664 return;
1665
1666 prom_debug("starting prom_initialize_tce_table\n");
1667
1668 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001669 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001670 local_alloc_bottom = local_alloc_top;
1671
1672 /* Search all nodes looking for PHBs. */
1673 for (node = 0; prom_next_node(&node); ) {
1674 compatible[0] = 0;
1675 type[0] = 0;
1676 model[0] = 0;
1677 prom_getprop(node, "compatible",
1678 compatible, sizeof(compatible));
1679 prom_getprop(node, "device_type", type, sizeof(type));
1680 prom_getprop(node, "model", model, sizeof(model));
1681
Anton Blanchard5827d412012-11-26 17:40:03 +00001682 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001683 continue;
1684
Linas Vepstase788ff12007-09-07 03:45:21 +10001685 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001686 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001687 if ((strstr(compatible, "python") == NULL) &&
1688 (strstr(compatible, "Speedwagon") == NULL) &&
1689 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001690 continue;
1691 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001692 if ((strstr(model, "ython") == NULL) &&
1693 (strstr(model, "peedwagon") == NULL) &&
1694 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001695 continue;
1696 }
1697
1698 if (prom_getprop(node, "tce-table-minalign", &minalign,
1699 sizeof(minalign)) == PROM_ERROR)
1700 minalign = 0;
1701 if (prom_getprop(node, "tce-table-minsize", &minsize,
1702 sizeof(minsize)) == PROM_ERROR)
1703 minsize = 4UL << 20;
1704
1705 /*
1706 * Even though we read what OF wants, we just set the table
1707 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1708 * By doing this, we avoid the pitfalls of trying to DMA to
1709 * MMIO space and the DMA alias hole.
1710 *
1711 * On POWER4, firmware sets the TCE region by assuming
1712 * each TCE table is 8MB. Using this memory for anything
1713 * else will impact performance, so we always allocate 8MB.
1714 * Anton
1715 */
Michael Ellermand3dbeef2012-08-19 21:44:01 +00001716 if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001717 minsize = 8UL << 20;
1718 else
1719 minsize = 4UL << 20;
1720
1721 /* Align to the greater of the align or size */
1722 align = max(minalign, minsize);
1723 base = alloc_down(minsize, align, 1);
1724 if (base == 0)
1725 prom_panic("ERROR, cannot find space for TCE table.\n");
1726 if (base < local_alloc_bottom)
1727 local_alloc_bottom = base;
1728
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001729 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001730 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001731 /* Call OF to setup the TCE hardware */
1732 if (call_prom("package-to-path", 3, 1, node,
1733 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1734 prom_printf("package-to-path failed\n");
1735 }
1736
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001737 /* Save away the TCE table attributes for later use. */
1738 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1739 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1740
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001741 prom_debug("TCE table: %s\n", path);
1742 prom_debug("\tnode = 0x%x\n", node);
1743 prom_debug("\tbase = 0x%x\n", base);
1744 prom_debug("\tsize = 0x%x\n", minsize);
1745
1746 /* Initialize the table to have a one-to-one mapping
1747 * over the allocated size.
1748 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001749 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001750 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1751 tce_entry = (i << PAGE_SHIFT);
1752 tce_entry |= 0x3;
1753 *tce_entryp = tce_entry;
1754 }
1755
1756 prom_printf("opening PHB %s", path);
1757 phb_node = call_prom("open", 1, 1, path);
1758 if (phb_node == 0)
1759 prom_printf("... failed\n");
1760 else
1761 prom_printf("... done\n");
1762
1763 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1764 phb_node, -1, minsize,
1765 (u32) base, (u32) (base >> 32));
1766 call_prom("close", 1, 0, phb_node);
1767 }
1768
1769 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1770
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001771 /* These are only really needed if there is a memory limit in
1772 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001773 prom_tce_alloc_start = local_alloc_bottom;
1774 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001775
1776 /* Flag the first invalid entry */
1777 prom_debug("ending prom_initialize_tce_table\n");
1778}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001779#endif /* __BIG_ENDIAN__ */
1780#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001781
1782/*
1783 * With CHRP SMP we need to use the OF to start the other processors.
1784 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1785 * so we have to put the processors into a holding pattern controlled
1786 * by the kernel (not OF) before we destroy the OF.
1787 *
1788 * This uses a chunk of low memory, puts some holding pattern
1789 * code there and sends the other processors off to there until
1790 * smp_boot_cpus tells them to do something. The holding pattern
1791 * checks that address until its cpu # is there, when it is that
1792 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1793 * of setting those values.
1794 *
1795 * We also use physical address 0x4 here to tell when a cpu
1796 * is in its holding pattern code.
1797 *
1798 * -- Cort
1799 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001800/*
1801 * We want to reference the copy of __secondary_hold_* in the
1802 * 0 - 0x100 address range
1803 */
1804#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1805
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001806static void __init prom_hold_cpus(void)
1807{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001808 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001809 phandle node;
1810 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001811 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001812 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001813 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001814 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001815 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001816
1817 prom_debug("prom_hold_cpus: start...\n");
1818 prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
1819 prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
1820 prom_debug(" 1) acknowledge = 0x%x\n",
1821 (unsigned long)acknowledge);
1822 prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
1823 prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
1824
1825 /* Set the common spinloop variable, so all of the secondary cpus
1826 * will block when they are awakened from their OF spinloop.
1827 * This must occur for both SMP and non SMP kernels, since OF will
1828 * be trashed when we move the kernel.
1829 */
1830 *spinloop = 0;
1831
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001832 /* look for cpus */
1833 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001834 unsigned int cpu_no;
1835 __be32 reg;
1836
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001837 type[0] = 0;
1838 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001839 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001840 continue;
1841
1842 /* Skip non-configured cpus. */
1843 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001844 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001845 continue;
1846
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001847 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001848 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001849 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001850
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001851 prom_debug("cpu hw idx = %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001852
1853 /* Init the acknowledge var which will be reset by
1854 * the secondary cpu when it awakens from its OF
1855 * spinloop.
1856 */
1857 *acknowledge = (unsigned long)-1;
1858
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001859 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001860 /* Primary Thread of non-boot cpu or any thread */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001861 prom_printf("starting cpu hw idx %lu... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001862 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001863 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001864
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001865 for (i = 0; (i < 100000000) &&
1866 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001867 mb();
1868
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001869 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001870 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001871 else
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001872 prom_printf("failed: %x\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001873 }
1874#ifdef CONFIG_SMP
1875 else
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001876 prom_printf("boot cpu hw idx %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001877#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001878 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001879
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001880 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001881}
1882
1883
1884static void __init prom_init_client_services(unsigned long pp)
1885{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001886 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00001887 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001888
1889 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00001890 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1891 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001892 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1893
1894 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00001895 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
1896 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001897 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001898
Anton Blanchard5827d412012-11-26 17:40:03 +00001899 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001900}
1901
Paul Mackerrasa575b802005-10-23 17:23:21 +10001902#ifdef CONFIG_PPC32
1903/*
1904 * For really old powermacs, we need to map things we claim.
1905 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001906 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10001907 */
1908static void __init prom_find_mmu(void)
1909{
Paul Mackerrasa575b802005-10-23 17:23:21 +10001910 phandle oprom;
1911 char version[64];
1912
1913 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1914 if (!PHANDLE_VALID(oprom))
1915 return;
1916 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1917 return;
1918 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10001919 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001920 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
1921 of_workarounds = OF_WA_CLAIM;
1922 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
1923 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
1924 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
1925 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10001926 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00001927 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
1928 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
1929 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001930 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00001931 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001932 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001933}
1934#else
1935#define prom_find_mmu()
1936#endif
1937
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001938static void __init prom_init_stdout(void)
1939{
Anton Blanchard5827d412012-11-26 17:40:03 +00001940 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001941 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001942 phandle stdout_node;
1943 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001944
Anton Blanchard5827d412012-11-26 17:40:03 +00001945 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001946 prom_panic("cannot find stdout");
1947
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001948 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001949
1950 /* Get the full OF pathname of the stdout device */
1951 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00001952 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001953 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
1954 val = cpu_to_be32(stdout_node);
Anton Blanchard5827d412012-11-26 17:40:03 +00001955 prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001956 &val, sizeof(val));
Anton Blanchard5827d412012-11-26 17:40:03 +00001957 prom_printf("OF stdout device is: %s\n", of_stdout_device);
1958 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001959 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001960
1961 /* If it's a display, note it */
1962 memset(type, 0, sizeof(type));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001963 prom_getprop(stdout_node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001964 if (strcmp(type, "display") == 0)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001965 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001966}
1967
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001968static int __init prom_find_machine_type(void)
1969{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001970 char compat[256];
1971 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001972#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001973 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001974 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001975#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001976
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001977 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00001978 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001979 compat, sizeof(compat)-1);
1980 if (len > 0) {
1981 compat[len] = 0;
1982 while (i < len) {
1983 char *p = &compat[i];
1984 int sl = strlen(p);
1985 if (sl == 0)
1986 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00001987 if (strstr(p, "Power Macintosh") ||
1988 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001989 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10001990#ifdef CONFIG_PPC64
1991 /* We must make sure we don't detect the IBM Cell
1992 * blades as pSeries due to some firmware issues,
1993 * so we do it here.
1994 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001995 if (strstr(p, "IBM,CBEA") ||
1996 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10001997 return PLATFORM_GENERIC;
1998#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001999 i += sl + 1;
2000 }
2001 }
2002#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002003 /* Try to detect OPAL */
2004 if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
2005 return PLATFORM_OPAL;
2006
2007 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002008 * PAPR compliant platform. We assume it is if :
2009 * - /device_type is "chrp" (please, do NOT use that for future
2010 * non-IBM designs !
2011 * - it has /rtas
2012 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002013 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002014 compat, sizeof(compat)-1);
2015 if (len <= 0)
2016 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00002017 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002018 return PLATFORM_GENERIC;
2019
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002020 /* Default to pSeries. We need to know if we are running LPAR */
2021 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002022 if (!PHANDLE_VALID(rtas))
2023 return PLATFORM_GENERIC;
2024 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2025 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002026 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002027 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002028 }
2029 return PLATFORM_PSERIES;
2030#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002031 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002032#endif
2033}
2034
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002035static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2036{
2037 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2038}
2039
2040/*
2041 * If we have a display that we don't know how to drive,
2042 * we will want to try to execute OF's open method for it
2043 * later. However, OF will probably fall over if we do that
2044 * we've taken over the MMU.
2045 * So we check whether we will need to open the display,
2046 * and if so, open it now.
2047 */
2048static void __init prom_check_displays(void)
2049{
2050 char type[16], *path;
2051 phandle node;
2052 ihandle ih;
2053 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002054
2055 static unsigned char default_colors[] = {
2056 0x00, 0x00, 0x00,
2057 0x00, 0x00, 0xaa,
2058 0x00, 0xaa, 0x00,
2059 0x00, 0xaa, 0xaa,
2060 0xaa, 0x00, 0x00,
2061 0xaa, 0x00, 0xaa,
2062 0xaa, 0xaa, 0x00,
2063 0xaa, 0xaa, 0xaa,
2064 0x55, 0x55, 0x55,
2065 0x55, 0x55, 0xff,
2066 0x55, 0xff, 0x55,
2067 0x55, 0xff, 0xff,
2068 0xff, 0x55, 0x55,
2069 0xff, 0x55, 0xff,
2070 0xff, 0xff, 0x55,
2071 0xff, 0xff, 0xff
2072 };
2073 const unsigned char *clut;
2074
Anton Blanchard4da727a2009-03-31 20:06:14 +00002075 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002076 for (node = 0; prom_next_node(&node); ) {
2077 memset(type, 0, sizeof(type));
2078 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00002079 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002080 continue;
2081
2082 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002083 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002084 memset(path, 0, PROM_SCRATCH_SIZE);
2085
2086 /*
2087 * leave some room at the end of the path for appending extra
2088 * arguments
2089 */
2090 if (call_prom("package-to-path", 3, 1, node, path,
2091 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
2092 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002093 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002094
2095 ih = call_prom("open", 1, 1, path);
2096 if (ih == 0) {
2097 prom_printf("failed\n");
2098 continue;
2099 }
2100
2101 /* Success */
2102 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002103 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002104
2105 /* Setup a usable color table when the appropriate
2106 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002107 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002108 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002109 if (prom_set_color(ih, i, clut[0], clut[1],
2110 clut[2]) != 0)
2111 break;
2112
2113#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002114 clut = PTRRELOC(logo_linux_clut224.clut);
2115 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002116 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2117 clut[2]) != 0)
2118 break;
2119#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002120
2121#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2122 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2123 PROM_ERROR) {
2124 u32 width, height, pitch, addr;
2125
2126 prom_printf("Setting btext !\n");
2127 prom_getprop(node, "width", &width, 4);
2128 prom_getprop(node, "height", &height, 4);
2129 prom_getprop(node, "linebytes", &pitch, 4);
2130 prom_getprop(node, "address", &addr, 4);
2131 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2132 width, height, pitch, addr);
2133 btext_setup_display(width, height, 8, pitch, addr);
2134 }
2135#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002136 }
2137}
2138
2139
2140/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2141static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2142 unsigned long needed, unsigned long align)
2143{
2144 void *ret;
2145
2146 *mem_start = _ALIGN(*mem_start, align);
2147 while ((*mem_start + needed) > *mem_end) {
2148 unsigned long room, chunk;
2149
2150 prom_debug("Chunk exhausted, claiming more at %x...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002151 alloc_bottom);
2152 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002153 if (room > DEVTREE_CHUNK_SIZE)
2154 room = DEVTREE_CHUNK_SIZE;
2155 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002156 prom_panic("No memory for flatten_device_tree "
2157 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002158 chunk = alloc_up(room, 0);
2159 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002160 prom_panic("No memory for flatten_device_tree "
2161 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002162 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002163 }
2164
2165 ret = (void *)*mem_start;
2166 *mem_start += needed;
2167
2168 return ret;
2169}
2170
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002171#define dt_push_token(token, mem_start, mem_end) do { \
2172 void *room = make_room(mem_start, mem_end, 4, 4); \
2173 *(__be32 *)room = cpu_to_be32(token); \
2174 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002175
2176static unsigned long __init dt_find_string(char *str)
2177{
2178 char *s, *os;
2179
Anton Blanchard5827d412012-11-26 17:40:03 +00002180 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002181 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002182 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002183 if (strcmp(s, str) == 0)
2184 return s - os;
2185 s += strlen(s) + 1;
2186 }
2187 return 0;
2188}
2189
2190/*
2191 * The Open Firmware 1275 specification states properties must be 31 bytes or
2192 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2193 */
2194#define MAX_PROPERTY_NAME 64
2195
2196static void __init scan_dt_build_strings(phandle node,
2197 unsigned long *mem_start,
2198 unsigned long *mem_end)
2199{
2200 char *prev_name, *namep, *sstart;
2201 unsigned long soff;
2202 phandle child;
2203
Anton Blanchard5827d412012-11-26 17:40:03 +00002204 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002205
2206 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002207 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002208 for (;;) {
2209 /* 64 is max len of name including nul. */
2210 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2211 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2212 /* No more nodes: unwind alloc */
2213 *mem_start = (unsigned long)namep;
2214 break;
2215 }
2216
2217 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002218 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002219 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002220 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002221 continue;
2222 }
2223 /* get/create string entry */
2224 soff = dt_find_string(namep);
2225 if (soff != 0) {
2226 *mem_start = (unsigned long)namep;
2227 namep = sstart + soff;
2228 } else {
2229 /* Trim off some if we can */
2230 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002231 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002232 }
2233 prev_name = namep;
2234 }
2235
2236 /* do all our children */
2237 child = call_prom("child", 1, 1, node);
2238 while (child != 0) {
2239 scan_dt_build_strings(child, mem_start, mem_end);
2240 child = call_prom("peer", 1, 1, child);
2241 }
2242}
2243
2244static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2245 unsigned long *mem_end)
2246{
2247 phandle child;
2248 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2249 unsigned long soff;
2250 unsigned char *valp;
2251 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002252 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002253
2254 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2255
2256 /* get the node's full name */
2257 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002258 room = *mem_end - *mem_start;
2259 if (room > 255)
2260 room = 255;
2261 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002262 if (l >= 0) {
2263 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002264 if (l >= room) {
2265 if (l >= *mem_end - *mem_start)
2266 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002267 call_prom("package-to-path", 3, 1, node, namep, l);
2268 }
2269 namep[l] = '\0';
2270
2271 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002272 * middle of the path in some properties, and extract
2273 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002274 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002275 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002276 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002277 lp = namep;
2278 else if (*p != 0)
2279 *lp++ = *p;
2280 }
2281 *lp = 0;
2282 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002283 }
2284
2285 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002286 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002287 memset(path, 0, PROM_SCRATCH_SIZE);
2288 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2289
2290 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002291 prev_name = "";
2292 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002293 for (;;) {
2294 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002295 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002296 break;
2297
2298 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002299 if (strcmp(pname, "name") == 0) {
2300 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002301 continue;
2302 }
2303
2304 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002305 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002306 if (soff == 0) {
2307 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002308 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002309 break;
2310 }
2311 prev_name = sstart + soff;
2312
2313 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002314 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002315
2316 /* sanity checks */
2317 if (l == PROM_ERROR)
2318 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002319
2320 /* push property head */
2321 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2322 dt_push_token(l, mem_start, mem_end);
2323 dt_push_token(soff, mem_start, mem_end);
2324
2325 /* push property content */
2326 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002327 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002328 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002329
Anton Blanchard5827d412012-11-26 17:40:03 +00002330 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002331 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002332 }
2333
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002334 /* Add a "linux,phandle" property if no "phandle" property already
2335 * existed (can happen with OPAL)
2336 */
2337 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002338 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002339 if (soff == 0)
2340 prom_printf("WARNING: Can't find string index for"
2341 " <linux-phandle> node %s\n", path);
2342 else {
2343 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2344 dt_push_token(4, mem_start, mem_end);
2345 dt_push_token(soff, mem_start, mem_end);
2346 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002347 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002348 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002349 }
2350
2351 /* do all our children */
2352 child = call_prom("child", 1, 1, node);
2353 while (child != 0) {
2354 scan_dt_build_struct(child, mem_start, mem_end);
2355 child = call_prom("peer", 1, 1, child);
2356 }
2357
2358 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2359}
2360
2361static void __init flatten_device_tree(void)
2362{
2363 phandle root;
2364 unsigned long mem_start, mem_end, room;
2365 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002366 char *namep;
2367 u64 *rsvmap;
2368
2369 /*
2370 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002371 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002372 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002373 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002374 if (room > DEVTREE_CHUNK_SIZE)
2375 room = DEVTREE_CHUNK_SIZE;
Anton Blanchard5827d412012-11-26 17:40:03 +00002376 prom_debug("starting device tree allocs at %x\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002377
2378 /* Now try to claim that */
2379 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2380 if (mem_start == 0)
2381 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002382 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002383
2384 /* Get root of tree */
2385 root = call_prom("peer", 1, 1, (phandle)0);
2386 if (root == (phandle)0)
2387 prom_panic ("couldn't get device tree root\n");
2388
2389 /* Build header and make room for mem rsv map */
2390 mem_start = _ALIGN(mem_start, 4);
2391 hdr = make_room(&mem_start, &mem_end,
2392 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002393 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002394 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2395
2396 /* Start of strings */
2397 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002398 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002399 mem_start += 4; /* hole */
2400
2401 /* Add "linux,phandle" in there, we'll need it */
2402 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002403 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002404 mem_start = (unsigned long)namep + strlen(namep) + 1;
2405
2406 /* Build string array */
2407 prom_printf("Building dt strings...\n");
2408 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002409 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002410
2411 /* Build structure */
2412 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002413 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002414 prom_printf("Building dt structure...\n");
2415 scan_dt_build_struct(root, &mem_start, &mem_end);
2416 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002417 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002418
2419 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002420 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2421 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2422 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2423 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2424 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2425 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2426 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2427 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002428 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002429 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002430
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002431 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002432 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002433
2434#ifdef DEBUG_PROM
2435 {
2436 int i;
2437 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002438 for (i = 0; i < mem_reserve_cnt; i++)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002439 prom_printf(" %x - %x\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002440 be64_to_cpu(mem_reserve_map[i].base),
2441 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002442 }
2443#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002444 /* Bump mem_reserve_cnt to cause further reservations to fail
2445 * since it's too late.
2446 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002447 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002448
2449 prom_printf("Device tree strings 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002450 dt_string_start, dt_string_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002451 prom_printf("Device tree struct 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002452 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002453}
2454
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002455#ifdef CONFIG_PPC_MAPLE
2456/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2457 * The values are bad, and it doesn't even have the right number of cells. */
2458static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002459{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002460 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002461 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002462 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002463 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002464
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002465 name = "/ht@0/isa@4";
2466 isa = call_prom("finddevice", 1, 1, ADDR(name));
2467 if (!PHANDLE_VALID(isa)) {
2468 name = "/ht@0/isa@6";
2469 isa = call_prom("finddevice", 1, 1, ADDR(name));
2470 rloc = 0x01003000; /* IO space; PCI device = 6 */
2471 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002472 if (!PHANDLE_VALID(isa))
2473 return;
2474
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002475 if (prom_getproplen(isa, "ranges") != 12)
2476 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002477 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2478 == PROM_ERROR)
2479 return;
2480
2481 if (isa_ranges[0] != 0x1 ||
2482 isa_ranges[1] != 0xf4000000 ||
2483 isa_ranges[2] != 0x00010000)
2484 return;
2485
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002486 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002487
2488 isa_ranges[0] = 0x1;
2489 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002490 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002491 isa_ranges[3] = 0x0;
2492 isa_ranges[4] = 0x0;
2493 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002494 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002495 isa_ranges, sizeof(isa_ranges));
2496}
Harry Ciao8f101a052009-06-17 16:28:00 -07002497
2498#define CPC925_MC_START 0xf8000000
2499#define CPC925_MC_LENGTH 0x1000000
2500/* The values for memory-controller don't have right number of cells */
2501static void __init fixup_device_tree_maple_memory_controller(void)
2502{
2503 phandle mc;
2504 u32 mc_reg[4];
2505 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002506 u32 ac, sc;
2507
2508 mc = call_prom("finddevice", 1, 1, ADDR(name));
2509 if (!PHANDLE_VALID(mc))
2510 return;
2511
2512 if (prom_getproplen(mc, "reg") != 8)
2513 return;
2514
Anton Blanchard5827d412012-11-26 17:40:03 +00002515 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2516 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002517 if ((ac != 2) || (sc != 2))
2518 return;
2519
2520 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2521 return;
2522
2523 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2524 return;
2525
2526 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2527
2528 mc_reg[0] = 0x0;
2529 mc_reg[1] = CPC925_MC_START;
2530 mc_reg[2] = 0x0;
2531 mc_reg[3] = CPC925_MC_LENGTH;
2532 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2533}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002534#else
2535#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002536#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002537#endif
2538
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002539#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002540/*
2541 * Pegasos and BriQ lacks the "ranges" property in the isa node
2542 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002543 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002544 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002545static void __init fixup_device_tree_chrp(void)
2546{
Olaf Heringe4805922007-04-04 18:20:04 +02002547 phandle ph;
2548 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002549 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002550 char *name;
2551 int rc;
2552
2553 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002554 ph = call_prom("finddevice", 1, 1, ADDR(name));
2555 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002556 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002557 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002558 rloc = 0x01003000; /* IO space; PCI device = 6 */
2559 }
Olaf Heringe4805922007-04-04 18:20:04 +02002560 if (PHANDLE_VALID(ph)) {
2561 rc = prom_getproplen(ph, "ranges");
2562 if (rc == 0 || rc == PROM_ERROR) {
2563 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002564
Olaf Heringe4805922007-04-04 18:20:04 +02002565 prop[0] = 0x1;
2566 prop[1] = 0x0;
2567 prop[2] = rloc;
2568 prop[3] = 0x0;
2569 prop[4] = 0x0;
2570 prop[5] = 0x00010000;
2571 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2572 }
2573 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002574
Olaf Heringe4805922007-04-04 18:20:04 +02002575 name = "/pci@80000000/ide@C,1";
2576 ph = call_prom("finddevice", 1, 1, ADDR(name));
2577 if (PHANDLE_VALID(ph)) {
2578 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2579 prop[0] = 14;
2580 prop[1] = 0x0;
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002581 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2582 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2583 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2584 if (rc == sizeof(u32)) {
2585 prop[0] &= ~0x5;
2586 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2587 }
Olaf Heringe4805922007-04-04 18:20:04 +02002588 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002589}
2590#else
2591#define fixup_device_tree_chrp()
2592#endif
2593
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002594#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002595static void __init fixup_device_tree_pmac(void)
2596{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002597 phandle u3, i2c, mpic;
2598 u32 u3_rev;
2599 u32 interrupts[2];
2600 u32 parent;
2601
2602 /* Some G5s have a missing interrupt definition, fix it up here */
2603 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2604 if (!PHANDLE_VALID(u3))
2605 return;
2606 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2607 if (!PHANDLE_VALID(i2c))
2608 return;
2609 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2610 if (!PHANDLE_VALID(mpic))
2611 return;
2612
2613 /* check if proper rev of u3 */
2614 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2615 == PROM_ERROR)
2616 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002617 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002618 return;
2619 /* does it need fixup ? */
2620 if (prom_getproplen(i2c, "interrupts") > 0)
2621 return;
2622
2623 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2624
2625 /* interrupt on this revision of u3 is number 0 and level */
2626 interrupts[0] = 0;
2627 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002628 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2629 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002630 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002631 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2632 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002633}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002634#else
2635#define fixup_device_tree_pmac()
2636#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002637
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002638#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002639/*
2640 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2641 * to talk to the phy. If the phy-handle property is missing, then this
2642 * function is called to add the appropriate nodes and link it to the
2643 * ethernet node.
2644 */
2645static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002646{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002647 u32 node;
2648 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002649 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002650
Grant Likely94d2dde2008-01-24 22:25:32 -07002651 /* Check if /builtin/ethernet exists - bail if it doesn't */
2652 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002653 if (!PHANDLE_VALID(node))
2654 return;
2655
Grant Likely94d2dde2008-01-24 22:25:32 -07002656 /* Check if the phy-handle property exists - bail if it does */
2657 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2658 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002659 return;
2660
Grant Likely94d2dde2008-01-24 22:25:32 -07002661 /*
2662 * At this point the ethernet device doesn't have a phy described.
2663 * Now we need to add the missing phy node and linkage
2664 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002665
Grant Likely94d2dde2008-01-24 22:25:32 -07002666 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002667 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2668 if (!PHANDLE_VALID(node)) {
2669 prom_printf("Adding Ethernet MDIO node\n");
2670 call_prom("interpret", 1, 1,
2671 " s\" /builtin\" find-device"
2672 " new-device"
2673 " 1 encode-int s\" #address-cells\" property"
2674 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002675 " s\" mdio\" device-name"
2676 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002677 " s\" compatible\" property"
2678 " 0xf0003000 0x400 reg"
2679 " 0x2 encode-int"
2680 " 0x5 encode-int encode+"
2681 " 0x3 encode-int encode+"
2682 " s\" interrupts\" property"
2683 " finish-device");
2684 };
2685
Grant Likely94d2dde2008-01-24 22:25:32 -07002686 /* Check for a PHY device node - if missing then create one and
2687 * give it's phandle to the ethernet node */
2688 node = call_prom("finddevice", 1, 1,
2689 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002690 if (!PHANDLE_VALID(node)) {
2691 prom_printf("Adding Ethernet PHY node\n");
2692 call_prom("interpret", 1, 1,
2693 " s\" /builtin/mdio\" find-device"
2694 " new-device"
2695 " s\" ethernet-phy\" device-name"
2696 " 0x10 encode-int s\" reg\" property"
2697 " my-self"
2698 " ihandle>phandle"
2699 " finish-device"
2700 " s\" /builtin/ethernet\" find-device"
2701 " encode-int"
2702 " s\" phy-handle\" property"
2703 " device-end");
2704 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002705}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002706
Grant Likely94d2dde2008-01-24 22:25:32 -07002707static void __init fixup_device_tree_efika(void)
2708{
2709 int sound_irq[3] = { 2, 2, 0 };
2710 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2711 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2712 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2713 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2714 u32 node;
2715 char prop[64];
2716 int rv, len;
2717
2718 /* Check if we're really running on a EFIKA */
2719 node = call_prom("finddevice", 1, 1, ADDR("/"));
2720 if (!PHANDLE_VALID(node))
2721 return;
2722
2723 rv = prom_getprop(node, "model", prop, sizeof(prop));
2724 if (rv == PROM_ERROR)
2725 return;
2726 if (strcmp(prop, "EFIKA5K2"))
2727 return;
2728
2729 prom_printf("Applying EFIKA device tree fixups\n");
2730
2731 /* Claiming to be 'chrp' is death */
2732 node = call_prom("finddevice", 1, 1, ADDR("/"));
2733 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2734 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2735 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2736
David Woodhouse7f4392c2008-04-14 02:52:38 +10002737 /* CODEGEN,description is exposed in /proc/cpuinfo so
2738 fix that too */
2739 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2740 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2741 prom_setprop(node, "/", "CODEGEN,description",
2742 "Efika 5200B PowerPC System",
2743 sizeof("Efika 5200B PowerPC System"));
2744
Grant Likely94d2dde2008-01-24 22:25:32 -07002745 /* Fixup bestcomm interrupts property */
2746 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2747 if (PHANDLE_VALID(node)) {
2748 len = prom_getproplen(node, "interrupts");
2749 if (len == 12) {
2750 prom_printf("Fixing bestcomm interrupts property\n");
2751 prom_setprop(node, "/builtin/bestcom", "interrupts",
2752 bcomm_irq, sizeof(bcomm_irq));
2753 }
2754 }
2755
2756 /* Fixup sound interrupts property */
2757 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2758 if (PHANDLE_VALID(node)) {
2759 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2760 if (rv == PROM_ERROR) {
2761 prom_printf("Adding sound interrupts property\n");
2762 prom_setprop(node, "/builtin/sound", "interrupts",
2763 sound_irq, sizeof(sound_irq));
2764 }
2765 }
2766
2767 /* Make sure ethernet phy-handle property exists */
2768 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002769}
2770#else
2771#define fixup_device_tree_efika()
2772#endif
2773
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002774static void __init fixup_device_tree(void)
2775{
2776 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07002777 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002778 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002779 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002780 fixup_device_tree_efika();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002781}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002782
2783static void __init prom_find_boot_cpu(void)
2784{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002785 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002786 ihandle prom_cpu;
2787 phandle cpu_pkg;
2788
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002789 rval = 0;
2790 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10002791 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002792 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002793
2794 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
2795
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002796 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
2797 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002798
Anton Blanchard5827d412012-11-26 17:40:03 +00002799 prom_debug("Booting CPU hw index = %lu\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002800}
2801
2802static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2803{
2804#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002805 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002806 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002807
Anton Blanchard5827d412012-11-26 17:40:03 +00002808 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
2809 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002810
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002811 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002812 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002813 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002814 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002815 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002816 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002817
Anton Blanchard5827d412012-11-26 17:40:03 +00002818 reserve_mem(prom_initrd_start,
2819 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002820
Anton Blanchard5827d412012-11-26 17:40:03 +00002821 prom_debug("initrd_start=0x%x\n", prom_initrd_start);
2822 prom_debug("initrd_end=0x%x\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002823 }
2824#endif /* CONFIG_BLK_DEV_INITRD */
2825}
2826
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002827#ifdef CONFIG_PPC64
2828#ifdef CONFIG_RELOCATABLE
2829static void reloc_toc(void)
2830{
2831}
2832
2833static void unreloc_toc(void)
2834{
2835}
2836#else
Anton Blanchard16744002013-03-12 01:51:51 +00002837static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002838{
2839 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00002840 unsigned long *toc_entry;
2841
2842 /* Get the start of the TOC by using r2 directly. */
2843 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002844
2845 for (i = 0; i < nr_entries; i++) {
2846 *toc_entry = *toc_entry + offset;
2847 toc_entry++;
2848 }
2849}
2850
2851static void reloc_toc(void)
2852{
2853 unsigned long offset = reloc_offset();
2854 unsigned long nr_entries =
2855 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2856
Anton Blanchard16744002013-03-12 01:51:51 +00002857 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002858
2859 mb();
2860}
2861
2862static void unreloc_toc(void)
2863{
2864 unsigned long offset = reloc_offset();
2865 unsigned long nr_entries =
2866 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2867
2868 mb();
2869
Anton Blanchard16744002013-03-12 01:51:51 +00002870 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002871}
2872#endif
2873#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002874
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002875/*
2876 * We enter here early on, when the Open Firmware prom is still
2877 * handling exceptions and the MMU hash table for us.
2878 */
2879
2880unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2881 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10002882 unsigned long r6, unsigned long r7,
2883 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002884{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002885 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002886
2887#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10002888 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002889 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002890#else
2891 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002892#endif
2893
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002894 /*
2895 * First zero the BSS
2896 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002897 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002898
2899 /*
2900 * Init interface to Open Firmware, get some node references,
2901 * like /chosen
2902 */
2903 prom_init_client_services(pp);
2904
2905 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002906 * See if this OF is old enough that we need to do explicit maps
2907 * and other workarounds
2908 */
2909 prom_find_mmu();
2910
2911 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002912 * Init prom stdout device
2913 */
2914 prom_init_stdout();
2915
Anton Blanchard5827d412012-11-26 17:40:03 +00002916 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00002917
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002918 /*
2919 * Get default machine type. At this point, we do not differentiate
2920 * between pSeries SMP and pSeries LPAR
2921 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002922 of_platform = prom_find_machine_type();
2923 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002924
Suzuki Poulose0f890c82011-12-14 22:57:15 +00002925#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01002926 /* Bail if this is a kdump kernel. */
2927 if (PHYSICAL_START > 0)
2928 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10002929#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01002930
2931 /*
2932 * Check for an initrd
2933 */
2934 prom_check_initrd(r3, r4);
2935
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002936#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002937 /*
2938 * On pSeries, inform the firmware about our capabilities
2939 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002940 if (of_platform == PLATFORM_PSERIES ||
2941 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002942 prom_send_capabilities();
2943#endif
2944
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002945 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05002946 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002947 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002948 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10002949 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002950
2951 /*
2952 * Do early parsing of command line
2953 */
2954 early_cmdline_parse();
2955
2956 /*
2957 * Initialize memory management within prom_init
2958 */
2959 prom_init_mem();
2960
2961 /*
2962 * Determine which cpu is actually running right _now_
2963 */
2964 prom_find_boot_cpu();
2965
2966 /*
2967 * Initialize display devices
2968 */
2969 prom_check_displays();
2970
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002971#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002972 /*
2973 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
2974 * that uses the allocator, we need to make sure we get the top of memory
2975 * available for us here...
2976 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002977 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002978 prom_initialize_tce_table();
2979#endif
2980
2981 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002982 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
2983 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002984 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002985 if (of_platform != PLATFORM_POWERMAC &&
2986 of_platform != PLATFORM_OPAL)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002987 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002988
2989#ifdef CONFIG_PPC_POWERNV
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002990#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002991 /* Detect HAL and try instanciating it & doing takeover */
Anton Blanchard5827d412012-11-26 17:40:03 +00002992 if (of_platform == PLATFORM_PSERIES_LPAR) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002993 prom_query_opal();
Anton Blanchard5827d412012-11-26 17:40:03 +00002994 if (of_platform == PLATFORM_OPAL) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002995 prom_opal_hold_cpus();
2996 prom_opal_takeover();
2997 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002998 } else
2999#endif /* __BIG_ENDIAN__ */
3000 if (of_platform == PLATFORM_OPAL)
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003001 prom_instantiate_opal();
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003002#endif /* CONFIG_PPC_POWERNV */
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003003
Ashley Lai4a727422012-08-14 18:34:57 -05003004#ifdef CONFIG_PPC64
3005 /* instantiate sml */
3006 prom_instantiate_sml();
3007#endif
3008
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003009 /*
3010 * On non-powermacs, put all CPUs in spin-loops.
3011 *
3012 * PowerMacs use a different mechanism to spin CPUs
3013 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003014 if (of_platform != PLATFORM_POWERMAC &&
3015 of_platform != PLATFORM_OPAL)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003016 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003017
3018 /*
3019 * Fill in some infos for use by the kernel later on
3020 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003021 if (prom_memory_limit) {
3022 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003023 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003024 &val, sizeof(val));
3025 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003026#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003027 if (prom_iommu_off)
3028 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003029 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003030
Anton Blanchard5827d412012-11-26 17:40:03 +00003031 if (prom_iommu_force_on)
3032 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003033 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003034
Anton Blanchard5827d412012-11-26 17:40:03 +00003035 if (prom_tce_alloc_start) {
3036 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3037 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003038 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003039 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3040 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003041 sizeof(prom_tce_alloc_end));
3042 }
3043#endif
3044
3045 /*
3046 * Fixup any known bugs in the device-tree
3047 */
3048 fixup_device_tree();
3049
3050 /*
3051 * Now finally create the flattened device-tree
3052 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003053 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003054 flatten_device_tree();
3055
Paul Mackerras3825ac02005-11-08 22:48:08 +11003056 /*
3057 * in case stdin is USB and still active on IBM machines...
3058 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003059 * closed stdin already (in particular the powerbook 101). It
3060 * appears that the OPAL version of OFW doesn't like it either.
Paul Mackerras3825ac02005-11-08 22:48:08 +11003061 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003062 if (of_platform != PLATFORM_POWERMAC &&
3063 of_platform != PLATFORM_OPAL)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003064 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003065
3066 /*
3067 * Call OF "quiesce" method to shut down pending DMA's from
3068 * devices etc...
3069 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003070 prom_printf("Calling quiesce...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003071 call_prom("quiesce", 0, 0);
3072
3073 /*
3074 * And finally, call the kernel passing it the flattened device
3075 * tree and NULL as r5, thus triggering the new entry point which
3076 * is common to us and kexec
3077 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003078 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003079
3080 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Anton Blanchard5827d412012-11-26 17:40:03 +00003081 if (of_platform != PLATFORM_OPAL) {
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003082 prom_printf("returning from prom_init\n");
3083 prom_debug("->dt_header_start=0x%x\n", hdr);
3084 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003085
3086#ifdef CONFIG_PPC32
3087 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003088#else
3089 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003090#endif
3091
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003092#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
3093 /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
3094 __start(hdr, kbase, 0, 0, 0,
Anton Blanchard5827d412012-11-26 17:40:03 +00003095 prom_opal_base, prom_opal_entry);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003096#else
3097 __start(hdr, kbase, 0, 0, 0, 0, 0);
3098#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003099
3100 return 0;
3101}