This patchset introduces device tree support on x86. The device tree is
passed by the bootloader via setup_data. It is used as an additional
source of information and does not replace the "traditional" x86 boot
page.
Right now we get the the following information from it:
- hpet location
- apic & ioapic location
- ioapic's interrupt routing
- legacy devices which are not initialized by bios
- devices which are behind a bus which does not support enumeration like
i2c
Histrory:
- v1 initial post
- v2: Benh took my device tree apart so once this got fixed I refactor a
lot of code. Here are the changes:
- device tree is unflattenend before kmalloc() is working,
alloc_bootmem() is used for that.
- irq_host got renamed to irq_domain. This custom implementation
will leave once the powerpc implementation is in generic shape
- of_irq_map_pci() is moved from ppc & microblaze into drivers/of
and used also by x86 instead of a tiny subset of it. Bridges are
not handled at all on x86 (I don't have any so for so I worry
later)
- the device tree is relocated from its initial location. That
means that the boot loader does not need to know anything about
kernel's memory layout.
The series is based on the tip tree and is also available at
git://git.linutronix.de/users/bigeasy/soda.git ce_of_v2
Sebastian Andrzej Siewior (15):
x86/e820: remove conditional early mapping in parse_e820_ext
x86: Add device tree support
x86/dtb: Add a device tree for CE4100
x86/dtb: add irq domain abstraction
x86/dtb: add early parsing of APIC and IO APIC
x86/dtb: add support hpet
of: move of_irq_map_pci() into generic code
x86/dtb: add support for PCI devices backed by dtb nodes
x86/dtb: Add generic bus probe
x86/ioapic: Add OF bindings for IO-APIC
x86/ce4100: use OF for ioapic
of/address: use propper endianess in get_flags
x86/rtc: don't ...This patch ensures that the memory passed from parse_setup_data() is
large enough to cover the complete data structure. That means that the
conditional mapping in parse_e820_ext() can go.
While here, I also attempt not to map two pages if the address is not
aligned to a page boundary.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
---
arch/x86/include/asm/e820.h | 2 +-
arch/x86/kernel/e820.c | 8 +-------
arch/x86/kernel/setup.c | 20 +++++++++++++++++---
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 5be1542..e956492 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -93,7 +93,7 @@ extern void e820_setup_gap(void);
extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
unsigned long start_addr, unsigned long long end_addr);
struct setup_data;
-extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data);
+extern void parse_e820_ext(struct setup_data *data);
#if defined(CONFIG_X86_64) || \
(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 0c2b7ef..33f6361 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -666,21 +666,15 @@ __init void e820_setup_gap(void)
* boot_params.e820_map, others are passed via SETUP_E820_EXT node of
* linked list of struct setup_data, which is parsed here.
*/
-void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
+void __init parse_e820_ext(struct setup_data *sdata)
{
- u32 map_len;
int entries;
struct e820entry *extmap;
entries = sdata->len / sizeof(struct e820entry);
- map_len = sdata->len + sizeof(struct setup_data);
- if (map_len > PAGE_SIZE)
- sdata = early_ioremap(pa_data, map_len);
extmap = (struct e820entry *)(sdata->data);
__append_e820_map(extmap, ...I assume this patch is a prereq for the rest of the series. Should I merge it via the devicetree tree when I pick up the other patches? It looks okay to me. One comment below, but not one that would prevent picking up this patch. if you add + map_len = data_len; ...this can be simplified to: - early_iounmap(data, PAGE_SIZE); --
This patch ensures that the memory passed from parse_setup_data() is
large enough to cover the complete data structure. That means that the
conditional mapping in parse_e820_ext() can go.
While here, I also attempt not to map two pages if the address is not
aligned to a page boundary.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
---
arch/x86/include/asm/e820.h | 2 +-
arch/x86/kernel/e820.c | 8 +-------
arch/x86/kernel/setup.c | 18 +++++++++++++++---
3 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 5be1542..e956492 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -93,7 +93,7 @@ extern void e820_setup_gap(void);
extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
unsigned long start_addr, unsigned long long end_addr);
struct setup_data;
-extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data);
+extern void parse_e820_ext(struct setup_data *data);
#if defined(CONFIG_X86_64) || \
(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 0c2b7ef..33f6361 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -666,21 +666,15 @@ __init void e820_setup_gap(void)
* boot_params.e820_map, others are passed via SETUP_E820_EXT node of
* linked list of struct setup_data, which is parsed here.
*/
-void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
+void __init parse_e820_ext(struct setup_data *sdata)
{
- u32 map_len;
int entries;
struct e820entry *extmap;
entries = sdata->len / sizeof(struct e820entry);
- map_len = sdata->len + sizeof(struct setup_data);
- if (map_len > PAGE_SIZE)
- sdata = early_ioremap(pa_data, map_len);
extmap = (struct e820entry *)(sdata->data);
__append_e820_map(extmap, ...Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> --- arch/x86/platform/ce4100/falconfalls.dts | 212 ++++++++++++++++++++++++++++++ 1 files changed, 212 insertions(+), 0 deletions(-) create mode 100644 arch/x86/platform/ce4100/falconfalls.dts diff --git a/arch/x86/platform/ce4100/falconfalls.dts b/arch/x86/platform/ce4100/falconfalls.dts new file mode 100644 index 0000000..24e67ca --- /dev/null +++ b/arch/x86/platform/ce4100/falconfalls.dts @@ -0,0 +1,212 @@ +/* + * CE4100 on Falcon Falls + * + * (c) Copyright 2010 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2 of the License. + */ +/dts-v1/; +/ { + model = "Intel,FalconFalls"; + compatible = "Intel,FalconFalls"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "Intel,ce4100"; + reg = <0>; + lapic = <&lapic0>; + }; + }; + + soc@0 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + compatible = "Intel,ce4100"; + ranges; + + ioapic1: pic@fec00000 { + #interrupt-cells = <2>; + compatible = "Intel,ioapic"; + interrupt-controller; + device_type = "interrupt-controller"; + id = <1>; + reg = <0xfec00000 0x1000>; + }; + + hpet@fed00000 { + compatible = "Intel,hpet-ce4100", "Intel,hpet"; + reg = <0xfed00000 0x200>; + }; + + lapic0: lapic@fee00000 { + compatible = "Intel,lapic-ce4100", "Intel,lapic"; + reg = <0xfee00000 0x1000>; + }; + + pci@3fc { + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; + compatible = "Intel,ce4100-pci", "pci"; + device_type = "pci"; + bus-range = <0 0>; + ranges = <0x2000000 0 0xbffff000 ...
To-date the convention has been to use all lowercase in compatible I'd like to say ditto here, but it might require a change to the current kernel code. I believe ePAPR specified a compatible value If you put an interrupt-parent property in the root node, then it will become the default interrupt controller for the system which is All these i2c bus controllers should have a compatible value so that the OS knows what driver to bind to them. Also, the node names for the i2c devices should reflect what the device does, not what the part number is (grep ePAPR for 'generic --
The node i2c@15a00 is the PCI device. This PCI device has three bars, each bar is a complete i2c controller. All three controller share one IRQ. The device is probed via its pci-id and therefore I have no compatible value here. Do you want me to add compatible values based on "Vendor ID, Device ID, Subsystem Vendor ID, ..." as mention in the PCI-bindings? The child nodes here (i2c@0,...) represent the bars. I probably should replace i2c@0 with bar@0 and the reg property with a bar property. Would Okay. This probably also means that I should replace pic@ with interrupt-controller and so on. Sebastian --
If you have a node describing a device, then it *must* have a compatible value. Use the OF PCI binding to determine what the compatible value should be something like: compatible = "pciVVVV,DDDD,SSSS,ssss", "pciVVVV,DDDD" See page 9 on this pdf: http://www.openbios.org/data/docs/bus.pci.pdf The list of possible formats in the binding doc is long, but most of them probably don't apply in your case (but include the other entries if they do). Also, since the i2c@15a00 is *not* an actual i2c bus, it should not be named 'i2c@...'. Name it something like i2c-controller@15a00,0,0. You'll also note that I added ',0,0' to the end of the address. That's because the node address reflects the parent bus address format That depends. Are the child nodes separately memory mapped devices? Or are all three controlled by a shared register bank in the controller? If they are addressable (which they probably are) then you need to use a ranges property to describe the translation from the parent node to the child node. Since you say that the registers define describe the bars, it probably makes sense to use a 2 cell addressing scheme: one cell for the bar# and one cell for the offset off the bar base address (which will be 0 for each I expect). Something like this: i2c-controller@15a00 { compatible = "intel,<blah>", "pciVVVV,DDDD,SSSS,ssss", "pciVVVV,DDDD"; #address-cells = <2>; #size-cells = <1>; // not 0! 0 is used for // devices that cannot be // memory mapped. reg = <0x15a00 0x0 0x0 0x0>; // Here's where the magic happens. Each entry in // ranges describes how the parent pci address space // (middle group of 3) is translated to the local // address space (first group of 2) and the size of // each range (last cell). In this particular case, // the first cell of the local address is chosen to be // 1:1 mapped to the BARs, and the second is the // offset from be base of the BAR (which would be // non-zero if you had 2 or more ...
The here introduced irq_domain abstraction represents a generic irq controller. It is a subset of powerpc's irq_host which is going to be renamed to irq_domain and then become generic. This implementation will be removed once it is generic. The xlate callback is resposible to parse irq informations like irq type and number and returns the hardware irq number which is reported by the hardware as active. Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Tested-by: Dirk Brandewie <dirk.brandewie@gmail.com> --- arch/x86/include/asm/irq_controller.h | 12 ++++++++ arch/x86/include/asm/prom.h | 2 + arch/x86/kernel/prom.c | 47 ++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 1 deletions(-) create mode 100644 arch/x86/include/asm/irq_controller.h diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h new file mode 100644 index 0000000..423bbbd --- /dev/null +++ b/arch/x86/include/asm/irq_controller.h @@ -0,0 +1,12 @@ +#ifndef __IRQ_CONTROLLER__ +#define __IRQ_CONTROLLER__ + +struct irq_domain { + int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize, + u32 *out_hwirq, u32 *out_type); + void *priv; + struct device_node *controller; + struct list_head l; +}; + +#endif diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 2fbe3e8..9076ae4 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -19,9 +19,11 @@ #include <asm/irq.h> #include <asm/atomic.h> #include <asm/setup.h> +#include <asm/irq_controller.h> #ifdef CONFIG_OF extern void add_dtb(u64 data); +void add_interrupt_host(struct irq_domain *ih); #else static inline void add_dtb(u64 data) { } #endif diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c index 249ebd3..53948cb 100644 --- a/arch/x86/kernel/prom.c +++ b/arch/x86/kernel/prom.c @@ -3,18 +3,63 @@ */ #include ...
Set hpet_address based on information provied form DTB Cc: devicetree-discuss@lists.ozlabs.org Cc: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- arch/x86/kernel/prom.c | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c index 9cbb52b..40ad8c0 100644 --- a/arch/x86/kernel/prom.c +++ b/arch/x86/kernel/prom.c @@ -10,6 +10,7 @@ #include <linux/of_platform.h> #include <linux/slab.h> +#include <asm/hpet.h> #include <asm/irq_controller.h> #include <asm/io_apic.h> @@ -101,6 +102,23 @@ void __init add_dtb(u64 data) initial_dtb = data + offsetof(struct setup_data, data); } +static void __init dtb_setup_hpet(void) +{ + struct device_node *dn; + struct resource r; + int ret; + + dn = of_find_compatible_node(NULL, NULL, "intel,hpet"); + if (!dn) + return; + ret = of_address_to_resource(dn, 0, &r); + if (ret) { + WARN_ON(1); + return; + } + hpet_address = r.start; +} + static void __init dtb_lapic_setup(void) { #ifdef CONFIG_X86_LOCAL_APIC @@ -212,5 +230,6 @@ void __init x86_dtb_get_config(unsigned int unused) of_scan_flat_dt(early_init_dt_scan_root, NULL); unflatten_device_tree(); + dtb_setup_hpet(); dtb_apic_setup(); } -- 1.7.3.2 --
x86_of_pci_init() does two things: - it provides a generic irq enable and disable function. enable queries the device tree for the interrupt information, calls ->xlate on the irq host and updates the pci->irq information for the device. - it walks through PCI buss(es) in the device tree and adds its children (devices) nodes to appropriate pci_dev nodes in kernel. So the dtb node information is available at probe time of the PCI device. Adding a PCI bus based on the information in the device tree is currently not supported. Right now direct access via ioports is used. Cc: devicetree-discuss@lists.ozlabs.org Tested-by: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- arch/x86/include/asm/prom.h | 17 +++++++++ arch/x86/kernel/prom.c | 80 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 3bc8ed5..9f7484e 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -16,6 +16,7 @@ #include <linux/of.h> #include <linux/types.h> +#include <linux/pci.h> #include <asm/irq.h> #include <asm/atomic.h> #include <asm/setup.h> @@ -28,8 +29,24 @@ extern void add_dtb(u64 data); void x86_dtb_find_config(void); void x86_dtb_get_config(unsigned int unused); void add_interrupt_host(struct irq_domain *ih); +void __cpuinit x86_of_pci_init(void); + +static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) +{ + return pdev->dev.of_node; +} + +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) +{ + if (bus->self) + return pci_device_to_OF_node(bus->self); + else + return NULL; +} + #else static inline void add_dtb(u64 data) { } +static inline void x86_of_pci_init(void) { } #define x86_dtb_find_config x86_init_noop #define x86_dtb_get_config x86_init_uint_noop #define of_ioapic 0 diff --git ...
For now we probe these busses and we change is to board dependent probes once we have to. Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> --- arch/x86/kernel/prom.c | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c index a449dc6..6eddafd 100644 --- a/arch/x86/kernel/prom.c +++ b/arch/x86/kernel/prom.c @@ -105,6 +105,25 @@ void __init add_dtb(u64 data) initial_dtb = data + offsetof(struct setup_data, data); } +/* + * CE4100 ids. Will be moved to machine_device_initcall() once we have it. + */ +static struct of_device_id __initdata ce4100_ids[] = { + { .type = "soc", }, + { .compatible = "isa", }, + { .compatible = "pci", }, + {}, +}; + +static int __init add_bus_probe(void) +{ + if (!initial_boot_params) + return 0; + + return of_platform_bus_probe(NULL, ce4100_ids, NULL); +} +module_init(add_bus_probe); + static int x86_of_pci_irq_enable(struct pci_dev *dev) { struct of_irq oirq; -- 1.7.3.2 --
The apic & ioapic have to be added to system early because native_init_IRQ() requires it. In order to obtain the address of the ioapic the device tree has to be unflattened because of_address_to_resource() has to work. The device tree is relocated to ensure it is always covered by the kernel and the boot loader does not have to make assumptions about kernel's memory layout. Cc: devicetree-discuss@lists.ozlabs.org Cc: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- arch/x86/include/asm/prom.h | 7 +++ arch/x86/kernel/irqinit.c | 2 +- arch/x86/kernel/prom.c | 123 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 128 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 9076ae4..3bc8ed5 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -22,10 +22,17 @@ #include <asm/irq_controller.h> #ifdef CONFIG_OF +extern int of_ioapic; +extern u64 initial_dtb; extern void add_dtb(u64 data); +void x86_dtb_find_config(void); +void x86_dtb_get_config(unsigned int unused); void add_interrupt_host(struct irq_domain *ih); #else static inline void add_dtb(u64 data) { } +#define x86_dtb_find_config x86_init_noop +#define x86_dtb_get_config x86_init_uint_noop +#define of_ioapic 0 #endif extern char cmd_line[COMMAND_LINE_SIZE]; diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 149c87f..4cadf86 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -244,7 +244,7 @@ void __init native_init_IRQ(void) set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); } - if (!acpi_ioapic) + if (!acpi_ioapic && !of_ioapic) setup_irq(2, &irq2); #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c index 53948cb..9cbb52b 100644 --- a/arch/x86/kernel/prom.c +++ b/arch/x86/kernel/prom.c @@ -6,15 +6,20 @@ #include <linux/interrupt.h> ...
The apic & ioapic have to be added to system early because native_init_IRQ() requires it. In order to obtain the address of the ioapic the device tree has to be unflattened because of_address_to_resource() has to work. The device tree is relocated to ensure it is always covered by the kernel and the boot loader does not have to make assumptions about kernel's memory layout. Cc: devicetree-discuss@lists.ozlabs.org Cc: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- arch/x86/include/asm/prom.h | 7 +++ arch/x86/kernel/irqinit.c | 2 +- arch/x86/kernel/prom.c | 121 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 9076ae4..3bc8ed5 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -22,10 +22,17 @@ #include <asm/irq_controller.h> #ifdef CONFIG_OF +extern int of_ioapic; +extern u64 initial_dtb; extern void add_dtb(u64 data); +void x86_dtb_find_config(void); +void x86_dtb_get_config(unsigned int unused); void add_interrupt_host(struct irq_domain *ih); #else static inline void add_dtb(u64 data) { } +#define x86_dtb_find_config x86_init_noop +#define x86_dtb_get_config x86_init_uint_noop +#define of_ioapic 0 #endif extern char cmd_line[COMMAND_LINE_SIZE]; diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 149c87f..4cadf86 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -244,7 +244,7 @@ void __init native_init_IRQ(void) set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); } - if (!acpi_ioapic) + if (!acpi_ioapic && !of_ioapic) setup_irq(2, &irq2); #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c index 53948cb..388fdff 100644 --- a/arch/x86/kernel/prom.c +++ b/arch/x86/kernel/prom.c @@ -6,15 +6,20 @@ #include <linux/interrupt.h> ...
or we end up with two of those things.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/x86/kernel/rtc.c | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 1cfbbfc..382c6cb 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bcd.h>
#include <linux/pnp.h>
+#include <linux/of.h>
#include <asm/vsyscall.h>
#include <asm/x86_init.h>
@@ -218,6 +219,25 @@ static struct platform_device rtc_device = {
.num_resources = ARRAY_SIZE(rtc_resources),
};
+#ifdef CONFIG_OF
+static __init int have_rtc_of_node(void)
+{
+ struct device_node *n;
+
+ n = of_find_compatible_node(NULL, NULL, "motorola,mc146818");
+ if (n) {
+ of_node_put(n);
+ return 1;
+ }
+ return 0;
+}
+#else
+static inline int have_rtc_of_node(void)
+{
+ return 0;
+}
+#endif
+
static __init int add_rtc_cmos(void)
{
#ifdef CONFIG_PNP
@@ -237,6 +257,9 @@ static __init int add_rtc_cmos(void)
}
#endif
+ if (have_rtc_of_node())
+ return 0;
+
platform_device_register(&rtc_device);
dev_info(&rtc_device.dev,
"registered platform RTC device (no PNP device found)\n");
--
1.7.3.2
--
More generically, rather than searching for an rtc node, I imagine simply the presence of a device tree blob means that the rtc registration should be suppressed. --
or we might end up with two device nodes for the same hardware.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/x86/kernel/rtc.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 1cfbbfc..0cfa138 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bcd.h>
#include <linux/pnp.h>
+#include <linux/of.h>
#include <asm/vsyscall.h>
#include <asm/x86_init.h>
@@ -218,6 +219,20 @@ static struct platform_device rtc_device = {
.num_resources = ARRAY_SIZE(rtc_resources),
};
+#ifdef CONFIG_OF
+static __init int have_DTB(void)
+{
+ if (initial_boot_params)
+ return 1;
+ return 0;
+}
+#else
+static inline int have_DTB(void)
+{
+ return 0;
+}
+#endif
+
static __init int add_rtc_cmos(void)
{
#ifdef CONFIG_PNP
@@ -237,6 +252,9 @@ static __init int add_rtc_cmos(void)
}
#endif
+ if (have_DTB())
+ return 0;
+
platform_device_register(&rtc_device);
dev_info(&rtc_device.dev,
"registered platform RTC device (no PNP device found)\n");
--
1.7.3.2
--
|arch/x86/pci/ce4100.c: In function `ce4100_conf_read':
|arch/x86/pci/ce4100.c:257:9: warning: unused variable `retval'
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/x86/pci/ce4100.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index 85b68ef..c63c6d3 100644
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -254,7 +254,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
static int ce4100_conf_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
- int i, retval = 1;
+ int i;
if (bus == 1) {
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
--
1.7.3.2
--
This allows to load the OF driver based informations from the device tree. Systems without BIOS may need to perform some initialization. PowerPC creates a PNP device from the OF information and performs this kind of initialization in their private PCI quirk. This looks more generic. Cc: rtc-linux@googlegroups.com Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> --- Documentation/powerpc/dts-bindings/rtc-cmos.txt | 28 ++++++++++++++++ drivers/rtc/rtc-cmos.c | 40 +++++++++++++++++++++++ 2 files changed, 68 insertions(+), 0 deletions(-) create mode 100644 Documentation/powerpc/dts-bindings/rtc-cmos.txt diff --git a/Documentation/powerpc/dts-bindings/rtc-cmos.txt b/Documentation/powerpc/dts-bindings/rtc-cmos.txt new file mode 100644 index 0000000..7382989 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/rtc-cmos.txt @@ -0,0 +1,28 @@ + Motorola mc146818 compatible RTC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Required properties: + - compatible : "motorola,mc146818" + - reg : should contain registers location and length. + +Optional properties: + - interrupts : should contain interrupt. + - interrupt-parent : interrupt source phandle. + - ctrl-reg : Contains the initial value of the control register also + called "Register B". + - freq-reg : Contains the initial value of the frequency register also + called "Regsiter A". + +"Register A" and "B" are usually initialized by the firmware (BIOS for +instance). If this is not done, it can be performed by the driver. + +ISA Example: + + rtc@70 { + compatible = "motorola,mc146818"; + interrupts = <8 3>; + interrupt-parent = <&ioapic1>; + ctrl-reg = <2>; + freq-reg = <0x26>; + reg = <1 0x70 2>; + }; diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index ...
ioapic_xlate provides a translation from the information in device tree to ioapic related informations. This includes - obtaining hw irq which is the vector number "=> pin number + gsi" - obtaining type (level/edge/..) - programming this information into ioapic ioapic_add_ofnode adds an irq_domain based on informations from the device tree. This information (irq_domain) is required in order to map a device to its proper interrupt controller. Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> --- arch/x86/include/asm/io_apic.h | 7 +++ arch/x86/include/asm/prom.h | 2 + arch/x86/kernel/apic/io_apic.c | 99 ++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/irqinit.c | 6 ++ arch/x86/kernel/prom.c | 15 ++++++ 5 files changed, 129 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index f327d38..5a8b950 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -177,6 +177,13 @@ struct mp_ioapic_gsi{ u32 gsi_base; u32 gsi_end; }; +#ifdef CONFIG_X86_OF +struct mp_of_ioapic { + struct device_node *node; +}; +extern struct mp_of_ioapic mp_of_ioapic[MAX_IO_APICS]; +void __init ioapic_add_ofnode(struct device_node *np); +#endif extern struct mp_ioapic_gsi mp_gsi_routing[]; extern u32 gsi_top; int mp_find_ioapic(u32 gsi); diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 9f7484e..8386685 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -26,6 +26,7 @@ extern int of_ioapic; extern u64 initial_dtb; extern void add_dtb(u64 data); +extern void x86_add_irq_domains(void); void x86_dtb_find_config(void); void x86_dtb_get_config(unsigned int unused); void add_interrupt_host(struct irq_domain *ih); @@ -46,6 +47,7 @@ static inline struct device_node *pci_bus_to_OF_node(struct ...
This patch changes u32 to __be32 for all "ranges", "prop" and "addr" and such. Those variables are pointing to the device tree which containts intergers in big endian format. Most functions are doing it right because they are using using of_read_number() which is doing the right thing. of_bus_isa_get_flags(), of_bus_pci_get_flags() and of_bus_isa_map() were accessing the data directly and were doing it wrong. Cc: devicetree-discuss@lists.ozlabs.org Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- arch/powerpc/include/asm/prom.h | 2 +- drivers/of/address.c | 54 ++++++++++++++++++++------------------ include/linux/of_address.h | 6 ++-- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index 01c3302..b891fdc 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h @@ -42,7 +42,7 @@ extern void pci_create_OF_bus_map(void); /* Translate a DMA address from device space to CPU space */ extern u64 of_translate_dma_address(struct device_node *dev, - const u32 *in_addr); + const __be32 *in_addr); #ifdef CONFIG_PCI extern unsigned long pci_address_to_pio(phys_addr_t address); diff --git a/drivers/of/address.c b/drivers/of/address.c index 3a1c7e7..b4559c5 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -12,13 +12,13 @@ (ns) > 0) static struct of_bus *of_match_bus(struct device_node *np); -static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, - u64 size, unsigned int flags, +static int __of_address_to_resource(struct device_node *dev, + const __be32 *addrp, u64 size, unsigned int flags, struct resource *r); /* Debug utility */ #ifdef DEBUG -static void of_dump_addr(const char *s, const u32 *addr, int na) +static void of_dump_addr(const char *s, const __be32 *addr, int na) ...
This one is already applied to my next-devicetree branch --
and hpet and a few others things....
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/x86/platform/ce4100/ce4100.c | 24 +++++++++++++++++-------
1 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index d2c0d51..7877453 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -15,21 +15,19 @@
#include <linux/serial_reg.h>
#include <linux/serial_8250.h>
+#include <asm/prom.h>
#include <asm/setup.h>
+#include <asm/i8259.h>
#include <asm/io.h>
+#include <asm/io_apic.h>
static int ce4100_i8042_detect(void)
{
return 0;
}
-static void __init sdv_find_smp_config(void)
-{
-}
-
#ifdef CONFIG_SERIAL_8250
-
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@@ -118,6 +116,13 @@ static void __init sdv_arch_setup(void)
sdv_serial_fixup();
}
+static void __cpuinit sdv_pci_init(void)
+{
+ x86_of_pci_init();
+ /* We can't set this earlier, because we need calibrate the timer */
+ legacy_pic = &null_legacy_pic;
+}
+
/*
* CE4100 specific x86_init function overrides and early setup
* calls.
@@ -127,6 +132,11 @@ void __init x86_ce4100_early_setup(void)
x86_init.oem.arch_setup = sdv_arch_setup;
x86_platform.i8042_detect = ce4100_i8042_detect;
x86_init.resources.probe_roms = x86_init_noop;
- x86_init.mpparse.get_smp_config = x86_init_uint_noop;
- x86_init.mpparse.find_smp_config = sdv_find_smp_config;
+ x86_init.mpparse.get_smp_config = x86_dtb_get_config;
+ x86_init.mpparse.find_smp_config = x86_dtb_find_config;
+
+#ifdef CONFIG_X86_IO_APIC
+ x86_init.pci.init_irq = sdv_pci_init;
+ x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
+#endif
}
--
1.7.3.2
--
This patch adds minimal support for device tree support on x86. It will be passed to the kernel via setup_data which requires atleast boot protocol 2.09. Memory size, restricted memory regions, boot arguments are gathered the traditional way so things like cmd_line are just here to let the code compile. The current plan is use the device tree as an extension and to gather informations from it which can not be enumerated and have to be hardcoded otherwise. This includes things like - which devices are on this I2C/ SPI bus? - how are the interrupts wired to IO APIC? - where could my hpet be? Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> --- Documentation/x86/boot_with_dtb.txt | 26 +++++++++++++++ arch/x86/Kconfig | 7 ++++ arch/x86/include/asm/bootparam.h | 1 + arch/x86/include/asm/prom.h | 59 +++++++++++++++++++++++++++++++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/irqinit.c | 1 + arch/x86/kernel/prom.c | 54 ++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 4 ++ 8 files changed, 153 insertions(+), 0 deletions(-) create mode 100644 Documentation/x86/boot_with_dtb.txt create mode 100644 arch/x86/include/asm/prom.h create mode 100644 arch/x86/kernel/prom.c diff --git a/Documentation/x86/boot_with_dtb.txt b/Documentation/x86/boot_with_dtb.txt new file mode 100644 index 0000000..6a357aa --- /dev/null +++ b/Documentation/x86/boot_with_dtb.txt @@ -0,0 +1,26 @@ + Booting x86 with device tree +================================= + +1. Introduction +~~~~~~~~~~~~~~~ +This document contains device tree information which are specific to +the x86 platform. Generic informations as bindings can be found in +Documentation/powerpc/dts-bindings/ + +2. Passing the device tree +~~~~~~~~~~~~~~~~~~~~~~~~~~ +The pointer to the device tree block ...
Mostly looks good. Some comments below. 0 means NO_IRQ on x86 and most architectures. I will change this when Why is the physical address being passed in when the virtual address --
Hi Peter, Since this series is based on the tip tree, these should be merged via the same route. Aside from the comments below, I'm okay with patches 1 & 2 going in for 2.6.38 (assuming NO_IRQ is fixed). I've picked up patch 12 since it is a generic fix. I haven't made a decision on the remaining 14 yet. g. -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. --
OK... I'll see if I can get it into -tip early next week. I don't know how much time there is left before the .38 merge window opens, but I don't think there is too much. (tglx: if you want to put it instead of me, go for it and feel free to add my Ack.) -hpa --
cat /proc/interrupts
CPU0
add_dtb() changes it via phys_to_virt() so it is stored as virtual. I
can't touch this memory that early in the boot process so it is passed as
phys. phys_to_virt() isn't working (yet) so you need a fixmap or an
early_ioremap(). Earlier I used the device tree very late so the
phys_to_virt() memory was working.
Later in the series add_dtb() stores it in a custom u64 variable because I
might have to use the built-in dtb, I have to relocate the dtb (so the
boot loader does not have to care about kernel's memory layout) and I have
to use it "early" so I create a fixmap for it.
The dtb is not usable before the ->get_config() hook (x86_dtb_get_config,
Sebastian
--
0 for the timer is special. However, Linus has declared that NO_IRQ is to be zero, and that only very special interrupts like the PIT timer are allowed to break that. -hpa --
From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> There is a tiny difference between PPC32 and PPC64. Microblaze uses the PPC32 variant. Cc: devicetree-discuss@lists.ozlabs.org Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> --- arch/microblaze/include/asm/prom.h | 15 ----- arch/microblaze/kernel/prom_parse.c | 77 --------------------------- arch/microblaze/pci/pci-common.c | 1 + arch/powerpc/include/asm/prom.h | 15 ----- arch/powerpc/kernel/pci-common.c | 1 + arch/powerpc/kernel/prom_parse.c | 84 ------------------------------ drivers/of/Makefile | 1 + drivers/of/of_pci.c | 97 +++++++++++++++++++++++++++++++++++ include/linux/of_pci.h | 24 +++++++++ 9 files changed, 124 insertions(+), 191 deletions(-) create mode 100644 drivers/of/of_pci.c create mode 100644 include/linux/of_pci.h diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h index bdc3831..aa3ab12 100644 --- a/arch/microblaze/include/asm/prom.h +++ b/arch/microblaze/include/asm/prom.h @@ -67,21 +67,6 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); /* Get the MAC address */ extern const void *of_get_mac_address(struct device_node *np); -/** - * of_irq_map_pci - Resolve the interrupt for a PCI device - * @pdev: the device whose interrupt is to be resolved - * @out_irq: structure of_irq filled by this function - * - * This function resolves the PCI interrupt for a given PCI device. If a - * device-node exists for a given pci_dev, it will use normal OF tree - * walking. If not, it will implement standard swizzling and walk up the - * PCI tree until an device-node is found, at which point it will finish - * resolving using the OF tree walking. - */ -struct pci_dev; -struct of_irq; -extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); - #endif /* __ASSEMBLY__ ...
I'd like it better if instead you added pci_bus_to_OF_node() to ppc32 and microblaze. The easy way to do so is to do: struct pci_controller *host; if (bus->self) return pci_device_to_OF_node(bus->self); host = pci_bus_to_host(pdev->bus); return host ? host->dn : NULL; Cheers, Ben. --
From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> There is a tiny difference between PPC32 and PPC64. Microblaze uses the PPC32 variant. Cc: devicetree-discuss@lists.ozlabs.org Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> --- arch/microblaze/include/asm/pci-bridge.h | 10 ++++ arch/microblaze/include/asm/prom.h | 15 ----- arch/microblaze/kernel/prom_parse.c | 77 --------------------------- arch/microblaze/pci/pci-common.c | 1 + arch/powerpc/include/asm/pci-bridge.h | 10 ++++ arch/powerpc/include/asm/prom.h | 15 ----- arch/powerpc/kernel/pci-common.c | 1 + arch/powerpc/kernel/prom_parse.c | 84 ------------------------------ drivers/of/Makefile | 1 + drivers/of/of_pci.c | 80 ++++++++++++++++++++++++++++ include/linux/of_pci.h | 20 +++++++ 11 files changed, 123 insertions(+), 191 deletions(-) create mode 100644 drivers/of/of_pci.c create mode 100644 include/linux/of_pci.h diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h index 0c68764..0808217 100644 --- a/arch/microblaze/include/asm/pci-bridge.h +++ b/arch/microblaze/include/asm/pci-bridge.h @@ -109,6 +109,16 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) return bus->sysdata; } +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) +{ + struct pci_controller *host; + + if (bus->self) + return pci_device_to_OF_node(bus->self); + host = pci_bus_to_host(bus); + return host ? host->dn : NULL; +} + static inline int isa_vaddr_is_ioport(void __iomem *address) { /* No specific ISA handling on ppc32 at this stage, it diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h index bdc3831..aa3ab12 100644 --- a/arch/microblaze/include/asm/prom.h +++ ...
