Skip to contentSkip to conversation

Device-tree support for ARM

PATCH In review Jeremy Kerr 4 participants 17 messages Dec 22, 2009 – Mar 6, 2010 2 messages not in the archive

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover Device-tree support for ARM

Hi all,

The following series of patches is an early prototype to add device tree support to the ARM architecture.

If you're not familiar with device trees: a device tree is a data structure describing the hardware that the kernel is booted on. On boot, the bootloader can pass a 'device tree blob' to the kernel; the kernel then parses the blob and extracts data used to initialise the machine. Think ATAGS with a free-form structure and arbitrary property names and values.

For cases where we don't want to rely on the bootloader's device tree blob[1] (maybe we have an updated one with fixes), we can supply our own device tree, attached to the kernel and passed through a boot wrapper.

Device trees are currently used in the boot process for the powerpc, sparc and microblaze architectures.

This work is aimed at reducing the effort required to port to a new board. Some hardware changes to may not require a new kernel at all; these may be described by a corresponding change to the device tree.

We'd also hope to see an overall decrease in code required as drivers can be made generic enough to support a set of compatible devices, with the differences being represented in the device tree.

At this stage, I've just added a mechanism to probe a platform (Versatile PB) using a device tree; this is just a proof of concept for machine probe, the interesting stuff happens when we can add DT support to drivers that the DT-enabled platforms use. Also todo is the boot wrapper to enable us to embed an updated DT in a bootable image.

These patches are based on Grant Likely's test-devicetree repo[2], which is an effort to merge the common device tree code between the powerpc, sparc and microblaze architectures. I have a git tree[3] of these patches up too, based on his tree.

The approach I've chosen for a boot interface is to add an ATAG that points to a device tree blob. If this ATAG is found, we use the device-tree based discovery. There are a couple of other options, but I think this is the least-intrusive method of passing the DT to the kernel, and will continue to work with non-DT bootloaders.

If you'd like to try the code out, I have a page[4] up that has details of the kernel, a link to DT-enabled qemu sources and a sample device tree for the versatile machine.

This is only an initial prototype, but I'd appreciate any comments, feedback or review.

Cheers,

Jeremy

1: http://lkml.org/lkml/2009/5/27/446
2: http://git.secretlab.ca/?p=linux-2.6.git;a=shortlog;h=refs/heads/test-devicetree
3: http://kernel.ubuntu.com/git?p=jk/dt/linux-2.6.git;a=summary
4: https://wiki.ubuntu.com/KernelTeam/ARMDeviceTrees

---
Jeremy Kerr (11):
arm: change command_line to cmd_line, and export it
arm: use generic infrastructure for early params
arm: export arm_add_memory
arm-dt: Add ATAG_DEVTREE tag
arm-dt: Add CONFIG_ARM_DEVTREE
arm-dt: postpone machine detection until setup_arch with CONFIG_ARM_DEVTREE
arm-dt: parse devtree pointer on boot
arm-dt: parse memory info from DT
arm-dt: probe for device-tree enabled platforms
arm-dt: parse initrd from device tree
arm/versatile: probe via device tree

#1 lore raw

PATCH 1/11 arm: change command_line to cmd_line, and export it

drivers/of/fdt expects a cmd_line symbol, while arm uses command_line. Change to the former and make accessible from setup.h, so that we can share with the fdt code.

This means a change in section from .init.data to .data

---
 arch/arm/include/asm/setup.h |    6 ++++--
 arch/arm/kernel/setup.c      |    8 ++++----
 2 files changed, 8 insertions(+), 6 deletions(-)
arch/arm/include/asm/setup.h +4 -2
index 5ccce0a..1e2ab1b 100644
@@ -16,8 +16,6 @@
 
 #include <linux/types.h>
 
-#define COMMAND_LINE_SIZE 1024
-
 /* The list ends with an ATAG_NONE node. */
 #define ATAG_NONE	0x00000000
 
@@ -235,6 +233,10 @@ struct early_params {
 static struct early_params __early_##fn __used			\
 __attribute__((__section__(".early_param.init"))) = { name, fn }
 
+#define COMMAND_LINE_SIZE 1024
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+
 #endif  /*  __KERNEL__  */
 
 #endif
arch/arm/kernel/setup.c +4 -4
index c6c57b6..015803a 100644
@@ -117,7 +117,7 @@ EXPORT_SYMBOL(elf_platform);
 
 static const char *cpu_name;
 static const char *machine_name;
-static char __initdata command_line[COMMAND_LINE_SIZE];
+char cmd_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -446,7 +446,7 @@ __early_param("mem=", early_mem);
  */
 static void __init parse_cmdline(char **cmdline_p, char *from)
 {
-	char c = ' ', *to = command_line;
+	char c = ' ', *to = cmd_line;
 	int len = 0;
 
 	for (;;) {
@@ -458,7 +458,7 @@ static void __init parse_cmdline(char **cmdline_p, char *from)
 				int arglen = strlen(p->arg);
 
 				if (memcmp(from, p->arg, arglen) == 0) {
-					if (to != command_line)
+					if (to != cmd_line)
 						to -= 1;
 					from += arglen;
 					p->fn(&from);
@@ -477,7 +477,7 @@ static void __init parse_cmdline(char **cmdline_p, char *from)
 		*to++ = c;
 	}
 	*to = '\0';
-	*cmdline_p = command_line;
+	*cmdline_p = cmd_line;
 }
 
 static void __init
#2 lore raw

PATCH 2/11 arm: use generic infrastructure for early params

In reply to Jeremy Kerr

The ARM setup code includes its own parser for early params, there's also one in the generic init code.

This patch removes __early_init (and related code) from arch/arm/kernel/setup.c, and changes users to the generic early_init macro instead.

The generic macro takes a char * argument, rather than char **, so we need to update the parser functions a little.

---
 arch/arm/include/asm/setup.h      |   12 -----
 arch/arm/kernel/setup.c           |   62 +++++++-----------------------
 arch/arm/kernel/vmlinux.lds.S     |    3 -
 arch/arm/mach-footbridge/common.c |    7 +--
 arch/arm/mm/init.c                |   12 +++--
 arch/arm/mm/mmu.c                 |   41 ++++++++++---------
 6 files changed, 48 insertions(+), 89 deletions(-)
arch/arm/include/asm/setup.h +0 -12
index 1e2ab1b..3b6f461 100644
@@ -221,18 +221,6 @@ extern struct meminfo meminfo;
 #define bank_phys_end(bank)	((bank)->start + (bank)->size)
 #define bank_phys_size(bank)	(bank)->size
 
-/*
- * Early command line parameters.
- */
-struct early_params {
-	const char *arg;
-	void (*fn)(char **p);
-};
-
-#define __early_param(name,fn)					\
-static struct early_params __early_##fn __used			\
-__attribute__((__section__(".early_param.init"))) = { name, fn }
-
 #define COMMAND_LINE_SIZE 1024
 
 extern char cmd_line[COMMAND_LINE_SIZE];
arch/arm/kernel/setup.c +16 -46

87 lines not on this page · raw message

arch/arm/kernel/vmlinux.lds.S +0 -3
index aecf87d..1975c76 100644
@@ -46,9 +46,6 @@ SECTIONS
 		__setup_start = .;
 			*(.init.setup)
 		__setup_end = .;
-		__early_begin = .;
-			*(.early_param.init)
-		__early_end = .;
 		__initcall_start = .;
 			INITCALLS
 		__initcall_end = .;
arch/arm/mach-footbridge/common.c +4 -3
index b97f529..8a4a8d8 100644
@@ -32,12 +32,13 @@ unsigned int mem_fclk_21285 = 50000000;
 
 EXPORT_SYMBOL(mem_fclk_21285);
 
-static void __init early_fclk(char **arg)
+static int __init early_fclk(char *arg)
 {
-	mem_fclk_21285 = simple_strtoul(*arg, arg, 0);
+	mem_fclk_21285 = simple_strtoul(arg, NULL, 0);
+	return 0;
 }
 
-__early_param("mem_fclk_21285=", early_fclk);
+early_param("mem_fclk_21285", early_fclk);
 
 static int __init parse_tag_memclk(const struct tag *tag)
 {
arch/arm/mm/init.c +7 -5
index 52c40d1..4d3c90f 100644
@@ -32,19 +32,21 @@
 static unsigned long phys_initrd_start __initdata = 0;
 static unsigned long phys_initrd_size __initdata = 0;
 
-static void __init early_initrd(char **p)
+static int __init early_initrd(char *p)
 {
 	unsigned long start, size;
+	char *endp;
 
-	start = memparse(*p, p);
-	if (**p == ',') {
-		size = memparse((*p) + 1, p);
+	start = memparse(p, &endp);
+	if (*endp == ',') {
+		size = memparse(endp + 1, NULL);
 
 		phys_initrd_start = start;
 		phys_initrd_size = size;
 	}
+	return 0;
 }
-__early_param("initrd=", early_initrd);
+early_param("initrd", early_initrd);
 
 static int __init parse_tag_initrd(const struct tag *tag)
 {
arch/arm/mm/mmu.c +21 -20

92 lines not on this page · raw message

#3 lore raw

PATCH 2/11 arm: use generic infrastructure for early params

Quoted 2 lines · Jeremy Kerr

The ARM setup code includes its own parser for early params, there's also one in the generic init code.

This is something which should be separate from the rest of the DT patch - could we have this as a patch which can be applied to the current kernel tree please?

#4 lore raw

PATCH 2/11 arm: use generic infrastructure for early params

Russell,

Quoted 3 lines

This is something which should be separate from the rest of the DT patch - could we have this as a patch which can be applied to the current kernel tree please?

Sure, patch coming.

The first three patches of this series (prefixed with arm:, rather than arm- dt:) are all generic arm patches that don't specifically add device tree support, would you like the other two as well?

I'm in the process of rebasing my work onto a merge or your and Grant Likely's test-devicetree branch, so future patches should be easier to work with.

Cheers,

Jeremy

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 201003060733.57636.rob-VoJi6FS/[email protected]

#7 lore raw

Re: [PATCH 02/11] arm: use generic infrastructure for early params

Quoted 21 lines · Rob Landley
Quoted 12 lines · On Wednesday 06 January 2010 16:31:00 Jeremy Kerr wrote:

Russell,

Quoted 3 lines

This is something which should be separate from the rest of the DT patch - could we have this as a patch which can be applied to the current kernel tree please?

Sure, patch coming.

The first three patches of this series (prefixed with arm:, rather than arm- dt:) are all generic arm patches that don't specifically add device tree support, would you like the other two as well?

Quoted 5 lines

I'm in the process of rebasing my work onto a merge or your and Grant Likely's test-devicetree branch, so future patches should be easier to work with.

Cheers,

What's the current status on the device tree for arm stuff?

Quoted 8 lines

I'm going through some of my todo bookmarks and stumbled across
http://lwn.net/Articles/367752/ and I'd like to poke at it under qemu.

I've been patching the kernel kconfig stuff to let me plug various different arm processors into a versatile board (because it's convinced that you can't possibly have an armv6l versatilepb and qemu's -cpu option makes that easy). Feeding in a device tree (or better yet teaching qemu to generate one) sounds like a better long-term approach...

https://wiki.ubuntu.com/KernelTeam/ARMDeviceTrees

g.

#8 lore raw

PATCH 3/11 arm: export arm_add_memory

In reply to Jeremy Kerr

We'd like to add memory from the device tree, so make arm_add_memory non-static and add a prototype in setup.h

---
 arch/arm/include/asm/setup.h |    2 ++
 arch/arm/kernel/setup.c      |    2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)
arch/arm/include/asm/setup.h +2 -0
index 3b6f461..3fa2555 100644
@@ -225,6 +225,8 @@ extern struct meminfo meminfo;
 
 extern char cmd_line[COMMAND_LINE_SIZE];
 
+extern int arm_add_memory(unsigned long start, unsigned long size);
+
 #endif  /*  __KERNEL__  */
 
 #endif
arch/arm/kernel/setup.c +1 -1
index 4206286..84fd876 100644
@@ -383,7 +383,7 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
 	return list;
 }
 
-static int __init arm_add_memory(unsigned long start, unsigned long size)
+int __init arm_add_memory(unsigned long start, unsigned long size)
 {
 	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
 
#9 lore raw

PATCH 4/11 arm-dt: Add ATAG_DEVTREE tag

In reply to Jeremy Kerr

We'd like to provide a pointer to the device tree blob through the atags mechanism, so add a tag type containing a physical dtb pointer.

We won't need a parser for this, as we'll need to do the devtree parsing a little earlier than other tags.

---
 arch/arm/include/asm/setup.h |    8 ++++++++
 1 file changed, 8 insertions(+)
arch/arm/include/asm/setup.h +8 -0
index 3fa2555..99ba6db 100644
@@ -141,6 +141,13 @@ struct tag_memclk {
 	__u32 fmemclk;
 };
 
+/* OF device tree blob pointer */
+#define ATAG_DEVTREE	0x5441000a
+
+struct tag_devtree {
+	__u32 devtree;		/* physical address */
+};
+
 struct tag {
 	struct tag_header hdr;
 	union {
@@ -153,6 +160,7 @@ struct tag {
 		struct tag_revision	revision;
 		struct tag_videolfb	videolfb;
 		struct tag_cmdline	cmdline;
+		struct tag_devtree	devtree;
 
 		/*
 		 * Acorn specific
#10 lore raw

PATCH 5/11 arm-dt: Add CONFIG_ARM_DEVTREE

In reply to Jeremy Kerr

Add some basic empty infrastructure for DT support on ARM.

---
 arch/arm/Kconfig            |   13 +++++++++++++
 arch/arm/include/asm/prom.h |   28 ++++++++++++++++++++++++++++
 arch/arm/kernel/setup.c     |   28 ++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+)
arch/arm/Kconfig +13 -0
index 1c4119c..2e53d33 100644
@@ -1225,6 +1225,19 @@ endmenu
 
 menu "Boot options"
 
+config OF
+	bool
+	default n
+
+config ARM_DEVTREE
+	bool "Device tree support"
+	default y
+	depends on !DEBUG_LL
+	select OF
+	select OF_FLATTREE
+	help
+	  Support for OpenFirmware-style device trees
+
 # 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
arch/arm/include/asm/prom.h new file +28 -0
new file mode 100644
index 0000000..5260d22
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/include/asm/prom.h
+ *
+ *  Copyright (C) 2009 Canonical Ltd. <[email protected]>
+ *
+ * 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
+
+#include <asm/setup.h>
+
+#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT	1
+#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT	1
+
+#define of_compat_cmp(s1, s2, l)	strncasecmp((s1), (s2), (l))
+#define of_prop_cmp(s1, s2)		strcmp((s1), (s2))
+#define of_node_cmp(s1, s2)		strcasecmp((s1), (s2))
+
+/* _ALIGN expects upwards alignment */
+#define _ALIGN(addr, size)		(((addr)+((size)-1))&(~((size)-1)))
+
+extern struct device_node *of_chosen;
+
+#endif
arch/arm/kernel/setup.c +28 -0
index 84fd876..e662d17 100644
@@ -47,6 +47,11 @@
 #include "atags.h"
 #include "tcm.h"
 
+#ifdef CONFIG_ARM_DEVTREE
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#endif
+
 #ifndef MEM_SIZE
 #define MEM_SIZE	(16*1024*1024)
 #endif
@@ -659,6 +664,29 @@ static int __init customize_machine(void)
 }
 arch_initcall(customize_machine);
 
+/* arch-specific device tree handling */
+#ifdef CONFIG_ARM_DEVTREE
+void early_init_dt_scan_chosen_arch(unsigned long node) { }
+
+void early_init_dt_setup_initrd_arch(unsigned long start, unsigned long_end) { }
+
+void early_init_devtree_arch(void) { }
+
+int early_init_dt_scan_memory(unsigned long node, const char *uname,
+			      int depth, void *data)
+{
+	return 0;
+}
+
+int early_init_dt_scan_cpus(unsigned long node, const char *uname,
+			    int depth, void *data)
+{
+	return 0;
+}
+
+struct device_node *of_chosen;
+#endif /* CONFIG_ARM_DEVTREE */
+
 void __init setup_arch(char **cmdline_p)
 {
 	struct tag *tags = (struct tag *)&init_tags;
#11 lore raw

PATCH 6/11 arm-dt: postpone machine detection until setup_arch with CONFIG_ARM_DEVTREE

In reply to Jeremy Kerr

When we're using CONFIG_ARM_DEVTREE, we need to postpone machine detection until later in setup_arch. Because ARM_DEVTREE depends on !DEBUG_LL, we don't need the mdesc this early anyway.

We'll add support for ARM_DEVTREE && DEBUG_LL later.

---
 arch/arm/kernel/head.S |    9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/kernel/head.S +9 -0
index 38ccbe1..66bb56f 100644
@@ -82,9 +82,18 @@ ENTRY(stext)
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
 	beq	__error_p			@ yes, error 'p'
+
+	/* If we're using the device tree for machine detection, we don't
+	 * look for a machinfo here, as we'll dynamically create one in
+	 * setup_arch(). ARM_DEVTREE depends on !DEBUG_LL, so we won't need
+	 * any machinfo fields 'til later.
+	 */
+#ifndef CONFIG_ARM_DEVTREE
 	bl	__lookup_machine_type		@ r5=machinfo
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
+#endif
+
 	bl	__vet_atags
 	bl	__create_page_tables
 
#12 lore raw

PATCH 6/11 arm-dt: postpone machine detection until setup_arch with CONFIG_ARM_DEVTREE

Quoted 5 lines · Jeremy Kerr

When we're using CONFIG_ARM_DEVTREE, we need to postpone machine detection until later in setup_arch. Because ARM_DEVTREE depends on !DEBUG_LL, we don't need the mdesc this early anyway.

We'll add support for ARM_DEVTREE && DEBUG_LL later.

Why not add a specific machine type for 'this is device tree' and then these routines don't even need to #ifdef. It would especially be good as it allows dt and non-dt machines to coexist in the same kernel together.

Quoted 34 lines
---
 arch/arm/kernel/head.S |    9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/kernel/head.S +9 -0
index 38ccbe1..66bb56f 100644
@@ -82,9 +82,18 @@ ENTRY(stext)
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
 	beq	__error_p			@ yes, error 'p'
+
+	/* If we're using the device tree for machine detection, we don't
+	 * look for a machinfo here, as we'll dynamically create one in
+	 * setup_arch(). ARM_DEVTREE depends on !DEBUG_LL, so we won't need
+	 * any machinfo fields 'til later.
+	 */
+#ifndef CONFIG_ARM_DEVTREE
 	bl	__lookup_machine_type		@ r5=machinfo
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
+#endif
+
 	bl	__vet_atags
 	bl	__create_page_tables
 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#13 lore raw

PATCH 6/11 arm-dt: postpone machine detection until setup_arch with CONFIG_ARM_DEVTREE

Hi Ben,

Quoted 10 lines
Quoted 5 lines

When we're using CONFIG_ARM_DEVTREE, we need to postpone machine detection until later in setup_arch. Because ARM_DEVTREE depends on !DEBUG_LL, we don't need the mdesc this early anyway.

We'll add support for ARM_DEVTREE && DEBUG_LL later.

Why not add a specific machine type for 'this is device tree' and then these routines don't even need to #ifdef. It would especially be good as it allows dt and non-dt machines to coexist in the same kernel together.

Mainly because this doesn't gain us much; the machine_desc that is discovered from this new machine type would not have the correct data (phys_io & io_pg_offset) required for early setup (used for DEBUG_LL).

We could conditionally skip the detection if we see a DT machine type, but then we'd need to add similar checks for all the paths where the machine_desc is used.

However, my goal is indeed to allow DT and non-DT machines to coexist as much as possible, this patch is more a temporary workaround while I figure out how to handle the DEBUG_LL stuff nicely for DT cases.

Cheers,

Jeremy

#14 lore raw

PATCH 7/11 arm-dt: parse devtree pointer on boot

In reply to Jeremy Kerr

Add code to parse the device tree pointer from the atags, and an (empty) routine to create an mdesc from the discovered device tree.

Split the parsing code in setup_arch to handle both device-tree and tags based machine discovery.

---
 arch/arm/include/asm/devtree.h |   22 +++++++++
 arch/arm/kernel/Makefile       |    1 
 arch/arm/kernel/devtree.c      |   14 +++++
 arch/arm/kernel/setup.c        |   80 +++++++++++++++++++++------------
 4 files changed, 90 insertions(+), 27 deletions(-)
arch/arm/include/asm/devtree.h new file +22 -0
new file mode 100644
index 0000000..0914ac2
@@ -0,0 +1,22 @@
+/*
+ *  linux/arch/arm/include/asm/devtree.h
+ *
+ *  Copyright (C) 2009 Canonical Ltd. <[email protected]>
+ *
+ * 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.
+ */
+
+#ifdef CONFIG_ARM_DEVTREE
+
+extern struct machine_desc *parse_devicetree(void *devtree);
+
+#else
+
+static inline struct machine_desc *parse_devicetree(void *devtree)
+{
+	return NULL;
+}
+
+#endif
arch/arm/kernel/Makefile +1 -0
index 79087dd..45d2d82 100644
@@ -36,6 +36,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_ARM_DEVTREE)	+= devtree.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
arch/arm/kernel/devtree.c new file +14 -0
new file mode 100644
index 0000000..864eab5
@@ -0,0 +1,14 @@
+/*
+ *  linux/arch/arm/kernel/devtree.c
+ *
+ *  Copyright (C) 2009 Canonical Ltd. <[email protected]>
+ *
+ * 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.
+ */
+
+struct machine_desc * __init parse_devicetree(void *devtree)
+{
+	return NULL;
+}
arch/arm/kernel/setup.c +53 -27

113 lines not on this page · raw message

#15 lore raw

PATCH 8/11 arm-dt: parse memory info from DT

In reply to Jeremy Kerr

Move the early_init_dt hooks into a new file, and populate the _alloc_memory and _add_memory functions.

---
 arch/arm/kernel/devtree.c |   42 ++++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/setup.c   |   23 --------------------
 2 files changed, 42 insertions(+), 23 deletions(-)
arch/arm/kernel/devtree.c +42 -0
index 864eab5..a8496f6 100644
@@ -8,6 +8,48 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+
+#include <asm/setup.h>
+#include <asm/page.h>
+
+struct device_node *of_chosen;
+
+void __init early_init_dt_scan_chosen_arch(unsigned long node) { }
+
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+					    unsigned long end) { }
+
+void __init early_init_devtree_arch(void) { }
+
+int __init early_init_dt_scan_memory_arch(unsigned long node,
+					    const char *uname,
+					    int depth, void *data)
+{
+	return -EINVAL;
+}
+
+void __init early_init_dt_add_memory(u64 base, u64 size)
+{
+	arm_add_memory(base, size);
+}
+
+u64 __init early_init_dt_alloc_memory(u64 size, u64 align)
+{
+	return __pa(__alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)));
+}
+
+int __init early_init_dt_scan_cpus(unsigned long node, const char *uname,
+			    int depth, void *data)
+{
+	return 0;
+}
+
 struct machine_desc * __init parse_devicetree(void *devtree)
 {
 	return NULL;
arch/arm/kernel/setup.c +0 -23
index 8abb4be..88d4def 100644
@@ -676,29 +676,6 @@ static int __init customize_machine(void)
 }
 arch_initcall(customize_machine);
 
-/* arch-specific device tree handling */
-#ifdef CONFIG_ARM_DEVTREE
-void early_init_dt_scan_chosen_arch(unsigned long node) { }
-
-void early_init_dt_setup_initrd_arch(unsigned long start, unsigned long_end) { }
-
-void early_init_devtree_arch(void) { }
-
-int early_init_dt_scan_memory(unsigned long node, const char *uname,
-			      int depth, void *data)
-{
-	return 0;
-}
-
-int early_init_dt_scan_cpus(unsigned long node, const char *uname,
-			    int depth, void *data)
-{
-	return 0;
-}
-
-struct device_node *of_chosen;
-#endif /* CONFIG_ARM_DEVTREE */
-
 void __init setup_arch(char **cmdline_p)
 {
 	struct tag *tags = (struct tag *)&init_tags;
#16 lore raw

PATCH 9/11 arm-dt: probe for device-tree enabled platforms

In reply to Jeremy Kerr

Add a probe_dt pointer to struct machine_desc, which can be populated by platforms that support discovery via device trees.

At setup_arch time, each compiled-in machine_desc with a dt_probe member will be probed. If the probe function returns 1, we have a match.

---
 arch/arm/include/asm/mach/arch.h |   10 ++++++++++
 arch/arm/kernel/devtree.c        |   19 ++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)
arch/arm/include/asm/mach/arch.h +10 -0
index c59842d..b83af35 100644
@@ -41,6 +41,7 @@ struct machine_desc {
 	void			(*init_irq)(void);
 	struct sys_timer	*timer;		/* system tick timer	*/
 	void			(*init_machine)(void);
+	int			(*probe_dt)(unsigned long root);
 };
 
 /*
@@ -57,4 +58,13 @@ static const struct machine_desc __mach_desc_##_type	\
 #define MACHINE_END				\
 };
 
+#define MACH_TYPE_DT	0xffffffff
+
+#define DT_MACHINE_START(_name, _namestr)		\
+static const struct machine_desc __mach_desc_##_name	\
+ __used							\
+ __attribute__((__section__(".arch.info.init"))) = {	\
+	.nr		= MACH_TYPE_DT,			\
+	.name		= _namestr,
+
 #endif
arch/arm/kernel/devtree.c +18 -1
index a8496f6..2ff4bd0 100644
@@ -17,6 +17,7 @@
 
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/mach/arch.h>
 
 struct device_node *of_chosen;
 
@@ -52,5 +53,21 @@ int __init early_init_dt_scan_cpus(unsigned long node, const char *uname,
 
 struct machine_desc * __init parse_devicetree(void *devtree)
 {
-	return NULL;
+	extern struct machine_desc __arch_info_begin, __arch_info_end;
+	struct machine_desc *mdesc;
+	unsigned long dt_root;
+
+	early_init_devtree(devtree);
+
+	dt_root = of_get_flat_dt_root();
+
+	for (mdesc = &__arch_info_begin; mdesc < &__arch_info_end; mdesc++) {
+		if (mdesc->probe_dt && mdesc->probe_dt(dt_root))
+			break;
+	}
+
+	if (mdesc >= &__arch_info_end)
+		return NULL;
+
+	return mdesc;
 }
#17 lore raw

PATCH 10/11 arm-dt: parse initrd from device tree

In reply to Jeremy Kerr

Move early_init_dt_setup_initrd_arch to arch/arm/mm/init.c, and populate it to set the properties of the parsed initrd area.

---
 arch/arm/kernel/devtree.c |    3 ---
 arch/arm/mm/init.c        |   15 +++++++++++++++
 2 files changed, 15 insertions(+), 3 deletions(-)
arch/arm/kernel/devtree.c +0 -3
index 2ff4bd0..9fd1f24 100644
@@ -23,9 +23,6 @@ struct device_node *of_chosen;
 
 void __init early_init_dt_scan_chosen_arch(unsigned long node) { }
 
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-					    unsigned long end) { }
-
 void __init early_init_devtree_arch(void) { }
 
 int __init early_init_dt_scan_memory_arch(unsigned long node,
arch/arm/mm/init.c +15 -0
index 4d3c90f..77f09d6 100644
@@ -18,6 +18,11 @@
 #include <linux/sort.h>
 #include <linux/highmem.h>
 
+#ifdef CONFIG_ARM_DEVTREEE
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#endif /* CONFIG_ARM_DEVTREEE */
+
 #include <asm/mach-types.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -68,6 +73,16 @@ static int __init parse_tag_initrd2(const struct tag *tag)
 
 __tagtable(ATAG_INITRD2, parse_tag_initrd2);
 
+#if defined(CONFIG_BLK_DEV_INITRD) && defined(CONFIG_ARM_DEVTREE)
+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_BLK_DEV_INITRD && CONFIG_ARM_DEVTREE */
+
+
 /*
  * This keeps memory configuration data used by a couple memory
  * initialization functions, as well as show_mem() for the skipping
#18 lore raw

PATCH 11/11 arm/versatile: probe via device tree

In reply to Jeremy Kerr

For testing the dt work, define a dt-enabled versatile platform, separate from the existing versatile platform support.

---
 arch/arm/mach-versatile/Kconfig        |    7 +
 arch/arm/mach-versatile/Makefile       |    1 
 arch/arm/mach-versatile/versatile_dt.c |  129 +++++++++++++++++++++++++
 3 files changed, 137 insertions(+)
arch/arm/mach-versatile/Kconfig +7 -0
index c781f30..9e8f4a9 100644
@@ -14,4 +14,11 @@ config MACH_VERSATILE_AB
 	help
 	  Include support for the ARM(R) Versatile/AP platform.
 
+config MACH_VERSATILE_DT
+	bool "Support Versatile platform from device tree"
+	depends on ARM_DEVTREE
+	help
+	  Include support for the ARM(R) Versatile/PB platform,
+	  using the device tree for discovery
+
 endmenu
arch/arm/mach-versatile/Makefile +1 -0
index ba81e70..07d0701 100644
@@ -5,4 +5,5 @@
 obj-y					:= core.o clock.o
 obj-$(CONFIG_ARCH_VERSATILE_PB)		+= versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)		+= versatile_ab.o
+obj-$(CONFIG_MACH_VERSATILE_DT)		+= versatile_dt.o
 obj-$(CONFIG_PCI)			+= pci.o
arch/arm/mach-versatile/versatile_dt.c new file +129 -0

129 lines not on this page · raw message