mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
![David Gibson](/assets/img/avatar_default.png)
The powerpc kernel always requires an Open Firmware like device tree to supply device information. On systems without OF, this comes from a flattened device tree blob. This blob is usually generated by dtc, a tool which compiles a text description of the device tree into the flattened format used by the kernel. Sometimes, the bootwrapper makes small changes to the pre-compiled device tree blob (e.g. filling in the size of RAM). To do this it uses the libfdt library. Because these are only used on powerpc, the code for both these tools is included under arch/powerpc/boot (these were imported and are periodically updated from the upstream dtc tree). However, the microblaze architecture, currently being prepared for merging to mainline also uses dtc to produce device tree blobs. A few other archs have also mentioned some interest in using dtc. Therefore, this patch moves dtc and libfdt from arch/powerpc into scripts, where it can be used by any architecture. The vast bulk of this patch is a literal move, the rest is adjusting the various Makefiles to use dtc and libfdt correctly from their new locations. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
90 lines
2.8 KiB
C
90 lines
2.8 KiB
C
/*
|
|
* The simple platform -- for booting when firmware doesn't supply a device
|
|
* tree or any platform configuration information.
|
|
* All data is extracted from an embedded device tree
|
|
* blob.
|
|
*
|
|
* Authors: Scott Wood <scottwood@freescale.com>
|
|
* Grant Likely <grant.likely@secretlab.ca>
|
|
*
|
|
* Copyright (c) 2007 Freescale Semiconductor, Inc.
|
|
* Copyright (c) 2008 Secret Lab Technologies Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 as published
|
|
* by the Free Software Foundation.
|
|
*/
|
|
|
|
#include "ops.h"
|
|
#include "types.h"
|
|
#include "io.h"
|
|
#include "stdio.h"
|
|
#include <libfdt.h>
|
|
|
|
BSS_STACK(4*1024);
|
|
|
|
extern int platform_specific_init(void) __attribute__((weak));
|
|
|
|
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
|
|
unsigned long r6, unsigned long r7)
|
|
{
|
|
const u32 *na, *ns, *reg, *timebase;
|
|
u64 memsize64;
|
|
int node, size, i;
|
|
|
|
/* Make sure FDT blob is sane */
|
|
if (fdt_check_header(_dtb_start) != 0)
|
|
fatal("Invalid device tree blob\n");
|
|
|
|
/* Find the #address-cells and #size-cells properties */
|
|
node = fdt_path_offset(_dtb_start, "/");
|
|
if (node < 0)
|
|
fatal("Cannot find root node\n");
|
|
na = fdt_getprop(_dtb_start, node, "#address-cells", &size);
|
|
if (!na || (size != 4))
|
|
fatal("Cannot find #address-cells property");
|
|
ns = fdt_getprop(_dtb_start, node, "#size-cells", &size);
|
|
if (!ns || (size != 4))
|
|
fatal("Cannot find #size-cells property");
|
|
|
|
/* Find the memory range */
|
|
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
|
|
"memory", sizeof("memory"));
|
|
if (node < 0)
|
|
fatal("Cannot find memory node\n");
|
|
reg = fdt_getprop(_dtb_start, node, "reg", &size);
|
|
if (size < (*na+*ns) * sizeof(u32))
|
|
fatal("cannot get memory range\n");
|
|
|
|
/* Only interested in memory based at 0 */
|
|
for (i = 0; i < *na; i++)
|
|
if (*reg++ != 0)
|
|
fatal("Memory range is not based at address 0\n");
|
|
|
|
/* get the memsize and trucate it to under 4G on 32 bit machines */
|
|
memsize64 = 0;
|
|
for (i = 0; i < *ns; i++)
|
|
memsize64 = (memsize64 << 32) | *reg++;
|
|
if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
|
|
memsize64 = 0xffffffff;
|
|
|
|
/* finally, setup the timebase */
|
|
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
|
|
"cpu", sizeof("cpu"));
|
|
if (!node)
|
|
fatal("Cannot find cpu node\n");
|
|
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
|
|
if (timebase && (size == 4))
|
|
timebase_period_ns = 1000000000 / *timebase;
|
|
|
|
/* Now we have the memory size; initialize the heap */
|
|
simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);
|
|
|
|
/* prepare the device tree and find the console */
|
|
fdt_init(_dtb_start);
|
|
|
|
if (platform_specific_init)
|
|
platform_specific_init();
|
|
|
|
serial_console_init();
|
|
}
|