blob: 7b2e452be19db39b25c7cf7759e757d737242610 [file] [log] [blame]
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001/*
2 * Procedures for interfacing to Open Firmware.
3 *
4 * Paul Mackerras August 1996.
5 * Copyright (C) 1996-2005 Paul Mackerras.
6 *
7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
8 * {engebret|bergner}@us.ibm.com
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#undef DEBUG_PROM
17
18#include <stdarg.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100019#include <linux/kernel.h>
20#include <linux/string.h>
21#include <linux/init.h>
22#include <linux/threads.h>
23#include <linux/spinlock.h>
24#include <linux/types.h>
25#include <linux/pci.h>
26#include <linux/proc_fs.h>
27#include <linux/stringify.h>
28#include <linux/delay.h>
29#include <linux/initrd.h>
30#include <linux/bitops.h>
31#include <asm/prom.h>
32#include <asm/rtas.h>
33#include <asm/page.h>
34#include <asm/processor.h>
35#include <asm/irq.h>
36#include <asm/io.h>
37#include <asm/smp.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100038#include <asm/mmu.h>
39#include <asm/pgtable.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100040#include <asm/iommu.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100041#include <asm/btext.h>
42#include <asm/sections.h>
43#include <asm/machdep.h>
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +000044#include <asm/opal.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100045
Paul Mackerras9b6b5632005-10-06 12:06:20 +100046#include <linux/linux_logo.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100047
48/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +100049 * Eventually bump that one up
50 */
51#define DEVTREE_CHUNK_SIZE 0x100000
52
53/*
54 * This is the size of the local memory reserve map that gets copied
55 * into the boot params passed to the kernel. That size is totally
56 * flexible as the kernel just reads the list until it encounters an
57 * entry with size 0, so it can be changed without breaking binary
58 * compatibility
59 */
60#define MEM_RESERVE_MAP_SIZE 8
61
62/*
63 * prom_init() is called very early on, before the kernel text
64 * and data have been mapped to KERNELBASE. At this point the code
65 * is running at whatever address it has been loaded at.
66 * On ppc32 we compile with -mrelocatable, which means that references
67 * to extern and static variables get relocated automatically.
Anton Blanchard5ac47f72012-11-26 17:39:03 +000068 * ppc64 objects are always relocatable, we just need to relocate the
69 * TOC.
Paul Mackerras9b6b5632005-10-06 12:06:20 +100070 *
71 * Because OF may have mapped I/O devices into the area starting at
72 * KERNELBASE, particularly on CHRP machines, we can't safely call
73 * OF once the kernel has been mapped to KERNELBASE. Therefore all
74 * OF calls must be done within prom_init().
75 *
76 * ADDR is used in calls to call_prom. The 4th and following
77 * arguments to call_prom should be 32-bit values.
78 * On ppc64, 64 bit values are truncated to 32 bits (and
79 * fortunately don't get interpreted as two arguments).
80 */
Anton Blanchard5ac47f72012-11-26 17:39:03 +000081#define ADDR(x) (u32)(unsigned long)(x)
82
Paul Mackerras9b6b5632005-10-06 12:06:20 +100083#ifdef CONFIG_PPC64
Paul Mackerrasa23414b2005-11-10 12:00:55 +110084#define OF_WORKAROUNDS 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +100085#else
Paul Mackerrasa23414b2005-11-10 12:00:55 +110086#define OF_WORKAROUNDS of_workarounds
87int of_workarounds;
Paul Mackerras9b6b5632005-10-06 12:06:20 +100088#endif
89
Paul Mackerrasa23414b2005-11-10 12:00:55 +110090#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
91#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
92
Paul Mackerras9b6b5632005-10-06 12:06:20 +100093#define PROM_BUG() do { \
94 prom_printf("kernel BUG at %s line 0x%x!\n", \
Anton Blanchard5827d412012-11-26 17:40:03 +000095 __FILE__, __LINE__); \
Paul Mackerras9b6b5632005-10-06 12:06:20 +100096 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
97} while (0)
98
99#ifdef DEBUG_PROM
100#define prom_debug(x...) prom_printf(x)
101#else
102#define prom_debug(x...)
103#endif
104
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000105
106typedef u32 prom_arg_t;
107
108struct prom_args {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000109 __be32 service;
110 __be32 nargs;
111 __be32 nret;
112 __be32 args[10];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000113};
114
115struct prom_t {
116 ihandle root;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100117 phandle chosen;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000118 int cpu;
119 ihandle stdout;
Paul Mackerrasa575b802005-10-23 17:23:21 +1000120 ihandle mmumap;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100121 ihandle memory;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000122};
123
124struct mem_map_entry {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000125 __be64 base;
126 __be64 size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000127};
128
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000129typedef __be32 cell_t;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000130
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +0000131extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
132 unsigned long r6, unsigned long r7, unsigned long r8,
133 unsigned long r9);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000134
135#ifdef CONFIG_PPC64
Paul Mackerrasc49888202005-10-26 21:52:53 +1000136extern int enter_prom(struct prom_args *args, unsigned long entry);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000137#else
Paul Mackerrasc49888202005-10-26 21:52:53 +1000138static inline int enter_prom(struct prom_args *args, unsigned long entry)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000139{
Paul Mackerrasc49888202005-10-26 21:52:53 +1000140 return ((int (*)(struct prom_args *))entry)(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000141}
142#endif
143
144extern void copy_and_flush(unsigned long dest, unsigned long src,
145 unsigned long size, unsigned long offset);
146
147/* prom structure */
148static struct prom_t __initdata prom;
149
150static unsigned long prom_entry __initdata;
151
152#define PROM_SCRATCH_SIZE 256
153
154static char __initdata of_stdout_device[256];
155static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
156
157static unsigned long __initdata dt_header_start;
158static unsigned long __initdata dt_struct_start, dt_struct_end;
159static unsigned long __initdata dt_string_start, dt_string_end;
160
161static unsigned long __initdata prom_initrd_start, prom_initrd_end;
162
163#ifdef CONFIG_PPC64
Jeremy Kerr165785e2006-11-11 17:25:18 +1100164static int __initdata prom_iommu_force_on;
165static int __initdata prom_iommu_off;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000166static unsigned long __initdata prom_tce_alloc_start;
167static unsigned long __initdata prom_tce_alloc_end;
168#endif
169
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100170/* Platforms codes are now obsolete in the kernel. Now only used within this
171 * file and ultimately gone too. Feel free to change them if you need, they
172 * are not shared with anything outside of this file anymore
173 */
174#define PLATFORM_PSERIES 0x0100
175#define PLATFORM_PSERIES_LPAR 0x0101
176#define PLATFORM_LPAR 0x0001
177#define PLATFORM_POWERMAC 0x0400
178#define PLATFORM_GENERIC 0x0500
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000179#define PLATFORM_OPAL 0x0600
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100180
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000181static int __initdata of_platform;
182
183static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
184
Benjamin Krillcf687872009-07-27 22:02:39 +0000185static unsigned long __initdata prom_memory_limit;
186
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000187static unsigned long __initdata alloc_top;
188static unsigned long __initdata alloc_top_high;
189static unsigned long __initdata alloc_bottom;
190static unsigned long __initdata rmo_top;
191static unsigned long __initdata ram_top;
192
193static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
194static int __initdata mem_reserve_cnt;
195
196static cell_t __initdata regbuf[1024];
197
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000198static bool rtas_has_query_cpu_stopped;
199
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000200
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000201/*
202 * Error results ... some OF calls will return "-1" on error, some
203 * will return 0, some will return either. To simplify, here are
204 * macros to use with any ihandle or phandle return value to check if
205 * it is valid
206 */
207
208#define PROM_ERROR (-1u)
209#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
210#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
211
212
213/* This is the one and *ONLY* place where we actually call open
214 * firmware.
215 */
216
217static int __init call_prom(const char *service, int nargs, int nret, ...)
218{
219 int i;
220 struct prom_args args;
221 va_list list;
222
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000223 args.service = cpu_to_be32(ADDR(service));
224 args.nargs = cpu_to_be32(nargs);
225 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000226
227 va_start(list, nret);
228 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000229 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000230 va_end(list);
231
232 for (i = 0; i < nret; i++)
233 args.args[nargs+i] = 0;
234
Anton Blanchard5827d412012-11-26 17:40:03 +0000235 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000236 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000237
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000238 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000239}
240
241static int __init call_prom_ret(const char *service, int nargs, int nret,
242 prom_arg_t *rets, ...)
243{
244 int i;
245 struct prom_args args;
246 va_list list;
247
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000248 args.service = cpu_to_be32(ADDR(service));
249 args.nargs = cpu_to_be32(nargs);
250 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000251
252 va_start(list, rets);
253 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000254 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000255 va_end(list);
256
257 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100258 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000259
Anton Blanchard5827d412012-11-26 17:40:03 +0000260 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000261 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000262
263 if (rets != NULL)
264 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000265 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000266
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000267 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000268}
269
270
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000271static void __init prom_print(const char *msg)
272{
273 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000274
Anton Blanchard5827d412012-11-26 17:40:03 +0000275 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000276 return;
277
278 for (p = msg; *p != 0; p = q) {
279 for (q = p; *q != 0 && *q != '\n'; ++q)
280 ;
281 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000282 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000283 if (*q == 0)
284 break;
285 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000286 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000287 }
288}
289
290
291static void __init prom_print_hex(unsigned long val)
292{
293 int i, nibbles = sizeof(val)*2;
294 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000295
296 for (i = nibbles-1; i >= 0; i--) {
297 buf[i] = (val & 0xf) + '0';
298 if (buf[i] > '9')
299 buf[i] += ('a'-'0'-10);
300 val >>= 4;
301 }
302 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000303 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000304}
305
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000306/* max number of decimal digits in an unsigned long */
307#define UL_DIGITS 21
308static void __init prom_print_dec(unsigned long val)
309{
310 int i, size;
311 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000312
313 for (i = UL_DIGITS-1; i >= 0; i--) {
314 buf[i] = (val % 10) + '0';
315 val = val/10;
316 if (val == 0)
317 break;
318 }
319 /* shift stuff down */
320 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000321 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000322}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000323
324static void __init prom_printf(const char *format, ...)
325{
326 const char *p, *q, *s;
327 va_list args;
328 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000329 long vs;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000330
331 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000332 for (p = format; *p != 0; p = q) {
333 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
334 ;
335 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000336 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000337 if (*q == 0)
338 break;
339 if (*q == '\n') {
340 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000341 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000342 ADDR("\r\n"), 2);
343 continue;
344 }
345 ++q;
346 if (*q == 0)
347 break;
348 switch (*q) {
349 case 's':
350 ++q;
351 s = va_arg(args, const char *);
352 prom_print(s);
353 break;
354 case 'x':
355 ++q;
356 v = va_arg(args, unsigned long);
357 prom_print_hex(v);
358 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000359 case 'd':
360 ++q;
361 vs = va_arg(args, int);
362 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000363 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000364 vs = -vs;
365 }
366 prom_print_dec(vs);
367 break;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000368 case 'l':
369 ++q;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000370 if (*q == 0)
371 break;
372 else if (*q == 'x') {
373 ++q;
374 v = va_arg(args, unsigned long);
375 prom_print_hex(v);
376 } else if (*q == 'u') { /* '%lu' */
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000377 ++q;
378 v = va_arg(args, unsigned long);
379 prom_print_dec(v);
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000380 } else if (*q == 'd') { /* %ld */
381 ++q;
382 vs = va_arg(args, long);
383 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000384 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000385 vs = -vs;
386 }
387 prom_print_dec(vs);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000388 }
389 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000390 }
391 }
392}
393
394
Paul Mackerrasa575b802005-10-23 17:23:21 +1000395static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
396 unsigned long align)
397{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000398
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100399 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
400 /*
401 * Old OF requires we claim physical and virtual separately
402 * and then map explicitly (assuming virtual mode)
403 */
404 int ret;
405 prom_arg_t result;
406
407 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000408 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100409 align, size, virt);
410 if (ret != 0 || result == -1)
411 return -1;
412 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000413 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100414 align, size, virt);
415 if (ret != 0) {
416 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000417 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100418 return -1;
419 }
420 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000421 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000422 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100423 return virt;
424 }
425 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
426 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000427}
428
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000429static void __init __attribute__((noreturn)) prom_panic(const char *reason)
430{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000431 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100432 /* Do not call exit because it clears the screen on pmac
433 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000434 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100435 asm("trap\n");
436
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000437 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000438 call_prom("exit", 0, 0);
439
440 for (;;) /* should never get here */
441 ;
442}
443
444
445static int __init prom_next_node(phandle *nodep)
446{
447 phandle node;
448
449 if ((node = *nodep) != 0
450 && (*nodep = call_prom("child", 1, 1, node)) != 0)
451 return 1;
452 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
453 return 1;
454 for (;;) {
455 if ((node = call_prom("parent", 1, 1, node)) == 0)
456 return 0;
457 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
458 return 1;
459 }
460}
461
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +1100462static int inline prom_getprop(phandle node, const char *pname,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000463 void *value, size_t valuelen)
464{
465 return call_prom("getprop", 4, 1, node, ADDR(pname),
466 (u32)(unsigned long) value, (u32) valuelen);
467}
468
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +1100469static int inline prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000470{
471 return call_prom("getproplen", 2, 1, node, ADDR(pname));
472}
473
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100474static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000475{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100476 char *p = *str;
477
478 while (*q)
479 *p++ = *q++;
480 *p++ = ' ';
481 *str = p;
482}
483
484static char *tohex(unsigned int x)
485{
486 static char digits[] = "0123456789abcdef";
487 static char result[9];
488 int i;
489
490 result[8] = 0;
491 i = 8;
492 do {
493 --i;
494 result[i] = digits[x & 0xf];
495 x >>= 4;
496 } while (x != 0 && i > 0);
497 return &result[i];
498}
499
500static int __init prom_setprop(phandle node, const char *nodename,
501 const char *pname, void *value, size_t valuelen)
502{
503 char cmd[256], *p;
504
505 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
506 return call_prom("setprop", 4, 1, node, ADDR(pname),
507 (u32)(unsigned long) value, (u32) valuelen);
508
509 /* gah... setprop doesn't work on longtrail, have to use interpret */
510 p = cmd;
511 add_string(&p, "dev");
512 add_string(&p, nodename);
513 add_string(&p, tohex((u32)(unsigned long) value));
514 add_string(&p, tohex(valuelen));
515 add_string(&p, tohex(ADDR(pname)));
Anton Blanchard5827d412012-11-26 17:40:03 +0000516 add_string(&p, tohex(strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100517 add_string(&p, "property");
518 *p = 0;
519 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000520}
521
Anton Blanchard5827d412012-11-26 17:40:03 +0000522/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000523#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
524 || ('a' <= (c) && (c) <= 'f') \
525 || ('A' <= (c) && (c) <= 'F'))
526
527#define isdigit(c) ('0' <= (c) && (c) <= '9')
528#define islower(c) ('a' <= (c) && (c) <= 'z')
529#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
530
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000531static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000532{
533 unsigned long result = 0, base = 10, value;
534
535 if (*cp == '0') {
536 base = 8;
537 cp++;
538 if (toupper(*cp) == 'X') {
539 cp++;
540 base = 16;
541 }
542 }
543
544 while (isxdigit(*cp) &&
545 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
546 result = result * base + value;
547 cp++;
548 }
549
550 if (endp)
551 *endp = cp;
552
553 return result;
554}
555
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000556static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000557{
558 unsigned long ret = prom_strtoul(ptr, retptr);
559 int shift = 0;
560
561 /*
562 * We can't use a switch here because GCC *may* generate a
563 * jump table which won't work, because we're not running at
564 * the address we're linked at.
565 */
566 if ('G' == **retptr || 'g' == **retptr)
567 shift = 30;
568
569 if ('M' == **retptr || 'm' == **retptr)
570 shift = 20;
571
572 if ('K' == **retptr || 'k' == **retptr)
573 shift = 10;
574
575 if (shift) {
576 ret <<= shift;
577 (*retptr)++;
578 }
579
580 return ret;
581}
582
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000583/*
584 * Early parsing of the command line passed to the kernel, used for
585 * "mem=x" and the options that affect the iommu
586 */
587static void __init early_cmdline_parse(void)
588{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100589 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000590
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100591 char *p;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000592 int l = 0;
593
Anton Blanchard5827d412012-11-26 17:40:03 +0000594 prom_cmd_line[0] = 0;
595 p = prom_cmd_line;
596 if ((long)prom.chosen > 0)
597 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000598#ifdef CONFIG_CMDLINE
Amos Waterland0e4aa9c2006-06-12 23:45:02 -0400599 if (l <= 0 || p[0] == '\0') /* dbl check */
Anton Blanchard5827d412012-11-26 17:40:03 +0000600 strlcpy(prom_cmd_line,
601 CONFIG_CMDLINE, sizeof(prom_cmd_line));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000602#endif /* CONFIG_CMDLINE */
Anton Blanchard5827d412012-11-26 17:40:03 +0000603 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000604
605#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +0000606 opt = strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000607 if (opt) {
608 prom_printf("iommu opt is: %s\n", opt);
609 opt += 6;
610 while (*opt && *opt == ' ')
611 opt++;
Anton Blanchard5827d412012-11-26 17:40:03 +0000612 if (!strncmp(opt, "off", 3))
613 prom_iommu_off = 1;
614 else if (!strncmp(opt, "force", 5))
615 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000616 }
617#endif
Anton Blanchard5827d412012-11-26 17:40:03 +0000618 opt = strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000619 if (opt) {
620 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000621 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000622#ifdef CONFIG_PPC64
623 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000624 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000625#endif
626 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000627}
628
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000629#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000630/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000631 * The architecture vector has an array of PVR mask/value pairs,
632 * followed by # option vectors - 1, followed by the option vectors.
633 *
634 * See prom.h for the definition of the bits specified in the
635 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000636 *
637 * Because the description vector contains a mix of byte and word
638 * values, we declare it as an unsigned char array, and use this
639 * macro to put word values in.
640 */
641#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
642 ((x) >> 8) & 0xff, (x) & 0xff
643
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000644/* Firmware expects the value to be n - 1, where n is the # of vectors */
645#define NUM_VECTORS(n) ((n) - 1)
646
647/*
648 * Firmware expects 1 + n - 2, where n is the length of the option vector in
649 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
650 */
651#define VECTOR_LENGTH(n) (1 + (n) - 2)
652
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000653unsigned char ibm_architecture_vec[] = {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000654 W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
Anton Blanchard03054d52006-04-29 09:51:06 +1000655 W(0xffff0000), W(0x003e0000), /* POWER6 */
Michael Neulinge952e6c2008-06-18 10:47:26 +1000656 W(0xffff0000), W(0x003f0000), /* POWER7 */
Michael Neuling33959f82013-07-18 11:31:51 +1000657 W(0xffff0000), W(0x004b0000), /* POWER8E */
658 W(0xffff0000), W(0x004d0000), /* POWER8 */
Michael Neulingdf77c792012-11-08 20:23:11 +0000659 W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
Joel Schopp0cb99012008-06-19 06:23:23 +1000660 W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
Paul Mackerras0efbc182006-11-29 22:31:47 +1100661 W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000662 W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000663 NUM_VECTORS(6), /* 6 option vectors */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000664
665 /* option vector 1: processor architectures supported */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000666 VECTOR_LENGTH(2), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000667 0, /* don't ignore, don't halt */
668 OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
Michael Neulingdf77c792012-11-08 20:23:11 +0000669 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000670
671 /* option vector 2: Open Firmware options supported */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000672 VECTOR_LENGTH(33), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000673 OV2_REAL_MODE,
674 0, 0,
675 W(0xffffffff), /* real_base */
676 W(0xffffffff), /* real_size */
677 W(0xffffffff), /* virt_base */
678 W(0xffffffff), /* virt_size */
679 W(0xffffffff), /* load_base */
Anton Blanchard33392642011-12-04 13:13:58 +0000680 W(256), /* 256MB min RMA */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000681 W(0xffffffff), /* full client load */
682 0, /* min RMA percentage of total RAM */
683 48, /* max log_2(hash table size) */
684
685 /* option vector 3: processor options supported */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000686 VECTOR_LENGTH(2), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000687 0, /* don't ignore, don't halt */
Paul Mackerras974a76f2006-11-10 20:38:53 +1100688 OV3_FP | OV3_VMX | OV3_DFP,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000689
690 /* option vector 4: IBM PAPR implementation */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000691 VECTOR_LENGTH(2), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000692 0, /* don't halt */
Robert Jennings404e32e2012-05-10 08:55:49 +0000693 OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000694
695 /* option vector 5: PAPR/OF options */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000696 VECTOR_LENGTH(18), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000697 0, /* don't ignore, don't halt */
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000698 OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
699 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
700#ifdef CONFIG_PCI_MSI
701 /* PCIe/MSI support. Without MSI full PCIe is not supported */
702 OV5_FEAT(OV5_MSI),
703#else
Nathan Fontenot8391e422008-07-24 04:36:38 +1000704 0,
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000705#endif
706 0,
707#ifdef CONFIG_PPC_SMLPAR
708 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
709#else
710 0,
711#endif
Nathan Fontenot1b1218d2013-04-24 06:06:17 +0000712 OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000713 0,
714 0,
715 0,
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100716 /* WARNING: The offset of the "number of cores" field below
717 * must match by the macro below. Update the definition if
718 * the structure layout changes.
719 */
Michael Neuling33959f82013-07-18 11:31:51 +1000720#define IBM_ARCH_VEC_NRCORES_OFFSET 125
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100721 W(NR_CPUS), /* number of cores supported */
Kent Yoder828d2b52012-04-12 05:17:51 +0000722 0,
723 0,
724 0,
725 0,
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000726 OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
727 OV5_FEAT(OV5_PFO_HW_842),
728 OV5_FEAT(OV5_SUB_PROCESSORS),
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000729
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000730 /* option vector 6: IBM PAPR hints */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000731 VECTOR_LENGTH(3), /* length */
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000732 0,
733 0,
734 OV6_LINUX,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000735};
736
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000737/* Old method - ELF header with PT_NOTE sections only works on BE */
738#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000739static struct fake_elf {
740 Elf32_Ehdr elfhdr;
741 Elf32_Phdr phdr[2];
742 struct chrpnote {
743 u32 namesz;
744 u32 descsz;
745 u32 type;
746 char name[8]; /* "PowerPC" */
747 struct chrpdesc {
748 u32 real_mode;
749 u32 real_base;
750 u32 real_size;
751 u32 virt_base;
752 u32 virt_size;
753 u32 load_base;
754 } chrpdesc;
755 } chrpnote;
756 struct rpanote {
757 u32 namesz;
758 u32 descsz;
759 u32 type;
760 char name[24]; /* "IBM,RPA-Client-Config" */
761 struct rpadesc {
762 u32 lpar_affinity;
763 u32 min_rmo_size;
764 u32 min_rmo_percent;
765 u32 max_pft_size;
766 u32 splpar;
767 u32 min_load;
768 u32 new_mem_def;
769 u32 ignore_me;
770 } rpadesc;
771 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100772} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000773 .elfhdr = {
774 .e_ident = { 0x7f, 'E', 'L', 'F',
775 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
776 .e_type = ET_EXEC, /* yeah right */
777 .e_machine = EM_PPC,
778 .e_version = EV_CURRENT,
779 .e_phoff = offsetof(struct fake_elf, phdr),
780 .e_phentsize = sizeof(Elf32_Phdr),
781 .e_phnum = 2
782 },
783 .phdr = {
784 [0] = {
785 .p_type = PT_NOTE,
786 .p_offset = offsetof(struct fake_elf, chrpnote),
787 .p_filesz = sizeof(struct chrpnote)
788 }, [1] = {
789 .p_type = PT_NOTE,
790 .p_offset = offsetof(struct fake_elf, rpanote),
791 .p_filesz = sizeof(struct rpanote)
792 }
793 },
794 .chrpnote = {
795 .namesz = sizeof("PowerPC"),
796 .descsz = sizeof(struct chrpdesc),
797 .type = 0x1275,
798 .name = "PowerPC",
799 .chrpdesc = {
800 .real_mode = ~0U, /* ~0 means "don't care" */
801 .real_base = ~0U,
802 .real_size = ~0U,
803 .virt_base = ~0U,
804 .virt_size = ~0U,
805 .load_base = ~0U
806 },
807 },
808 .rpanote = {
809 .namesz = sizeof("IBM,RPA-Client-Config"),
810 .descsz = sizeof(struct rpadesc),
811 .type = 0x12759999,
812 .name = "IBM,RPA-Client-Config",
813 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +1100814 .lpar_affinity = 0,
815 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000816 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +1100817 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000818 .splpar = 1,
819 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +1100820 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000821 }
822 }
823};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000824#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000825
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100826static int __init prom_count_smt_threads(void)
827{
828 phandle node;
829 char type[64];
830 unsigned int plen;
831
832 /* Pick up th first CPU node we can find */
833 for (node = 0; prom_next_node(&node); ) {
834 type[0] = 0;
835 prom_getprop(node, "device_type", type, sizeof(type));
836
Anton Blanchard5827d412012-11-26 17:40:03 +0000837 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100838 continue;
839 /*
840 * There is an entry for each smt thread, each entry being
841 * 4 bytes long. All cpus should have the same number of
842 * smt threads, so return after finding the first.
843 */
844 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
845 if (plen == PROM_ERROR)
846 break;
847 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000848 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100849
850 /* Sanity check */
851 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000852 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100853 (unsigned long)plen);
854 return 1;
855 }
856 return plen;
857 }
858 prom_debug("No threads found, assuming 1 per core\n");
859
860 return 1;
861
862}
863
864
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000865static void __init prom_send_capabilities(void)
866{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000867 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000868 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200869 u32 cores;
870 unsigned char *ptcores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000871
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000872 root = call_prom("open", 1, 1, ADDR("/"));
873 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100874 /* We need to tell the FW about the number of cores we support.
875 *
876 * To do that, we count the number of threads on the first core
877 * (we assume this is the same for all cores) and use it to
878 * divide NR_CPUS.
879 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200880
881 /* The core value may start at an odd address. If such a word
882 * access is made at a cache line boundary, this leads to an
883 * exception which may not be handled at this time.
884 * Forcing a per byte access to avoid exception.
885 */
886 ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
887 cores = 0;
888 cores |= ptcores[0] << 24;
889 cores |= ptcores[1] << 16;
890 cores |= ptcores[2] << 8;
891 cores |= ptcores[3];
892 if (cores != NR_CPUS) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100893 prom_printf("WARNING ! "
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000894 "ibm_architecture_vec structure inconsistent: %lu!\n",
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200895 cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100896 } else {
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200897 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000898 prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200899 cores, NR_CPUS);
900 ptcores[0] = (cores >> 24) & 0xff;
901 ptcores[1] = (cores >> 16) & 0xff;
902 ptcores[2] = (cores >> 8) & 0xff;
903 ptcores[3] = cores & 0xff;
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100904 }
905
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000906 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +0000907 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000908 if (call_prom_ret("call-method", 3, 2, &ret,
909 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +1000910 root,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000911 ADDR(ibm_architecture_vec)) == 0) {
912 /* the call exists... */
913 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +0000914 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000915 "-support call FAILED!\n");
916 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +0000917 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000918 return;
919 }
920 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +0000921 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000922 }
923
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000924#ifdef __BIG_ENDIAN__
925 {
926 ihandle elfloader;
927
928 /* no ibm,client-architecture-support call, try the old way */
929 elfloader = call_prom("open", 1, 1,
930 ADDR("/packages/elf-loader"));
931 if (elfloader == 0) {
932 prom_printf("couldn't open /packages/elf-loader\n");
933 return;
934 }
935 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
936 elfloader, ADDR(&fake_elf));
937 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000938 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000939#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000940}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000941#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000942
943/*
944 * Memory allocation strategy... our layout is normally:
945 *
946 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
947 * rare cases, initrd might end up being before the kernel though.
948 * We assume this won't override the final kernel at 0, we have no
949 * provision to handle that in this version, but it should hopefully
950 * never happen.
951 *
952 * alloc_top is set to the top of RMO, eventually shrink down if the
953 * TCEs overlap
954 *
955 * alloc_bottom is set to the top of kernel/initrd
956 *
957 * from there, allocations are done this way : rtas is allocated
958 * topmost, and the device-tree is allocated from the bottom. We try
959 * to grow the device-tree allocation as we progress. If we can't,
960 * then we fail, we don't currently have a facility to restart
961 * elsewhere, but that shouldn't be necessary.
962 *
963 * Note that calls to reserve_mem have to be done explicitly, memory
964 * allocated with either alloc_up or alloc_down isn't automatically
965 * reserved.
966 */
967
968
969/*
970 * Allocates memory in the RMO upward from the kernel/initrd
971 *
972 * When align is 0, this is a special case, it means to allocate in place
973 * at the current location of alloc_bottom or fail (that is basically
974 * extending the previous allocation). Used for the device-tree flattening
975 */
976static unsigned long __init alloc_up(unsigned long size, unsigned long align)
977{
Anton Blanchard5827d412012-11-26 17:40:03 +0000978 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000979 unsigned long addr = 0;
980
Paul Mackerrasc49888202005-10-26 21:52:53 +1000981 if (align)
982 base = _ALIGN_UP(base, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000983 prom_debug("alloc_up(%x, %x)\n", size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +0000984 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000985 prom_panic("alloc_up() called with mem not initialized\n");
986
987 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +0000988 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000989 else
Anton Blanchard5827d412012-11-26 17:40:03 +0000990 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000991
Anton Blanchard5827d412012-11-26 17:40:03 +0000992 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000993 base = _ALIGN_UP(base + 0x100000, align)) {
994 prom_debug(" trying: 0x%x\n\r", base);
995 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +1000996 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000997 break;
998 addr = 0;
999 if (align == 0)
1000 break;
1001 }
1002 if (addr == 0)
1003 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001004 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001005
1006 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001007 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1008 prom_debug(" alloc_top : %x\n", alloc_top);
1009 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1010 prom_debug(" rmo_top : %x\n", rmo_top);
1011 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001012
1013 return addr;
1014}
1015
1016/*
1017 * Allocates memory downward, either from top of RMO, or if highmem
1018 * is set, from the top of RAM. Note that this one doesn't handle
1019 * failures. It does claim memory if highmem is not set.
1020 */
1021static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1022 int highmem)
1023{
1024 unsigned long base, addr = 0;
1025
1026 prom_debug("alloc_down(%x, %x, %s)\n", size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001027 highmem ? "(high)" : "(low)");
1028 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001029 prom_panic("alloc_down() called with mem not initialized\n");
1030
1031 if (highmem) {
1032 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001033 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1034 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001035 return 0;
1036 /* Will we bump into the RMO ? If yes, check out that we
1037 * didn't overlap existing allocations there, if we did,
1038 * we are dead, we must be the first in town !
1039 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001040 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001041 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001042 if (alloc_top == rmo_top)
1043 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001044 else
1045 return 0;
1046 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001047 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001048 goto bail;
1049 }
1050
Anton Blanchard5827d412012-11-26 17:40:03 +00001051 base = _ALIGN_DOWN(alloc_top - size, align);
1052 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001053 base = _ALIGN_DOWN(base - 0x100000, align)) {
1054 prom_debug(" trying: 0x%x\n\r", base);
1055 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001056 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001057 break;
1058 addr = 0;
1059 }
1060 if (addr == 0)
1061 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001062 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001063
1064 bail:
1065 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001066 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1067 prom_debug(" alloc_top : %x\n", alloc_top);
1068 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1069 prom_debug(" rmo_top : %x\n", rmo_top);
1070 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001071
1072 return addr;
1073}
1074
1075/*
1076 * Parse a "reg" cell
1077 */
1078static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1079{
1080 cell_t *p = *cellp;
1081 unsigned long r = 0;
1082
1083 /* Ignore more than 2 cells */
1084 while (s > sizeof(unsigned long) / 4) {
1085 p++;
1086 s--;
1087 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001088 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001089#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001090 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001091 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001092 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001093 }
1094#endif
1095 *cellp = p;
1096 return r;
1097}
1098
1099/*
1100 * Very dumb function for adding to the memory reserve list, but
1101 * we don't need anything smarter at this point
1102 *
1103 * XXX Eventually check for collisions. They should NEVER happen.
1104 * If problems seem to show up, it would be a good start to track
1105 * them down.
1106 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001107static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001108{
Kumar Galacbbcf342006-01-11 17:57:13 -06001109 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001110 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001111
1112 if (size == 0)
1113 return;
1114
1115 /* We need to always keep one empty entry so that we
1116 * have our terminator with "size" set to 0 since we are
1117 * dumb and just copy this entire array to the boot params
1118 */
1119 base = _ALIGN_DOWN(base, PAGE_SIZE);
1120 top = _ALIGN_UP(top, PAGE_SIZE);
1121 size = top - base;
1122
1123 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1124 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001125 mem_reserve_map[cnt].base = cpu_to_be64(base);
1126 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001127 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001128}
1129
1130/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001131 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001132 * obtain that way the top of memory and RMO to setup out local allocator
1133 */
1134static void __init prom_init_mem(void)
1135{
1136 phandle node;
1137 char *path, type[64];
1138 unsigned int plen;
1139 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001140 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001141 u32 rac, rsc;
1142
1143 /*
1144 * We iterate the memory nodes to find
1145 * 1) top of RMO (first node)
1146 * 2) top of memory
1147 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001148 val = cpu_to_be32(2);
1149 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1150 rac = be32_to_cpu(val);
1151 val = cpu_to_be32(1);
1152 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1153 rsc = be32_to_cpu(val);
1154 prom_debug("root_addr_cells: %x\n", rac);
1155 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001156
1157 prom_debug("scanning memory:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001158 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001159
1160 for (node = 0; prom_next_node(&node); ) {
1161 type[0] = 0;
1162 prom_getprop(node, "device_type", type, sizeof(type));
1163
Paul Mackerrasc49888202005-10-26 21:52:53 +10001164 if (type[0] == 0) {
1165 /*
1166 * CHRP Longtrail machines have no device_type
1167 * on the memory node, so check the name instead...
1168 */
1169 prom_getprop(node, "name", type, sizeof(type));
1170 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001171 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001172 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001173
Anton Blanchard5827d412012-11-26 17:40:03 +00001174 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001175 if (plen > sizeof(regbuf)) {
1176 prom_printf("memory node too large for buffer !\n");
1177 plen = sizeof(regbuf);
1178 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001179 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001180 endp = p + (plen / sizeof(cell_t));
1181
1182#ifdef DEBUG_PROM
1183 memset(path, 0, PROM_SCRATCH_SIZE);
1184 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1185 prom_debug(" node %s :\n", path);
1186#endif /* DEBUG_PROM */
1187
1188 while ((endp - p) >= (rac + rsc)) {
1189 unsigned long base, size;
1190
1191 base = prom_next_cell(rac, &p);
1192 size = prom_next_cell(rsc, &p);
1193
1194 if (size == 0)
1195 continue;
1196 prom_debug(" %x %x\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001197 if (base == 0 && (of_platform & PLATFORM_LPAR))
1198 rmo_top = size;
1199 if ((base + size) > ram_top)
1200 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001201 }
1202 }
1203
Anton Blanchard5827d412012-11-26 17:40:03 +00001204 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001205
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001206 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001207 * If prom_memory_limit is set we reduce the upper limits *except* for
1208 * alloc_top_high. This must be the real top of RAM so we can put
1209 * TCE's up there.
1210 */
1211
Anton Blanchard5827d412012-11-26 17:40:03 +00001212 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001213
Anton Blanchard5827d412012-11-26 17:40:03 +00001214 if (prom_memory_limit) {
1215 if (prom_memory_limit <= alloc_bottom) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001216 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001217 prom_memory_limit);
1218 prom_memory_limit = 0;
1219 } else if (prom_memory_limit >= ram_top) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001220 prom_printf("Ignoring mem=%x >= ram_top.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001221 prom_memory_limit);
1222 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001223 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001224 ram_top = prom_memory_limit;
1225 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001226 }
1227 }
1228
1229 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001230 * Setup our top alloc point, that is top of RMO or top of
1231 * segment 0 when running non-LPAR.
1232 * Some RS64 machines have buggy firmware where claims up at
1233 * 1GB fail. Cap at 768MB as a workaround.
1234 * Since 768MB is plenty of room, and we need to cap to something
1235 * reasonable on 32-bit, cap at 768MB on all machines.
1236 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001237 if (!rmo_top)
1238 rmo_top = ram_top;
1239 rmo_top = min(0x30000000ul, rmo_top);
1240 alloc_top = rmo_top;
1241 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001242
Paul Mackerras64968f62011-12-13 17:54:13 +00001243 /*
1244 * Check if we have an initrd after the kernel but still inside
1245 * the RMO. If we do move our bottom point to after it.
1246 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001247 if (prom_initrd_start &&
1248 prom_initrd_start < rmo_top &&
1249 prom_initrd_end > alloc_bottom)
1250 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001251
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001252 prom_printf("memory layout at init:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001253 prom_printf(" memory_limit : %x (16 MB aligned)\n", prom_memory_limit);
1254 prom_printf(" alloc_bottom : %x\n", alloc_bottom);
1255 prom_printf(" alloc_top : %x\n", alloc_top);
1256 prom_printf(" alloc_top_hi : %x\n", alloc_top_high);
1257 prom_printf(" rmo_top : %x\n", rmo_top);
1258 prom_printf(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001259}
1260
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001261static void __init prom_close_stdin(void)
1262{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001263 __be32 val;
1264 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001265
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001266 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1267 stdin = be32_to_cpu(val);
1268 call_prom("close", 1, 0, stdin);
1269 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001270}
1271
1272#ifdef CONFIG_PPC_POWERNV
1273
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001274#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1275static u64 __initdata prom_opal_base;
1276static u64 __initdata prom_opal_entry;
1277#endif
1278
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001279/*
1280 * Allocate room for and instantiate OPAL
1281 */
1282static void __init prom_instantiate_opal(void)
1283{
1284 phandle opal_node;
1285 ihandle opal_inst;
1286 u64 base, entry;
1287 u64 size = 0, align = 0x10000;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001288 __be64 val64;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001289 u32 rets[2];
1290
1291 prom_debug("prom_instantiate_opal: start...\n");
1292
1293 opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
1294 prom_debug("opal_node: %x\n", opal_node);
1295 if (!PHANDLE_VALID(opal_node))
1296 return;
1297
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001298 val64 = 0;
1299 prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64));
1300 size = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001301 if (size == 0)
1302 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001303 val64 = 0;
1304 prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64));
1305 align = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001306
1307 base = alloc_down(size, align, 0);
1308 if (base == 0) {
1309 prom_printf("OPAL allocation failed !\n");
1310 return;
1311 }
1312
1313 opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
1314 if (!IHANDLE_VALID(opal_inst)) {
1315 prom_printf("opening opal package failed (%x)\n", opal_inst);
1316 return;
1317 }
1318
1319 prom_printf("instantiating opal at 0x%x...", base);
1320
1321 if (call_prom_ret("call-method", 4, 3, rets,
1322 ADDR("load-opal-runtime"),
1323 opal_inst,
1324 base >> 32, base & 0xffffffff) != 0
1325 || (rets[0] == 0 && rets[1] == 0)) {
1326 prom_printf(" failed\n");
1327 return;
1328 }
1329 entry = (((u64)rets[0]) << 32) | rets[1];
1330
1331 prom_printf(" done\n");
1332
1333 reserve_mem(base, size);
1334
1335 prom_debug("opal base = 0x%x\n", base);
1336 prom_debug("opal align = 0x%x\n", align);
1337 prom_debug("opal entry = 0x%x\n", entry);
1338 prom_debug("opal size = 0x%x\n", (long)size);
1339
1340 prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
1341 &base, sizeof(base));
1342 prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
1343 &entry, sizeof(entry));
1344
1345#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
Anton Blanchard5827d412012-11-26 17:40:03 +00001346 prom_opal_base = base;
1347 prom_opal_entry = entry;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001348#endif
1349 prom_debug("prom_instantiate_opal: end...\n");
1350}
1351
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001352#endif /* CONFIG_PPC_POWERNV */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001353
1354/*
1355 * Allocate room for and instantiate RTAS
1356 */
1357static void __init prom_instantiate_rtas(void)
1358{
1359 phandle rtas_node;
1360 ihandle rtas_inst;
1361 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001362 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001363 u32 size = 0;
1364
1365 prom_debug("prom_instantiate_rtas: start...\n");
1366
1367 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1368 prom_debug("rtas_node: %x\n", rtas_node);
1369 if (!PHANDLE_VALID(rtas_node))
1370 return;
1371
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001372 val = 0;
1373 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1374 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001375 if (size == 0)
1376 return;
1377
1378 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001379 if (base == 0)
1380 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001381
1382 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1383 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001384 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001385 return;
1386 }
1387
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001388 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001389
1390 if (call_prom_ret("call-method", 3, 2, &entry,
1391 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001392 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001393 || entry == 0) {
1394 prom_printf(" failed\n");
1395 return;
1396 }
1397 prom_printf(" done\n");
1398
1399 reserve_mem(base, size);
1400
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001401 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001402 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001403 &val, sizeof(val));
1404 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001405 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001406 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001407
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001408 /* Check if it supports "query-cpu-stopped-state" */
1409 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1410 &val, sizeof(val)) != PROM_ERROR)
1411 rtas_has_query_cpu_stopped = true;
1412
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001413 prom_debug("rtas base = 0x%x\n", base);
1414 prom_debug("rtas entry = 0x%x\n", entry);
1415 prom_debug("rtas size = 0x%x\n", (long)size);
1416
1417 prom_debug("prom_instantiate_rtas: end...\n");
1418}
1419
1420#ifdef CONFIG_PPC64
1421/*
Ashley Lai4a727422012-08-14 18:34:57 -05001422 * Allocate room for and instantiate Stored Measurement Log (SML)
1423 */
1424static void __init prom_instantiate_sml(void)
1425{
1426 phandle ibmvtpm_node;
1427 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001428 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001429 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001430 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001431
1432 prom_debug("prom_instantiate_sml: start...\n");
1433
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001434 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001435 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1436 if (!PHANDLE_VALID(ibmvtpm_node))
1437 return;
1438
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001439 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001440 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1441 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1442 return;
1443 }
1444
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001445 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1446 &val, sizeof(val)) != PROM_ERROR) {
1447 if (call_prom_ret("call-method", 2, 2, &succ,
1448 ADDR("reformat-sml-to-efi-alignment"),
1449 ibmvtpm_inst) != 0 || succ == 0) {
1450 prom_printf("Reformat SML to EFI alignment failed\n");
1451 return;
1452 }
1453 }
1454
Ashley Lai4a727422012-08-14 18:34:57 -05001455 if (call_prom_ret("call-method", 2, 2, &size,
1456 ADDR("sml-get-handover-size"),
1457 ibmvtpm_inst) != 0 || size == 0) {
1458 prom_printf("SML get handover size failed\n");
1459 return;
1460 }
1461
1462 base = alloc_down(size, PAGE_SIZE, 0);
1463 if (base == 0)
1464 prom_panic("Could not allocate memory for sml\n");
1465
1466 prom_printf("instantiating sml at 0x%x...", base);
1467
1468 if (call_prom_ret("call-method", 4, 2, &entry,
1469 ADDR("sml-handover"),
1470 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1471 prom_printf("SML handover failed\n");
1472 return;
1473 }
1474 prom_printf(" done\n");
1475
1476 reserve_mem(base, size);
1477
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001478 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001479 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001480 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001481 &size, sizeof(size));
1482
1483 prom_debug("sml base = 0x%x\n", base);
1484 prom_debug("sml size = 0x%x\n", (long)size);
1485
1486 prom_debug("prom_instantiate_sml: end...\n");
1487}
1488
1489/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001490 * Allocate room for and initialize TCE tables
1491 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001492#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001493static void __init prom_initialize_tce_table(void)
1494{
1495 phandle node;
1496 ihandle phb_node;
1497 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001498 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001499 u64 base, align;
1500 u32 minalign, minsize;
1501 u64 tce_entry, *tce_entryp;
1502 u64 local_alloc_top, local_alloc_bottom;
1503 u64 i;
1504
Anton Blanchard5827d412012-11-26 17:40:03 +00001505 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001506 return;
1507
1508 prom_debug("starting prom_initialize_tce_table\n");
1509
1510 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001511 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001512 local_alloc_bottom = local_alloc_top;
1513
1514 /* Search all nodes looking for PHBs. */
1515 for (node = 0; prom_next_node(&node); ) {
1516 compatible[0] = 0;
1517 type[0] = 0;
1518 model[0] = 0;
1519 prom_getprop(node, "compatible",
1520 compatible, sizeof(compatible));
1521 prom_getprop(node, "device_type", type, sizeof(type));
1522 prom_getprop(node, "model", model, sizeof(model));
1523
Anton Blanchard5827d412012-11-26 17:40:03 +00001524 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001525 continue;
1526
Linas Vepstase788ff12007-09-07 03:45:21 +10001527 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001528 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001529 if ((strstr(compatible, "python") == NULL) &&
1530 (strstr(compatible, "Speedwagon") == NULL) &&
1531 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001532 continue;
1533 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001534 if ((strstr(model, "ython") == NULL) &&
1535 (strstr(model, "peedwagon") == NULL) &&
1536 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001537 continue;
1538 }
1539
1540 if (prom_getprop(node, "tce-table-minalign", &minalign,
1541 sizeof(minalign)) == PROM_ERROR)
1542 minalign = 0;
1543 if (prom_getprop(node, "tce-table-minsize", &minsize,
1544 sizeof(minsize)) == PROM_ERROR)
1545 minsize = 4UL << 20;
1546
1547 /*
1548 * Even though we read what OF wants, we just set the table
1549 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1550 * By doing this, we avoid the pitfalls of trying to DMA to
1551 * MMIO space and the DMA alias hole.
1552 *
1553 * On POWER4, firmware sets the TCE region by assuming
1554 * each TCE table is 8MB. Using this memory for anything
1555 * else will impact performance, so we always allocate 8MB.
1556 * Anton
1557 */
Michael Ellermand3dbeef2012-08-19 21:44:01 +00001558 if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001559 minsize = 8UL << 20;
1560 else
1561 minsize = 4UL << 20;
1562
1563 /* Align to the greater of the align or size */
1564 align = max(minalign, minsize);
1565 base = alloc_down(minsize, align, 1);
1566 if (base == 0)
1567 prom_panic("ERROR, cannot find space for TCE table.\n");
1568 if (base < local_alloc_bottom)
1569 local_alloc_bottom = base;
1570
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001571 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001572 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001573 /* Call OF to setup the TCE hardware */
1574 if (call_prom("package-to-path", 3, 1, node,
1575 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1576 prom_printf("package-to-path failed\n");
1577 }
1578
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001579 /* Save away the TCE table attributes for later use. */
1580 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1581 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1582
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001583 prom_debug("TCE table: %s\n", path);
1584 prom_debug("\tnode = 0x%x\n", node);
1585 prom_debug("\tbase = 0x%x\n", base);
1586 prom_debug("\tsize = 0x%x\n", minsize);
1587
1588 /* Initialize the table to have a one-to-one mapping
1589 * over the allocated size.
1590 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001591 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001592 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1593 tce_entry = (i << PAGE_SHIFT);
1594 tce_entry |= 0x3;
1595 *tce_entryp = tce_entry;
1596 }
1597
1598 prom_printf("opening PHB %s", path);
1599 phb_node = call_prom("open", 1, 1, path);
1600 if (phb_node == 0)
1601 prom_printf("... failed\n");
1602 else
1603 prom_printf("... done\n");
1604
1605 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1606 phb_node, -1, minsize,
1607 (u32) base, (u32) (base >> 32));
1608 call_prom("close", 1, 0, phb_node);
1609 }
1610
1611 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1612
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001613 /* These are only really needed if there is a memory limit in
1614 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001615 prom_tce_alloc_start = local_alloc_bottom;
1616 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001617
1618 /* Flag the first invalid entry */
1619 prom_debug("ending prom_initialize_tce_table\n");
1620}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001621#endif /* __BIG_ENDIAN__ */
1622#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001623
1624/*
1625 * With CHRP SMP we need to use the OF to start the other processors.
1626 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1627 * so we have to put the processors into a holding pattern controlled
1628 * by the kernel (not OF) before we destroy the OF.
1629 *
1630 * This uses a chunk of low memory, puts some holding pattern
1631 * code there and sends the other processors off to there until
1632 * smp_boot_cpus tells them to do something. The holding pattern
1633 * checks that address until its cpu # is there, when it is that
1634 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1635 * of setting those values.
1636 *
1637 * We also use physical address 0x4 here to tell when a cpu
1638 * is in its holding pattern code.
1639 *
1640 * -- Cort
1641 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001642/*
1643 * We want to reference the copy of __secondary_hold_* in the
1644 * 0 - 0x100 address range
1645 */
1646#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1647
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001648static void __init prom_hold_cpus(void)
1649{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001650 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001651 phandle node;
1652 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001653 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001654 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001655 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001656 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001657 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001658
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001659 /*
1660 * On pseries, if RTAS supports "query-cpu-stopped-state",
1661 * we skip this stage, the CPUs will be started by the
1662 * kernel using RTAS.
1663 */
1664 if ((of_platform == PLATFORM_PSERIES ||
1665 of_platform == PLATFORM_PSERIES_LPAR) &&
1666 rtas_has_query_cpu_stopped) {
1667 prom_printf("prom_hold_cpus: skipped\n");
1668 return;
1669 }
1670
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001671 prom_debug("prom_hold_cpus: start...\n");
1672 prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
1673 prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
1674 prom_debug(" 1) acknowledge = 0x%x\n",
1675 (unsigned long)acknowledge);
1676 prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
1677 prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
1678
1679 /* Set the common spinloop variable, so all of the secondary cpus
1680 * will block when they are awakened from their OF spinloop.
1681 * This must occur for both SMP and non SMP kernels, since OF will
1682 * be trashed when we move the kernel.
1683 */
1684 *spinloop = 0;
1685
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001686 /* look for cpus */
1687 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001688 unsigned int cpu_no;
1689 __be32 reg;
1690
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001691 type[0] = 0;
1692 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001693 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001694 continue;
1695
1696 /* Skip non-configured cpus. */
1697 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001698 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001699 continue;
1700
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001701 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001702 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001703 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001704
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001705 prom_debug("cpu hw idx = %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001706
1707 /* Init the acknowledge var which will be reset by
1708 * the secondary cpu when it awakens from its OF
1709 * spinloop.
1710 */
1711 *acknowledge = (unsigned long)-1;
1712
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001713 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001714 /* Primary Thread of non-boot cpu or any thread */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001715 prom_printf("starting cpu hw idx %lu... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001716 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001717 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001718
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001719 for (i = 0; (i < 100000000) &&
1720 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001721 mb();
1722
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001723 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001724 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001725 else
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001726 prom_printf("failed: %x\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001727 }
1728#ifdef CONFIG_SMP
1729 else
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001730 prom_printf("boot cpu hw idx %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001731#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001732 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001733
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001734 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001735}
1736
1737
1738static void __init prom_init_client_services(unsigned long pp)
1739{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001740 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00001741 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001742
1743 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00001744 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1745 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001746 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1747
1748 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00001749 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
1750 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001751 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001752
Anton Blanchard5827d412012-11-26 17:40:03 +00001753 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001754}
1755
Paul Mackerrasa575b802005-10-23 17:23:21 +10001756#ifdef CONFIG_PPC32
1757/*
1758 * For really old powermacs, we need to map things we claim.
1759 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001760 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10001761 */
1762static void __init prom_find_mmu(void)
1763{
Paul Mackerrasa575b802005-10-23 17:23:21 +10001764 phandle oprom;
1765 char version[64];
1766
1767 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1768 if (!PHANDLE_VALID(oprom))
1769 return;
1770 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1771 return;
1772 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10001773 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001774 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
1775 of_workarounds = OF_WA_CLAIM;
1776 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
1777 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
1778 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
1779 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10001780 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00001781 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
1782 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
1783 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001784 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00001785 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001786 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001787}
1788#else
1789#define prom_find_mmu()
1790#endif
1791
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001792static void __init prom_init_stdout(void)
1793{
Anton Blanchard5827d412012-11-26 17:40:03 +00001794 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001795 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001796 phandle stdout_node;
1797 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001798
Anton Blanchard5827d412012-11-26 17:40:03 +00001799 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001800 prom_panic("cannot find stdout");
1801
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001802 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001803
1804 /* Get the full OF pathname of the stdout device */
1805 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00001806 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00001807 prom_printf("OF stdout device is: %s\n", of_stdout_device);
1808 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001809 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001810
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11001811 /* instance-to-package fails on PA-Semi */
1812 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
1813 if (stdout_node != PROM_ERROR) {
1814 val = cpu_to_be32(stdout_node);
1815 prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
1816 &val, sizeof(val));
1817
1818 /* If it's a display, note it */
1819 memset(type, 0, sizeof(type));
1820 prom_getprop(stdout_node, "device_type", type, sizeof(type));
1821 if (strcmp(type, "display") == 0)
1822 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
1823 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001824}
1825
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001826static int __init prom_find_machine_type(void)
1827{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001828 char compat[256];
1829 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001830#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001831 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001832 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001833#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001834
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001835 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00001836 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001837 compat, sizeof(compat)-1);
1838 if (len > 0) {
1839 compat[len] = 0;
1840 while (i < len) {
1841 char *p = &compat[i];
1842 int sl = strlen(p);
1843 if (sl == 0)
1844 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00001845 if (strstr(p, "Power Macintosh") ||
1846 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001847 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10001848#ifdef CONFIG_PPC64
1849 /* We must make sure we don't detect the IBM Cell
1850 * blades as pSeries due to some firmware issues,
1851 * so we do it here.
1852 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001853 if (strstr(p, "IBM,CBEA") ||
1854 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10001855 return PLATFORM_GENERIC;
1856#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001857 i += sl + 1;
1858 }
1859 }
1860#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001861 /* Try to detect OPAL */
1862 if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
1863 return PLATFORM_OPAL;
1864
1865 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001866 * PAPR compliant platform. We assume it is if :
1867 * - /device_type is "chrp" (please, do NOT use that for future
1868 * non-IBM designs !
1869 * - it has /rtas
1870 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001871 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001872 compat, sizeof(compat)-1);
1873 if (len <= 0)
1874 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00001875 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001876 return PLATFORM_GENERIC;
1877
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001878 /* Default to pSeries. We need to know if we are running LPAR */
1879 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001880 if (!PHANDLE_VALID(rtas))
1881 return PLATFORM_GENERIC;
1882 x = prom_getproplen(rtas, "ibm,hypertas-functions");
1883 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00001884 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001885 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001886 }
1887 return PLATFORM_PSERIES;
1888#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001889 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001890#endif
1891}
1892
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001893static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
1894{
1895 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
1896}
1897
1898/*
1899 * If we have a display that we don't know how to drive,
1900 * we will want to try to execute OF's open method for it
1901 * later. However, OF will probably fall over if we do that
1902 * we've taken over the MMU.
1903 * So we check whether we will need to open the display,
1904 * and if so, open it now.
1905 */
1906static void __init prom_check_displays(void)
1907{
1908 char type[16], *path;
1909 phandle node;
1910 ihandle ih;
1911 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001912
1913 static unsigned char default_colors[] = {
1914 0x00, 0x00, 0x00,
1915 0x00, 0x00, 0xaa,
1916 0x00, 0xaa, 0x00,
1917 0x00, 0xaa, 0xaa,
1918 0xaa, 0x00, 0x00,
1919 0xaa, 0x00, 0xaa,
1920 0xaa, 0xaa, 0x00,
1921 0xaa, 0xaa, 0xaa,
1922 0x55, 0x55, 0x55,
1923 0x55, 0x55, 0xff,
1924 0x55, 0xff, 0x55,
1925 0x55, 0xff, 0xff,
1926 0xff, 0x55, 0x55,
1927 0xff, 0x55, 0xff,
1928 0xff, 0xff, 0x55,
1929 0xff, 0xff, 0xff
1930 };
1931 const unsigned char *clut;
1932
Anton Blanchard4da727a2009-03-31 20:06:14 +00001933 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001934 for (node = 0; prom_next_node(&node); ) {
1935 memset(type, 0, sizeof(type));
1936 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001937 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001938 continue;
1939
1940 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00001941 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001942 memset(path, 0, PROM_SCRATCH_SIZE);
1943
1944 /*
1945 * leave some room at the end of the path for appending extra
1946 * arguments
1947 */
1948 if (call_prom("package-to-path", 3, 1, node, path,
1949 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
1950 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001951 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001952
1953 ih = call_prom("open", 1, 1, path);
1954 if (ih == 0) {
1955 prom_printf("failed\n");
1956 continue;
1957 }
1958
1959 /* Success */
1960 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001961 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001962
1963 /* Setup a usable color table when the appropriate
1964 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00001965 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00001966 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001967 if (prom_set_color(ih, i, clut[0], clut[1],
1968 clut[2]) != 0)
1969 break;
1970
1971#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00001972 clut = PTRRELOC(logo_linux_clut224.clut);
1973 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001974 if (prom_set_color(ih, i + 32, clut[0], clut[1],
1975 clut[2]) != 0)
1976 break;
1977#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10001978
1979#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
1980 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
1981 PROM_ERROR) {
1982 u32 width, height, pitch, addr;
1983
1984 prom_printf("Setting btext !\n");
1985 prom_getprop(node, "width", &width, 4);
1986 prom_getprop(node, "height", &height, 4);
1987 prom_getprop(node, "linebytes", &pitch, 4);
1988 prom_getprop(node, "address", &addr, 4);
1989 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
1990 width, height, pitch, addr);
1991 btext_setup_display(width, height, 8, pitch, addr);
1992 }
1993#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001994 }
1995}
1996
1997
1998/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
1999static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2000 unsigned long needed, unsigned long align)
2001{
2002 void *ret;
2003
2004 *mem_start = _ALIGN(*mem_start, align);
2005 while ((*mem_start + needed) > *mem_end) {
2006 unsigned long room, chunk;
2007
2008 prom_debug("Chunk exhausted, claiming more at %x...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002009 alloc_bottom);
2010 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002011 if (room > DEVTREE_CHUNK_SIZE)
2012 room = DEVTREE_CHUNK_SIZE;
2013 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002014 prom_panic("No memory for flatten_device_tree "
2015 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002016 chunk = alloc_up(room, 0);
2017 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002018 prom_panic("No memory for flatten_device_tree "
2019 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002020 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002021 }
2022
2023 ret = (void *)*mem_start;
2024 *mem_start += needed;
2025
2026 return ret;
2027}
2028
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002029#define dt_push_token(token, mem_start, mem_end) do { \
2030 void *room = make_room(mem_start, mem_end, 4, 4); \
2031 *(__be32 *)room = cpu_to_be32(token); \
2032 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002033
2034static unsigned long __init dt_find_string(char *str)
2035{
2036 char *s, *os;
2037
Anton Blanchard5827d412012-11-26 17:40:03 +00002038 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002039 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002040 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002041 if (strcmp(s, str) == 0)
2042 return s - os;
2043 s += strlen(s) + 1;
2044 }
2045 return 0;
2046}
2047
2048/*
2049 * The Open Firmware 1275 specification states properties must be 31 bytes or
2050 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2051 */
2052#define MAX_PROPERTY_NAME 64
2053
2054static void __init scan_dt_build_strings(phandle node,
2055 unsigned long *mem_start,
2056 unsigned long *mem_end)
2057{
2058 char *prev_name, *namep, *sstart;
2059 unsigned long soff;
2060 phandle child;
2061
Anton Blanchard5827d412012-11-26 17:40:03 +00002062 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002063
2064 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002065 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002066 for (;;) {
2067 /* 64 is max len of name including nul. */
2068 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2069 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2070 /* No more nodes: unwind alloc */
2071 *mem_start = (unsigned long)namep;
2072 break;
2073 }
2074
2075 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002076 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002077 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002078 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002079 continue;
2080 }
2081 /* get/create string entry */
2082 soff = dt_find_string(namep);
2083 if (soff != 0) {
2084 *mem_start = (unsigned long)namep;
2085 namep = sstart + soff;
2086 } else {
2087 /* Trim off some if we can */
2088 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002089 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002090 }
2091 prev_name = namep;
2092 }
2093
2094 /* do all our children */
2095 child = call_prom("child", 1, 1, node);
2096 while (child != 0) {
2097 scan_dt_build_strings(child, mem_start, mem_end);
2098 child = call_prom("peer", 1, 1, child);
2099 }
2100}
2101
2102static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2103 unsigned long *mem_end)
2104{
2105 phandle child;
2106 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2107 unsigned long soff;
2108 unsigned char *valp;
2109 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002110 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002111
2112 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2113
2114 /* get the node's full name */
2115 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002116 room = *mem_end - *mem_start;
2117 if (room > 255)
2118 room = 255;
2119 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002120 if (l >= 0) {
2121 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002122 if (l >= room) {
2123 if (l >= *mem_end - *mem_start)
2124 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002125 call_prom("package-to-path", 3, 1, node, namep, l);
2126 }
2127 namep[l] = '\0';
2128
2129 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002130 * middle of the path in some properties, and extract
2131 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002132 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002133 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002134 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002135 lp = namep;
2136 else if (*p != 0)
2137 *lp++ = *p;
2138 }
2139 *lp = 0;
2140 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002141 }
2142
2143 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002144 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002145 memset(path, 0, PROM_SCRATCH_SIZE);
2146 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2147
2148 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002149 prev_name = "";
2150 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002151 for (;;) {
2152 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002153 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002154 break;
2155
2156 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002157 if (strcmp(pname, "name") == 0) {
2158 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002159 continue;
2160 }
2161
2162 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002163 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002164 if (soff == 0) {
2165 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002166 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002167 break;
2168 }
2169 prev_name = sstart + soff;
2170
2171 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002172 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002173
2174 /* sanity checks */
2175 if (l == PROM_ERROR)
2176 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002177
2178 /* push property head */
2179 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2180 dt_push_token(l, mem_start, mem_end);
2181 dt_push_token(soff, mem_start, mem_end);
2182
2183 /* push property content */
2184 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002185 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002186 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002187
Anton Blanchard5827d412012-11-26 17:40:03 +00002188 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002189 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002190 }
2191
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002192 /* Add a "linux,phandle" property if no "phandle" property already
2193 * existed (can happen with OPAL)
2194 */
2195 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002196 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002197 if (soff == 0)
2198 prom_printf("WARNING: Can't find string index for"
2199 " <linux-phandle> node %s\n", path);
2200 else {
2201 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2202 dt_push_token(4, mem_start, mem_end);
2203 dt_push_token(soff, mem_start, mem_end);
2204 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002205 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002206 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002207 }
2208
2209 /* do all our children */
2210 child = call_prom("child", 1, 1, node);
2211 while (child != 0) {
2212 scan_dt_build_struct(child, mem_start, mem_end);
2213 child = call_prom("peer", 1, 1, child);
2214 }
2215
2216 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2217}
2218
2219static void __init flatten_device_tree(void)
2220{
2221 phandle root;
2222 unsigned long mem_start, mem_end, room;
2223 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002224 char *namep;
2225 u64 *rsvmap;
2226
2227 /*
2228 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002229 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002230 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002231 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002232 if (room > DEVTREE_CHUNK_SIZE)
2233 room = DEVTREE_CHUNK_SIZE;
Anton Blanchard5827d412012-11-26 17:40:03 +00002234 prom_debug("starting device tree allocs at %x\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002235
2236 /* Now try to claim that */
2237 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2238 if (mem_start == 0)
2239 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002240 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002241
2242 /* Get root of tree */
2243 root = call_prom("peer", 1, 1, (phandle)0);
2244 if (root == (phandle)0)
2245 prom_panic ("couldn't get device tree root\n");
2246
2247 /* Build header and make room for mem rsv map */
2248 mem_start = _ALIGN(mem_start, 4);
2249 hdr = make_room(&mem_start, &mem_end,
2250 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002251 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002252 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2253
2254 /* Start of strings */
2255 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002256 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002257 mem_start += 4; /* hole */
2258
2259 /* Add "linux,phandle" in there, we'll need it */
2260 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002261 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002262 mem_start = (unsigned long)namep + strlen(namep) + 1;
2263
2264 /* Build string array */
2265 prom_printf("Building dt strings...\n");
2266 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002267 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002268
2269 /* Build structure */
2270 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002271 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002272 prom_printf("Building dt structure...\n");
2273 scan_dt_build_struct(root, &mem_start, &mem_end);
2274 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002275 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002276
2277 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002278 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2279 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2280 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2281 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2282 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2283 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2284 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2285 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002286 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002287 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002288
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002289 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002290 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002291
2292#ifdef DEBUG_PROM
2293 {
2294 int i;
2295 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002296 for (i = 0; i < mem_reserve_cnt; i++)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002297 prom_printf(" %x - %x\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002298 be64_to_cpu(mem_reserve_map[i].base),
2299 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002300 }
2301#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002302 /* Bump mem_reserve_cnt to cause further reservations to fail
2303 * since it's too late.
2304 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002305 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002306
2307 prom_printf("Device tree strings 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002308 dt_string_start, dt_string_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002309 prom_printf("Device tree struct 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002310 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002311}
2312
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002313#ifdef CONFIG_PPC_MAPLE
2314/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2315 * The values are bad, and it doesn't even have the right number of cells. */
2316static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002317{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002318 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002319 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002320 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002321 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002322
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002323 name = "/ht@0/isa@4";
2324 isa = call_prom("finddevice", 1, 1, ADDR(name));
2325 if (!PHANDLE_VALID(isa)) {
2326 name = "/ht@0/isa@6";
2327 isa = call_prom("finddevice", 1, 1, ADDR(name));
2328 rloc = 0x01003000; /* IO space; PCI device = 6 */
2329 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002330 if (!PHANDLE_VALID(isa))
2331 return;
2332
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002333 if (prom_getproplen(isa, "ranges") != 12)
2334 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002335 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2336 == PROM_ERROR)
2337 return;
2338
2339 if (isa_ranges[0] != 0x1 ||
2340 isa_ranges[1] != 0xf4000000 ||
2341 isa_ranges[2] != 0x00010000)
2342 return;
2343
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002344 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002345
2346 isa_ranges[0] = 0x1;
2347 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002348 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002349 isa_ranges[3] = 0x0;
2350 isa_ranges[4] = 0x0;
2351 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002352 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002353 isa_ranges, sizeof(isa_ranges));
2354}
Harry Ciao8f101a052009-06-17 16:28:00 -07002355
2356#define CPC925_MC_START 0xf8000000
2357#define CPC925_MC_LENGTH 0x1000000
2358/* The values for memory-controller don't have right number of cells */
2359static void __init fixup_device_tree_maple_memory_controller(void)
2360{
2361 phandle mc;
2362 u32 mc_reg[4];
2363 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002364 u32 ac, sc;
2365
2366 mc = call_prom("finddevice", 1, 1, ADDR(name));
2367 if (!PHANDLE_VALID(mc))
2368 return;
2369
2370 if (prom_getproplen(mc, "reg") != 8)
2371 return;
2372
Anton Blanchard5827d412012-11-26 17:40:03 +00002373 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2374 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002375 if ((ac != 2) || (sc != 2))
2376 return;
2377
2378 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2379 return;
2380
2381 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2382 return;
2383
2384 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2385
2386 mc_reg[0] = 0x0;
2387 mc_reg[1] = CPC925_MC_START;
2388 mc_reg[2] = 0x0;
2389 mc_reg[3] = CPC925_MC_LENGTH;
2390 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2391}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002392#else
2393#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002394#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002395#endif
2396
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002397#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002398/*
2399 * Pegasos and BriQ lacks the "ranges" property in the isa node
2400 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002401 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002402 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002403static void __init fixup_device_tree_chrp(void)
2404{
Olaf Heringe4805922007-04-04 18:20:04 +02002405 phandle ph;
2406 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002407 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002408 char *name;
2409 int rc;
2410
2411 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002412 ph = call_prom("finddevice", 1, 1, ADDR(name));
2413 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002414 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002415 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002416 rloc = 0x01003000; /* IO space; PCI device = 6 */
2417 }
Olaf Heringe4805922007-04-04 18:20:04 +02002418 if (PHANDLE_VALID(ph)) {
2419 rc = prom_getproplen(ph, "ranges");
2420 if (rc == 0 || rc == PROM_ERROR) {
2421 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002422
Olaf Heringe4805922007-04-04 18:20:04 +02002423 prop[0] = 0x1;
2424 prop[1] = 0x0;
2425 prop[2] = rloc;
2426 prop[3] = 0x0;
2427 prop[4] = 0x0;
2428 prop[5] = 0x00010000;
2429 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2430 }
2431 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002432
Olaf Heringe4805922007-04-04 18:20:04 +02002433 name = "/pci@80000000/ide@C,1";
2434 ph = call_prom("finddevice", 1, 1, ADDR(name));
2435 if (PHANDLE_VALID(ph)) {
2436 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2437 prop[0] = 14;
2438 prop[1] = 0x0;
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002439 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2440 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2441 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2442 if (rc == sizeof(u32)) {
2443 prop[0] &= ~0x5;
2444 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2445 }
Olaf Heringe4805922007-04-04 18:20:04 +02002446 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002447}
2448#else
2449#define fixup_device_tree_chrp()
2450#endif
2451
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002452#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002453static void __init fixup_device_tree_pmac(void)
2454{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002455 phandle u3, i2c, mpic;
2456 u32 u3_rev;
2457 u32 interrupts[2];
2458 u32 parent;
2459
2460 /* Some G5s have a missing interrupt definition, fix it up here */
2461 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2462 if (!PHANDLE_VALID(u3))
2463 return;
2464 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2465 if (!PHANDLE_VALID(i2c))
2466 return;
2467 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2468 if (!PHANDLE_VALID(mpic))
2469 return;
2470
2471 /* check if proper rev of u3 */
2472 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2473 == PROM_ERROR)
2474 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002475 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002476 return;
2477 /* does it need fixup ? */
2478 if (prom_getproplen(i2c, "interrupts") > 0)
2479 return;
2480
2481 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2482
2483 /* interrupt on this revision of u3 is number 0 and level */
2484 interrupts[0] = 0;
2485 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002486 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2487 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002488 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002489 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2490 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002491}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002492#else
2493#define fixup_device_tree_pmac()
2494#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002495
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002496#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002497/*
2498 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2499 * to talk to the phy. If the phy-handle property is missing, then this
2500 * function is called to add the appropriate nodes and link it to the
2501 * ethernet node.
2502 */
2503static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002504{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002505 u32 node;
2506 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002507 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002508
Grant Likely94d2dde2008-01-24 22:25:32 -07002509 /* Check if /builtin/ethernet exists - bail if it doesn't */
2510 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002511 if (!PHANDLE_VALID(node))
2512 return;
2513
Grant Likely94d2dde2008-01-24 22:25:32 -07002514 /* Check if the phy-handle property exists - bail if it does */
2515 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2516 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002517 return;
2518
Grant Likely94d2dde2008-01-24 22:25:32 -07002519 /*
2520 * At this point the ethernet device doesn't have a phy described.
2521 * Now we need to add the missing phy node and linkage
2522 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002523
Grant Likely94d2dde2008-01-24 22:25:32 -07002524 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002525 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2526 if (!PHANDLE_VALID(node)) {
2527 prom_printf("Adding Ethernet MDIO node\n");
2528 call_prom("interpret", 1, 1,
2529 " s\" /builtin\" find-device"
2530 " new-device"
2531 " 1 encode-int s\" #address-cells\" property"
2532 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002533 " s\" mdio\" device-name"
2534 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002535 " s\" compatible\" property"
2536 " 0xf0003000 0x400 reg"
2537 " 0x2 encode-int"
2538 " 0x5 encode-int encode+"
2539 " 0x3 encode-int encode+"
2540 " s\" interrupts\" property"
2541 " finish-device");
2542 };
2543
Grant Likely94d2dde2008-01-24 22:25:32 -07002544 /* Check for a PHY device node - if missing then create one and
2545 * give it's phandle to the ethernet node */
2546 node = call_prom("finddevice", 1, 1,
2547 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002548 if (!PHANDLE_VALID(node)) {
2549 prom_printf("Adding Ethernet PHY node\n");
2550 call_prom("interpret", 1, 1,
2551 " s\" /builtin/mdio\" find-device"
2552 " new-device"
2553 " s\" ethernet-phy\" device-name"
2554 " 0x10 encode-int s\" reg\" property"
2555 " my-self"
2556 " ihandle>phandle"
2557 " finish-device"
2558 " s\" /builtin/ethernet\" find-device"
2559 " encode-int"
2560 " s\" phy-handle\" property"
2561 " device-end");
2562 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002563}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002564
Grant Likely94d2dde2008-01-24 22:25:32 -07002565static void __init fixup_device_tree_efika(void)
2566{
2567 int sound_irq[3] = { 2, 2, 0 };
2568 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2569 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2570 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2571 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2572 u32 node;
2573 char prop[64];
2574 int rv, len;
2575
2576 /* Check if we're really running on a EFIKA */
2577 node = call_prom("finddevice", 1, 1, ADDR("/"));
2578 if (!PHANDLE_VALID(node))
2579 return;
2580
2581 rv = prom_getprop(node, "model", prop, sizeof(prop));
2582 if (rv == PROM_ERROR)
2583 return;
2584 if (strcmp(prop, "EFIKA5K2"))
2585 return;
2586
2587 prom_printf("Applying EFIKA device tree fixups\n");
2588
2589 /* Claiming to be 'chrp' is death */
2590 node = call_prom("finddevice", 1, 1, ADDR("/"));
2591 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2592 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2593 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2594
David Woodhouse7f4392c2008-04-14 02:52:38 +10002595 /* CODEGEN,description is exposed in /proc/cpuinfo so
2596 fix that too */
2597 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2598 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2599 prom_setprop(node, "/", "CODEGEN,description",
2600 "Efika 5200B PowerPC System",
2601 sizeof("Efika 5200B PowerPC System"));
2602
Grant Likely94d2dde2008-01-24 22:25:32 -07002603 /* Fixup bestcomm interrupts property */
2604 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2605 if (PHANDLE_VALID(node)) {
2606 len = prom_getproplen(node, "interrupts");
2607 if (len == 12) {
2608 prom_printf("Fixing bestcomm interrupts property\n");
2609 prom_setprop(node, "/builtin/bestcom", "interrupts",
2610 bcomm_irq, sizeof(bcomm_irq));
2611 }
2612 }
2613
2614 /* Fixup sound interrupts property */
2615 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2616 if (PHANDLE_VALID(node)) {
2617 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2618 if (rv == PROM_ERROR) {
2619 prom_printf("Adding sound interrupts property\n");
2620 prom_setprop(node, "/builtin/sound", "interrupts",
2621 sound_irq, sizeof(sound_irq));
2622 }
2623 }
2624
2625 /* Make sure ethernet phy-handle property exists */
2626 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002627}
2628#else
2629#define fixup_device_tree_efika()
2630#endif
2631
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002632static void __init fixup_device_tree(void)
2633{
2634 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07002635 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002636 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002637 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002638 fixup_device_tree_efika();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002639}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002640
2641static void __init prom_find_boot_cpu(void)
2642{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002643 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002644 ihandle prom_cpu;
2645 phandle cpu_pkg;
2646
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002647 rval = 0;
2648 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10002649 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002650 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002651
2652 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
2653
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002654 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
2655 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002656
Anton Blanchard5827d412012-11-26 17:40:03 +00002657 prom_debug("Booting CPU hw index = %lu\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002658}
2659
2660static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2661{
2662#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002663 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002664 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002665
Anton Blanchard5827d412012-11-26 17:40:03 +00002666 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
2667 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002668
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002669 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002670 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002671 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002672 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002673 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002674 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002675
Anton Blanchard5827d412012-11-26 17:40:03 +00002676 reserve_mem(prom_initrd_start,
2677 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002678
Anton Blanchard5827d412012-11-26 17:40:03 +00002679 prom_debug("initrd_start=0x%x\n", prom_initrd_start);
2680 prom_debug("initrd_end=0x%x\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002681 }
2682#endif /* CONFIG_BLK_DEV_INITRD */
2683}
2684
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002685#ifdef CONFIG_PPC64
2686#ifdef CONFIG_RELOCATABLE
2687static void reloc_toc(void)
2688{
2689}
2690
2691static void unreloc_toc(void)
2692{
2693}
2694#else
Anton Blanchard16744002013-03-12 01:51:51 +00002695static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002696{
2697 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00002698 unsigned long *toc_entry;
2699
2700 /* Get the start of the TOC by using r2 directly. */
2701 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002702
2703 for (i = 0; i < nr_entries; i++) {
2704 *toc_entry = *toc_entry + offset;
2705 toc_entry++;
2706 }
2707}
2708
2709static void reloc_toc(void)
2710{
2711 unsigned long offset = reloc_offset();
2712 unsigned long nr_entries =
2713 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2714
Anton Blanchard16744002013-03-12 01:51:51 +00002715 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002716
2717 mb();
2718}
2719
2720static void unreloc_toc(void)
2721{
2722 unsigned long offset = reloc_offset();
2723 unsigned long nr_entries =
2724 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2725
2726 mb();
2727
Anton Blanchard16744002013-03-12 01:51:51 +00002728 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002729}
2730#endif
2731#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002732
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002733/*
2734 * We enter here early on, when the Open Firmware prom is still
2735 * handling exceptions and the MMU hash table for us.
2736 */
2737
2738unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2739 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10002740 unsigned long r6, unsigned long r7,
2741 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002742{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002743 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002744
2745#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10002746 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002747 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002748#else
2749 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002750#endif
2751
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002752 /*
2753 * First zero the BSS
2754 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002755 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002756
2757 /*
2758 * Init interface to Open Firmware, get some node references,
2759 * like /chosen
2760 */
2761 prom_init_client_services(pp);
2762
2763 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002764 * See if this OF is old enough that we need to do explicit maps
2765 * and other workarounds
2766 */
2767 prom_find_mmu();
2768
2769 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002770 * Init prom stdout device
2771 */
2772 prom_init_stdout();
2773
Anton Blanchard5827d412012-11-26 17:40:03 +00002774 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00002775
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002776 /*
2777 * Get default machine type. At this point, we do not differentiate
2778 * between pSeries SMP and pSeries LPAR
2779 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002780 of_platform = prom_find_machine_type();
2781 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002782
Suzuki Poulose0f890c82011-12-14 22:57:15 +00002783#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01002784 /* Bail if this is a kdump kernel. */
2785 if (PHYSICAL_START > 0)
2786 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10002787#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01002788
2789 /*
2790 * Check for an initrd
2791 */
2792 prom_check_initrd(r3, r4);
2793
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002794#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002795 /*
2796 * On pSeries, inform the firmware about our capabilities
2797 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002798 if (of_platform == PLATFORM_PSERIES ||
2799 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002800 prom_send_capabilities();
2801#endif
2802
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002803 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05002804 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002805 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002806 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10002807 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002808
2809 /*
2810 * Do early parsing of command line
2811 */
2812 early_cmdline_parse();
2813
2814 /*
2815 * Initialize memory management within prom_init
2816 */
2817 prom_init_mem();
2818
2819 /*
2820 * Determine which cpu is actually running right _now_
2821 */
2822 prom_find_boot_cpu();
2823
2824 /*
2825 * Initialize display devices
2826 */
2827 prom_check_displays();
2828
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002829#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002830 /*
2831 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
2832 * that uses the allocator, we need to make sure we get the top of memory
2833 * available for us here...
2834 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002835 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002836 prom_initialize_tce_table();
2837#endif
2838
2839 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002840 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
2841 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002842 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002843 if (of_platform != PLATFORM_POWERMAC &&
2844 of_platform != PLATFORM_OPAL)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002845 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002846
2847#ifdef CONFIG_PPC_POWERNV
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002848 if (of_platform == PLATFORM_OPAL)
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002849 prom_instantiate_opal();
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002850#endif /* CONFIG_PPC_POWERNV */
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002851
Ashley Lai4a727422012-08-14 18:34:57 -05002852#ifdef CONFIG_PPC64
2853 /* instantiate sml */
2854 prom_instantiate_sml();
2855#endif
2856
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002857 /*
2858 * On non-powermacs, put all CPUs in spin-loops.
2859 *
2860 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002861 *
2862 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002863 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002864 if (of_platform != PLATFORM_POWERMAC &&
2865 of_platform != PLATFORM_OPAL)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002866 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002867
2868 /*
2869 * Fill in some infos for use by the kernel later on
2870 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002871 if (prom_memory_limit) {
2872 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00002873 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002874 &val, sizeof(val));
2875 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002876#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00002877 if (prom_iommu_off)
2878 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002879 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002880
Anton Blanchard5827d412012-11-26 17:40:03 +00002881 if (prom_iommu_force_on)
2882 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002883 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002884
Anton Blanchard5827d412012-11-26 17:40:03 +00002885 if (prom_tce_alloc_start) {
2886 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
2887 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002888 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00002889 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
2890 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002891 sizeof(prom_tce_alloc_end));
2892 }
2893#endif
2894
2895 /*
2896 * Fixup any known bugs in the device-tree
2897 */
2898 fixup_device_tree();
2899
2900 /*
2901 * Now finally create the flattened device-tree
2902 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002903 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002904 flatten_device_tree();
2905
Paul Mackerras3825ac02005-11-08 22:48:08 +11002906 /*
2907 * in case stdin is USB and still active on IBM machines...
2908 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00002909 * closed stdin already (in particular the powerbook 101). It
2910 * appears that the OPAL version of OFW doesn't like it either.
Paul Mackerras3825ac02005-11-08 22:48:08 +11002911 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002912 if (of_platform != PLATFORM_POWERMAC &&
2913 of_platform != PLATFORM_OPAL)
Paul Mackerras3825ac02005-11-08 22:48:08 +11002914 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002915
2916 /*
2917 * Call OF "quiesce" method to shut down pending DMA's from
2918 * devices etc...
2919 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11002920 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002921 call_prom("quiesce", 0, 0);
2922
2923 /*
2924 * And finally, call the kernel passing it the flattened device
2925 * tree and NULL as r5, thus triggering the new entry point which
2926 * is common to us and kexec
2927 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002928 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00002929
2930 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Anton Blanchard5827d412012-11-26 17:40:03 +00002931 if (of_platform != PLATFORM_OPAL) {
Michael Ellerman7e862d72015-03-30 17:38:09 +11002932 prom_printf("Booting Linux via __start() ...\n");
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00002933 prom_debug("->dt_header_start=0x%x\n", hdr);
2934 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002935
2936#ifdef CONFIG_PPC32
2937 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002938#else
2939 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002940#endif
2941
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002942#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
2943 /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
2944 __start(hdr, kbase, 0, 0, 0,
Anton Blanchard5827d412012-11-26 17:40:03 +00002945 prom_opal_base, prom_opal_entry);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002946#else
2947 __start(hdr, kbase, 0, 0, 0, 0, 0);
2948#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002949
2950 return 0;
2951}