Merge branch 'devicetree/arm-next' of git://git.secretlab.ca/git/linux-2.6 into devel-stable
This commit is contained in:
Коммит
03eb14199e
|
@ -65,13 +65,19 @@ looks at the connected hardware is beyond the scope of this document.
|
|||
The boot loader must ultimately be able to provide a MACH_TYPE_xxx
|
||||
value to the kernel. (see linux/arch/arm/tools/mach-types).
|
||||
|
||||
|
||||
4. Setup the kernel tagged list
|
||||
-------------------------------
|
||||
4. Setup boot data
|
||||
------------------
|
||||
|
||||
Existing boot loaders: OPTIONAL, HIGHLY RECOMMENDED
|
||||
New boot loaders: MANDATORY
|
||||
|
||||
The boot loader must provide either a tagged list or a dtb image for
|
||||
passing configuration data to the kernel. The physical address of the
|
||||
boot data is passed to the kernel in register r2.
|
||||
|
||||
4a. Setup the kernel tagged list
|
||||
--------------------------------
|
||||
|
||||
The boot loader must create and initialise the kernel tagged list.
|
||||
A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE.
|
||||
The ATAG_CORE tag may or may not be empty. An empty ATAG_CORE tag
|
||||
|
@ -101,6 +107,24 @@ The tagged list must be placed in a region of memory where neither
|
|||
the kernel decompressor nor initrd 'bootp' program will overwrite
|
||||
it. The recommended placement is in the first 16KiB of RAM.
|
||||
|
||||
4b. Setup the device tree
|
||||
-------------------------
|
||||
|
||||
The boot loader must load a device tree image (dtb) into system ram
|
||||
at a 64bit aligned address and initialize it with the boot data. The
|
||||
dtb format is documented in Documentation/devicetree/booting-without-of.txt.
|
||||
The kernel will look for the dtb magic value of 0xd00dfeed at the dtb
|
||||
physical address to determine if a dtb has been passed instead of a
|
||||
tagged list.
|
||||
|
||||
The boot loader must pass at a minimum the size and location of the
|
||||
system memory, and the root filesystem location. The dtb must be
|
||||
placed in a region of memory where the kernel decompressor will not
|
||||
overwrite it. The recommended placement is in the first 16KiB of RAM
|
||||
with the caveat that it may not be located at physical address 0 since
|
||||
the kernel interprets a value of 0 in r2 to mean neither a tagged list
|
||||
nor a dtb were passed.
|
||||
|
||||
5. Calling the kernel image
|
||||
---------------------------
|
||||
|
||||
|
@ -125,7 +149,8 @@ In either case, the following conditions must be met:
|
|||
- CPU register settings
|
||||
r0 = 0,
|
||||
r1 = machine type number discovered in (3) above.
|
||||
r2 = physical address of tagged list in system RAM.
|
||||
r2 = physical address of tagged list in system RAM, or
|
||||
physical address of device tree block (dtb) in system RAM
|
||||
|
||||
- CPU mode
|
||||
All forms of interrupts must be disabled (IRQs and FIQs)
|
||||
|
|
|
@ -12,8 +12,9 @@ Table of Contents
|
|||
=================
|
||||
|
||||
I - Introduction
|
||||
1) Entry point for arch/powerpc
|
||||
2) Entry point for arch/x86
|
||||
1) Entry point for arch/arm
|
||||
2) Entry point for arch/powerpc
|
||||
3) Entry point for arch/x86
|
||||
|
||||
II - The DT block format
|
||||
1) Header
|
||||
|
@ -148,7 +149,46 @@ upgrades without significantly impacting the kernel code or cluttering
|
|||
it with special cases.
|
||||
|
||||
|
||||
1) Entry point for arch/powerpc
|
||||
1) Entry point for arch/arm
|
||||
---------------------------
|
||||
|
||||
There is one single entry point to the kernel, at the start
|
||||
of the kernel image. That entry point supports two calling
|
||||
conventions. A summary of the interface is described here. A full
|
||||
description of the boot requirements is documented in
|
||||
Documentation/arm/Booting
|
||||
|
||||
a) ATAGS interface. Minimal information is passed from firmware
|
||||
to the kernel with a tagged list of predefined parameters.
|
||||
|
||||
r0 : 0
|
||||
|
||||
r1 : Machine type number
|
||||
|
||||
r2 : Physical address of tagged list in system RAM
|
||||
|
||||
b) Entry with a flattened device-tree block. Firmware loads the
|
||||
physical address of the flattened device tree block (dtb) into r2,
|
||||
r1 is not used, but it is considered good practise to use a valid
|
||||
machine number as described in Documentation/arm/Booting.
|
||||
|
||||
r0 : 0
|
||||
|
||||
r1 : Valid machine type number. When using a device tree,
|
||||
a single machine type number will often be assigned to
|
||||
represent a class or family of SoCs.
|
||||
|
||||
r2 : physical pointer to the device-tree block
|
||||
(defined in chapter II) in RAM. Device tree can be located
|
||||
anywhere in system RAM, but it should be aligned on a 64 bit
|
||||
boundary.
|
||||
|
||||
The kernel will differentiate between ATAGS and device tree booting by
|
||||
reading the memory pointed to by r2 and looking for either the flattened
|
||||
device tree block magic value (0xd00dfeed) or the ATAG_CORE value at
|
||||
offset 0x4 from r2 (0x54410001).
|
||||
|
||||
2) Entry point for arch/powerpc
|
||||
-------------------------------
|
||||
|
||||
There is one single entry point to the kernel, at the start
|
||||
|
@ -226,7 +266,7 @@ it with special cases.
|
|||
cannot support both configurations with Book E and configurations
|
||||
with classic Powerpc architectures.
|
||||
|
||||
2) Entry point for arch/x86
|
||||
3) Entry point for arch/x86
|
||||
-------------------------------
|
||||
|
||||
There is one single 32bit entry point to the kernel at code32_start,
|
||||
|
|
|
@ -1683,6 +1683,13 @@ endmenu
|
|||
|
||||
menu "Boot options"
|
||||
|
||||
config USE_OF
|
||||
bool "Flattened Device Tree support"
|
||||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
help
|
||||
Include support for flattened device tree machine descriptions.
|
||||
|
||||
# Compressed boot loader in ROM. Yes, we really want to ask about
|
||||
# TEXT and BSS so we preserve their values in the config files.
|
||||
config ZBOOT_ROM_TEXT
|
||||
|
|
|
@ -18,6 +18,8 @@ struct machine_desc {
|
|||
unsigned int nr; /* architecture number */
|
||||
const char *name; /* architecture name */
|
||||
unsigned long boot_params; /* tagged list */
|
||||
const char **dt_compat; /* array of device tree
|
||||
* 'compatible' strings */
|
||||
|
||||
unsigned int nr_irqs; /* number of IRQs */
|
||||
|
||||
|
@ -47,6 +49,13 @@ struct machine_desc {
|
|||
*/
|
||||
extern struct machine_desc *machine_desc;
|
||||
|
||||
/*
|
||||
* Machine type table - also only accessible during boot
|
||||
*/
|
||||
extern struct machine_desc __arch_info_begin[], __arch_info_end[];
|
||||
#define for_each_machine_desc(p) \
|
||||
for (p = __arch_info_begin; p < __arch_info_end; p++)
|
||||
|
||||
/*
|
||||
* Set of macros to define architecture features. This is built into
|
||||
* a table by the linker.
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* arch/arm/include/asm/prom.h
|
||||
*
|
||||
* Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __ASMARM_PROM_H
|
||||
#define __ASMARM_PROM_H
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
static inline void irq_dispose_mapping(unsigned int virq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
|
||||
extern void arm_dt_memblock_reserve(void);
|
||||
|
||||
#else /* CONFIG_OF */
|
||||
|
||||
static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void arm_dt_memblock_reserve(void) { }
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
#endif /* ASMARM_PROM_H */
|
|
@ -217,6 +217,10 @@ extern struct meminfo meminfo;
|
|||
#define bank_phys_end(bank) ((bank)->start + (bank)->size)
|
||||
#define bank_phys_size(bank) (bank)->size
|
||||
|
||||
extern int arm_add_memory(phys_addr_t start, unsigned long size);
|
||||
extern void early_print(const char *str, ...);
|
||||
extern void dump_machine_table(void);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,7 @@ obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
|
|||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_ARM_UNWIND) += unwind.o
|
||||
obj-$(CONFIG_HAVE_TCM) += tcm.o
|
||||
obj-$(CONFIG_OF) += devtree.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||
obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o
|
||||
CFLAGS_swp_emulate.o := -Wa,-march=armv7-a
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* linux/arch/arm/kernel/devtree.c
|
||||
*
|
||||
* Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com>
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
||||
{
|
||||
arm_add_memory(base, size);
|
||||
}
|
||||
|
||||
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
||||
{
|
||||
return alloc_bootmem_align(size, align);
|
||||
}
|
||||
|
||||
void __init arm_dt_memblock_reserve(void)
|
||||
{
|
||||
u64 *reserve_map, base, size;
|
||||
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
/* Reserve the dtb region */
|
||||
memblock_reserve(virt_to_phys(initial_boot_params),
|
||||
be32_to_cpu(initial_boot_params->totalsize));
|
||||
|
||||
/*
|
||||
* Process the reserve map. This will probably overlap the initrd
|
||||
* and dtb locations which are already reserved, but overlaping
|
||||
* doesn't hurt anything
|
||||
*/
|
||||
reserve_map = ((void*)initial_boot_params) +
|
||||
be32_to_cpu(initial_boot_params->off_mem_rsvmap);
|
||||
while (1) {
|
||||
base = be64_to_cpup(reserve_map++);
|
||||
size = be64_to_cpup(reserve_map++);
|
||||
if (!size)
|
||||
break;
|
||||
memblock_reserve(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
|
||||
* @dt_phys: physical address of dt blob
|
||||
*
|
||||
* If a dtb was passed to the kernel in r2, then use it to choose the
|
||||
* correct machine_desc and to setup the system.
|
||||
*/
|
||||
struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
|
||||
{
|
||||
struct boot_param_header *devtree;
|
||||
struct machine_desc *mdesc, *mdesc_best = NULL;
|
||||
unsigned int score, mdesc_score = ~1;
|
||||
unsigned long dt_root;
|
||||
const char *model;
|
||||
|
||||
devtree = phys_to_virt(dt_phys);
|
||||
|
||||
/* check device tree validity */
|
||||
if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
|
||||
return NULL;
|
||||
|
||||
/* Search the mdescs for the 'best' compatible value match */
|
||||
initial_boot_params = devtree;
|
||||
dt_root = of_get_flat_dt_root();
|
||||
for_each_machine_desc(mdesc) {
|
||||
score = of_flat_dt_match(dt_root, mdesc->dt_compat);
|
||||
if (score > 0 && score < mdesc_score) {
|
||||
mdesc_best = mdesc;
|
||||
mdesc_score = score;
|
||||
}
|
||||
}
|
||||
if (!mdesc_best) {
|
||||
const char *prop;
|
||||
long size;
|
||||
|
||||
early_print("\nError: unrecognized/unsupported "
|
||||
"device tree compatible list:\n[ ");
|
||||
|
||||
prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
|
||||
while (size > 0) {
|
||||
early_print("'%s' ", prop);
|
||||
size -= strlen(prop) + 1;
|
||||
prop += strlen(prop) + 1;
|
||||
}
|
||||
early_print("]\n\n");
|
||||
|
||||
dump_machine_table(); /* does not return */
|
||||
}
|
||||
|
||||
model = of_get_flat_dt_prop(dt_root, "model", NULL);
|
||||
if (!model)
|
||||
model = of_get_flat_dt_prop(dt_root, "compatible", NULL);
|
||||
if (!model)
|
||||
model = "<unknown>";
|
||||
pr_info("Machine: %s, model: %s\n", mdesc_best->name, model);
|
||||
|
||||
/* Retrieve various information from the /chosen node */
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
|
||||
/* Initialize {size,address}-cells info */
|
||||
of_scan_flat_dt(early_init_dt_scan_root, NULL);
|
||||
/* Setup memory, calling early_init_dt_add_memory_arch */
|
||||
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
||||
|
||||
/* Change machine number to match the mdesc we're using */
|
||||
__machine_arch_type = mdesc_best->nr;
|
||||
|
||||
return mdesc_best;
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
|
||||
*
|
||||
* Currently the mapping mechanism is trivial; simple flat hwirq numbers are
|
||||
* mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not
|
||||
* supported.
|
||||
*/
|
||||
unsigned int irq_create_of_mapping(struct device_node *controller,
|
||||
const u32 *intspec, unsigned int intsize)
|
||||
{
|
||||
return intspec[0];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
|
|
@ -15,6 +15,12 @@
|
|||
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
|
||||
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define OF_DT_MAGIC 0xd00dfeed
|
||||
#else
|
||||
#define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exception handling. Something went wrong and we can't proceed. We
|
||||
* ought to tell the user, but since we don't have any guarantee that
|
||||
|
@ -28,20 +34,26 @@
|
|||
|
||||
/* Determine validity of the r2 atags pointer. The heuristic requires
|
||||
* that the pointer be aligned, in the first 16k of physical RAM and
|
||||
* that the ATAG_CORE marker is first and present. Future revisions
|
||||
* that the ATAG_CORE marker is first and present. If CONFIG_OF_FLATTREE
|
||||
* is selected, then it will also accept a dtb pointer. Future revisions
|
||||
* of this function may be more lenient with the physical address and
|
||||
* may also be able to move the ATAGS block if necessary.
|
||||
*
|
||||
* Returns:
|
||||
* r2 either valid atags pointer, or zero
|
||||
* r2 either valid atags pointer, valid dtb pointer, or zero
|
||||
* r5, r6 corrupted
|
||||
*/
|
||||
__vet_atags:
|
||||
tst r2, #0x3 @ aligned?
|
||||
bne 1f
|
||||
|
||||
ldr r5, [r2, #0] @ is first tag ATAG_CORE?
|
||||
cmp r5, #ATAG_CORE_SIZE
|
||||
ldr r5, [r2, #0]
|
||||
#ifdef CONFIG_OF_FLATTREE
|
||||
ldr r6, =OF_DT_MAGIC @ is it a DTB?
|
||||
cmp r5, r6
|
||||
beq 2f
|
||||
#endif
|
||||
cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE?
|
||||
cmpne r5, #ATAG_CORE_SIZE_EMPTY
|
||||
bne 1f
|
||||
ldr r5, [r2, #4]
|
||||
|
@ -49,7 +61,7 @@ __vet_atags:
|
|||
cmp r5, r6
|
||||
bne 1f
|
||||
|
||||
mov pc, lr @ atag pointer is ok
|
||||
2: mov pc, lr @ atag/dtb pointer is ok
|
||||
|
||||
1: mov r2, #0
|
||||
mov pc, lr
|
||||
|
@ -61,7 +73,7 @@ ENDPROC(__vet_atags)
|
|||
*
|
||||
* r0 = cp#15 control register
|
||||
* r1 = machine ID
|
||||
* r2 = atags pointer
|
||||
* r2 = atags/dtb pointer
|
||||
* r9 = processor ID
|
||||
*/
|
||||
__INIT
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
*
|
||||
* This is normally called from the decompressor code. The requirements
|
||||
* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
|
||||
* r1 = machine nr, r2 = atags pointer.
|
||||
* r1 = machine nr, r2 = atags or dtb pointer.
|
||||
*
|
||||
* This code is mostly position independent, so if you link the kernel at
|
||||
* 0xc0008000, you call this at __pa(0xc0008000).
|
||||
|
@ -91,7 +91,7 @@ ENTRY(stext)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* r1 = machine no, r2 = atags,
|
||||
* r1 = machine no, r2 = atags or dtb,
|
||||
* r8 = phys_offset, r9 = cpuid, r10 = procinfo
|
||||
*/
|
||||
bl __vet_atags
|
||||
|
@ -339,7 +339,7 @@ __secondary_data:
|
|||
*
|
||||
* r0 = cp#15 control register
|
||||
* r1 = machine ID
|
||||
* r2 = atags pointer
|
||||
* r2 = atags or dtb pointer
|
||||
* r4 = page table pointer
|
||||
* r9 = processor ID
|
||||
* r13 = *virtual* address to jump to upon completion
|
||||
|
@ -376,7 +376,7 @@ ENDPROC(__enable_mmu)
|
|||
*
|
||||
* r0 = cp#15 control register
|
||||
* r1 = machine ID
|
||||
* r2 = atags pointer
|
||||
* r2 = atags or dtb pointer
|
||||
* r9 = processor ID
|
||||
* r13 = *virtual* address to jump to upon completion
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/screen_info.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/crash_dump.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/cpu.h>
|
||||
|
@ -42,6 +43,7 @@
|
|||
#include <asm/cachetype.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
@ -309,7 +311,7 @@ static void __init cacheid_init(void)
|
|||
*/
|
||||
extern struct proc_info_list *lookup_processor_type(unsigned int);
|
||||
|
||||
static void __init early_print(const char *str, ...)
|
||||
void __init early_print(const char *str, ...)
|
||||
{
|
||||
extern void printascii(const char *);
|
||||
char buf[256];
|
||||
|
@ -439,25 +441,12 @@ void cpu_init(void)
|
|||
: "r14");
|
||||
}
|
||||
|
||||
static struct machine_desc * __init setup_machine(unsigned int nr)
|
||||
void __init dump_machine_table(void)
|
||||
{
|
||||
extern struct machine_desc __arch_info_begin[], __arch_info_end[];
|
||||
struct machine_desc *p;
|
||||
|
||||
/*
|
||||
* locate machine in the list of supported machines.
|
||||
*/
|
||||
for (p = __arch_info_begin; p < __arch_info_end; p++)
|
||||
if (nr == p->nr) {
|
||||
printk("Machine: %s\n", p->name);
|
||||
return p;
|
||||
}
|
||||
|
||||
early_print("\n"
|
||||
"Error: unrecognized/unsupported machine ID (r1 = 0x%08x).\n\n"
|
||||
"Available machine support:\n\nID (hex)\tNAME\n", nr);
|
||||
|
||||
for (p = __arch_info_begin; p < __arch_info_end; p++)
|
||||
early_print("Available machine support:\n\nID (hex)\tNAME\n");
|
||||
for_each_machine_desc(p)
|
||||
early_print("%08x\t%s\n", p->nr, p->name);
|
||||
|
||||
early_print("\nPlease check your kernel config and/or bootloader.\n");
|
||||
|
@ -466,7 +455,7 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
|
|||
/* can't use cpu_relax() here as it may require MMU setup */;
|
||||
}
|
||||
|
||||
static int __init arm_add_memory(phys_addr_t start, unsigned long size)
|
||||
int __init arm_add_memory(phys_addr_t start, unsigned long size)
|
||||
{
|
||||
struct membank *bank = &meminfo.bank[meminfo.nr_banks];
|
||||
|
||||
|
@ -801,23 +790,29 @@ static void __init squash_mem_tags(struct tag *tag)
|
|||
tag->hdr.tag = ATAG_NONE;
|
||||
}
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
static struct machine_desc * __init setup_machine_tags(unsigned int nr)
|
||||
{
|
||||
struct tag *tags = (struct tag *)&init_tags;
|
||||
struct machine_desc *mdesc;
|
||||
struct machine_desc *mdesc = NULL, *p;
|
||||
char *from = default_command_line;
|
||||
|
||||
init_tags.mem.start = PHYS_OFFSET;
|
||||
|
||||
unwind_init();
|
||||
/*
|
||||
* locate machine in the list of supported machines.
|
||||
*/
|
||||
for_each_machine_desc(p)
|
||||
if (nr == p->nr) {
|
||||
printk("Machine: %s\n", p->name);
|
||||
mdesc = p;
|
||||
break;
|
||||
}
|
||||
|
||||
setup_processor();
|
||||
mdesc = setup_machine(machine_arch_type);
|
||||
machine_desc = mdesc;
|
||||
machine_name = mdesc->name;
|
||||
|
||||
if (mdesc->soft_reboot)
|
||||
reboot_setup("s");
|
||||
if (!mdesc) {
|
||||
early_print("\nError: unrecognized/unsupported machine ID"
|
||||
" (r1 = 0x%08x).\n\n", nr);
|
||||
dump_machine_table(); /* does not return */
|
||||
}
|
||||
|
||||
if (__atags_pointer)
|
||||
tags = phys_to_virt(__atags_pointer);
|
||||
|
@ -849,8 +844,17 @@ void __init setup_arch(char **cmdline_p)
|
|||
if (tags->hdr.tag != ATAG_CORE)
|
||||
convert_to_tag_list(tags);
|
||||
#endif
|
||||
if (tags->hdr.tag != ATAG_CORE)
|
||||
|
||||
if (tags->hdr.tag != ATAG_CORE) {
|
||||
#if defined(CONFIG_OF)
|
||||
/*
|
||||
* If CONFIG_OF is set, then assume this is a reasonably
|
||||
* modern system that should pass boot parameters
|
||||
*/
|
||||
early_print("Warning: Neither atags nor dtb found\n");
|
||||
#endif
|
||||
tags = (struct tag *)&init_tags;
|
||||
}
|
||||
|
||||
if (mdesc->fixup)
|
||||
mdesc->fixup(mdesc, tags, &from, &meminfo);
|
||||
|
@ -862,14 +866,34 @@ void __init setup_arch(char **cmdline_p)
|
|||
parse_tags(tags);
|
||||
}
|
||||
|
||||
/* parse_early_param needs a boot_command_line */
|
||||
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||
|
||||
return mdesc;
|
||||
}
|
||||
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
struct machine_desc *mdesc;
|
||||
|
||||
unwind_init();
|
||||
|
||||
setup_processor();
|
||||
mdesc = setup_machine_fdt(__atags_pointer);
|
||||
if (!mdesc)
|
||||
mdesc = setup_machine_tags(machine_arch_type);
|
||||
machine_desc = mdesc;
|
||||
machine_name = mdesc->name;
|
||||
|
||||
if (mdesc->soft_reboot)
|
||||
reboot_setup("s");
|
||||
|
||||
init_mm.start_code = (unsigned long) _text;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
|
||||
/* parse_early_param needs a boot_command_line */
|
||||
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||
|
||||
/* populate cmd_line too for later use, preserving boot_command_line */
|
||||
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
*cmdline_p = cmd_line;
|
||||
|
@ -881,6 +905,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
paging_init(mdesc);
|
||||
request_standard_resources(mdesc);
|
||||
|
||||
unflatten_device_tree();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (is_smp())
|
||||
smp_init_cpus();
|
||||
|
|
|
@ -15,12 +15,14 @@
|
|||
#include <linux/mman.h>
|
||||
#include <linux/nodemask.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/sizes.h>
|
||||
|
@ -71,6 +73,14 @@ static int __init parse_tag_initrd2(const struct tag *tag)
|
|||
|
||||
__tagtable(ATAG_INITRD2, parse_tag_initrd2);
|
||||
|
||||
#ifdef CONFIG_OF_FLATTREE
|
||||
void __init early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end)
|
||||
{
|
||||
phys_initrd_start = start;
|
||||
phys_initrd_size = end - start;
|
||||
}
|
||||
#endif /* CONFIG_OF_FLATTREE */
|
||||
|
||||
/*
|
||||
* This keeps memory configuration data used by a couple memory
|
||||
* initialization functions, as well as show_mem() for the skipping
|
||||
|
@ -334,6 +344,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
|
|||
#endif
|
||||
|
||||
arm_mm_memblock_reserve();
|
||||
arm_dt_memblock_reserve();
|
||||
|
||||
/* reserve any platform specific memblock areas */
|
||||
if (mdesc->reserve)
|
||||
|
|
|
@ -130,7 +130,7 @@ void __init early_init_devtree(void *params)
|
|||
* device-tree, including the platform type, initrd location and
|
||||
* size, TCE reserve, and more ...
|
||||
*/
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line);
|
||||
|
||||
/* Scan memory nodes and rebuild MEMBLOCKs */
|
||||
memblock_init();
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
#ifdef CONFIG_OF
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
/* which is compatible with the flattened device tree (FDT) */
|
||||
#define cmd_line arcs_cmdline
|
||||
|
||||
extern int early_init_dt_scan_memory_arch(unsigned long node,
|
||||
const char *uname, int depth, void *data);
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ void __init early_init_devtree(void *params)
|
|||
* device-tree, including the platform type, initrd location and
|
||||
* size, and more ...
|
||||
*/
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, arcs_cmdline);
|
||||
|
||||
|
||||
/* Scan memory nodes */
|
||||
of_scan_flat_dt(early_init_dt_scan_root, NULL);
|
||||
|
|
|
@ -694,7 +694,7 @@ void __init early_init_devtree(void *params)
|
|||
* device-tree, including the platform type, initrd location and
|
||||
* size, TCE reserve, and more ...
|
||||
*/
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen_ppc, NULL);
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen_ppc, cmd_line);
|
||||
|
||||
/* Scan memory nodes and rebuild MEMBLOCKs */
|
||||
memblock_init();
|
||||
|
|
|
@ -670,7 +670,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
|||
|
||||
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
|
||||
|
||||
if (depth != 1 ||
|
||||
if (depth != 1 || !data ||
|
||||
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
|
||||
return 0;
|
||||
|
||||
|
@ -679,16 +679,16 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
|||
/* Retrieve command line */
|
||||
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
||||
if (p != NULL && l > 0)
|
||||
strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
|
||||
strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
|
||||
|
||||
#ifdef CONFIG_CMDLINE
|
||||
#ifndef CONFIG_CMDLINE_FORCE
|
||||
if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
|
||||
#endif
|
||||
strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#endif /* CONFIG_CMDLINE */
|
||||
|
||||
pr_debug("Command line is: %s\n", cmd_line);
|
||||
pr_debug("Command line is: %s\n", (char*)data);
|
||||
|
||||
/* break now */
|
||||
return 1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче