blob: ccd2037c797f9e48c82b545ed4eb5febf03d95f6 [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 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100392 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000393}
394
395
Paul Mackerrasa575b802005-10-23 17:23:21 +1000396static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
397 unsigned long align)
398{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000399
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100400 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
401 /*
402 * Old OF requires we claim physical and virtual separately
403 * and then map explicitly (assuming virtual mode)
404 */
405 int ret;
406 prom_arg_t result;
407
408 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000409 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100410 align, size, virt);
411 if (ret != 0 || result == -1)
412 return -1;
413 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000414 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100415 align, size, virt);
416 if (ret != 0) {
417 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000418 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100419 return -1;
420 }
421 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000422 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000423 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100424 return virt;
425 }
426 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
427 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000428}
429
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000430static void __init __attribute__((noreturn)) prom_panic(const char *reason)
431{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000432 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100433 /* Do not call exit because it clears the screen on pmac
434 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000435 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100436 asm("trap\n");
437
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000438 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000439 call_prom("exit", 0, 0);
440
441 for (;;) /* should never get here */
442 ;
443}
444
445
446static int __init prom_next_node(phandle *nodep)
447{
448 phandle node;
449
450 if ((node = *nodep) != 0
451 && (*nodep = call_prom("child", 1, 1, node)) != 0)
452 return 1;
453 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
454 return 1;
455 for (;;) {
456 if ((node = call_prom("parent", 1, 1, node)) == 0)
457 return 0;
458 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
459 return 1;
460 }
461}
462
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +1100463static int inline prom_getprop(phandle node, const char *pname,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000464 void *value, size_t valuelen)
465{
466 return call_prom("getprop", 4, 1, node, ADDR(pname),
467 (u32)(unsigned long) value, (u32) valuelen);
468}
469
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +1100470static int inline prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000471{
472 return call_prom("getproplen", 2, 1, node, ADDR(pname));
473}
474
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100475static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000476{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100477 char *p = *str;
478
479 while (*q)
480 *p++ = *q++;
481 *p++ = ' ';
482 *str = p;
483}
484
485static char *tohex(unsigned int x)
486{
487 static char digits[] = "0123456789abcdef";
488 static char result[9];
489 int i;
490
491 result[8] = 0;
492 i = 8;
493 do {
494 --i;
495 result[i] = digits[x & 0xf];
496 x >>= 4;
497 } while (x != 0 && i > 0);
498 return &result[i];
499}
500
501static int __init prom_setprop(phandle node, const char *nodename,
502 const char *pname, void *value, size_t valuelen)
503{
504 char cmd[256], *p;
505
506 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
507 return call_prom("setprop", 4, 1, node, ADDR(pname),
508 (u32)(unsigned long) value, (u32) valuelen);
509
510 /* gah... setprop doesn't work on longtrail, have to use interpret */
511 p = cmd;
512 add_string(&p, "dev");
513 add_string(&p, nodename);
514 add_string(&p, tohex((u32)(unsigned long) value));
515 add_string(&p, tohex(valuelen));
516 add_string(&p, tohex(ADDR(pname)));
Anton Blanchard5827d412012-11-26 17:40:03 +0000517 add_string(&p, tohex(strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100518 add_string(&p, "property");
519 *p = 0;
520 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000521}
522
Anton Blanchard5827d412012-11-26 17:40:03 +0000523/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000524#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
525 || ('a' <= (c) && (c) <= 'f') \
526 || ('A' <= (c) && (c) <= 'F'))
527
528#define isdigit(c) ('0' <= (c) && (c) <= '9')
529#define islower(c) ('a' <= (c) && (c) <= 'z')
530#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
531
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000532static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000533{
534 unsigned long result = 0, base = 10, value;
535
536 if (*cp == '0') {
537 base = 8;
538 cp++;
539 if (toupper(*cp) == 'X') {
540 cp++;
541 base = 16;
542 }
543 }
544
545 while (isxdigit(*cp) &&
546 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
547 result = result * base + value;
548 cp++;
549 }
550
551 if (endp)
552 *endp = cp;
553
554 return result;
555}
556
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000557static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000558{
559 unsigned long ret = prom_strtoul(ptr, retptr);
560 int shift = 0;
561
562 /*
563 * We can't use a switch here because GCC *may* generate a
564 * jump table which won't work, because we're not running at
565 * the address we're linked at.
566 */
567 if ('G' == **retptr || 'g' == **retptr)
568 shift = 30;
569
570 if ('M' == **retptr || 'm' == **retptr)
571 shift = 20;
572
573 if ('K' == **retptr || 'k' == **retptr)
574 shift = 10;
575
576 if (shift) {
577 ret <<= shift;
578 (*retptr)++;
579 }
580
581 return ret;
582}
583
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000584/*
585 * Early parsing of the command line passed to the kernel, used for
586 * "mem=x" and the options that affect the iommu
587 */
588static void __init early_cmdline_parse(void)
589{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100590 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000591
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100592 char *p;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000593 int l = 0;
594
Anton Blanchard5827d412012-11-26 17:40:03 +0000595 prom_cmd_line[0] = 0;
596 p = prom_cmd_line;
597 if ((long)prom.chosen > 0)
598 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000599#ifdef CONFIG_CMDLINE
Amos Waterland0e4aa9c2006-06-12 23:45:02 -0400600 if (l <= 0 || p[0] == '\0') /* dbl check */
Anton Blanchard5827d412012-11-26 17:40:03 +0000601 strlcpy(prom_cmd_line,
602 CONFIG_CMDLINE, sizeof(prom_cmd_line));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000603#endif /* CONFIG_CMDLINE */
Anton Blanchard5827d412012-11-26 17:40:03 +0000604 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000605
606#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +0000607 opt = strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000608 if (opt) {
609 prom_printf("iommu opt is: %s\n", opt);
610 opt += 6;
611 while (*opt && *opt == ' ')
612 opt++;
Anton Blanchard5827d412012-11-26 17:40:03 +0000613 if (!strncmp(opt, "off", 3))
614 prom_iommu_off = 1;
615 else if (!strncmp(opt, "force", 5))
616 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000617 }
618#endif
Anton Blanchard5827d412012-11-26 17:40:03 +0000619 opt = strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000620 if (opt) {
621 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000622 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000623#ifdef CONFIG_PPC64
624 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000625 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000626#endif
627 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000628}
629
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000630#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000631/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000632 * The architecture vector has an array of PVR mask/value pairs,
633 * followed by # option vectors - 1, followed by the option vectors.
634 *
635 * See prom.h for the definition of the bits specified in the
636 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000637 *
638 * Because the description vector contains a mix of byte and word
639 * values, we declare it as an unsigned char array, and use this
640 * macro to put word values in.
641 */
642#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
643 ((x) >> 8) & 0xff, (x) & 0xff
644
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000645/* Firmware expects the value to be n - 1, where n is the # of vectors */
646#define NUM_VECTORS(n) ((n) - 1)
647
648/*
649 * Firmware expects 1 + n - 2, where n is the length of the option vector in
650 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
651 */
652#define VECTOR_LENGTH(n) (1 + (n) - 2)
653
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000654unsigned char ibm_architecture_vec[] = {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000655 W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
Anton Blanchard03054d52006-04-29 09:51:06 +1000656 W(0xffff0000), W(0x003e0000), /* POWER6 */
Michael Neulinge952e6c2008-06-18 10:47:26 +1000657 W(0xffff0000), W(0x003f0000), /* POWER7 */
Michael Neuling33959f82013-07-18 11:31:51 +1000658 W(0xffff0000), W(0x004b0000), /* POWER8E */
Thomas Huth7cc85102016-05-31 07:51:17 +0200659 W(0xffff0000), W(0x004c0000), /* POWER8NVL */
Michael Neuling33959f82013-07-18 11:31:51 +1000660 W(0xffff0000), W(0x004d0000), /* POWER8 */
Michael Neulingdf77c792012-11-08 20:23:11 +0000661 W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
Joel Schopp0cb99012008-06-19 06:23:23 +1000662 W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
Paul Mackerras0efbc182006-11-29 22:31:47 +1100663 W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000664 W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000665 NUM_VECTORS(6), /* 6 option vectors */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000666
667 /* option vector 1: processor architectures supported */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000668 VECTOR_LENGTH(2), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000669 0, /* don't ignore, don't halt */
670 OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
Michael Neulingdf77c792012-11-08 20:23:11 +0000671 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000672
673 /* option vector 2: Open Firmware options supported */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000674 VECTOR_LENGTH(33), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000675 OV2_REAL_MODE,
676 0, 0,
677 W(0xffffffff), /* real_base */
678 W(0xffffffff), /* real_size */
679 W(0xffffffff), /* virt_base */
680 W(0xffffffff), /* virt_size */
681 W(0xffffffff), /* load_base */
Anton Blanchard33392642011-12-04 13:13:58 +0000682 W(256), /* 256MB min RMA */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000683 W(0xffffffff), /* full client load */
684 0, /* min RMA percentage of total RAM */
685 48, /* max log_2(hash table size) */
686
687 /* option vector 3: processor options supported */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000688 VECTOR_LENGTH(2), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000689 0, /* don't ignore, don't halt */
Paul Mackerras974a76f2006-11-10 20:38:53 +1100690 OV3_FP | OV3_VMX | OV3_DFP,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000691
692 /* option vector 4: IBM PAPR implementation */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000693 VECTOR_LENGTH(2), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000694 0, /* don't halt */
Robert Jennings404e32e2012-05-10 08:55:49 +0000695 OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000696
697 /* option vector 5: PAPR/OF options */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000698 VECTOR_LENGTH(18), /* length */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000699 0, /* don't ignore, don't halt */
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000700 OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
701 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
702#ifdef CONFIG_PCI_MSI
703 /* PCIe/MSI support. Without MSI full PCIe is not supported */
704 OV5_FEAT(OV5_MSI),
705#else
Nathan Fontenot8391e422008-07-24 04:36:38 +1000706 0,
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000707#endif
708 0,
709#ifdef CONFIG_PPC_SMLPAR
710 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
711#else
712 0,
713#endif
Nathan Fontenot1b1218d2013-04-24 06:06:17 +0000714 OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000715 0,
716 0,
717 0,
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100718 /* WARNING: The offset of the "number of cores" field below
719 * must match by the macro below. Update the definition if
720 * the structure layout changes.
721 */
Michael Neuling33959f82013-07-18 11:31:51 +1000722#define IBM_ARCH_VEC_NRCORES_OFFSET 125
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100723 W(NR_CPUS), /* number of cores supported */
Kent Yoder828d2b52012-04-12 05:17:51 +0000724 0,
725 0,
726 0,
727 0,
Nathan Fontenotf0ff7eb2013-04-24 05:57:18 +0000728 OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
729 OV5_FEAT(OV5_PFO_HW_842),
730 OV5_FEAT(OV5_SUB_PROCESSORS),
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000731
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000732 /* option vector 6: IBM PAPR hints */
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000733 VECTOR_LENGTH(3), /* length */
jschopp@austin.ibm.com28bb9ee2010-02-01 12:50:48 +0000734 0,
735 0,
736 OV6_LINUX,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000737};
738
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000739/* Old method - ELF header with PT_NOTE sections only works on BE */
740#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000741static struct fake_elf {
742 Elf32_Ehdr elfhdr;
743 Elf32_Phdr phdr[2];
744 struct chrpnote {
745 u32 namesz;
746 u32 descsz;
747 u32 type;
748 char name[8]; /* "PowerPC" */
749 struct chrpdesc {
750 u32 real_mode;
751 u32 real_base;
752 u32 real_size;
753 u32 virt_base;
754 u32 virt_size;
755 u32 load_base;
756 } chrpdesc;
757 } chrpnote;
758 struct rpanote {
759 u32 namesz;
760 u32 descsz;
761 u32 type;
762 char name[24]; /* "IBM,RPA-Client-Config" */
763 struct rpadesc {
764 u32 lpar_affinity;
765 u32 min_rmo_size;
766 u32 min_rmo_percent;
767 u32 max_pft_size;
768 u32 splpar;
769 u32 min_load;
770 u32 new_mem_def;
771 u32 ignore_me;
772 } rpadesc;
773 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100774} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000775 .elfhdr = {
776 .e_ident = { 0x7f, 'E', 'L', 'F',
777 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
778 .e_type = ET_EXEC, /* yeah right */
779 .e_machine = EM_PPC,
780 .e_version = EV_CURRENT,
781 .e_phoff = offsetof(struct fake_elf, phdr),
782 .e_phentsize = sizeof(Elf32_Phdr),
783 .e_phnum = 2
784 },
785 .phdr = {
786 [0] = {
787 .p_type = PT_NOTE,
788 .p_offset = offsetof(struct fake_elf, chrpnote),
789 .p_filesz = sizeof(struct chrpnote)
790 }, [1] = {
791 .p_type = PT_NOTE,
792 .p_offset = offsetof(struct fake_elf, rpanote),
793 .p_filesz = sizeof(struct rpanote)
794 }
795 },
796 .chrpnote = {
797 .namesz = sizeof("PowerPC"),
798 .descsz = sizeof(struct chrpdesc),
799 .type = 0x1275,
800 .name = "PowerPC",
801 .chrpdesc = {
802 .real_mode = ~0U, /* ~0 means "don't care" */
803 .real_base = ~0U,
804 .real_size = ~0U,
805 .virt_base = ~0U,
806 .virt_size = ~0U,
807 .load_base = ~0U
808 },
809 },
810 .rpanote = {
811 .namesz = sizeof("IBM,RPA-Client-Config"),
812 .descsz = sizeof(struct rpadesc),
813 .type = 0x12759999,
814 .name = "IBM,RPA-Client-Config",
815 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +1100816 .lpar_affinity = 0,
817 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000818 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +1100819 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000820 .splpar = 1,
821 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +1100822 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000823 }
824 }
825};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000826#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000827
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100828static int __init prom_count_smt_threads(void)
829{
830 phandle node;
831 char type[64];
832 unsigned int plen;
833
834 /* Pick up th first CPU node we can find */
835 for (node = 0; prom_next_node(&node); ) {
836 type[0] = 0;
837 prom_getprop(node, "device_type", type, sizeof(type));
838
Anton Blanchard5827d412012-11-26 17:40:03 +0000839 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100840 continue;
841 /*
842 * There is an entry for each smt thread, each entry being
843 * 4 bytes long. All cpus should have the same number of
844 * smt threads, so return after finding the first.
845 */
846 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
847 if (plen == PROM_ERROR)
848 break;
849 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000850 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100851
852 /* Sanity check */
853 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000854 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100855 (unsigned long)plen);
856 return 1;
857 }
858 return plen;
859 }
860 prom_debug("No threads found, assuming 1 per core\n");
861
862 return 1;
863
864}
865
866
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000867static void __init prom_send_capabilities(void)
868{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000869 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000870 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200871 u32 cores;
872 unsigned char *ptcores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000873
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000874 root = call_prom("open", 1, 1, ADDR("/"));
875 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100876 /* We need to tell the FW about the number of cores we support.
877 *
878 * To do that, we count the number of threads on the first core
879 * (we assume this is the same for all cores) and use it to
880 * divide NR_CPUS.
881 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200882
883 /* The core value may start at an odd address. If such a word
884 * access is made at a cache line boundary, this leads to an
885 * exception which may not be handled at this time.
886 * Forcing a per byte access to avoid exception.
887 */
888 ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
889 cores = 0;
890 cores |= ptcores[0] << 24;
891 cores |= ptcores[1] << 16;
892 cores |= ptcores[2] << 8;
893 cores |= ptcores[3];
894 if (cores != NR_CPUS) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100895 prom_printf("WARNING ! "
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000896 "ibm_architecture_vec structure inconsistent: %lu!\n",
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200897 cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100898 } else {
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200899 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000900 prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +0200901 cores, NR_CPUS);
902 ptcores[0] = (cores >> 24) & 0xff;
903 ptcores[1] = (cores >> 16) & 0xff;
904 ptcores[2] = (cores >> 8) & 0xff;
905 ptcores[3] = cores & 0xff;
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +1100906 }
907
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000908 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +0000909 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000910 if (call_prom_ret("call-method", 3, 2, &ret,
911 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +1000912 root,
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000913 ADDR(ibm_architecture_vec)) == 0) {
914 /* the call exists... */
915 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +0000916 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000917 "-support call FAILED!\n");
918 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +0000919 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000920 return;
921 }
922 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +0000923 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000924 }
925
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000926#ifdef __BIG_ENDIAN__
927 {
928 ihandle elfloader;
929
930 /* no ibm,client-architecture-support call, try the old way */
931 elfloader = call_prom("open", 1, 1,
932 ADDR("/packages/elf-loader"));
933 if (elfloader == 0) {
934 prom_printf("couldn't open /packages/elf-loader\n");
935 return;
936 }
937 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
938 elfloader, ADDR(&fake_elf));
939 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000940 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000941#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000942}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000943#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000944
945/*
946 * Memory allocation strategy... our layout is normally:
947 *
948 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
949 * rare cases, initrd might end up being before the kernel though.
950 * We assume this won't override the final kernel at 0, we have no
951 * provision to handle that in this version, but it should hopefully
952 * never happen.
953 *
954 * alloc_top is set to the top of RMO, eventually shrink down if the
955 * TCEs overlap
956 *
957 * alloc_bottom is set to the top of kernel/initrd
958 *
959 * from there, allocations are done this way : rtas is allocated
960 * topmost, and the device-tree is allocated from the bottom. We try
961 * to grow the device-tree allocation as we progress. If we can't,
962 * then we fail, we don't currently have a facility to restart
963 * elsewhere, but that shouldn't be necessary.
964 *
965 * Note that calls to reserve_mem have to be done explicitly, memory
966 * allocated with either alloc_up or alloc_down isn't automatically
967 * reserved.
968 */
969
970
971/*
972 * Allocates memory in the RMO upward from the kernel/initrd
973 *
974 * When align is 0, this is a special case, it means to allocate in place
975 * at the current location of alloc_bottom or fail (that is basically
976 * extending the previous allocation). Used for the device-tree flattening
977 */
978static unsigned long __init alloc_up(unsigned long size, unsigned long align)
979{
Anton Blanchard5827d412012-11-26 17:40:03 +0000980 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000981 unsigned long addr = 0;
982
Paul Mackerrasc49888202005-10-26 21:52:53 +1000983 if (align)
984 base = _ALIGN_UP(base, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000985 prom_debug("alloc_up(%x, %x)\n", size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +0000986 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000987 prom_panic("alloc_up() called with mem not initialized\n");
988
989 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +0000990 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000991 else
Anton Blanchard5827d412012-11-26 17:40:03 +0000992 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000993
Anton Blanchard5827d412012-11-26 17:40:03 +0000994 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000995 base = _ALIGN_UP(base + 0x100000, align)) {
996 prom_debug(" trying: 0x%x\n\r", base);
997 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +1000998 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000999 break;
1000 addr = 0;
1001 if (align == 0)
1002 break;
1003 }
1004 if (addr == 0)
1005 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001006 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001007
1008 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001009 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1010 prom_debug(" alloc_top : %x\n", alloc_top);
1011 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1012 prom_debug(" rmo_top : %x\n", rmo_top);
1013 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001014
1015 return addr;
1016}
1017
1018/*
1019 * Allocates memory downward, either from top of RMO, or if highmem
1020 * is set, from the top of RAM. Note that this one doesn't handle
1021 * failures. It does claim memory if highmem is not set.
1022 */
1023static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1024 int highmem)
1025{
1026 unsigned long base, addr = 0;
1027
1028 prom_debug("alloc_down(%x, %x, %s)\n", size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001029 highmem ? "(high)" : "(low)");
1030 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001031 prom_panic("alloc_down() called with mem not initialized\n");
1032
1033 if (highmem) {
1034 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001035 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1036 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001037 return 0;
1038 /* Will we bump into the RMO ? If yes, check out that we
1039 * didn't overlap existing allocations there, if we did,
1040 * we are dead, we must be the first in town !
1041 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001042 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001043 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001044 if (alloc_top == rmo_top)
1045 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001046 else
1047 return 0;
1048 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001049 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001050 goto bail;
1051 }
1052
Anton Blanchard5827d412012-11-26 17:40:03 +00001053 base = _ALIGN_DOWN(alloc_top - size, align);
1054 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001055 base = _ALIGN_DOWN(base - 0x100000, align)) {
1056 prom_debug(" trying: 0x%x\n\r", base);
1057 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001058 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001059 break;
1060 addr = 0;
1061 }
1062 if (addr == 0)
1063 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001064 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001065
1066 bail:
1067 prom_debug(" -> %x\n", addr);
Anton Blanchard5827d412012-11-26 17:40:03 +00001068 prom_debug(" alloc_bottom : %x\n", alloc_bottom);
1069 prom_debug(" alloc_top : %x\n", alloc_top);
1070 prom_debug(" alloc_top_hi : %x\n", alloc_top_high);
1071 prom_debug(" rmo_top : %x\n", rmo_top);
1072 prom_debug(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001073
1074 return addr;
1075}
1076
1077/*
1078 * Parse a "reg" cell
1079 */
1080static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1081{
1082 cell_t *p = *cellp;
1083 unsigned long r = 0;
1084
1085 /* Ignore more than 2 cells */
1086 while (s > sizeof(unsigned long) / 4) {
1087 p++;
1088 s--;
1089 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001090 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001091#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001092 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001093 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001094 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001095 }
1096#endif
1097 *cellp = p;
1098 return r;
1099}
1100
1101/*
1102 * Very dumb function for adding to the memory reserve list, but
1103 * we don't need anything smarter at this point
1104 *
1105 * XXX Eventually check for collisions. They should NEVER happen.
1106 * If problems seem to show up, it would be a good start to track
1107 * them down.
1108 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001109static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001110{
Kumar Galacbbcf342006-01-11 17:57:13 -06001111 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001112 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001113
1114 if (size == 0)
1115 return;
1116
1117 /* We need to always keep one empty entry so that we
1118 * have our terminator with "size" set to 0 since we are
1119 * dumb and just copy this entire array to the boot params
1120 */
1121 base = _ALIGN_DOWN(base, PAGE_SIZE);
1122 top = _ALIGN_UP(top, PAGE_SIZE);
1123 size = top - base;
1124
1125 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1126 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001127 mem_reserve_map[cnt].base = cpu_to_be64(base);
1128 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001129 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001130}
1131
1132/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001133 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001134 * obtain that way the top of memory and RMO to setup out local allocator
1135 */
1136static void __init prom_init_mem(void)
1137{
1138 phandle node;
1139 char *path, type[64];
1140 unsigned int plen;
1141 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001142 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001143 u32 rac, rsc;
1144
1145 /*
1146 * We iterate the memory nodes to find
1147 * 1) top of RMO (first node)
1148 * 2) top of memory
1149 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001150 val = cpu_to_be32(2);
1151 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1152 rac = be32_to_cpu(val);
1153 val = cpu_to_be32(1);
1154 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1155 rsc = be32_to_cpu(val);
1156 prom_debug("root_addr_cells: %x\n", rac);
1157 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001158
1159 prom_debug("scanning memory:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001160 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001161
1162 for (node = 0; prom_next_node(&node); ) {
1163 type[0] = 0;
1164 prom_getprop(node, "device_type", type, sizeof(type));
1165
Paul Mackerrasc49888202005-10-26 21:52:53 +10001166 if (type[0] == 0) {
1167 /*
1168 * CHRP Longtrail machines have no device_type
1169 * on the memory node, so check the name instead...
1170 */
1171 prom_getprop(node, "name", type, sizeof(type));
1172 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001173 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001174 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001175
Anton Blanchard5827d412012-11-26 17:40:03 +00001176 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001177 if (plen > sizeof(regbuf)) {
1178 prom_printf("memory node too large for buffer !\n");
1179 plen = sizeof(regbuf);
1180 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001181 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001182 endp = p + (plen / sizeof(cell_t));
1183
1184#ifdef DEBUG_PROM
1185 memset(path, 0, PROM_SCRATCH_SIZE);
1186 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1187 prom_debug(" node %s :\n", path);
1188#endif /* DEBUG_PROM */
1189
1190 while ((endp - p) >= (rac + rsc)) {
1191 unsigned long base, size;
1192
1193 base = prom_next_cell(rac, &p);
1194 size = prom_next_cell(rsc, &p);
1195
1196 if (size == 0)
1197 continue;
1198 prom_debug(" %x %x\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001199 if (base == 0 && (of_platform & PLATFORM_LPAR))
1200 rmo_top = size;
1201 if ((base + size) > ram_top)
1202 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001203 }
1204 }
1205
Anton Blanchard5827d412012-11-26 17:40:03 +00001206 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001207
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001208 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001209 * If prom_memory_limit is set we reduce the upper limits *except* for
1210 * alloc_top_high. This must be the real top of RAM so we can put
1211 * TCE's up there.
1212 */
1213
Anton Blanchard5827d412012-11-26 17:40:03 +00001214 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001215
Anton Blanchard5827d412012-11-26 17:40:03 +00001216 if (prom_memory_limit) {
1217 if (prom_memory_limit <= alloc_bottom) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001218 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001219 prom_memory_limit);
1220 prom_memory_limit = 0;
1221 } else if (prom_memory_limit >= ram_top) {
Benjamin Krillcf687872009-07-27 22:02:39 +00001222 prom_printf("Ignoring mem=%x >= ram_top.\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00001223 prom_memory_limit);
1224 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001225 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001226 ram_top = prom_memory_limit;
1227 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001228 }
1229 }
1230
1231 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001232 * Setup our top alloc point, that is top of RMO or top of
1233 * segment 0 when running non-LPAR.
1234 * Some RS64 machines have buggy firmware where claims up at
1235 * 1GB fail. Cap at 768MB as a workaround.
1236 * Since 768MB is plenty of room, and we need to cap to something
1237 * reasonable on 32-bit, cap at 768MB on all machines.
1238 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001239 if (!rmo_top)
1240 rmo_top = ram_top;
1241 rmo_top = min(0x30000000ul, rmo_top);
1242 alloc_top = rmo_top;
1243 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001244
Paul Mackerras64968f62011-12-13 17:54:13 +00001245 /*
1246 * Check if we have an initrd after the kernel but still inside
1247 * the RMO. If we do move our bottom point to after it.
1248 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001249 if (prom_initrd_start &&
1250 prom_initrd_start < rmo_top &&
1251 prom_initrd_end > alloc_bottom)
1252 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001253
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001254 prom_printf("memory layout at init:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00001255 prom_printf(" memory_limit : %x (16 MB aligned)\n", prom_memory_limit);
1256 prom_printf(" alloc_bottom : %x\n", alloc_bottom);
1257 prom_printf(" alloc_top : %x\n", alloc_top);
1258 prom_printf(" alloc_top_hi : %x\n", alloc_top_high);
1259 prom_printf(" rmo_top : %x\n", rmo_top);
1260 prom_printf(" ram_top : %x\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001261}
1262
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001263static void __init prom_close_stdin(void)
1264{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001265 __be32 val;
1266 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001267
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001268 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1269 stdin = be32_to_cpu(val);
1270 call_prom("close", 1, 0, stdin);
1271 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001272}
1273
1274#ifdef CONFIG_PPC_POWERNV
1275
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001276#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1277static u64 __initdata prom_opal_base;
1278static u64 __initdata prom_opal_entry;
1279#endif
1280
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001281/*
1282 * Allocate room for and instantiate OPAL
1283 */
1284static void __init prom_instantiate_opal(void)
1285{
1286 phandle opal_node;
1287 ihandle opal_inst;
1288 u64 base, entry;
1289 u64 size = 0, align = 0x10000;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001290 __be64 val64;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001291 u32 rets[2];
1292
1293 prom_debug("prom_instantiate_opal: start...\n");
1294
1295 opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
1296 prom_debug("opal_node: %x\n", opal_node);
1297 if (!PHANDLE_VALID(opal_node))
1298 return;
1299
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001300 val64 = 0;
1301 prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64));
1302 size = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001303 if (size == 0)
1304 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001305 val64 = 0;
1306 prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64));
1307 align = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001308
1309 base = alloc_down(size, align, 0);
1310 if (base == 0) {
1311 prom_printf("OPAL allocation failed !\n");
1312 return;
1313 }
1314
1315 opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
1316 if (!IHANDLE_VALID(opal_inst)) {
1317 prom_printf("opening opal package failed (%x)\n", opal_inst);
1318 return;
1319 }
1320
1321 prom_printf("instantiating opal at 0x%x...", base);
1322
1323 if (call_prom_ret("call-method", 4, 3, rets,
1324 ADDR("load-opal-runtime"),
1325 opal_inst,
1326 base >> 32, base & 0xffffffff) != 0
1327 || (rets[0] == 0 && rets[1] == 0)) {
1328 prom_printf(" failed\n");
1329 return;
1330 }
1331 entry = (((u64)rets[0]) << 32) | rets[1];
1332
1333 prom_printf(" done\n");
1334
1335 reserve_mem(base, size);
1336
1337 prom_debug("opal base = 0x%x\n", base);
1338 prom_debug("opal align = 0x%x\n", align);
1339 prom_debug("opal entry = 0x%x\n", entry);
1340 prom_debug("opal size = 0x%x\n", (long)size);
1341
1342 prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
1343 &base, sizeof(base));
1344 prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
1345 &entry, sizeof(entry));
1346
1347#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
Anton Blanchard5827d412012-11-26 17:40:03 +00001348 prom_opal_base = base;
1349 prom_opal_entry = entry;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001350#endif
1351 prom_debug("prom_instantiate_opal: end...\n");
1352}
1353
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001354#endif /* CONFIG_PPC_POWERNV */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001355
1356/*
1357 * Allocate room for and instantiate RTAS
1358 */
1359static void __init prom_instantiate_rtas(void)
1360{
1361 phandle rtas_node;
1362 ihandle rtas_inst;
1363 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001364 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001365 u32 size = 0;
1366
1367 prom_debug("prom_instantiate_rtas: start...\n");
1368
1369 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1370 prom_debug("rtas_node: %x\n", rtas_node);
1371 if (!PHANDLE_VALID(rtas_node))
1372 return;
1373
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001374 val = 0;
1375 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1376 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001377 if (size == 0)
1378 return;
1379
1380 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001381 if (base == 0)
1382 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001383
1384 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1385 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001386 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001387 return;
1388 }
1389
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001390 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001391
1392 if (call_prom_ret("call-method", 3, 2, &entry,
1393 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001394 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001395 || entry == 0) {
1396 prom_printf(" failed\n");
1397 return;
1398 }
1399 prom_printf(" done\n");
1400
1401 reserve_mem(base, size);
1402
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001403 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001404 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001405 &val, sizeof(val));
1406 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001407 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001408 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001409
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001410 /* Check if it supports "query-cpu-stopped-state" */
1411 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1412 &val, sizeof(val)) != PROM_ERROR)
1413 rtas_has_query_cpu_stopped = true;
1414
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001415 prom_debug("rtas base = 0x%x\n", base);
1416 prom_debug("rtas entry = 0x%x\n", entry);
1417 prom_debug("rtas size = 0x%x\n", (long)size);
1418
1419 prom_debug("prom_instantiate_rtas: end...\n");
1420}
1421
1422#ifdef CONFIG_PPC64
1423/*
Ashley Lai4a727422012-08-14 18:34:57 -05001424 * Allocate room for and instantiate Stored Measurement Log (SML)
1425 */
1426static void __init prom_instantiate_sml(void)
1427{
1428 phandle ibmvtpm_node;
1429 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001430 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001431 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001432 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001433
1434 prom_debug("prom_instantiate_sml: start...\n");
1435
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001436 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001437 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1438 if (!PHANDLE_VALID(ibmvtpm_node))
1439 return;
1440
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001441 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001442 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1443 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1444 return;
1445 }
1446
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001447 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1448 &val, sizeof(val)) != PROM_ERROR) {
1449 if (call_prom_ret("call-method", 2, 2, &succ,
1450 ADDR("reformat-sml-to-efi-alignment"),
1451 ibmvtpm_inst) != 0 || succ == 0) {
1452 prom_printf("Reformat SML to EFI alignment failed\n");
1453 return;
1454 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001455
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001456 if (call_prom_ret("call-method", 2, 2, &size,
1457 ADDR("sml-get-allocated-size"),
1458 ibmvtpm_inst) != 0 || size == 0) {
1459 prom_printf("SML get allocated size failed\n");
1460 return;
1461 }
1462 } else {
1463 if (call_prom_ret("call-method", 2, 2, &size,
1464 ADDR("sml-get-handover-size"),
1465 ibmvtpm_inst) != 0 || size == 0) {
1466 prom_printf("SML get handover size failed\n");
1467 return;
1468 }
Ashley Lai4a727422012-08-14 18:34:57 -05001469 }
1470
1471 base = alloc_down(size, PAGE_SIZE, 0);
1472 if (base == 0)
1473 prom_panic("Could not allocate memory for sml\n");
1474
1475 prom_printf("instantiating sml at 0x%x...", base);
1476
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001477 memset((void *)base, 0, size);
1478
Ashley Lai4a727422012-08-14 18:34:57 -05001479 if (call_prom_ret("call-method", 4, 2, &entry,
1480 ADDR("sml-handover"),
1481 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1482 prom_printf("SML handover failed\n");
1483 return;
1484 }
1485 prom_printf(" done\n");
1486
1487 reserve_mem(base, size);
1488
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001489 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001490 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001491 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001492 &size, sizeof(size));
1493
1494 prom_debug("sml base = 0x%x\n", base);
1495 prom_debug("sml size = 0x%x\n", (long)size);
1496
1497 prom_debug("prom_instantiate_sml: end...\n");
1498}
1499
1500/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001501 * Allocate room for and initialize TCE tables
1502 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001503#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001504static void __init prom_initialize_tce_table(void)
1505{
1506 phandle node;
1507 ihandle phb_node;
1508 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001509 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001510 u64 base, align;
1511 u32 minalign, minsize;
1512 u64 tce_entry, *tce_entryp;
1513 u64 local_alloc_top, local_alloc_bottom;
1514 u64 i;
1515
Anton Blanchard5827d412012-11-26 17:40:03 +00001516 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001517 return;
1518
1519 prom_debug("starting prom_initialize_tce_table\n");
1520
1521 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001522 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001523 local_alloc_bottom = local_alloc_top;
1524
1525 /* Search all nodes looking for PHBs. */
1526 for (node = 0; prom_next_node(&node); ) {
1527 compatible[0] = 0;
1528 type[0] = 0;
1529 model[0] = 0;
1530 prom_getprop(node, "compatible",
1531 compatible, sizeof(compatible));
1532 prom_getprop(node, "device_type", type, sizeof(type));
1533 prom_getprop(node, "model", model, sizeof(model));
1534
Anton Blanchard5827d412012-11-26 17:40:03 +00001535 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001536 continue;
1537
Linas Vepstase788ff12007-09-07 03:45:21 +10001538 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001539 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001540 if ((strstr(compatible, "python") == NULL) &&
1541 (strstr(compatible, "Speedwagon") == NULL) &&
1542 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001543 continue;
1544 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001545 if ((strstr(model, "ython") == NULL) &&
1546 (strstr(model, "peedwagon") == NULL) &&
1547 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001548 continue;
1549 }
1550
1551 if (prom_getprop(node, "tce-table-minalign", &minalign,
1552 sizeof(minalign)) == PROM_ERROR)
1553 minalign = 0;
1554 if (prom_getprop(node, "tce-table-minsize", &minsize,
1555 sizeof(minsize)) == PROM_ERROR)
1556 minsize = 4UL << 20;
1557
1558 /*
1559 * Even though we read what OF wants, we just set the table
1560 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1561 * By doing this, we avoid the pitfalls of trying to DMA to
1562 * MMIO space and the DMA alias hole.
1563 *
1564 * On POWER4, firmware sets the TCE region by assuming
1565 * each TCE table is 8MB. Using this memory for anything
1566 * else will impact performance, so we always allocate 8MB.
1567 * Anton
1568 */
Michael Ellermand3dbeef2012-08-19 21:44:01 +00001569 if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001570 minsize = 8UL << 20;
1571 else
1572 minsize = 4UL << 20;
1573
1574 /* Align to the greater of the align or size */
1575 align = max(minalign, minsize);
1576 base = alloc_down(minsize, align, 1);
1577 if (base == 0)
1578 prom_panic("ERROR, cannot find space for TCE table.\n");
1579 if (base < local_alloc_bottom)
1580 local_alloc_bottom = base;
1581
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001582 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001583 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001584 /* Call OF to setup the TCE hardware */
1585 if (call_prom("package-to-path", 3, 1, node,
1586 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1587 prom_printf("package-to-path failed\n");
1588 }
1589
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001590 /* Save away the TCE table attributes for later use. */
1591 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1592 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1593
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001594 prom_debug("TCE table: %s\n", path);
1595 prom_debug("\tnode = 0x%x\n", node);
1596 prom_debug("\tbase = 0x%x\n", base);
1597 prom_debug("\tsize = 0x%x\n", minsize);
1598
1599 /* Initialize the table to have a one-to-one mapping
1600 * over the allocated size.
1601 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001602 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001603 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1604 tce_entry = (i << PAGE_SHIFT);
1605 tce_entry |= 0x3;
1606 *tce_entryp = tce_entry;
1607 }
1608
1609 prom_printf("opening PHB %s", path);
1610 phb_node = call_prom("open", 1, 1, path);
1611 if (phb_node == 0)
1612 prom_printf("... failed\n");
1613 else
1614 prom_printf("... done\n");
1615
1616 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1617 phb_node, -1, minsize,
1618 (u32) base, (u32) (base >> 32));
1619 call_prom("close", 1, 0, phb_node);
1620 }
1621
1622 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1623
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001624 /* These are only really needed if there is a memory limit in
1625 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001626 prom_tce_alloc_start = local_alloc_bottom;
1627 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001628
1629 /* Flag the first invalid entry */
1630 prom_debug("ending prom_initialize_tce_table\n");
1631}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001632#endif /* __BIG_ENDIAN__ */
1633#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001634
1635/*
1636 * With CHRP SMP we need to use the OF to start the other processors.
1637 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1638 * so we have to put the processors into a holding pattern controlled
1639 * by the kernel (not OF) before we destroy the OF.
1640 *
1641 * This uses a chunk of low memory, puts some holding pattern
1642 * code there and sends the other processors off to there until
1643 * smp_boot_cpus tells them to do something. The holding pattern
1644 * checks that address until its cpu # is there, when it is that
1645 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1646 * of setting those values.
1647 *
1648 * We also use physical address 0x4 here to tell when a cpu
1649 * is in its holding pattern code.
1650 *
1651 * -- Cort
1652 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001653/*
1654 * We want to reference the copy of __secondary_hold_* in the
1655 * 0 - 0x100 address range
1656 */
1657#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1658
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001659static void __init prom_hold_cpus(void)
1660{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001661 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001662 phandle node;
1663 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001664 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001665 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001666 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001667 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001668 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001669
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001670 /*
1671 * On pseries, if RTAS supports "query-cpu-stopped-state",
1672 * we skip this stage, the CPUs will be started by the
1673 * kernel using RTAS.
1674 */
1675 if ((of_platform == PLATFORM_PSERIES ||
1676 of_platform == PLATFORM_PSERIES_LPAR) &&
1677 rtas_has_query_cpu_stopped) {
1678 prom_printf("prom_hold_cpus: skipped\n");
1679 return;
1680 }
1681
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001682 prom_debug("prom_hold_cpus: start...\n");
1683 prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
1684 prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
1685 prom_debug(" 1) acknowledge = 0x%x\n",
1686 (unsigned long)acknowledge);
1687 prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
1688 prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
1689
1690 /* Set the common spinloop variable, so all of the secondary cpus
1691 * will block when they are awakened from their OF spinloop.
1692 * This must occur for both SMP and non SMP kernels, since OF will
1693 * be trashed when we move the kernel.
1694 */
1695 *spinloop = 0;
1696
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001697 /* look for cpus */
1698 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001699 unsigned int cpu_no;
1700 __be32 reg;
1701
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001702 type[0] = 0;
1703 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001704 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001705 continue;
1706
1707 /* Skip non-configured cpus. */
1708 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001709 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001710 continue;
1711
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001712 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001713 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001714 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001715
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001716 prom_debug("cpu hw idx = %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001717
1718 /* Init the acknowledge var which will be reset by
1719 * the secondary cpu when it awakens from its OF
1720 * spinloop.
1721 */
1722 *acknowledge = (unsigned long)-1;
1723
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001724 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001725 /* Primary Thread of non-boot cpu or any thread */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001726 prom_printf("starting cpu hw idx %lu... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001727 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001728 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001729
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001730 for (i = 0; (i < 100000000) &&
1731 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001732 mb();
1733
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001734 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001735 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001736 else
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001737 prom_printf("failed: %x\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001738 }
1739#ifdef CONFIG_SMP
1740 else
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001741 prom_printf("boot cpu hw idx %lu\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001742#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001743 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001744
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001745 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001746}
1747
1748
1749static void __init prom_init_client_services(unsigned long pp)
1750{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001751 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00001752 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001753
1754 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00001755 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1756 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001757 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1758
1759 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00001760 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
1761 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001762 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001763
Anton Blanchard5827d412012-11-26 17:40:03 +00001764 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001765}
1766
Paul Mackerrasa575b802005-10-23 17:23:21 +10001767#ifdef CONFIG_PPC32
1768/*
1769 * For really old powermacs, we need to map things we claim.
1770 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001771 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10001772 */
1773static void __init prom_find_mmu(void)
1774{
Paul Mackerrasa575b802005-10-23 17:23:21 +10001775 phandle oprom;
1776 char version[64];
1777
1778 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1779 if (!PHANDLE_VALID(oprom))
1780 return;
1781 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1782 return;
1783 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10001784 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001785 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
1786 of_workarounds = OF_WA_CLAIM;
1787 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
1788 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
1789 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
1790 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10001791 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00001792 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
1793 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
1794 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001795 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00001796 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001797 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001798}
1799#else
1800#define prom_find_mmu()
1801#endif
1802
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001803static void __init prom_init_stdout(void)
1804{
Anton Blanchard5827d412012-11-26 17:40:03 +00001805 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001806 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001807 phandle stdout_node;
1808 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001809
Anton Blanchard5827d412012-11-26 17:40:03 +00001810 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001811 prom_panic("cannot find stdout");
1812
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001813 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001814
1815 /* Get the full OF pathname of the stdout device */
1816 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00001817 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00001818 prom_printf("OF stdout device is: %s\n", of_stdout_device);
1819 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001820 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001821
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11001822 /* instance-to-package fails on PA-Semi */
1823 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
1824 if (stdout_node != PROM_ERROR) {
1825 val = cpu_to_be32(stdout_node);
1826 prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
1827 &val, sizeof(val));
1828
1829 /* If it's a display, note it */
1830 memset(type, 0, sizeof(type));
1831 prom_getprop(stdout_node, "device_type", type, sizeof(type));
1832 if (strcmp(type, "display") == 0)
1833 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
1834 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001835}
1836
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001837static int __init prom_find_machine_type(void)
1838{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001839 char compat[256];
1840 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001841#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001842 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001843 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11001844#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001845
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001846 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00001847 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001848 compat, sizeof(compat)-1);
1849 if (len > 0) {
1850 compat[len] = 0;
1851 while (i < len) {
1852 char *p = &compat[i];
1853 int sl = strlen(p);
1854 if (sl == 0)
1855 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00001856 if (strstr(p, "Power Macintosh") ||
1857 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001858 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10001859#ifdef CONFIG_PPC64
1860 /* We must make sure we don't detect the IBM Cell
1861 * blades as pSeries due to some firmware issues,
1862 * so we do it here.
1863 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001864 if (strstr(p, "IBM,CBEA") ||
1865 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10001866 return PLATFORM_GENERIC;
1867#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001868 i += sl + 1;
1869 }
1870 }
1871#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001872 /* Try to detect OPAL */
1873 if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
1874 return PLATFORM_OPAL;
1875
1876 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001877 * PAPR compliant platform. We assume it is if :
1878 * - /device_type is "chrp" (please, do NOT use that for future
1879 * non-IBM designs !
1880 * - it has /rtas
1881 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001882 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001883 compat, sizeof(compat)-1);
1884 if (len <= 0)
1885 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00001886 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001887 return PLATFORM_GENERIC;
1888
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001889 /* Default to pSeries. We need to know if we are running LPAR */
1890 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001891 if (!PHANDLE_VALID(rtas))
1892 return PLATFORM_GENERIC;
1893 x = prom_getproplen(rtas, "ibm,hypertas-functions");
1894 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00001895 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001896 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001897 }
1898 return PLATFORM_PSERIES;
1899#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11001900 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001901#endif
1902}
1903
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001904static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
1905{
1906 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
1907}
1908
1909/*
1910 * If we have a display that we don't know how to drive,
1911 * we will want to try to execute OF's open method for it
1912 * later. However, OF will probably fall over if we do that
1913 * we've taken over the MMU.
1914 * So we check whether we will need to open the display,
1915 * and if so, open it now.
1916 */
1917static void __init prom_check_displays(void)
1918{
1919 char type[16], *path;
1920 phandle node;
1921 ihandle ih;
1922 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001923
1924 static unsigned char default_colors[] = {
1925 0x00, 0x00, 0x00,
1926 0x00, 0x00, 0xaa,
1927 0x00, 0xaa, 0x00,
1928 0x00, 0xaa, 0xaa,
1929 0xaa, 0x00, 0x00,
1930 0xaa, 0x00, 0xaa,
1931 0xaa, 0xaa, 0x00,
1932 0xaa, 0xaa, 0xaa,
1933 0x55, 0x55, 0x55,
1934 0x55, 0x55, 0xff,
1935 0x55, 0xff, 0x55,
1936 0x55, 0xff, 0xff,
1937 0xff, 0x55, 0x55,
1938 0xff, 0x55, 0xff,
1939 0xff, 0xff, 0x55,
1940 0xff, 0xff, 0xff
1941 };
1942 const unsigned char *clut;
1943
Anton Blanchard4da727a2009-03-31 20:06:14 +00001944 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001945 for (node = 0; prom_next_node(&node); ) {
1946 memset(type, 0, sizeof(type));
1947 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001948 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001949 continue;
1950
1951 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00001952 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001953 memset(path, 0, PROM_SCRATCH_SIZE);
1954
1955 /*
1956 * leave some room at the end of the path for appending extra
1957 * arguments
1958 */
1959 if (call_prom("package-to-path", 3, 1, node, path,
1960 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
1961 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001962 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001963
1964 ih = call_prom("open", 1, 1, path);
1965 if (ih == 0) {
1966 prom_printf("failed\n");
1967 continue;
1968 }
1969
1970 /* Success */
1971 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001972 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001973
1974 /* Setup a usable color table when the appropriate
1975 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00001976 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00001977 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001978 if (prom_set_color(ih, i, clut[0], clut[1],
1979 clut[2]) != 0)
1980 break;
1981
1982#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00001983 clut = PTRRELOC(logo_linux_clut224.clut);
1984 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001985 if (prom_set_color(ih, i + 32, clut[0], clut[1],
1986 clut[2]) != 0)
1987 break;
1988#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10001989
1990#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
1991 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
1992 PROM_ERROR) {
1993 u32 width, height, pitch, addr;
1994
1995 prom_printf("Setting btext !\n");
1996 prom_getprop(node, "width", &width, 4);
1997 prom_getprop(node, "height", &height, 4);
1998 prom_getprop(node, "linebytes", &pitch, 4);
1999 prom_getprop(node, "address", &addr, 4);
2000 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2001 width, height, pitch, addr);
2002 btext_setup_display(width, height, 8, pitch, addr);
2003 }
2004#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002005 }
2006}
2007
2008
2009/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2010static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2011 unsigned long needed, unsigned long align)
2012{
2013 void *ret;
2014
2015 *mem_start = _ALIGN(*mem_start, align);
2016 while ((*mem_start + needed) > *mem_end) {
2017 unsigned long room, chunk;
2018
2019 prom_debug("Chunk exhausted, claiming more at %x...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002020 alloc_bottom);
2021 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002022 if (room > DEVTREE_CHUNK_SIZE)
2023 room = DEVTREE_CHUNK_SIZE;
2024 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002025 prom_panic("No memory for flatten_device_tree "
2026 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002027 chunk = alloc_up(room, 0);
2028 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002029 prom_panic("No memory for flatten_device_tree "
2030 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002031 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002032 }
2033
2034 ret = (void *)*mem_start;
2035 *mem_start += needed;
2036
2037 return ret;
2038}
2039
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002040#define dt_push_token(token, mem_start, mem_end) do { \
2041 void *room = make_room(mem_start, mem_end, 4, 4); \
2042 *(__be32 *)room = cpu_to_be32(token); \
2043 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002044
2045static unsigned long __init dt_find_string(char *str)
2046{
2047 char *s, *os;
2048
Anton Blanchard5827d412012-11-26 17:40:03 +00002049 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002050 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002051 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002052 if (strcmp(s, str) == 0)
2053 return s - os;
2054 s += strlen(s) + 1;
2055 }
2056 return 0;
2057}
2058
2059/*
2060 * The Open Firmware 1275 specification states properties must be 31 bytes or
2061 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2062 */
2063#define MAX_PROPERTY_NAME 64
2064
2065static void __init scan_dt_build_strings(phandle node,
2066 unsigned long *mem_start,
2067 unsigned long *mem_end)
2068{
2069 char *prev_name, *namep, *sstart;
2070 unsigned long soff;
2071 phandle child;
2072
Anton Blanchard5827d412012-11-26 17:40:03 +00002073 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002074
2075 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002076 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002077 for (;;) {
2078 /* 64 is max len of name including nul. */
2079 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2080 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2081 /* No more nodes: unwind alloc */
2082 *mem_start = (unsigned long)namep;
2083 break;
2084 }
2085
2086 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002087 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002088 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002089 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002090 continue;
2091 }
2092 /* get/create string entry */
2093 soff = dt_find_string(namep);
2094 if (soff != 0) {
2095 *mem_start = (unsigned long)namep;
2096 namep = sstart + soff;
2097 } else {
2098 /* Trim off some if we can */
2099 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002100 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002101 }
2102 prev_name = namep;
2103 }
2104
2105 /* do all our children */
2106 child = call_prom("child", 1, 1, node);
2107 while (child != 0) {
2108 scan_dt_build_strings(child, mem_start, mem_end);
2109 child = call_prom("peer", 1, 1, child);
2110 }
2111}
2112
2113static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2114 unsigned long *mem_end)
2115{
2116 phandle child;
2117 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2118 unsigned long soff;
2119 unsigned char *valp;
2120 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002121 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002122
2123 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2124
2125 /* get the node's full name */
2126 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002127 room = *mem_end - *mem_start;
2128 if (room > 255)
2129 room = 255;
2130 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002131 if (l >= 0) {
2132 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002133 if (l >= room) {
2134 if (l >= *mem_end - *mem_start)
2135 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002136 call_prom("package-to-path", 3, 1, node, namep, l);
2137 }
2138 namep[l] = '\0';
2139
2140 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002141 * middle of the path in some properties, and extract
2142 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002143 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002144 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002145 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002146 lp = namep;
2147 else if (*p != 0)
2148 *lp++ = *p;
2149 }
2150 *lp = 0;
2151 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002152 }
2153
2154 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002155 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002156 memset(path, 0, PROM_SCRATCH_SIZE);
2157 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2158
2159 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002160 prev_name = "";
2161 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002162 for (;;) {
2163 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002164 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002165 break;
2166
2167 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002168 if (strcmp(pname, "name") == 0) {
2169 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002170 continue;
2171 }
2172
2173 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002174 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002175 if (soff == 0) {
2176 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002177 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002178 break;
2179 }
2180 prev_name = sstart + soff;
2181
2182 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002183 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002184
2185 /* sanity checks */
2186 if (l == PROM_ERROR)
2187 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188
2189 /* push property head */
2190 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2191 dt_push_token(l, mem_start, mem_end);
2192 dt_push_token(soff, mem_start, mem_end);
2193
2194 /* push property content */
2195 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002196 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002197 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002198
Anton Blanchard5827d412012-11-26 17:40:03 +00002199 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002200 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002201 }
2202
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002203 /* Add a "linux,phandle" property if no "phandle" property already
2204 * existed (can happen with OPAL)
2205 */
2206 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002207 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002208 if (soff == 0)
2209 prom_printf("WARNING: Can't find string index for"
2210 " <linux-phandle> node %s\n", path);
2211 else {
2212 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2213 dt_push_token(4, mem_start, mem_end);
2214 dt_push_token(soff, mem_start, mem_end);
2215 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002216 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002217 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002218 }
2219
2220 /* do all our children */
2221 child = call_prom("child", 1, 1, node);
2222 while (child != 0) {
2223 scan_dt_build_struct(child, mem_start, mem_end);
2224 child = call_prom("peer", 1, 1, child);
2225 }
2226
2227 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2228}
2229
2230static void __init flatten_device_tree(void)
2231{
2232 phandle root;
2233 unsigned long mem_start, mem_end, room;
2234 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002235 char *namep;
2236 u64 *rsvmap;
2237
2238 /*
2239 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002240 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002241 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002242 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002243 if (room > DEVTREE_CHUNK_SIZE)
2244 room = DEVTREE_CHUNK_SIZE;
Anton Blanchard5827d412012-11-26 17:40:03 +00002245 prom_debug("starting device tree allocs at %x\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002246
2247 /* Now try to claim that */
2248 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2249 if (mem_start == 0)
2250 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002251 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002252
2253 /* Get root of tree */
2254 root = call_prom("peer", 1, 1, (phandle)0);
2255 if (root == (phandle)0)
2256 prom_panic ("couldn't get device tree root\n");
2257
2258 /* Build header and make room for mem rsv map */
2259 mem_start = _ALIGN(mem_start, 4);
2260 hdr = make_room(&mem_start, &mem_end,
2261 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002262 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002263 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2264
2265 /* Start of strings */
2266 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002267 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002268 mem_start += 4; /* hole */
2269
2270 /* Add "linux,phandle" in there, we'll need it */
2271 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002272 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002273 mem_start = (unsigned long)namep + strlen(namep) + 1;
2274
2275 /* Build string array */
2276 prom_printf("Building dt strings...\n");
2277 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002278 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002279
2280 /* Build structure */
2281 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002282 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002283 prom_printf("Building dt structure...\n");
2284 scan_dt_build_struct(root, &mem_start, &mem_end);
2285 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002286 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002287
2288 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002289 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2290 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2291 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2292 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2293 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2294 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2295 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2296 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002297 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002298 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002299
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002300 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002301 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002302
2303#ifdef DEBUG_PROM
2304 {
2305 int i;
2306 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002307 for (i = 0; i < mem_reserve_cnt; i++)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002308 prom_printf(" %x - %x\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002309 be64_to_cpu(mem_reserve_map[i].base),
2310 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002311 }
2312#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002313 /* Bump mem_reserve_cnt to cause further reservations to fail
2314 * since it's too late.
2315 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002316 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002317
2318 prom_printf("Device tree strings 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002319 dt_string_start, dt_string_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002320 prom_printf("Device tree struct 0x%x -> 0x%x\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002321 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002322}
2323
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002324#ifdef CONFIG_PPC_MAPLE
2325/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2326 * The values are bad, and it doesn't even have the right number of cells. */
2327static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002328{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002329 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002330 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002331 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002332 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002333
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002334 name = "/ht@0/isa@4";
2335 isa = call_prom("finddevice", 1, 1, ADDR(name));
2336 if (!PHANDLE_VALID(isa)) {
2337 name = "/ht@0/isa@6";
2338 isa = call_prom("finddevice", 1, 1, ADDR(name));
2339 rloc = 0x01003000; /* IO space; PCI device = 6 */
2340 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002341 if (!PHANDLE_VALID(isa))
2342 return;
2343
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002344 if (prom_getproplen(isa, "ranges") != 12)
2345 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002346 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2347 == PROM_ERROR)
2348 return;
2349
2350 if (isa_ranges[0] != 0x1 ||
2351 isa_ranges[1] != 0xf4000000 ||
2352 isa_ranges[2] != 0x00010000)
2353 return;
2354
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002355 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002356
2357 isa_ranges[0] = 0x1;
2358 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002359 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002360 isa_ranges[3] = 0x0;
2361 isa_ranges[4] = 0x0;
2362 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002363 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002364 isa_ranges, sizeof(isa_ranges));
2365}
Harry Ciao8f101a052009-06-17 16:28:00 -07002366
2367#define CPC925_MC_START 0xf8000000
2368#define CPC925_MC_LENGTH 0x1000000
2369/* The values for memory-controller don't have right number of cells */
2370static void __init fixup_device_tree_maple_memory_controller(void)
2371{
2372 phandle mc;
2373 u32 mc_reg[4];
2374 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002375 u32 ac, sc;
2376
2377 mc = call_prom("finddevice", 1, 1, ADDR(name));
2378 if (!PHANDLE_VALID(mc))
2379 return;
2380
2381 if (prom_getproplen(mc, "reg") != 8)
2382 return;
2383
Anton Blanchard5827d412012-11-26 17:40:03 +00002384 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2385 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002386 if ((ac != 2) || (sc != 2))
2387 return;
2388
2389 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2390 return;
2391
2392 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2393 return;
2394
2395 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2396
2397 mc_reg[0] = 0x0;
2398 mc_reg[1] = CPC925_MC_START;
2399 mc_reg[2] = 0x0;
2400 mc_reg[3] = CPC925_MC_LENGTH;
2401 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2402}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002403#else
2404#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002405#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002406#endif
2407
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002408#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002409/*
2410 * Pegasos and BriQ lacks the "ranges" property in the isa node
2411 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002412 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002413 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002414static void __init fixup_device_tree_chrp(void)
2415{
Olaf Heringe4805922007-04-04 18:20:04 +02002416 phandle ph;
2417 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002418 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002419 char *name;
2420 int rc;
2421
2422 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002423 ph = call_prom("finddevice", 1, 1, ADDR(name));
2424 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002425 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002426 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002427 rloc = 0x01003000; /* IO space; PCI device = 6 */
2428 }
Olaf Heringe4805922007-04-04 18:20:04 +02002429 if (PHANDLE_VALID(ph)) {
2430 rc = prom_getproplen(ph, "ranges");
2431 if (rc == 0 || rc == PROM_ERROR) {
2432 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002433
Olaf Heringe4805922007-04-04 18:20:04 +02002434 prop[0] = 0x1;
2435 prop[1] = 0x0;
2436 prop[2] = rloc;
2437 prop[3] = 0x0;
2438 prop[4] = 0x0;
2439 prop[5] = 0x00010000;
2440 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2441 }
2442 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002443
Olaf Heringe4805922007-04-04 18:20:04 +02002444 name = "/pci@80000000/ide@C,1";
2445 ph = call_prom("finddevice", 1, 1, ADDR(name));
2446 if (PHANDLE_VALID(ph)) {
2447 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2448 prop[0] = 14;
2449 prop[1] = 0x0;
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002450 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2451 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2452 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2453 if (rc == sizeof(u32)) {
2454 prop[0] &= ~0x5;
2455 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2456 }
Olaf Heringe4805922007-04-04 18:20:04 +02002457 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002458}
2459#else
2460#define fixup_device_tree_chrp()
2461#endif
2462
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002463#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002464static void __init fixup_device_tree_pmac(void)
2465{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002466 phandle u3, i2c, mpic;
2467 u32 u3_rev;
2468 u32 interrupts[2];
2469 u32 parent;
2470
2471 /* Some G5s have a missing interrupt definition, fix it up here */
2472 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2473 if (!PHANDLE_VALID(u3))
2474 return;
2475 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2476 if (!PHANDLE_VALID(i2c))
2477 return;
2478 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2479 if (!PHANDLE_VALID(mpic))
2480 return;
2481
2482 /* check if proper rev of u3 */
2483 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2484 == PROM_ERROR)
2485 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002486 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002487 return;
2488 /* does it need fixup ? */
2489 if (prom_getproplen(i2c, "interrupts") > 0)
2490 return;
2491
2492 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2493
2494 /* interrupt on this revision of u3 is number 0 and level */
2495 interrupts[0] = 0;
2496 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002497 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2498 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002499 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002500 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2501 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002502}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002503#else
2504#define fixup_device_tree_pmac()
2505#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002506
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002507#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002508/*
2509 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2510 * to talk to the phy. If the phy-handle property is missing, then this
2511 * function is called to add the appropriate nodes and link it to the
2512 * ethernet node.
2513 */
2514static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002515{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002516 u32 node;
2517 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002518 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002519
Grant Likely94d2dde2008-01-24 22:25:32 -07002520 /* Check if /builtin/ethernet exists - bail if it doesn't */
2521 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002522 if (!PHANDLE_VALID(node))
2523 return;
2524
Grant Likely94d2dde2008-01-24 22:25:32 -07002525 /* Check if the phy-handle property exists - bail if it does */
2526 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2527 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002528 return;
2529
Grant Likely94d2dde2008-01-24 22:25:32 -07002530 /*
2531 * At this point the ethernet device doesn't have a phy described.
2532 * Now we need to add the missing phy node and linkage
2533 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002534
Grant Likely94d2dde2008-01-24 22:25:32 -07002535 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002536 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2537 if (!PHANDLE_VALID(node)) {
2538 prom_printf("Adding Ethernet MDIO node\n");
2539 call_prom("interpret", 1, 1,
2540 " s\" /builtin\" find-device"
2541 " new-device"
2542 " 1 encode-int s\" #address-cells\" property"
2543 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002544 " s\" mdio\" device-name"
2545 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002546 " s\" compatible\" property"
2547 " 0xf0003000 0x400 reg"
2548 " 0x2 encode-int"
2549 " 0x5 encode-int encode+"
2550 " 0x3 encode-int encode+"
2551 " s\" interrupts\" property"
2552 " finish-device");
2553 };
2554
Grant Likely94d2dde2008-01-24 22:25:32 -07002555 /* Check for a PHY device node - if missing then create one and
2556 * give it's phandle to the ethernet node */
2557 node = call_prom("finddevice", 1, 1,
2558 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002559 if (!PHANDLE_VALID(node)) {
2560 prom_printf("Adding Ethernet PHY node\n");
2561 call_prom("interpret", 1, 1,
2562 " s\" /builtin/mdio\" find-device"
2563 " new-device"
2564 " s\" ethernet-phy\" device-name"
2565 " 0x10 encode-int s\" reg\" property"
2566 " my-self"
2567 " ihandle>phandle"
2568 " finish-device"
2569 " s\" /builtin/ethernet\" find-device"
2570 " encode-int"
2571 " s\" phy-handle\" property"
2572 " device-end");
2573 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002574}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002575
Grant Likely94d2dde2008-01-24 22:25:32 -07002576static void __init fixup_device_tree_efika(void)
2577{
2578 int sound_irq[3] = { 2, 2, 0 };
2579 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2580 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2581 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2582 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2583 u32 node;
2584 char prop[64];
2585 int rv, len;
2586
2587 /* Check if we're really running on a EFIKA */
2588 node = call_prom("finddevice", 1, 1, ADDR("/"));
2589 if (!PHANDLE_VALID(node))
2590 return;
2591
2592 rv = prom_getprop(node, "model", prop, sizeof(prop));
2593 if (rv == PROM_ERROR)
2594 return;
2595 if (strcmp(prop, "EFIKA5K2"))
2596 return;
2597
2598 prom_printf("Applying EFIKA device tree fixups\n");
2599
2600 /* Claiming to be 'chrp' is death */
2601 node = call_prom("finddevice", 1, 1, ADDR("/"));
2602 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2603 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2604 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2605
David Woodhouse7f4392c2008-04-14 02:52:38 +10002606 /* CODEGEN,description is exposed in /proc/cpuinfo so
2607 fix that too */
2608 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2609 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2610 prom_setprop(node, "/", "CODEGEN,description",
2611 "Efika 5200B PowerPC System",
2612 sizeof("Efika 5200B PowerPC System"));
2613
Grant Likely94d2dde2008-01-24 22:25:32 -07002614 /* Fixup bestcomm interrupts property */
2615 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2616 if (PHANDLE_VALID(node)) {
2617 len = prom_getproplen(node, "interrupts");
2618 if (len == 12) {
2619 prom_printf("Fixing bestcomm interrupts property\n");
2620 prom_setprop(node, "/builtin/bestcom", "interrupts",
2621 bcomm_irq, sizeof(bcomm_irq));
2622 }
2623 }
2624
2625 /* Fixup sound interrupts property */
2626 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2627 if (PHANDLE_VALID(node)) {
2628 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2629 if (rv == PROM_ERROR) {
2630 prom_printf("Adding sound interrupts property\n");
2631 prom_setprop(node, "/builtin/sound", "interrupts",
2632 sound_irq, sizeof(sound_irq));
2633 }
2634 }
2635
2636 /* Make sure ethernet phy-handle property exists */
2637 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002638}
2639#else
2640#define fixup_device_tree_efika()
2641#endif
2642
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002643static void __init fixup_device_tree(void)
2644{
2645 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07002646 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002647 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002648 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002649 fixup_device_tree_efika();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002650}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002651
2652static void __init prom_find_boot_cpu(void)
2653{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002654 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002655 ihandle prom_cpu;
2656 phandle cpu_pkg;
2657
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002658 rval = 0;
2659 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10002660 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002661 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002662
2663 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
2664
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002665 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
2666 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002667
Anton Blanchard5827d412012-11-26 17:40:03 +00002668 prom_debug("Booting CPU hw index = %lu\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002669}
2670
2671static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2672{
2673#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002674 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002675 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002676
Anton Blanchard5827d412012-11-26 17:40:03 +00002677 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
2678 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002679
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002680 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002681 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002682 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002683 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002684 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002685 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002686
Anton Blanchard5827d412012-11-26 17:40:03 +00002687 reserve_mem(prom_initrd_start,
2688 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002689
Anton Blanchard5827d412012-11-26 17:40:03 +00002690 prom_debug("initrd_start=0x%x\n", prom_initrd_start);
2691 prom_debug("initrd_end=0x%x\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002692 }
2693#endif /* CONFIG_BLK_DEV_INITRD */
2694}
2695
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002696#ifdef CONFIG_PPC64
2697#ifdef CONFIG_RELOCATABLE
2698static void reloc_toc(void)
2699{
2700}
2701
2702static void unreloc_toc(void)
2703{
2704}
2705#else
Anton Blanchard16744002013-03-12 01:51:51 +00002706static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002707{
2708 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00002709 unsigned long *toc_entry;
2710
2711 /* Get the start of the TOC by using r2 directly. */
2712 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002713
2714 for (i = 0; i < nr_entries; i++) {
2715 *toc_entry = *toc_entry + offset;
2716 toc_entry++;
2717 }
2718}
2719
2720static void reloc_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
Anton Blanchard16744002013-03-12 01:51:51 +00002726 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002727
2728 mb();
2729}
2730
2731static void unreloc_toc(void)
2732{
2733 unsigned long offset = reloc_offset();
2734 unsigned long nr_entries =
2735 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
2736
2737 mb();
2738
Anton Blanchard16744002013-03-12 01:51:51 +00002739 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002740}
2741#endif
2742#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002743
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002744/*
2745 * We enter here early on, when the Open Firmware prom is still
2746 * handling exceptions and the MMU hash table for us.
2747 */
2748
2749unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2750 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10002751 unsigned long r6, unsigned long r7,
2752 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002753{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002754 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002755
2756#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10002757 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002758 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002759#else
2760 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002761#endif
2762
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002763 /*
2764 * First zero the BSS
2765 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002766 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002767
2768 /*
2769 * Init interface to Open Firmware, get some node references,
2770 * like /chosen
2771 */
2772 prom_init_client_services(pp);
2773
2774 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002775 * See if this OF is old enough that we need to do explicit maps
2776 * and other workarounds
2777 */
2778 prom_find_mmu();
2779
2780 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002781 * Init prom stdout device
2782 */
2783 prom_init_stdout();
2784
Anton Blanchard5827d412012-11-26 17:40:03 +00002785 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00002786
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002787 /*
2788 * Get default machine type. At this point, we do not differentiate
2789 * between pSeries SMP and pSeries LPAR
2790 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002791 of_platform = prom_find_machine_type();
2792 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002793
Suzuki Poulose0f890c82011-12-14 22:57:15 +00002794#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01002795 /* Bail if this is a kdump kernel. */
2796 if (PHYSICAL_START > 0)
2797 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10002798#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01002799
2800 /*
2801 * Check for an initrd
2802 */
2803 prom_check_initrd(r3, r4);
2804
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002805#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002806 /*
2807 * On pSeries, inform the firmware about our capabilities
2808 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002809 if (of_platform == PLATFORM_PSERIES ||
2810 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002811 prom_send_capabilities();
2812#endif
2813
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002814 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05002815 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002816 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002817 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10002818 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002819
2820 /*
2821 * Do early parsing of command line
2822 */
2823 early_cmdline_parse();
2824
2825 /*
2826 * Initialize memory management within prom_init
2827 */
2828 prom_init_mem();
2829
2830 /*
2831 * Determine which cpu is actually running right _now_
2832 */
2833 prom_find_boot_cpu();
2834
2835 /*
2836 * Initialize display devices
2837 */
2838 prom_check_displays();
2839
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002840#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002841 /*
2842 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
2843 * that uses the allocator, we need to make sure we get the top of memory
2844 * available for us here...
2845 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002846 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002847 prom_initialize_tce_table();
2848#endif
2849
2850 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002851 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
2852 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002853 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002854 if (of_platform != PLATFORM_POWERMAC &&
2855 of_platform != PLATFORM_OPAL)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002856 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002857
2858#ifdef CONFIG_PPC_POWERNV
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002859 if (of_platform == PLATFORM_OPAL)
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002860 prom_instantiate_opal();
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002861#endif /* CONFIG_PPC_POWERNV */
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002862
Ashley Lai4a727422012-08-14 18:34:57 -05002863#ifdef CONFIG_PPC64
2864 /* instantiate sml */
2865 prom_instantiate_sml();
2866#endif
2867
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002868 /*
2869 * On non-powermacs, put all CPUs in spin-loops.
2870 *
2871 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002872 *
2873 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002874 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002875 if (of_platform != PLATFORM_POWERMAC &&
2876 of_platform != PLATFORM_OPAL)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002877 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002878
2879 /*
2880 * Fill in some infos for use by the kernel later on
2881 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002882 if (prom_memory_limit) {
2883 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00002884 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002885 &val, sizeof(val));
2886 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002887#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00002888 if (prom_iommu_off)
2889 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002890 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002891
Anton Blanchard5827d412012-11-26 17:40:03 +00002892 if (prom_iommu_force_on)
2893 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002894 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002895
Anton Blanchard5827d412012-11-26 17:40:03 +00002896 if (prom_tce_alloc_start) {
2897 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
2898 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002899 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00002900 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
2901 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002902 sizeof(prom_tce_alloc_end));
2903 }
2904#endif
2905
2906 /*
2907 * Fixup any known bugs in the device-tree
2908 */
2909 fixup_device_tree();
2910
2911 /*
2912 * Now finally create the flattened device-tree
2913 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002914 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002915 flatten_device_tree();
2916
Paul Mackerras3825ac02005-11-08 22:48:08 +11002917 /*
2918 * in case stdin is USB and still active on IBM machines...
2919 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00002920 * closed stdin already (in particular the powerbook 101). It
2921 * appears that the OPAL version of OFW doesn't like it either.
Paul Mackerras3825ac02005-11-08 22:48:08 +11002922 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002923 if (of_platform != PLATFORM_POWERMAC &&
2924 of_platform != PLATFORM_OPAL)
Paul Mackerras3825ac02005-11-08 22:48:08 +11002925 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002926
2927 /*
2928 * Call OF "quiesce" method to shut down pending DMA's from
2929 * devices etc...
2930 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11002931 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002932 call_prom("quiesce", 0, 0);
2933
2934 /*
2935 * And finally, call the kernel passing it the flattened device
2936 * tree and NULL as r5, thus triggering the new entry point which
2937 * is common to us and kexec
2938 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002939 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00002940
2941 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Anton Blanchard5827d412012-11-26 17:40:03 +00002942 if (of_platform != PLATFORM_OPAL) {
Michael Ellerman7e862d72015-03-30 17:38:09 +11002943 prom_printf("Booting Linux via __start() ...\n");
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00002944 prom_debug("->dt_header_start=0x%x\n", hdr);
2945 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002946
2947#ifdef CONFIG_PPC32
2948 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002949#else
2950 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002951#endif
2952
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002953#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
2954 /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
2955 __start(hdr, kbase, 0, 0, 0,
Anton Blanchard5827d412012-11-26 17:40:03 +00002956 prom_opal_base, prom_opal_entry);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002957#else
2958 __start(hdr, kbase, 0, 0, 0, 0, 0);
2959#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002960
2961 return 0;
2962}