* [PATCH 02/15] x86: Add device tree support
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
2010-12-30 8:43 ` Grant Likely
2010-12-17 15:33 ` [PATCH 03/15] x86/dtb: Add a device tree for CE4100 Sebastian Andrzej Siewior
` (9 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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 (dtb) is passed via setup_data
+(see [0]) which requires at least boot protocol 2.09. The type filed is
+defined as
+
+#define SETUP_DTB 2
+
+3. Purpose
+~~~~~~~~~~~
+The device tree is used as an extension to the "boot page". As such it does not
+parse / consider data which are already covered by the boot page. This includes
+memory size, command line arguments or initrd address.
+It simply holds information which can not be retrieved otherwise like interrupt
+routing or a list of devices behind an I2C bus.
+
+[0] Documentation/x86/boot.txt
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b6fccb0..0522354 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -299,6 +299,13 @@ config X86_BIGSMP
---help---
This option is needed for the systems that have more than 8 CPUs
+config X86_OF
+ bool "Support for device tree"
+ select OF
+ select OF_FLATTREE
+ ---help---
+ Device tree support on X86.
+
if X86_32
config X86_EXTENDED_PLATFORM
bool "Support for extended (non-PC) x86 platforms"
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index c8bfe63..e020d88 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -12,6 +12,7 @@
/* setup data types */
#define SETUP_NONE 0
#define SETUP_E820_EXT 1
+#define SETUP_DTB 2
/* extensible setup data list node */
struct setup_data {
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
new file mode 100644
index 0000000..2fbe3e8
--- /dev/null
+++ b/arch/x86/include/asm/prom.h
@@ -0,0 +1,59 @@
+/*
+ * Definitions for Device tree / OpenFirmware handling on X86
+ *
+ * based on arch/powerpc/include/asm/prom.h which is
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_X86_PROM_H
+#define _ASM_X86_PROM_H
+#ifndef __ASSEMBLY__
+
+#include <linux/of.h>
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_OF
+extern void add_dtb(u64 data);
+#else
+static inline void add_dtb(u64 data) { }
+#endif
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+/* This number is used when no interrupt has been assigned */
+#define NO_IRQ (-1)
+
+#define pci_address_to_pio pci_address_to_pio
+unsigned long pci_address_to_pio(phys_addr_t addr);
+
+/**
+ * irq_dispose_mapping - Unmap an interrupt
+ * @virq: linux virq number of the interrupt to unmap
+ *
+ * FIXME: We really should implement proper virq handling like power,
+ * but that's going to be major surgery.
+ */
+static inline void irq_dispose_mapping(unsigned int virq) { }
+
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * These includes are put at the bottom because they may contain things
+ * that are overridden by this file. Ideally they shouldn't be included
+ * by this file, but there are a bunch of .c files that currently depend
+ * on it. Eventually they will be cleaned up.
+ */
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index f60153d..40bc33d 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
+obj-$(CONFIG_X86_OF) += prom.o
###
# 64 bit specific files
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index c752e97..149c87f 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -25,6 +25,7 @@
#include <asm/setup.h>
#include <asm/i8259.h>
#include <asm/traps.h>
+#include <asm/prom.h>
/*
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
new file mode 100644
index 0000000..249ebd3
--- /dev/null
+++ b/arch/x86/kernel/prom.c
@@ -0,0 +1,54 @@
+/*
+ * Architecture specific OF callbacks.
+ */
+#include <linux/bootmem.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+
+char __initdata cmd_line[COMMAND_LINE_SIZE];
+
+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);
+
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+ /*
+ * The ioport address can be directly used by inX / outX
+ */
+ BUG_ON(address >= (1 << 16));
+ return (unsigned long)address;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
+void __init early_init_dt_scan_chosen_arch(unsigned long node)
+{
+ BUG();
+}
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+ BUG();
+}
+
+u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+ void *mem;
+
+ mem = __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
+ return virt_to_phys(mem);
+}
+
+void __init add_dtb(u64 data)
+{
+ initial_boot_params = (struct boot_param_header *)
+ phys_to_virt((u64) (u32) data +
+ offsetof(struct setup_data, data));
+}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 577d06b..26f2c9a 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -113,6 +113,7 @@
#endif
#include <asm/mce.h>
#include <asm/alternative.h>
+#include <asm/prom.h>
/*
* end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -445,6 +446,9 @@ static void __init parse_setup_data(void)
case SETUP_E820_EXT:
parse_e820_ext(data);
break;
+ case SETUP_DTB:
+ add_dtb(pa_data);
+ break;
default:
break;
}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 03/15] x86/dtb: Add a device tree for CE4100
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 02/15] x86: Add device tree support Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-4-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 04/15] x86/dtb: add irq domain abstraction Sebastian Andrzej Siewior
` (8 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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 0xbffff000 0 0x1000
+ 0x0000000 0 0x0 0x0 0 0x100>;
+
+ isa@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "isa";
+ ranges = <1 0 0 0 0 0x100>;
+
+ rtc@70 {
+ compatible = "motorola,mc146818";
+ interrupts = <8 3>;
+ interrupt-parent = <&ioapic1>;
+ ctrl-reg = <2>;
+ freq-reg = <0x26>;
+ reg = <1 0x70 2>;
+ };
+ };
+
+ /* Secondary IO-APIC */
+ ioapic2: pic@bffff000 {
+ #interrupt-cells = <2>;
+ compatible = "Intel,ioapic-ce4100", "Intel,ioapic";
+ interrupt-controller;
+ device_type = "interrupt-controller";
+ id = <2>;
+ reg = <0x100 0x0 0x0 0x0 0x0>;
+ assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+ };
+
+ pci@av {
+ #address-cells = <3>;
+ #interrupt-cells = <1>;
+ #size-cells = <1>;
+ compatible = "Intel,ce4100-pci";
+ device_type = "pci";
+ bus-range = <1 1>;
+ interrupt-map-mask = <0xffffff 0x0 0x0 0x0>;
+ interrupt-map = <
+ /* GFX: 0x2E5B */
+ 0x11000 0x0 0x0 0x0 &ioapic2 0 0x1
+ /* ***** FIXME ****** Compositing Engine: 0x2E72 */
+ /* 0x11100 0x0 0x0 0x1 &ioapic2 0 0x1 */
+ /* MFD: 0x2E5C */
+ 0x11800 0x0 0x0 0x0 &ioapic2 2 0x1
+ /* TS Prefilter: 0x2E5D */
+ 0x12000 0x0 0x0 0x0 &ioapic2 4 0x1
+ /* TS Demux: 0x2E5E */
+ 0x12100 0x0 0x0 0x0 &ioapic2 5 0x1
+ /* ***** FIXME ***** Audio DSP: 0x2E5F */
+ /* 0x13000 0x0 0x0 0x1 &ioapic2 0 0x1 */
+ /* Audio Interfaces: 0x2E60 */
+ 0x13200 0x0 0x0 0x0 &ioapic2 8 0x1
+ /* VDC: 0x2E61 */
+ 0x14000 0x0 0x0 0x0 &ioapic2 9 0x1
+ /* DPE: 0x2E62 */
+ 0x14100 0x0 0x0 0x0 &ioapic2 10 0x1
+ /* HDMI Tx: 0x2E63 */
+ 0x14200 0x0 0x0 0x0 &ioapic2 11 0x1
+ /* SEC: 0x2E64 */
+ 0x14800 0x0 0x0 0x0 &ioapic2 12 0x1
+ /* EXP: 0x2E65 */
+ 0x15000 0x0 0x0 0x0 &ioapic2 13 0x1
+ /* UART0/1: 0x2E66 */
+ 0x15800 0x0 0x0 0x0 &ioapic2 14 0x1
+ /* GPIO: 0x2E67 */
+ 0x15900 0x0 0x0 0x0 &ioapic2 15 0x1
+ /* I2C0/1/2: 0x2E68 */
+ 0x15a00 0x0 0x0 0x0 &ioapic2 16 0x1
+ /* Smart Card 0/1: 0x2E69 */
+ 0x15b00 0x0 0x0 0x0 &ioapic2 15 0x1
+ /* SPI: 0x2E6A */
+ 0x15c00 0x0 0x0 0x0 &ioapic2 15 0x1
+ /* MSPOD: 0x2E6B */
+ 0x15d00 0x0 0x0 0x0 &ioapic2 19 0x1
+ /* IR: 0x2E6C */
+ 0x15e00 0x0 0x0 0x0 &ioapic2 16 0x1
+ /* **** FIXME ***** DFX: 0x2E6D */
+ /* 0x15f00 0x0 0x0 0x1 &ioapic2 0x0 0x1 */
+ /* Gig Ethernet: 0x2E6E */
+ 0x16000 0x0 0x0 0x0 &ioapic2 21 0x1
+ /* IEEE1588 and Clock Recovery Unit: 0x2E6F */
+ 0x16100 0x0 0x0 0x0 &ioapic2 3 0x1
+ /* USB0: 0x2E70 */
+ 0x16800 0x0 0x0 0x0 &ioapic2 22 0x3
+ /* USB1: 0x2E70 */
+ 0x16900 0x0 0x0 0x0 &ioapic2 22 0x3
+ /* SATA: 0x2E71 */
+ 0x17000 0x0 0x0 0x0 &ioapic2 23 0x3
+ >;
+
+ i2c@15a00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x15a00 0x0 0x0 0x0>;
+
+
+ i2c@0 {
+ reg = <0>;
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ pcf8575@26 {
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ pcf8575@26 {
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ };
+ };
+ };
+
+ spi@15c00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x15c00 0x0 0x0 0x0>;
+
+ pcm1755@0 {
+ compatible = "ti,pcm1755";
+ reg = <0>;
+ spi-max-frequency = <115200>;
+ };
+
+ pcm1609a@1 {
+ compatible = "ti,pcm1609a";
+ reg = <1>;
+ spi-max-frequency = <115200>;
+ };
+
+ at93c46@2 {
+ compatible = "atmel,at93c46";
+ reg = <2>;
+ spi-max-frequency = <115200>;
+ };
+ };
+ };
+ };
+ };
+};
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 04/15] x86/dtb: add irq domain abstraction
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 02/15] x86: Add device tree support Sebastian Andrzej Siewior
2010-12-17 15:33 ` [PATCH 03/15] x86/dtb: Add a device tree for CE4100 Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
2011-01-11 22:03 ` Grant Likely
2010-12-17 15:33 ` [PATCH 05/15] x86/dtb: add early parsing of APIC and IO APIC Sebastian Andrzej Siewior
` (7 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Tested-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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 <linux/bootmem.h>
#include <linux/io.h>
+#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
+#include <asm/irq_controller.h>
+
char __initdata cmd_line[COMMAND_LINE_SIZE];
+static LIST_HEAD(irq_domains);
+static DEFINE_RAW_SPINLOCK(big_irq_lock);
+
+void add_interrupt_host(struct irq_domain *ih)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&big_irq_lock, flags);
+ list_add(&ih->l, &irq_domains);
+ raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+}
+
+static struct irq_domain *get_ih_from_node(struct device_node *controller)
+{
+ struct irq_domain *ih, *found = NULL;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&big_irq_lock, flags);
+ list_for_each_entry(ih, &irq_domains, l) {
+ if (ih->controller == controller) {
+ found = ih;
+ break;
+ }
+ }
+ raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+ return found;
+}
unsigned int irq_create_of_mapping(struct device_node *controller,
const u32 *intspec, unsigned int intsize)
{
- return intspec[0];
+ struct irq_domain *ih;
+ u32 virq;
+ u32 type;
+ int ret;
+ ih = get_ih_from_node(controller);
+ if (!ih)
+ return -ENODEV;
+ ret = ih->xlate(ih, intspec, intsize, &virq, &type);
+ if (ret)
+ return ret;
+ if (type == IRQ_TYPE_NONE)
+ return virq;
+ /* set the mask if it is different from current */
+ if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
+ set_irq_type(virq, type);
+ return virq;
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 05/15] x86/dtb: add early parsing of APIC and IO APIC
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (2 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 04/15] x86/dtb: add irq domain abstraction Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-6-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 06/15] x86/dtb: add support hpet Sebastian Andrzej Siewior
` (6 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
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>
#include <linux/list.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <asm/irq_controller.h>
+#include <asm/io_apic.h>
+__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
static LIST_HEAD(irq_domains);
static DEFINE_RAW_SPINLOCK(big_irq_lock);
+int __initdata of_ioapic;
+
void add_interrupt_host(struct irq_domain *ih)
{
unsigned long flags;
@@ -93,7 +98,119 @@ u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
void __init add_dtb(u64 data)
{
- initial_boot_params = (struct boot_param_header *)
- phys_to_virt((u64) (u32) data +
- offsetof(struct setup_data, data));
+ initial_dtb = data + offsetof(struct setup_data, data);
+}
+
+static void __init dtb_lapic_setup(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ if (apic_force_enable())
+ return;
+
+ smp_found_config = 1;
+ pic_mode = 1;
+ /* Required for ioapic registration */
+ set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+ if (boot_cpu_physical_apicid == -1U)
+ boot_cpu_physical_apicid = read_apic_id();
+
+ generic_processor_info(boot_cpu_physical_apicid,
+ GET_APIC_VERSION(apic_read(APIC_LVR)));
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+static void __init dtb_add_ioapic(struct device_node *dn)
+{
+ unsigned int ioapic_id;
+ const __be32 *cell;
+ int len;
+ struct resource r;
+ int ret;
+
+ cell = of_get_property(dn, "id", &len);
+ if (!cell) {
+ printk(KERN_ERR "Node %s is missing id property.\n",
+ dn->full_name);
+ return;
+ }
+ ioapic_id = of_read_ulong(cell, len / 4);
+
+ ret = of_address_to_resource(dn, 0, &r);
+ if (ret) {
+ printk(KERN_ERR "Can't obtain address from node %s.\n",
+ dn->full_name);
+ return;
+ }
+ mp_register_ioapic(ioapic_id, r.start, gsi_top);
+}
+
+static void __init dtb_ioapic_setup(void)
+{
+ struct device_node *dn;
+
+ if (!smp_found_config)
+ return;
+
+ for_each_compatible_node(dn, NULL, "intel,ioapic")
+ dtb_add_ioapic(dn);
+
+ if (nr_ioapics) {
+ of_ioapic = 1;
+ return;
+ }
+ printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+ smp_found_config = 0;
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
+
+static void __init dtb_apic_setup(void)
+{
+ dtb_lapic_setup();
+ dtb_ioapic_setup();
+}
+
+void __init x86_dtb_find_config(void)
+{
+ if (initial_dtb)
+ smp_found_config = 1;
+ else
+ printk(KERN_ERR "Missing device tree!.\n");
+}
+
+void __init x86_dtb_get_config(unsigned int unused)
+{
+ u32 size;
+ u32 map_len;
+ void *new_dtb;
+
+ if (!initial_dtb)
+ return;
+
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
+ (u64)sizeof(struct boot_param_header));
+
+ initial_boot_params = early_memremap(initial_dtb, map_len);
+ size = be32_to_cpu(initial_boot_params->totalsize);
+ if (map_len < size) {
+ early_iounmap(initial_boot_params, map_len);
+ initial_boot_params = early_memremap(initial_dtb, size);
+ }
+
+ new_dtb = alloc_bootmem(size);
+ memcpy(new_dtb, initial_boot_params, size);
+ if (map_len < size)
+ early_iounmap(initial_boot_params, size);
+ else
+ early_iounmap(initial_boot_params, map_len);
+
+ initial_boot_params = new_dtb;
+
+ /* root level address cells */
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+ unflatten_device_tree();
+ dtb_apic_setup();
}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 06/15] x86/dtb: add support hpet
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (3 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 05/15] x86/dtb: add early parsing of APIC and IO APIC Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-7-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 07/15] of: move of_irq_map_pci() into generic code Sebastian Andrzej Siewior
` (5 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Set hpet_address based on information provied form DTB
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
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
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 07/15] of: move of_irq_map_pci() into generic code
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (4 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 06/15] x86/dtb: add support hpet Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
2010-12-17 21:16 ` Benjamin Herrenschmidt
2010-12-17 15:33 ` [PATCH 08/15] x86/dtb: add support for PCI devices backed by dtb nodes Sebastian Andrzej Siewior
` (4 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, sodaville-hfZtesqFncYOwBW4kG4KsQ,
Sebastian Andrzej Siewior
From: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
There is a tiny difference between PPC32 and PPC64. Microblaze uses the
PPC32 variant.
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
---
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__ */
#endif /* __KERNEL__ */
diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
index 99d9b61..306f41d 100644
--- a/arch/microblaze/kernel/prom_parse.c
+++ b/arch/microblaze/kernel/prom_parse.c
@@ -2,88 +2,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- u32 laddr[3];
- u8 pin;
- int rc;
-
- /* Check if we have a device node, if yes, fallback to standard OF
- * parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn)
- return of_irq_map_one(dn, 0, out_irq);
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
- struct pci_controller *host;
- host = pci_bus_to_host(pdev->bus);
- ppnode = host ? host->dn : NULL;
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't
- * include the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
-
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
- */
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
- }
-
- laddr[0] = (pdev->bus->number << 16)
- | (pdev->devfn << 8);
- laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index e363615..1e01a12 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <asm/processor.h>
#include <asm/io.h>
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index ae26f2e..01c3302 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -73,21 +73,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
#endif
#define of_node_to_nid of_node_to_nid
-/**
- * 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);
-
extern void of_instantiate_rtc(void);
/* These includes are put at the bottom because they may contain things
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 10a44e6..eb341be 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/syscalls.h>
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 88334af..306f41d 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -2,95 +2,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- u32 laddr[3];
- u8 pin;
- int rc;
-
- /* Check if we have a device node, if yes, fallback to standard OF
- * parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn) {
- rc = of_irq_map_one(dn, 0, out_irq);
- if (!rc)
- return rc;
- }
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
- ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
- struct pci_controller *host;
- host = pci_bus_to_host(pdev->bus);
- ppnode = host ? host->dn : NULL;
-#endif
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't include
- * the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
-
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
- */
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
- }
-
- laddr[0] = (pdev->bus->number << 16)
- | (pdev->devfn << 8);
- laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 7888155..4dcb177 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_SPI) += of_spi.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
+obj-$(CONFIG_PCI) += of_pci.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 0000000..5450d16
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,97 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <asm/prom.h>
+
+#if defined(CONFIG_PPC64) || defined(CONFIG_X86)
+static struct device_node *pci_get_parent_node(struct pci_dev *pdev)
+{
+ return pci_bus_to_OF_node(pdev->bus);
+}
+#endif
+
+#if defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)
+static struct device_node *pci_get_parent_node(struct pci_dev *pdev)
+{
+ struct pci_controller *host;
+
+ host = pci_bus_to_host(pdev->bus);
+ return host ? host->dn : NULL;
+}
+#endif
+
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+ struct device_node *dn, *ppnode;
+ struct pci_dev *ppdev;
+ u32 lspec;
+ __be32 lspec_be;
+ __be32 laddr[3];
+ u8 pin;
+ int rc;
+
+ /* Check if we have a device node, if yes, fallback to standard OF
+ * parsing
+ */
+ dn = pci_device_to_OF_node(pdev);
+ if (dn) {
+ rc = of_irq_map_one(dn, 0, out_irq);
+ if (!rc)
+ return rc;
+ }
+
+ /* Ok, we don't, time to have fun. Let's start by building up an
+ * interrupt spec. we assume #interrupt-cells is 1, which is standard
+ * for PCI. If you do different, then don't use that routine.
+ */
+ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+ if (rc != 0)
+ return rc;
+ /* No pin, exit */
+ if (pin == 0)
+ return -ENODEV;
+
+ /* Now we walk up the PCI tree */
+ lspec = pin;
+ for (;;) {
+ /* Get the pci_dev of our parent */
+ ppdev = pdev->bus->self;
+
+ /* Ouch, it's a host bridge... */
+ if (ppdev == NULL) {
+ ppnode = pci_get_parent_node(pdev);
+
+ /* No node for host bridge ? give up */
+ if (ppnode == NULL)
+ return -EINVAL;
+ } else {
+ /* We found a P2P bridge, check if it has a node */
+ ppnode = pci_device_to_OF_node(ppdev);
+ }
+
+ /* Ok, we have found a parent with a device-node, hand over to
+ * the OF parsing code.
+ * We build a unit address from the linux device to be used for
+ * resolution. Note that we use the linux bus number which may
+ * not match your firmware bus numbering.
+ * Fortunately, in most cases, interrupt-map-mask doesn't
+ * include the bus number as part of the matching.
+ * You should still be careful about that though if you intend
+ * to rely on this function (you ship a firmware that doesn't
+ * create device nodes for all PCI devices).
+ */
+ if (ppnode)
+ break;
+
+ /* We can only get here if we hit a P2P bridge with no node,
+ * let's do standard swizzling and try again
+ */
+ lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+ pdev = ppdev;
+ }
+
+ lspec_be = cpu_to_be32(lspec);
+ laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+ laddr[1] = laddr[2] = cpu_to_be32(0);
+ return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
new file mode 100644
index 0000000..36b3cfa
--- /dev/null
+++ b/include/linux/of_pci.h
@@ -0,0 +1,24 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_PPC_OF
+#include <asm/pci-bridge.h>
+#endif
+
+/**
+ * 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;
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+#endif
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 08/15] x86/dtb: add support for PCI devices backed by dtb nodes
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (5 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 07/15] of: move of_irq_map_pci() into generic code Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-9-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 09/15] x86/dtb: Add generic bus probe Sebastian Andrzej Siewior
` (3 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Tested-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
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 a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
index 40ad8c0..a449dc6 100644
--- a/arch/x86/kernel/prom.c
+++ b/arch/x86/kernel/prom.c
@@ -9,10 +9,13 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/of_pci.h>
#include <asm/hpet.h>
#include <asm/irq_controller.h>
#include <asm/io_apic.h>
+#include <asm/pci_x86.h>
__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
@@ -102,6 +105,83 @@ void __init add_dtb(u64 data)
initial_dtb = data + offsetof(struct setup_data, data);
}
+static int x86_of_pci_irq_enable(struct pci_dev *dev)
+{
+ struct of_irq oirq;
+ u32 virq;
+ int ret;
+ u8 pin;
+
+ ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (ret)
+ return ret;
+ if (!pin)
+ return 0;
+
+ ret = of_irq_map_pci(dev, &oirq);
+ if (ret)
+ return ret;
+
+ virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+ oirq.size);
+ if (virq == NO_IRQ)
+ return -EINVAL;
+ dev->irq = virq;
+ return 0;
+}
+
+static void x86_of_pci_irq_disable(struct pci_dev *dev)
+{
+}
+
+void __cpuinit x86_of_pci_init(void)
+{
+ struct device_node *np;
+
+ pcibios_enable_irq = x86_of_pci_irq_enable;
+ pcibios_disable_irq = x86_of_pci_irq_disable;
+
+ for_each_node_by_type(np, "pci") {
+ const void *prop;
+ struct pci_bus *bus;
+ unsigned int bus_min;
+ struct device_node *child;
+
+ prop = of_get_property(np, "bus-range", NULL);
+ if (!prop)
+ continue;
+ bus_min = be32_to_cpup(prop);
+
+ bus = pci_find_bus(0, bus_min);
+ if (!bus) {
+ printk(KERN_ERR "Can't find a node for bus %s.\n",
+ np->full_name);
+ continue;
+ }
+
+ if (bus->self)
+ bus->self->dev.of_node = np;
+ else
+ bus->dev.of_node = np;
+
+ for_each_child_of_node(np, child) {
+ struct pci_dev *dev;
+ u32 devfn;
+
+ prop = of_get_property(child, "reg", NULL);
+ if (!prop)
+ continue;
+
+ devfn = (be32_to_cpup(prop) >> 8) & 0xff;
+ dev = pci_get_slot(bus, devfn);
+ if (!dev)
+ continue;
+ dev->dev.of_node = child;
+ pci_dev_put(dev);
+ }
+ }
+}
+
static void __init dtb_setup_hpet(void)
{
struct device_node *dn;
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 09/15] x86/dtb: Add generic bus probe
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (6 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 08/15] x86/dtb: add support for PCI devices backed by dtb nodes Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-10-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC Sebastian Andrzej Siewior
` (2 subsequent siblings)
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
For now we probe these busses and we change is to board dependent probes
once we have to.
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (7 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 09/15] x86/dtb: Add generic bus probe Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-11-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 12/15] of/address: use propper endianess in get_flags Sebastian Andrzej Siewior
2010-12-17 15:33 ` [PATCH 14/15] rtc/cmos: add OF bindings Sebastian Andrzej Siewior
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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 pci_bus *bus)
#else
static inline void add_dtb(u64 data) { }
+static inline void x86_add_irq_domains(void) { }
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
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 7eb0027..4dece80 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -43,6 +43,7 @@
#include <linux/bootmem.h>
#include <linux/dmar.h>
#include <linux/hpet.h>
+#include <linux/of_address.h>
#include <asm/idle.h>
#include <asm/io.h>
@@ -60,6 +61,7 @@
#include <asm/irq_remapping.h>
#include <asm/hpet.h>
#include <asm/hw_irq.h>
+#include <asm/irq_controller.h>
#include <asm/apic.h>
@@ -88,6 +90,10 @@ int nr_ioapics;
/* IO APIC gsi routing info */
struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS];
+#ifdef CONFIG_X86_OF
+/* OF -> IO APIC lookup */
+struct mp_of_ioapic mp_of_ioapic[MAX_IO_APICS];
+#endif
/* The one past the highest gsi number used */
u32 gsi_top;
@@ -4080,6 +4086,99 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
nr_ioapics++;
}
+#ifdef CONFIG_X86_OF
+static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
+ u32 *out_hwirq, u32 *out_type)
+{
+ u32 line;
+ u32 idx;
+ u32 type;
+ u32 trigger;
+ u32 polarity;
+ struct irq_cfg *cfg;
+ struct irq_desc *desc;
+
+ if (intsize < 1)
+ return -EINVAL;
+
+ line = *intspec;
+ idx = (u32) id->priv;
+ *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
+ if (intsize > 1) {
+ intspec++;
+ type = *intspec;
+ switch (type) {
+ case 0:
+ *out_type = IRQ_TYPE_EDGE_RISING;
+ trigger = IOAPIC_EDGE;
+ polarity = 1;
+ break;
+ case 1:
+ *out_type = IRQ_TYPE_LEVEL_LOW;
+ trigger = IOAPIC_LEVEL;
+ polarity = 0;
+ break;
+ case 2:
+ *out_type = IRQ_TYPE_LEVEL_HIGH;
+ trigger = IOAPIC_LEVEL;
+ polarity = 1;
+ break;
+ case 3:
+ *out_type = IRQ_TYPE_EDGE_FALLING;
+ trigger = IOAPIC_EDGE;
+ polarity = 0;
+ break;
+ default:
+ *out_type = IRQ_TYPE_NONE;
+ trigger = IOAPIC_AUTO;
+ polarity = 0;
+ break;
+ };
+ } else {
+ *out_type = IRQ_TYPE_NONE;
+ trigger = IOAPIC_AUTO;
+ polarity = 0;
+ }
+ /* And now tell the IO APIC to make the line ready */
+ desc = irq_to_desc_alloc_node(*out_hwirq, 0);
+ cfg = irq_cfg(*out_hwirq);
+ add_pin_to_irq_node(cfg, 0, idx, line);
+ /* make it edge by default, settype will update it */
+ setup_ioapic_irq(idx, line, *out_hwirq, cfg, trigger, polarity);
+ return 0;
+}
+
+void __init ioapic_add_ofnode(struct device_node *np)
+{
+ int i;
+ int ret;
+ struct resource r;
+
+ ret = of_address_to_resource(np, 0, &r);
+ if (ret) {
+ printk(KERN_ERR "Failed to obtain address for %s\n",
+ np->full_name);
+ return;
+ }
+
+ for (i = 0; i < nr_ioapics; i++) {
+ if (r.start == mp_ioapics[i].apicaddr) {
+ struct irq_domain *id;
+
+ mp_of_ioapic[i].node = np;
+ id = kzalloc(sizeof(*id), GFP_KERNEL);
+ BUG_ON(!id);
+ id->controller = np;
+ id->xlate = ioapic_xlate;
+ id->priv = (void *)i;
+ add_interrupt_host(id);
+ return;
+ }
+ }
+ printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+}
+#endif
+
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 4cadf86..9f76f89 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -119,6 +119,12 @@ void __init init_IRQ(void)
int i;
/*
+ * We probably need a better place for this, but it works for
+ * now ...
+ */
+ x86_add_irq_domains();
+
+ /*
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
* then this configuration will likely be static after the boot. If
diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
index 6eddafd..edcaf1b 100644
--- a/arch/x86/kernel/prom.c
+++ b/arch/x86/kernel/prom.c
@@ -11,9 +11,11 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/of_pci.h>
+#include <linux/of_fdt.h>
#include <asm/hpet.h>
#include <asm/irq_controller.h>
+#include <asm/apic.h>
#include <asm/io_apic.h>
#include <asm/pci_x86.h>
@@ -332,3 +334,16 @@ void __init x86_dtb_get_config(unsigned int unused)
dtb_setup_hpet();
dtb_apic_setup();
}
+
+void __init x86_add_irq_domains(void)
+{
+ struct device_node *dp;
+
+ if (!initial_boot_params)
+ return;
+
+ for_each_node_by_type(dp, "interrupt-controller") {
+ if (of_device_is_compatible(dp, "intel,ioapic"))
+ ioapic_add_ofnode(dp);
+ }
+}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 12/15] of/address: use propper endianess in get_flags
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (8 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
2010-12-30 9:05 ` Grant Likely
2010-12-17 15:33 ` [PATCH 14/15] rtc/cmos: add OF bindings Sebastian Andrzej Siewior
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Acked-by: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
---
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)
{
printk(KERN_DEBUG "%s", s);
while (na--)
@@ -26,7 +26,7 @@ static void of_dump_addr(const char *s, const u32 *addr, int na)
printk("\n");
}
#else
-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) { }
#endif
/* Callbacks for bus specific translators */
@@ -36,10 +36,10 @@ struct of_bus {
int (*match)(struct device_node *parent);
void (*count_cells)(struct device_node *child,
int *addrc, int *sizec);
- u64 (*map)(u32 *addr, const u32 *range,
+ u64 (*map)(u32 *addr, const __be32 *range,
int na, int ns, int pna);
int (*translate)(u32 *addr, u64 offset, int na);
- unsigned int (*get_flags)(const u32 *addr);
+ unsigned int (*get_flags)(const __be32 *addr);
};
/*
@@ -55,7 +55,7 @@ static void of_bus_default_count_cells(struct device_node *dev,
*sizec = of_n_size_cells(dev);
}
-static u64 of_bus_default_map(u32 *addr, const u32 *range,
+static u64 of_bus_default_map(u32 *addr, const __be32 *range,
int na, int ns, int pna)
{
u64 cp, s, da;
@@ -85,7 +85,7 @@ static int of_bus_default_translate(u32 *addr, u64 offset, int na)
return 0;
}
-static unsigned int of_bus_default_get_flags(const u32 *addr)
+static unsigned int of_bus_default_get_flags(const __be32 *addr)
{
return IORESOURCE_MEM;
}
@@ -110,10 +110,10 @@ static void of_bus_pci_count_cells(struct device_node *np,
*sizec = 2;
}
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
+static unsigned int of_bus_pci_get_flags(const __be32 *addr)
{
unsigned int flags = 0;
- u32 w = addr[0];
+ u32 w = be32_to_cpup(addr);
switch((w >> 24) & 0x03) {
case 0x01:
@@ -129,7 +129,8 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
return flags;
}
-static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
+ int pna)
{
u64 cp, s, da;
unsigned int af, rf;
@@ -160,7 +161,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
return of_bus_default_translate(addr + 1, offset, na - 1);
}
-const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
+const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
unsigned int *flags)
{
const __be32 *prop;
@@ -207,7 +208,7 @@ EXPORT_SYMBOL(of_get_pci_address);
int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r)
{
- const u32 *addrp;
+ const __be32 *addrp;
u64 size;
unsigned int flags;
@@ -237,12 +238,13 @@ static void of_bus_isa_count_cells(struct device_node *child,
*sizec = 1;
}
-static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
+ int pna)
{
u64 cp, s, da;
/* Check address type match */
- if ((addr[0] ^ range[0]) & 0x00000001)
+ if ((addr[0] ^ range[0]) & cpu_to_be32(1))
return OF_BAD_ADDR;
/* Read address values, skipping high cell */
@@ -264,10 +266,10 @@ static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
return of_bus_default_translate(addr + 1, offset, na - 1);
}
-static unsigned int of_bus_isa_get_flags(const u32 *addr)
+static unsigned int of_bus_isa_get_flags(const __be32 *addr)
{
unsigned int flags = 0;
- u32 w = addr[0];
+ u32 w = be32_to_cpup(addr);
if (w & 1)
flags |= IORESOURCE_IO;
@@ -330,7 +332,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
struct of_bus *pbus, u32 *addr,
int na, int ns, int pna, const char *rprop)
{
- const u32 *ranges;
+ const __be32 *ranges;
unsigned int rlen;
int rone;
u64 offset = OF_BAD_ADDR;
@@ -398,7 +400,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
* that can be mapped to a cpu physical address). This is not really specified
* that way, but this is traditionally the way IBM at least do things
*/
-u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
+u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr,
const char *rprop)
{
struct device_node *parent = NULL;
@@ -475,22 +477,22 @@ u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
return result;
}
-u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
{
return __of_translate_address(dev, in_addr, "ranges");
}
EXPORT_SYMBOL(of_translate_address);
-u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr)
+u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
{
return __of_translate_address(dev, in_addr, "dma-ranges");
}
EXPORT_SYMBOL(of_translate_dma_address);
-const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
+const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
unsigned int *flags)
{
- const u32 *prop;
+ const __be32 *prop;
unsigned int psize;
struct device_node *parent;
struct of_bus *bus;
@@ -525,8 +527,8 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
}
EXPORT_SYMBOL(of_get_address);
-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)
{
u64 taddr;
@@ -564,7 +566,7 @@ static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
int of_address_to_resource(struct device_node *dev, int index,
struct resource *r)
{
- const u32 *addrp;
+ const __be32 *addrp;
u64 size;
unsigned int flags;
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 8aea06f..2feda6e 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -3,7 +3,7 @@
#include <linux/ioport.h>
#include <linux/of.h>
-extern u64 of_translate_address(struct device_node *np, const u32 *addr);
+extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
extern void __iomem *of_iomap(struct device_node *device, int index);
@@ -21,7 +21,7 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
#endif
#ifdef CONFIG_PCI
-extern const u32 *of_get_pci_address(struct device_node *dev, int bar_no,
+extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,
u64 *size, unsigned int *flags);
extern int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r);
@@ -32,7 +32,7 @@ static inline int of_pci_address_to_resource(struct device_node *dev, int bar,
return -ENOSYS;
}
-static inline const u32 *of_get_pci_address(struct device_node *dev,
+static inline const __be32 *of_get_pci_address(struct device_node *dev,
int bar_no, u64 *size, unsigned int *flags)
{
return NULL;
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH 14/15] rtc/cmos: add OF bindings
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
` (9 preceding siblings ...)
2010-12-17 15:33 ` [PATCH 12/15] of/address: use propper endianess in get_flags Sebastian Andrzej Siewior
@ 2010-12-17 15:33 ` Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-15-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
10 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2010-12-17 15:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Alessandro Zummo, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
Sebastian Andrzej Siewior, x86-DgEjT+Ai2ygdnm+yROfE0A,
sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
Cc: Alessandro Zummo <a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
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 5856167..8cf0049 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -36,6 +36,8 @@
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
@@ -1121,6 +1123,15 @@ static struct pnp_driver cmos_pnp_driver = {
#endif /* CONFIG_PNP */
+#ifdef CONFIG_OF
+static const struct of_device_id of_cmos_match[] = {
+ {
+ .compatible = "motorola,mc146818",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, of_cmos_match);
+#endif
/*----------------------------------------------------------------*/
/* Platform setup should have set up an RTC device, when PNP is
@@ -1129,6 +1140,32 @@ static struct pnp_driver cmos_pnp_driver = {
static int __init cmos_platform_probe(struct platform_device *pdev)
{
+#ifdef CONFIG_OF
+ if (pdev->dev.of_node) {
+ struct device_node *node = pdev->dev.of_node;
+ struct rtc_time time;
+ int ret;
+ const __be32 *val;
+
+ val = of_get_property(node, "ctrl-reg", NULL);
+ if (val)
+ CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL);
+
+ val = of_get_property(node, "freq-reg", NULL);
+ if (val)
+ CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
+
+ get_rtc_time(&time);
+ ret = rtc_valid_tm(&time);
+ if (ret) {
+ struct rtc_time def_time = {
+ .tm_year = 1,
+ .tm_mday = 1,
+ };
+ set_rtc_time(&def_time);
+ }
+ }
+#endif
cmos_wake_setup(&pdev->dev);
return cmos_do_probe(&pdev->dev,
platform_get_resource(pdev, IORESOURCE_IO, 0),
@@ -1157,6 +1194,9 @@ static struct platform_driver cmos_platform_driver = {
.shutdown = cmos_platform_shutdown,
.driver = {
.name = (char *) driver_name,
+#if defined(CONFIG_OF)
+ .of_match_table = of_cmos_match,
+#endif
.suspend = cmos_suspend,
.resume = cmos_resume,
}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH 07/15] of: move of_irq_map_pci() into generic code
2010-12-17 15:33 ` [PATCH 07/15] of: move of_irq_map_pci() into generic code Sebastian Andrzej Siewior
@ 2010-12-17 21:16 ` Benjamin Herrenschmidt
2011-01-04 14:27 ` [PATCH v2 " Sebastian Andrzej Siewior
0 siblings, 1 reply; 42+ messages in thread
From: Benjamin Herrenschmidt @ 2010-12-17 21:16 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, sodaville, x86, dirk.brandewie,
Sebastian Andrzej Siewior, devicetree-discuss
On Fri, 2010-12-17 at 16:33 +0100, Sebastian Andrzej Siewior wrote:
> +
> +#if defined(CONFIG_PPC64) || defined(CONFIG_X86)
> +static struct device_node *pci_get_parent_node(struct pci_dev *pdev)
> +{
> + return pci_bus_to_OF_node(pdev->bus);
> +}
> +#endif
> +
> +#if defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)
> +static struct device_node *pci_get_parent_node(struct pci_dev *pdev)
> +{
> + struct pci_controller *host;
> +
> + host = pci_bus_to_host(pdev->bus);
> + return host ? host->dn : NULL;
> +}
> +#endif
> +
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.
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 02/15] x86: Add device tree support
2010-12-17 15:33 ` [PATCH 02/15] x86: Add device tree support Sebastian Andrzej Siewior
@ 2010-12-30 8:43 ` Grant Likely
[not found] ` <20101230084311.GD11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2010-12-30 8:43 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, sodaville, x86, devicetree-discuss
On Fri, Dec 17, 2010 at 04:33:40PM +0100, Sebastian Andrzej Siewior wrote:
> 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>
Mostly looks good. Some comments below.
g.
> ---
> 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 (dtb) is passed via setup_data
> +(see [0]) which requires at least boot protocol 2.09. The type filed is
> +defined as
> +
> +#define SETUP_DTB 2
> +
> +3. Purpose
> +~~~~~~~~~~~
> +The device tree is used as an extension to the "boot page". As such it does not
> +parse / consider data which are already covered by the boot page. This includes
> +memory size, command line arguments or initrd address.
> +It simply holds information which can not be retrieved otherwise like interrupt
> +routing or a list of devices behind an I2C bus.
> +
> +[0] Documentation/x86/boot.txt
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index b6fccb0..0522354 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -299,6 +299,13 @@ config X86_BIGSMP
> ---help---
> This option is needed for the systems that have more than 8 CPUs
>
> +config X86_OF
> + bool "Support for device tree"
> + select OF
> + select OF_FLATTREE
> + ---help---
> + Device tree support on X86.
> +
> if X86_32
> config X86_EXTENDED_PLATFORM
> bool "Support for extended (non-PC) x86 platforms"
> diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
> index c8bfe63..e020d88 100644
> --- a/arch/x86/include/asm/bootparam.h
> +++ b/arch/x86/include/asm/bootparam.h
> @@ -12,6 +12,7 @@
> /* setup data types */
> #define SETUP_NONE 0
> #define SETUP_E820_EXT 1
> +#define SETUP_DTB 2
>
> /* extensible setup data list node */
> struct setup_data {
> diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
> new file mode 100644
> index 0000000..2fbe3e8
> --- /dev/null
> +++ b/arch/x86/include/asm/prom.h
> @@ -0,0 +1,59 @@
> +/*
> + * Definitions for Device tree / OpenFirmware handling on X86
> + *
> + * based on arch/powerpc/include/asm/prom.h which is
> + * Copyright (C) 1996-2005 Paul Mackerras.
> + *
> + * 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; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#ifndef _ASM_X86_PROM_H
> +#define _ASM_X86_PROM_H
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/of.h>
> +#include <linux/types.h>
> +#include <asm/irq.h>
> +#include <asm/atomic.h>
> +#include <asm/setup.h>
> +
> +#ifdef CONFIG_OF
> +extern void add_dtb(u64 data);
> +#else
> +static inline void add_dtb(u64 data) { }
> +#endif
> +
> +extern char cmd_line[COMMAND_LINE_SIZE];
> +/* This number is used when no interrupt has been assigned */
> +#define NO_IRQ (-1)
0 means NO_IRQ on x86 and most architectures. I will change this when
I pick up the patch.
> +
> +#define pci_address_to_pio pci_address_to_pio
> +unsigned long pci_address_to_pio(phys_addr_t addr);
> +
> +/**
> + * irq_dispose_mapping - Unmap an interrupt
> + * @virq: linux virq number of the interrupt to unmap
> + *
> + * FIXME: We really should implement proper virq handling like power,
> + * but that's going to be major surgery.
> + */
> +static inline void irq_dispose_mapping(unsigned int virq) { }
> +
> +#define HAVE_ARCH_DEVTREE_FIXUPS
> +
> +#endif /* __ASSEMBLY__ */
> +
> +/*
> + * These includes are put at the bottom because they may contain things
> + * that are overridden by this file. Ideally they shouldn't be included
> + * by this file, but there are a bunch of .c files that currently depend
> + * on it. Eventually they will be cleaned up.
> + */
> +#include <linux/of_fdt.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +
> +#endif
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index f60153d..40bc33d 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -108,6 +108,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
> obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
>
> obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
> +obj-$(CONFIG_X86_OF) += prom.o
>
> ###
> # 64 bit specific files
> diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
> index c752e97..149c87f 100644
> --- a/arch/x86/kernel/irqinit.c
> +++ b/arch/x86/kernel/irqinit.c
> @@ -25,6 +25,7 @@
> #include <asm/setup.h>
> #include <asm/i8259.h>
> #include <asm/traps.h>
> +#include <asm/prom.h>
>
> /*
> * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
> diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
> new file mode 100644
> index 0000000..249ebd3
> --- /dev/null
> +++ b/arch/x86/kernel/prom.c
> @@ -0,0 +1,54 @@
> +/*
> + * Architecture specific OF callbacks.
> + */
> +#include <linux/bootmem.h>
> +#include <linux/io.h>
> +#include <linux/list.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +
> +char __initdata cmd_line[COMMAND_LINE_SIZE];
> +
> +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);
> +
> +unsigned long pci_address_to_pio(phys_addr_t address)
> +{
> + /*
> + * The ioport address can be directly used by inX / outX
> + */
> + BUG_ON(address >= (1 << 16));
> + return (unsigned long)address;
> +}
> +EXPORT_SYMBOL_GPL(pci_address_to_pio);
> +
> +void __init early_init_dt_scan_chosen_arch(unsigned long node)
> +{
> + BUG();
> +}
> +
> +void __init early_init_dt_add_memory_arch(u64 base, u64 size)
> +{
> + BUG();
> +}
> +
> +u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
> +{
> + void *mem;
> +
> + mem = __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
> + return virt_to_phys(mem);
> +}
> +
> +void __init add_dtb(u64 data)
> +{
> + initial_boot_params = (struct boot_param_header *)
> + phys_to_virt((u64) (u32) data +
> + offsetof(struct setup_data, data));
> +}
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 577d06b..26f2c9a 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -113,6 +113,7 @@
> #endif
> #include <asm/mce.h>
> #include <asm/alternative.h>
> +#include <asm/prom.h>
>
> /*
> * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
> @@ -445,6 +446,9 @@ static void __init parse_setup_data(void)
> case SETUP_E820_EXT:
> parse_e820_ext(data);
> break;
> + case SETUP_DTB:
> + add_dtb(pa_data);
> + break;
Why is the physical address being passed in when the virtual address
is needed to be stored in initial_boot_params by add_dtb()?
> default:
> break;
> }
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 03/15] x86/dtb: Add a device tree for CE4100
[not found] ` <1292600033-12271-4-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2010-12-30 8:51 ` Grant Likely
[not found] ` <20101230085122.GE11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2010-12-30 8:51 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Fri, Dec 17, 2010 at 04:33:41PM +0100, Sebastian Andrzej Siewior wrote:
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> 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";
To-date the convention has been to use all lowercase in compatible
properties. Ditto throughout this file.
> + #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";
Drop device_type property.
> + compatible = "Intel,ce4100";
> + ranges;
> +
> + ioapic1: pic@fec00000 {
> + #interrupt-cells = <2>;
> + compatible = "Intel,ioapic";
> + interrupt-controller;
> + device_type = "interrupt-controller";
Ditto
> + 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";
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
alternative to 'device_type = "pci";'.
> + bus-range = <0 0>;
> + ranges = <0x2000000 0 0xbffff000 0xbffff000 0 0x1000
> + 0x0000000 0 0x0 0x0 0 0x100>;
> +
> + isa@0 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "isa";
> + ranges = <1 0 0 0 0 0x100>;
> +
> + rtc@70 {
> + compatible = "motorola,mc146818";
> + interrupts = <8 3>;
> + interrupt-parent = <&ioapic1>;
If you put an interrupt-parent property in the root node, then it will
become the default interrupt controller for the system which is
usually convenient to have.
> + ctrl-reg = <2>;
> + freq-reg = <0x26>;
> + reg = <1 0x70 2>;
> + };
> + };
> +
> + /* Secondary IO-APIC */
> + ioapic2: pic@bffff000 {
> + #interrupt-cells = <2>;
> + compatible = "Intel,ioapic-ce4100", "Intel,ioapic";
> + interrupt-controller;
> + device_type = "interrupt-controller";
Drop device_type.
> + id = <2>;
> + reg = <0x100 0x0 0x0 0x0 0x0>;
> + assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
> + };
> +
> + pci@av {
> + #address-cells = <3>;
> + #interrupt-cells = <1>;
> + #size-cells = <1>;
> + compatible = "Intel,ce4100-pci";
> + device_type = "pci";
> + bus-range = <1 1>;
> + interrupt-map-mask = <0xffffff 0x0 0x0 0x0>;
> + interrupt-map = <
> + /* GFX: 0x2E5B */
> + 0x11000 0x0 0x0 0x0 &ioapic2 0 0x1
> + /* ***** FIXME ****** Compositing Engine: 0x2E72 */
> + /* 0x11100 0x0 0x0 0x1 &ioapic2 0 0x1 */
> + /* MFD: 0x2E5C */
> + 0x11800 0x0 0x0 0x0 &ioapic2 2 0x1
> + /* TS Prefilter: 0x2E5D */
> + 0x12000 0x0 0x0 0x0 &ioapic2 4 0x1
> + /* TS Demux: 0x2E5E */
> + 0x12100 0x0 0x0 0x0 &ioapic2 5 0x1
> + /* ***** FIXME ***** Audio DSP: 0x2E5F */
> + /* 0x13000 0x0 0x0 0x1 &ioapic2 0 0x1 */
> + /* Audio Interfaces: 0x2E60 */
> + 0x13200 0x0 0x0 0x0 &ioapic2 8 0x1
> + /* VDC: 0x2E61 */
> + 0x14000 0x0 0x0 0x0 &ioapic2 9 0x1
> + /* DPE: 0x2E62 */
> + 0x14100 0x0 0x0 0x0 &ioapic2 10 0x1
> + /* HDMI Tx: 0x2E63 */
> + 0x14200 0x0 0x0 0x0 &ioapic2 11 0x1
> + /* SEC: 0x2E64 */
> + 0x14800 0x0 0x0 0x0 &ioapic2 12 0x1
> + /* EXP: 0x2E65 */
> + 0x15000 0x0 0x0 0x0 &ioapic2 13 0x1
> + /* UART0/1: 0x2E66 */
> + 0x15800 0x0 0x0 0x0 &ioapic2 14 0x1
> + /* GPIO: 0x2E67 */
> + 0x15900 0x0 0x0 0x0 &ioapic2 15 0x1
> + /* I2C0/1/2: 0x2E68 */
> + 0x15a00 0x0 0x0 0x0 &ioapic2 16 0x1
> + /* Smart Card 0/1: 0x2E69 */
> + 0x15b00 0x0 0x0 0x0 &ioapic2 15 0x1
> + /* SPI: 0x2E6A */
> + 0x15c00 0x0 0x0 0x0 &ioapic2 15 0x1
> + /* MSPOD: 0x2E6B */
> + 0x15d00 0x0 0x0 0x0 &ioapic2 19 0x1
> + /* IR: 0x2E6C */
> + 0x15e00 0x0 0x0 0x0 &ioapic2 16 0x1
> + /* **** FIXME ***** DFX: 0x2E6D */
> + /* 0x15f00 0x0 0x0 0x1 &ioapic2 0x0 0x1 */
> + /* Gig Ethernet: 0x2E6E */
> + 0x16000 0x0 0x0 0x0 &ioapic2 21 0x1
> + /* IEEE1588 and Clock Recovery Unit: 0x2E6F */
> + 0x16100 0x0 0x0 0x0 &ioapic2 3 0x1
> + /* USB0: 0x2E70 */
> + 0x16800 0x0 0x0 0x0 &ioapic2 22 0x3
> + /* USB1: 0x2E70 */
> + 0x16900 0x0 0x0 0x0 &ioapic2 22 0x3
> + /* SATA: 0x2E71 */
> + 0x17000 0x0 0x0 0x0 &ioapic2 23 0x3
> + >;
> +
> + i2c@15a00 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x15a00 0x0 0x0 0x0>;
> +
> +
> + i2c@0 {
> + reg = <0>;
> + };
> +
> + i2c@1 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <1>;
> +
> + pcf8575@26 {
> + compatible = "ti,pcf8575";
> + reg = <0x26>;
> + };
> + };
> +
> + i2c@2 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <2>;
> +
> + pcf8575@26 {
> + compatible = "ti,pcf8575";
> + reg = <0x26>;
> + };
> + };
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
names')
> + };
> +
> + spi@15c00 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x15c00 0x0 0x0 0x0>;
> +
> + pcm1755@0 {
> + compatible = "ti,pcm1755";
> + reg = <0>;
> + spi-max-frequency = <115200>;
> + };
> +
> + pcm1609a@1 {
> + compatible = "ti,pcm1609a";
> + reg = <1>;
> + spi-max-frequency = <115200>;
> + };
> +
> + at93c46@2 {
> + compatible = "atmel,at93c46";
> + reg = <2>;
> + spi-max-frequency = <115200>;
> + };
> + };
Ditto above comments for SPI bus and devices.
> + };
> + };
> + };
> +};
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 05/15] x86/dtb: add early parsing of APIC and IO APIC
[not found] ` <1292600033-12271-6-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2010-12-30 8:54 ` Grant Likely
2011-01-04 13:23 ` [PATCH v2 " Sebastian Andrzej Siewior
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2010-12-30 8:54 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Fri, Dec 17, 2010 at 04:33:43PM +0100, Sebastian Andrzej Siewior wrote:
> 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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> ---
> 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>
> #include <linux/list.h>
> #include <linux/of.h>
> +#include <linux/of_address.h>
> #include <linux/of_platform.h>
> #include <linux/slab.h>
>
> #include <asm/irq_controller.h>
> +#include <asm/io_apic.h>
>
> +__initdata u64 initial_dtb;
> char __initdata cmd_line[COMMAND_LINE_SIZE];
> static LIST_HEAD(irq_domains);
> static DEFINE_RAW_SPINLOCK(big_irq_lock);
>
> +int __initdata of_ioapic;
> +
> void add_interrupt_host(struct irq_domain *ih)
> {
> unsigned long flags;
> @@ -93,7 +98,119 @@ u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
>
> void __init add_dtb(u64 data)
> {
> - initial_boot_params = (struct boot_param_header *)
> - phys_to_virt((u64) (u32) data +
> - offsetof(struct setup_data, data));
> + initial_dtb = data + offsetof(struct setup_data, data);
> +}
> +
> +static void __init dtb_lapic_setup(void)
> +{
> +#ifdef CONFIG_X86_LOCAL_APIC
> + if (apic_force_enable())
> + return;
> +
> + smp_found_config = 1;
> + pic_mode = 1;
> + /* Required for ioapic registration */
> + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
> + if (boot_cpu_physical_apicid == -1U)
> + boot_cpu_physical_apicid = read_apic_id();
> +
> + generic_processor_info(boot_cpu_physical_apicid,
> + GET_APIC_VERSION(apic_read(APIC_LVR)));
> +#endif
> +}
> +
> +#ifdef CONFIG_X86_IO_APIC
> +static void __init dtb_add_ioapic(struct device_node *dn)
> +{
> + unsigned int ioapic_id;
> + const __be32 *cell;
> + int len;
> + struct resource r;
> + int ret;
> +
> + cell = of_get_property(dn, "id", &len);
> + if (!cell) {
> + printk(KERN_ERR "Node %s is missing id property.\n",
> + dn->full_name);
> + return;
> + }
> + ioapic_id = of_read_ulong(cell, len / 4);
> +
> + ret = of_address_to_resource(dn, 0, &r);
> + if (ret) {
> + printk(KERN_ERR "Can't obtain address from node %s.\n",
> + dn->full_name);
> + return;
> + }
> + mp_register_ioapic(ioapic_id, r.start, gsi_top);
> +}
> +
> +static void __init dtb_ioapic_setup(void)
> +{
> + struct device_node *dn;
> +
> + if (!smp_found_config)
> + return;
> +
> + for_each_compatible_node(dn, NULL, "intel,ioapic")
> + dtb_add_ioapic(dn);
> +
> + if (nr_ioapics) {
> + of_ioapic = 1;
> + return;
> + }
> + printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
> + smp_found_config = 0;
> +}
> +#else
> +static void __init dtb_ioapic_setup(void) {}
> +#endif
> +
> +static void __init dtb_apic_setup(void)
> +{
> + dtb_lapic_setup();
> + dtb_ioapic_setup();
> +}
> +
> +void __init x86_dtb_find_config(void)
> +{
> + if (initial_dtb)
> + smp_found_config = 1;
> + else
> + printk(KERN_ERR "Missing device tree!.\n");
> +}
> +
> +void __init x86_dtb_get_config(unsigned int unused)
> +{
> + u32 size;
> + u32 map_len;
> + void *new_dtb;
> +
> + if (!initial_dtb)
> + return;
> +
> + map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
> + (u64)sizeof(struct boot_param_header));
> +
> + initial_boot_params = early_memremap(initial_dtb, map_len);
> + size = be32_to_cpu(initial_boot_params->totalsize);
> + if (map_len < size) {
> + early_iounmap(initial_boot_params, map_len);
> + initial_boot_params = early_memremap(initial_dtb, size);
Add "map_len = size;" here eliminate the early_iounmap() dance done below.
> + }
> +
> + new_dtb = alloc_bootmem(size);
> + memcpy(new_dtb, initial_boot_params, size);
> + if (map_len < size)
> + early_iounmap(initial_boot_params, size);
> + else
> + early_iounmap(initial_boot_params, map_len);
> +
> + initial_boot_params = new_dtb;
> +
> + /* root level address cells */
> + of_scan_flat_dt(early_init_dt_scan_root, NULL);
> +
> + unflatten_device_tree();
> + dtb_apic_setup();
> }
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 12/15] of/address: use propper endianess in get_flags
2010-12-17 15:33 ` [PATCH 12/15] of/address: use propper endianess in get_flags Sebastian Andrzej Siewior
@ 2010-12-30 9:05 ` Grant Likely
0 siblings, 0 replies; 42+ messages in thread
From: Grant Likely @ 2010-12-30 9:05 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, sodaville, x86, devicetree-discuss
On Fri, Dec 17, 2010 at 04:33:50PM +0100, Sebastian Andrzej Siewior wrote:
> 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>
This one is already applied to my next-devicetree branch
g.
> ---
> 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)
> {
> printk(KERN_DEBUG "%s", s);
> while (na--)
> @@ -26,7 +26,7 @@ static void of_dump_addr(const char *s, const u32 *addr, int na)
> printk("\n");
> }
> #else
> -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) { }
> #endif
>
> /* Callbacks for bus specific translators */
> @@ -36,10 +36,10 @@ struct of_bus {
> int (*match)(struct device_node *parent);
> void (*count_cells)(struct device_node *child,
> int *addrc, int *sizec);
> - u64 (*map)(u32 *addr, const u32 *range,
> + u64 (*map)(u32 *addr, const __be32 *range,
> int na, int ns, int pna);
> int (*translate)(u32 *addr, u64 offset, int na);
> - unsigned int (*get_flags)(const u32 *addr);
> + unsigned int (*get_flags)(const __be32 *addr);
> };
>
> /*
> @@ -55,7 +55,7 @@ static void of_bus_default_count_cells(struct device_node *dev,
> *sizec = of_n_size_cells(dev);
> }
>
> -static u64 of_bus_default_map(u32 *addr, const u32 *range,
> +static u64 of_bus_default_map(u32 *addr, const __be32 *range,
> int na, int ns, int pna)
> {
> u64 cp, s, da;
> @@ -85,7 +85,7 @@ static int of_bus_default_translate(u32 *addr, u64 offset, int na)
> return 0;
> }
>
> -static unsigned int of_bus_default_get_flags(const u32 *addr)
> +static unsigned int of_bus_default_get_flags(const __be32 *addr)
> {
> return IORESOURCE_MEM;
> }
> @@ -110,10 +110,10 @@ static void of_bus_pci_count_cells(struct device_node *np,
> *sizec = 2;
> }
>
> -static unsigned int of_bus_pci_get_flags(const u32 *addr)
> +static unsigned int of_bus_pci_get_flags(const __be32 *addr)
> {
> unsigned int flags = 0;
> - u32 w = addr[0];
> + u32 w = be32_to_cpup(addr);
>
> switch((w >> 24) & 0x03) {
> case 0x01:
> @@ -129,7 +129,8 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
> return flags;
> }
>
> -static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
> +static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
> + int pna)
> {
> u64 cp, s, da;
> unsigned int af, rf;
> @@ -160,7 +161,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
> return of_bus_default_translate(addr + 1, offset, na - 1);
> }
>
> -const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
> +const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
> unsigned int *flags)
> {
> const __be32 *prop;
> @@ -207,7 +208,7 @@ EXPORT_SYMBOL(of_get_pci_address);
> int of_pci_address_to_resource(struct device_node *dev, int bar,
> struct resource *r)
> {
> - const u32 *addrp;
> + const __be32 *addrp;
> u64 size;
> unsigned int flags;
>
> @@ -237,12 +238,13 @@ static void of_bus_isa_count_cells(struct device_node *child,
> *sizec = 1;
> }
>
> -static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna)
> +static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
> + int pna)
> {
> u64 cp, s, da;
>
> /* Check address type match */
> - if ((addr[0] ^ range[0]) & 0x00000001)
> + if ((addr[0] ^ range[0]) & cpu_to_be32(1))
> return OF_BAD_ADDR;
>
> /* Read address values, skipping high cell */
> @@ -264,10 +266,10 @@ static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
> return of_bus_default_translate(addr + 1, offset, na - 1);
> }
>
> -static unsigned int of_bus_isa_get_flags(const u32 *addr)
> +static unsigned int of_bus_isa_get_flags(const __be32 *addr)
> {
> unsigned int flags = 0;
> - u32 w = addr[0];
> + u32 w = be32_to_cpup(addr);
>
> if (w & 1)
> flags |= IORESOURCE_IO;
> @@ -330,7 +332,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> struct of_bus *pbus, u32 *addr,
> int na, int ns, int pna, const char *rprop)
> {
> - const u32 *ranges;
> + const __be32 *ranges;
> unsigned int rlen;
> int rone;
> u64 offset = OF_BAD_ADDR;
> @@ -398,7 +400,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> * that can be mapped to a cpu physical address). This is not really specified
> * that way, but this is traditionally the way IBM at least do things
> */
> -u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
> +u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr,
> const char *rprop)
> {
> struct device_node *parent = NULL;
> @@ -475,22 +477,22 @@ u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
> return result;
> }
>
> -u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
> +u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
> {
> return __of_translate_address(dev, in_addr, "ranges");
> }
> EXPORT_SYMBOL(of_translate_address);
>
> -u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr)
> +u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
> {
> return __of_translate_address(dev, in_addr, "dma-ranges");
> }
> EXPORT_SYMBOL(of_translate_dma_address);
>
> -const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
> +const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
> unsigned int *flags)
> {
> - const u32 *prop;
> + const __be32 *prop;
> unsigned int psize;
> struct device_node *parent;
> struct of_bus *bus;
> @@ -525,8 +527,8 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
> }
> EXPORT_SYMBOL(of_get_address);
>
> -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)
> {
> u64 taddr;
> @@ -564,7 +566,7 @@ static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
> int of_address_to_resource(struct device_node *dev, int index,
> struct resource *r)
> {
> - const u32 *addrp;
> + const __be32 *addrp;
> u64 size;
> unsigned int flags;
>
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 8aea06f..2feda6e 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -3,7 +3,7 @@
> #include <linux/ioport.h>
> #include <linux/of.h>
>
> -extern u64 of_translate_address(struct device_node *np, const u32 *addr);
> +extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
> extern int of_address_to_resource(struct device_node *dev, int index,
> struct resource *r);
> extern void __iomem *of_iomap(struct device_node *device, int index);
> @@ -21,7 +21,7 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
> #endif
>
> #ifdef CONFIG_PCI
> -extern const u32 *of_get_pci_address(struct device_node *dev, int bar_no,
> +extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,
> u64 *size, unsigned int *flags);
> extern int of_pci_address_to_resource(struct device_node *dev, int bar,
> struct resource *r);
> @@ -32,7 +32,7 @@ static inline int of_pci_address_to_resource(struct device_node *dev, int bar,
> return -ENOSYS;
> }
>
> -static inline const u32 *of_get_pci_address(struct device_node *dev,
> +static inline const __be32 *of_get_pci_address(struct device_node *dev,
> int bar_no, u64 *size, unsigned int *flags)
> {
> return NULL;
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 02/15] x86: Add device tree support
[not found] ` <20101230084311.GD11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2010-12-30 21:01 ` Grant Likely
[not found] ` <AANLkTi=EFewaizO=1FLALE0eQPUmaFPfTmgoeF+JRpkt-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-01-03 12:20 ` Sebastian Andrzej Siewior
1 sibling, 1 reply; 42+ messages in thread
From: Grant Likely @ 2010-12-30 21:01 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, H. Peter Anvin,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
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.
On Thu, Dec 30, 2010 at 1:43 AM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> On Fri, Dec 17, 2010 at 04:33:40PM +0100, Sebastian Andrzej Siewior wrote:
>> 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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
>> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
>> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> Mostly looks good. Some comments below.
>
> g.
>
>> ---
>> 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 (dtb) is passed via setup_data
>> +(see [0]) which requires at least boot protocol 2.09. The type filed is
>> +defined as
>> +
>> +#define SETUP_DTB 2
>> +
>> +3. Purpose
>> +~~~~~~~~~~~
>> +The device tree is used as an extension to the "boot page". As such it does not
>> +parse / consider data which are already covered by the boot page. This includes
>> +memory size, command line arguments or initrd address.
>> +It simply holds information which can not be retrieved otherwise like interrupt
>> +routing or a list of devices behind an I2C bus.
>> +
>> +[0] Documentation/x86/boot.txt
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index b6fccb0..0522354 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -299,6 +299,13 @@ config X86_BIGSMP
>> ---help---
>> This option is needed for the systems that have more than 8 CPUs
>>
>> +config X86_OF
>> + bool "Support for device tree"
>> + select OF
>> + select OF_FLATTREE
>> + ---help---
>> + Device tree support on X86.
>> +
>> if X86_32
>> config X86_EXTENDED_PLATFORM
>> bool "Support for extended (non-PC) x86 platforms"
>> diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
>> index c8bfe63..e020d88 100644
>> --- a/arch/x86/include/asm/bootparam.h
>> +++ b/arch/x86/include/asm/bootparam.h
>> @@ -12,6 +12,7 @@
>> /* setup data types */
>> #define SETUP_NONE 0
>> #define SETUP_E820_EXT 1
>> +#define SETUP_DTB 2
>>
>> /* extensible setup data list node */
>> struct setup_data {
>> diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
>> new file mode 100644
>> index 0000000..2fbe3e8
>> --- /dev/null
>> +++ b/arch/x86/include/asm/prom.h
>> @@ -0,0 +1,59 @@
>> +/*
>> + * Definitions for Device tree / OpenFirmware handling on X86
>> + *
>> + * based on arch/powerpc/include/asm/prom.h which is
>> + * Copyright (C) 1996-2005 Paul Mackerras.
>> + *
>> + * 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; either version
>> + * 2 of the License, or (at your option) any later version.
>> + */
>> +
>> +#ifndef _ASM_X86_PROM_H
>> +#define _ASM_X86_PROM_H
>> +#ifndef __ASSEMBLY__
>> +
>> +#include <linux/of.h>
>> +#include <linux/types.h>
>> +#include <asm/irq.h>
>> +#include <asm/atomic.h>
>> +#include <asm/setup.h>
>> +
>> +#ifdef CONFIG_OF
>> +extern void add_dtb(u64 data);
>> +#else
>> +static inline void add_dtb(u64 data) { }
>> +#endif
>> +
>> +extern char cmd_line[COMMAND_LINE_SIZE];
>> +/* This number is used when no interrupt has been assigned */
>> +#define NO_IRQ (-1)
>
> 0 means NO_IRQ on x86 and most architectures. I will change this when
> I pick up the patch.
>
>> +
>> +#define pci_address_to_pio pci_address_to_pio
>> +unsigned long pci_address_to_pio(phys_addr_t addr);
>> +
>> +/**
>> + * irq_dispose_mapping - Unmap an interrupt
>> + * @virq: linux virq number of the interrupt to unmap
>> + *
>> + * FIXME: We really should implement proper virq handling like power,
>> + * but that's going to be major surgery.
>> + */
>> +static inline void irq_dispose_mapping(unsigned int virq) { }
>> +
>> +#define HAVE_ARCH_DEVTREE_FIXUPS
>> +
>> +#endif /* __ASSEMBLY__ */
>> +
>> +/*
>> + * These includes are put at the bottom because they may contain things
>> + * that are overridden by this file. Ideally they shouldn't be included
>> + * by this file, but there are a bunch of .c files that currently depend
>> + * on it. Eventually they will be cleaned up.
>> + */
>> +#include <linux/of_fdt.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/platform_device.h>
>> +
>> +#endif
>> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
>> index f60153d..40bc33d 100644
>> --- a/arch/x86/kernel/Makefile
>> +++ b/arch/x86/kernel/Makefile
>> @@ -108,6 +108,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
>> obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
>>
>> obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
>> +obj-$(CONFIG_X86_OF) += prom.o
>>
>> ###
>> # 64 bit specific files
>> diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
>> index c752e97..149c87f 100644
>> --- a/arch/x86/kernel/irqinit.c
>> +++ b/arch/x86/kernel/irqinit.c
>> @@ -25,6 +25,7 @@
>> #include <asm/setup.h>
>> #include <asm/i8259.h>
>> #include <asm/traps.h>
>> +#include <asm/prom.h>
>>
>> /*
>> * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
>> diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
>> new file mode 100644
>> index 0000000..249ebd3
>> --- /dev/null
>> +++ b/arch/x86/kernel/prom.c
>> @@ -0,0 +1,54 @@
>> +/*
>> + * Architecture specific OF callbacks.
>> + */
>> +#include <linux/bootmem.h>
>> +#include <linux/io.h>
>> +#include <linux/list.h>
>> +#include <linux/of.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/slab.h>
>> +
>> +char __initdata cmd_line[COMMAND_LINE_SIZE];
>> +
>> +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);
>> +
>> +unsigned long pci_address_to_pio(phys_addr_t address)
>> +{
>> + /*
>> + * The ioport address can be directly used by inX / outX
>> + */
>> + BUG_ON(address >= (1 << 16));
>> + return (unsigned long)address;
>> +}
>> +EXPORT_SYMBOL_GPL(pci_address_to_pio);
>> +
>> +void __init early_init_dt_scan_chosen_arch(unsigned long node)
>> +{
>> + BUG();
>> +}
>> +
>> +void __init early_init_dt_add_memory_arch(u64 base, u64 size)
>> +{
>> + BUG();
>> +}
>> +
>> +u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
>> +{
>> + void *mem;
>> +
>> + mem = __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
>> + return virt_to_phys(mem);
>> +}
>> +
>> +void __init add_dtb(u64 data)
>> +{
>> + initial_boot_params = (struct boot_param_header *)
>> + phys_to_virt((u64) (u32) data +
>> + offsetof(struct setup_data, data));
>> +}
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 577d06b..26f2c9a 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -113,6 +113,7 @@
>> #endif
>> #include <asm/mce.h>
>> #include <asm/alternative.h>
>> +#include <asm/prom.h>
>>
>> /*
>> * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
>> @@ -445,6 +446,9 @@ static void __init parse_setup_data(void)
>> case SETUP_E820_EXT:
>> parse_e820_ext(data);
>> break;
>> + case SETUP_DTB:
>> + add_dtb(pa_data);
>> + break;
>
> Why is the physical address being passed in when the virtual address
> is needed to be stored in initial_boot_params by add_dtb()?
>
>
>> default:
>> break;
>> }
>> --
>> 1.7.3.2
>>
>> _______________________________________________
>> devicetree-discuss mailing list
>> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
>> https://lists.ozlabs.org/listinfo/devicetree-discuss
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 02/15] x86: Add device tree support
[not found] ` <AANLkTi=EFewaizO=1FLALE0eQPUmaFPfTmgoeF+JRpkt-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-01-02 0:40 ` H. Peter Anvin
0 siblings, 0 replies; 42+ messages in thread
From: H. Peter Anvin @ 2011-01-02 0:40 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Thomas Gleixner,
Sebastian Andrzej Siewior
On 12/30/2010 01:01 PM, Grant Likely wrote:
> 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.
>
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
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 03/15] x86/dtb: Add a device tree for CE4100
[not found] ` <20101230085122.GE11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-03 11:28 ` Sebastian Andrzej Siewior
2011-01-03 17:45 ` Grant Likely
2011-01-05 10:01 ` [PATCH " Sebastian Andrzej Siewior
2011-01-05 23:20 ` David Gibson
2 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-03 11:28 UTC (permalink / raw)
To: Grant Likely
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Grant Likely wrote:
>> 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
>> +
>> + i2c@15a00 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <0x15a00 0x0 0x0 0x0>;
>> +
>> +
>> + i2c@0 {
>> + reg = <0>;
>> + };
>> +
>> + i2c@1 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <1>;
>> +
>> + pcf8575@26 {
>> + compatible = "ti,pcf8575";
>> + reg = <0x26>;
>> + };
>> + };
>> +
>> + i2c@2 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <2>;
>> +
>> + pcf8575@26 {
>> + compatible = "ti,pcf8575";
>> + reg = <0x26>;
>> + };
>> + };
>
> All these i2c bus controllers should have a compatible value so that
> the OS knows what driver to bind to them.
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
that be okay?
> Also, the node names for the i2c devices should reflect what the
> device does, not what the part number is (grep ePAPR for 'generic
> names')
Okay. This probably also means that I should replace pic@ with
interrupt-controller and so on.
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 02/15] x86: Add device tree support
[not found] ` <20101230084311.GD11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2010-12-30 21:01 ` Grant Likely
@ 2011-01-03 12:20 ` Sebastian Andrzej Siewior
2011-01-03 18:05 ` [sodaville] " H. Peter Anvin
1 sibling, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-03 12:20 UTC (permalink / raw)
To: Grant Likely
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Grant Likely wrote:
>> +extern char cmd_line[COMMAND_LINE_SIZE];
>> +/* This number is used when no interrupt has been assigned */
>> +#define NO_IRQ (-1)
>
> 0 means NO_IRQ on x86 and most architectures. I will change this when
> I pick up the patch.
cat /proc/interrupts
CPU0
0: 40 IO-APIC-edge timer
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 577d06b..26f2c9a 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -113,6 +113,7 @@
>> #endif
>> #include <asm/mce.h>
>> #include <asm/alternative.h>
>> +#include <asm/prom.h>
>>
>> /*
>> * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
>> @@ -445,6 +446,9 @@ static void __init parse_setup_data(void)
>> case SETUP_E820_EXT:
>> parse_e820_ext(data);
>> break;
>> + case SETUP_DTB:
>> + add_dtb(pa_data);
>> + break;
>
> Why is the physical address being passed in when the virtual address
> is needed to be stored in initial_boot_params by add_dtb()?
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,
patch #5) is called. After that initial_boot_params is set and can be used.
>> default:
>> break;
>> }
>> --
>> 1.7.3.2
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 03/15] x86/dtb: Add a device tree for CE4100
2011-01-03 11:28 ` Sebastian Andrzej Siewior
@ 2011-01-03 17:45 ` Grant Likely
[not found] ` <20110103174500.GC2522-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2011-01-03 17:45 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, sodaville, x86, devicetree-discuss
On Mon, Jan 03, 2011 at 12:28:24PM +0100, Sebastian Andrzej Siewior wrote:
> Grant Likely wrote:
>
> >>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
> >>+
> >>+ i2c@15a00 {
> >>+ #address-cells = <1>;
> >>+ #size-cells = <0>;
> >>+ reg = <0x15a00 0x0 0x0 0x0>;
> >>+
> >>+
> >>+ i2c@0 {
> >>+ reg = <0>;
> >>+ };
> >>+
> >>+ i2c@1 {
> >>+ #address-cells = <1>;
> >>+ #size-cells = <0>;
> >>+ reg = <1>;
> >>+
> >>+ pcf8575@26 {
> >>+ compatible = "ti,pcf8575";
> >>+ reg = <0x26>;
> >>+ };
> >>+ };
> >>+
> >>+ i2c@2 {
> >>+ #address-cells = <1>;
> >>+ #size-cells = <0>;
> >>+ reg = <2>;
> >>+
> >>+ pcf8575@26 {
> >>+ compatible = "ti,pcf8575";
> >>+ reg = <0x26>;
> >>+ };
> >>+ };
> >
> >All these i2c bus controllers should have a compatible value so that
> >the OS knows what driver to bind to them.
>
> 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?
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
which uses 3 cells in this case.
> 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
> that be okay?
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 devices mapped off
// the same BAR)
//
// ranges allows the address mapping to be described
// in a way that the OS can interpret without
// requiring custom device driver code.
//
// This example assumes that each child node has it's
// own range of memory mapped registers.
ranges = <0 0 0x02000000 0 0xa0000000 0x1000>
<1 0 0x02000000 0 0xa0002000 0x1000>
<2 0 0x02000000 0 0xa0004000 0x1000>
i2c@0,0 {
#address-cells = <1>
#size-cells = <0>;
compatible = <need something here>;
reg = <1 0 0x1000>;
};
i2c@1,0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = <need something here>;
reg = <1 0 0x1000>;
pcf8575@26 {
compatible = "ti,pcf8575";
reg = <0x26>;
};
};
i2c@2,0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = <need something here>;
reg = <2 0 0x1000>;
pcf8575@26 {
compatible = "ti,pcf8575";
reg = <0x26>;
};
};
>
> >Also, the node names for the i2c devices should reflect what the
> >device does, not what the part number is (grep ePAPR for 'generic
> >names')
> Okay. This probably also means that I should replace pic@ with
> interrupt-controller and so on.
Correct.
g.
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [sodaville] [PATCH 02/15] x86: Add device tree support
2011-01-03 12:20 ` Sebastian Andrzej Siewior
@ 2011-01-03 18:05 ` H. Peter Anvin
0 siblings, 0 replies; 42+ messages in thread
From: H. Peter Anvin @ 2011-01-03 18:05 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Grant Likely, sodaville, devicetree-discuss, x86, linux-kernel
On 01/03/2011 04:20 AM, Sebastian Andrzej Siewior wrote:
> Grant Likely wrote:
>>> +extern char cmd_line[COMMAND_LINE_SIZE];
>>> +/* This number is used when no interrupt has been assigned */
>>> +#define NO_IRQ (-1)
>>
>> 0 means NO_IRQ on x86 and most architectures. I will change this when
>> I pick up the patch.
>
> cat /proc/interrupts
> CPU0
> 0: 40 IO-APIC-edge timer
>
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
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 05/15] x86/dtb: add early parsing of APIC and IO APIC
2010-12-30 8:54 ` Grant Likely
@ 2011-01-04 13:23 ` Sebastian Andrzej Siewior
[not found] ` <20110104132302.GB21359-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-04 13:23 UTC (permalink / raw)
To: Grant Likely
Cc: Sebastian Andrzej Siewior, linux-kernel, sodaville, x86,
devicetree-discuss
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>
#include <linux/list.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <asm/irq_controller.h>
+#include <asm/io_apic.h>
+__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
static LIST_HEAD(irq_domains);
static DEFINE_RAW_SPINLOCK(big_irq_lock);
+int __initdata of_ioapic;
+
void add_interrupt_host(struct irq_domain *ih)
{
unsigned long flags;
@@ -93,7 +98,117 @@ u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
void __init add_dtb(u64 data)
{
- initial_boot_params = (struct boot_param_header *)
- phys_to_virt((u64) (u32) data +
- offsetof(struct setup_data, data));
+ initial_dtb = data + offsetof(struct setup_data, data);
+}
+
+static void __init dtb_lapic_setup(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ if (apic_force_enable())
+ return;
+
+ smp_found_config = 1;
+ pic_mode = 1;
+ /* Required for ioapic registration */
+ set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+ if (boot_cpu_physical_apicid == -1U)
+ boot_cpu_physical_apicid = read_apic_id();
+
+ generic_processor_info(boot_cpu_physical_apicid,
+ GET_APIC_VERSION(apic_read(APIC_LVR)));
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+static void __init dtb_add_ioapic(struct device_node *dn)
+{
+ unsigned int ioapic_id;
+ const __be32 *cell;
+ int len;
+ struct resource r;
+ int ret;
+
+ cell = of_get_property(dn, "id", &len);
+ if (!cell) {
+ printk(KERN_ERR "Node %s is missing id property.\n",
+ dn->full_name);
+ return;
+ }
+ ioapic_id = of_read_ulong(cell, len / 4);
+
+ ret = of_address_to_resource(dn, 0, &r);
+ if (ret) {
+ printk(KERN_ERR "Can't obtain address from node %s.\n",
+ dn->full_name);
+ return;
+ }
+ mp_register_ioapic(ioapic_id, r.start, gsi_top);
+}
+
+static void __init dtb_ioapic_setup(void)
+{
+ struct device_node *dn;
+
+ if (!smp_found_config)
+ return;
+
+ for_each_compatible_node(dn, NULL, "intel,ioapic")
+ dtb_add_ioapic(dn);
+
+ if (nr_ioapics) {
+ of_ioapic = 1;
+ return;
+ }
+ printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+ smp_found_config = 0;
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
+
+static void __init dtb_apic_setup(void)
+{
+ dtb_lapic_setup();
+ dtb_ioapic_setup();
+}
+
+void __init x86_dtb_find_config(void)
+{
+ if (initial_dtb)
+ smp_found_config = 1;
+ else
+ printk(KERN_ERR "Missing device tree!.\n");
+}
+
+void __init x86_dtb_get_config(unsigned int unused)
+{
+ u32 size;
+ u32 map_len;
+ void *new_dtb;
+
+ if (!initial_dtb)
+ return;
+
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
+ (u64)sizeof(struct boot_param_header));
+
+ initial_boot_params = early_memremap(initial_dtb, map_len);
+ size = be32_to_cpu(initial_boot_params->totalsize);
+ if (map_len < size) {
+ early_iounmap(initial_boot_params, map_len);
+ initial_boot_params = early_memremap(initial_dtb, size);
+ map_len = size;
+ }
+
+ new_dtb = alloc_bootmem(size);
+ memcpy(new_dtb, initial_boot_params, size);
+ early_iounmap(initial_boot_params, map_len);
+
+ initial_boot_params = new_dtb;
+
+ /* root level address cells */
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+ unflatten_device_tree();
+ dtb_apic_setup();
}
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 07/15] of: move of_irq_map_pci() into generic code
2010-12-17 21:16 ` Benjamin Herrenschmidt
@ 2011-01-04 14:27 ` Sebastian Andrzej Siewior
[not found] ` <20110104142754.GD21359-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-04 14:27 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Sebastian Andrzej Siewior, x86-DgEjT+Ai2ygdnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
There is a tiny difference between PPC32 and PPC64. Microblaze uses the
PPC32 variant.
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
---
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
+++ 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__ */
#endif /* __KERNEL__ */
diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
index 99d9b61..306f41d 100644
--- a/arch/microblaze/kernel/prom_parse.c
+++ b/arch/microblaze/kernel/prom_parse.c
@@ -2,88 +2,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- u32 laddr[3];
- u8 pin;
- int rc;
-
- /* Check if we have a device node, if yes, fallback to standard OF
- * parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn)
- return of_irq_map_one(dn, 0, out_irq);
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
- struct pci_controller *host;
- host = pci_bus_to_host(pdev->bus);
- ppnode = host ? host->dn : NULL;
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't
- * include the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
-
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
- */
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
- }
-
- laddr[0] = (pdev->bus->number << 16)
- | (pdev->devfn << 8);
- laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index e363615..1e01a12 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <asm/processor.h>
#include <asm/io.h>
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 51e9e6f..edeb80f 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -171,6 +171,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/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index ae26f2e..01c3302 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -73,21 +73,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
#endif
#define of_node_to_nid of_node_to_nid
-/**
- * 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);
-
extern void of_instantiate_rtc(void);
/* These includes are put at the bottom because they may contain things
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 10a44e6..eb341be 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/syscalls.h>
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 88334af..306f41d 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -2,95 +2,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- u32 laddr[3];
- u8 pin;
- int rc;
-
- /* Check if we have a device node, if yes, fallback to standard OF
- * parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn) {
- rc = of_irq_map_one(dn, 0, out_irq);
- if (!rc)
- return rc;
- }
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
- ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
- struct pci_controller *host;
- host = pci_bus_to_host(pdev->bus);
- ppnode = host ? host->dn : NULL;
-#endif
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't include
- * the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
-
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
- */
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
- }
-
- laddr[0] = (pdev->bus->number << 16)
- | (pdev->devfn << 8);
- laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 7888155..4dcb177 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_SPI) += of_spi.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
+obj-$(CONFIG_PCI) += of_pci.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 0000000..dd862d2
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,80 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <asm/prom.h>
+
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+ struct device_node *dn, *ppnode;
+ struct pci_dev *ppdev;
+ u32 lspec;
+ __be32 lspec_be;
+ __be32 laddr[3];
+ u8 pin;
+ int rc;
+
+ /* Check if we have a device node, if yes, fallback to standard OF
+ * parsing
+ */
+ dn = pci_device_to_OF_node(pdev);
+ if (dn) {
+ rc = of_irq_map_one(dn, 0, out_irq);
+ if (!rc)
+ return rc;
+ }
+
+ /* Ok, we don't, time to have fun. Let's start by building up an
+ * interrupt spec. we assume #interrupt-cells is 1, which is standard
+ * for PCI. If you do different, then don't use that routine.
+ */
+ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+ if (rc != 0)
+ return rc;
+ /* No pin, exit */
+ if (pin == 0)
+ return -ENODEV;
+
+ /* Now we walk up the PCI tree */
+ lspec = pin;
+ for (;;) {
+ /* Get the pci_dev of our parent */
+ ppdev = pdev->bus->self;
+
+ /* Ouch, it's a host bridge... */
+ if (ppdev == NULL) {
+ ppnode = pci_bus_to_OF_node(pdev->bus);
+
+ /* No node for host bridge ? give up */
+ if (ppnode == NULL)
+ return -EINVAL;
+ } else {
+ /* We found a P2P bridge, check if it has a node */
+ ppnode = pci_device_to_OF_node(ppdev);
+ }
+
+ /* Ok, we have found a parent with a device-node, hand over to
+ * the OF parsing code.
+ * We build a unit address from the linux device to be used for
+ * resolution. Note that we use the linux bus number which may
+ * not match your firmware bus numbering.
+ * Fortunately, in most cases, interrupt-map-mask doesn't
+ * include the bus number as part of the matching.
+ * You should still be careful about that though if you intend
+ * to rely on this function (you ship a firmware that doesn't
+ * create device nodes for all PCI devices).
+ */
+ if (ppnode)
+ break;
+
+ /* We can only get here if we hit a P2P bridge with no node,
+ * let's do standard swizzling and try again
+ */
+ lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+ pdev = ppdev;
+ }
+
+ lspec_be = cpu_to_be32(lspec);
+ laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+ laddr[1] = laddr[2] = cpu_to_be32(0);
+ return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
new file mode 100644
index 0000000..9b0ba67
--- /dev/null
+++ b/include/linux/of_pci.h
@@ -0,0 +1,20 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+/**
+ * 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;
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+#endif
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 03/15] x86/dtb: Add a device tree for CE4100
[not found] ` <20110103174500.GC2522-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-05 9:48 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-05 9:48 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
Okay I
- dropped device_type except for cpu & pci. I have the compatible string
for pci so I can drop the device_type once it is possible
- I lowercased all compatible types. I will need to resend some patches
which have upper case intel
- The cpu had the same compatible string as the soc node. So I added to
the soc node -immr for internel memory mapped registers.
- I added generic names for all parts.
- I reworked the i2c bars matching the way you suggested. I added a
compatible node for the PCI device which only the PCI ids in its
compatible string. The bars (each represents a complete i2c
controller) have a "intel,ce4100-i2c-controller" compatible node. It
is not used by the driver.
The driver is probed via PCI ids (by the pci subsystem not OF) and
matches the bar address against the ressource in the child node. Once
there is a hit the node is attached.
- The SPI driver is also probed via pci. However I also attached a
compatible property based on PCI ids :)
arch/x86/platform/ce4100/falconfalls.dts | 230 ++++++++++++++++++++++++++++++
1 files changed, 230 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..4419864
--- /dev/null
+++ b/arch/x86/platform/ce4100/falconfalls.dts
@@ -0,0 +1,230 @@
+/*
+ * 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>;
+ compatible = "intel,ce4100-immr";
+ ranges;
+
+ ioapic1: pic@fec00000 {
+ #interrupt-cells = <2>;
+ compatible = "intel,ioapic";
+ interrupt-controller;
+ id = <1>;
+ reg = <0xfec00000 0x1000>;
+ };
+
+ timer@fed00000 {
+ compatible = "intel,hpet-ce4100", "intel,hpet";
+ reg = <0xfed00000 0x200>;
+ };
+
+ lapic0: interrupt-controller@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 0xbffff000 0 0x1000
+ 0x2000000 0 0xdffe0000 0xdffe0000 0 0x1000
+ 0x0000000 0 0x0 0x0 0 0x100>;
+
+ isa@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "isa";
+ ranges = <1 0 0 0 0 0x100>;
+
+ rtc@70 {
+ compatible = "motorola,mc146818";
+ interrupts = <8 3>;
+ interrupt-parent = <&ioapic1>;
+ ctrl-reg = <2>;
+ freq-reg = <0x26>;
+ reg = <1 0x70 2>;
+ };
+ };
+
+ /* Secondary IO-APIC */
+ ioapic2: pic@bffff000 {
+ #interrupt-cells = <2>;
+ compatible = "intel,ioapic-ce4100", "intel,ioapic";
+ interrupt-controller;
+ id = <2>;
+ reg = <0x100 0x0 0x0 0x0 0x0>;
+ assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+ };
+
+ pci@av {
+ #address-cells = <3>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ compatible = "intel,ce4100-pci";
+ device_type = "pci";
+ bus-range = <1 1>;
+ ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
+
+ interrupt-map-mask = <0xffffff 0x0 0x0 0x0>;
+ interrupt-map = <
+ /* GFX: 0x2E5B */
+ 0x11000 0x0 0x0 0x0 &ioapic2 0 0x1
+ /* ***** FIXME ****** Compositing Engine: 0x2E72 */
+ /* 0x11100 0x0 0x0 0x1 &ioapic2 0 0x1 */
+ /* MFD: 0x2E5C */
+ 0x11800 0x0 0x0 0x0 &ioapic2 2 0x1
+ /* TS Prefilter: 0x2E5D */
+ 0x12000 0x0 0x0 0x0 &ioapic2 4 0x1
+ /* TS Demux: 0x2E5E */
+ 0x12100 0x0 0x0 0x0 &ioapic2 5 0x1
+ /* ***** FIXME ***** Audio DSP: 0x2E5F */
+ /* 0x13000 0x0 0x0 0x1 &ioapic2 0 0x1 */
+ /* Audio Interfaces: 0x2E60 */
+ 0x13200 0x0 0x0 0x0 &ioapic2 8 0x1
+ /* VDC: 0x2E61 */
+ 0x14000 0x0 0x0 0x0 &ioapic2 9 0x1
+ /* DPE: 0x2E62 */
+ 0x14100 0x0 0x0 0x0 &ioapic2 10 0x1
+ /* HDMI Tx: 0x2E63 */
+ 0x14200 0x0 0x0 0x0 &ioapic2 11 0x1
+ /* SEC: 0x2E64 */
+ 0x14800 0x0 0x0 0x0 &ioapic2 12 0x1
+ /* EXP: 0x2E65 */
+ 0x15000 0x0 0x0 0x0 &ioapic2 13 0x1
+ /* UART0/1: 0x2E66 */
+ 0x15800 0x0 0x0 0x0 &ioapic2 14 0x1
+ /* GPIO: 0x2E67 */
+ 0x15900 0x0 0x0 0x0 &ioapic2 15 0x1
+ /* I2C0/1/2: 0x2E68 */
+ 0x15a00 0x0 0x0 0x0 &ioapic2 16 0x1
+ /* Smart Card 0/1: 0x2E69 */
+ 0x15b00 0x0 0x0 0x0 &ioapic2 15 0x1
+ /* SPI: 0x2E6A */
+ 0x15c00 0x0 0x0 0x0 &ioapic2 15 0x1
+ /* MSPOD: 0x2E6B */
+ 0x15d00 0x0 0x0 0x0 &ioapic2 19 0x1
+ /* IR: 0x2E6C */
+ 0x15e00 0x0 0x0 0x0 &ioapic2 16 0x1
+ /* **** FIXME ***** DFX: 0x2E6D */
+ /* 0x15f00 0x0 0x0 0x1 &ioapic2 0x0 0x1 */
+ /* Gig Ethernet: 0x2E6E */
+ 0x16000 0x0 0x0 0x0 &ioapic2 21 0x1
+ /* IEEE1588 and Clock Recovery Unit: 0x2E6F */
+ 0x16100 0x0 0x0 0x0 &ioapic2 3 0x1
+ /* USB0: 0x2E70 */
+ 0x16800 0x0 0x0 0x0 &ioapic2 22 0x3
+ /* USB1: 0x2E70 */
+ 0x16900 0x0 0x0 0x0 &ioapic2 22 0x3
+ /* SATA: 0x2E71 */
+ 0x17000 0x0 0x0 0x0 &ioapic2 23 0x3
+ >;
+
+ i2c-controller@15a00,0,0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "pci8086,2e68.2",
+ "pci8086,2e68",
+ "pciclass,ff0000",
+ "pciclass,ff00";
+
+ reg = <0x15a00 0x0 0x0 0x0 0x0>;
+ ranges = <0 0 0x02000000 0 0xdffe0500 0x100
+ 1 0 0x02000000 0 0xdffe0600 0x100
+ 2 0 0x02000000 0 0xdffe0700 0x100>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ce4100-i2c-controller";
+ reg = <0 0 0x100>;
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ce4100-i2c-controller";
+ reg = <1 0 0x100>;
+
+ gpio@26 {
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ce4100-i2c-controller";
+ reg = <2 0 0x100>;
+
+ gpio@26 {
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ };
+ };
+ };
+
+ spi-controller@15c00,0,0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible =
+ "pci8086,2e6a.2",
+ "pci8086,2e6a",
+ "pciclass,ff0000",
+ "pciclass,ff00";
+
+ reg = <0x15c00 0x0 0x0 0x0 0x0>;
+
+ dac@0 {
+ compatible = "ti,pcm1755";
+ reg = <0>;
+ spi-max-frequency = <115200>;
+ };
+
+ dac@1 {
+ compatible = "ti,pcm1609a";
+ reg = <1>;
+ spi-max-frequency = <115200>;
+ };
+
+ eeprom@2 {
+ compatible = "atmel,at93c46";
+ reg = <2>;
+ spi-max-frequency = <115200>;
+ };
+ };
+ };
+ };
+ };
+};
--
1.7.3.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH 03/15] x86/dtb: Add a device tree for CE4100
[not found] ` <20101230085122.GE11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-03 11:28 ` Sebastian Andrzej Siewior
@ 2011-01-05 10:01 ` Sebastian Andrzej Siewior
2011-01-05 23:20 ` David Gibson
2 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-05 10:01 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
* Grant Likely | 2010-12-30 01:51:22 [-0700]:
>> 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";
>
>To-date the convention has been to use all lowercase in compatible
>properties. Ditto throughout this file.
done
>> + soc@0 {
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> + device_type = "soc";
>
>Drop device_type property.
done
>> + ioapic1: pic@fec00000 {
>> + #interrupt-cells = <2>;
>> + compatible = "Intel,ioapic";
>> + interrupt-controller;
>> + device_type = "interrupt-controller";
>
>Ditto
done
>> + pci@3fc {
>> + #address-cells = <3>;
>> + #interrupt-cells = <1>;
>> + #size-cells = <2>;
>> + compatible = "Intel,ce4100-pci", "pci";
>> + device_type = "pci";
>
>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
>alternative to 'device_type = "pci";'.
I have the pci property. So I drop the device_type once it is possible.
>> + isa@0 {
>> + #address-cells = <2>;
>> + #size-cells = <1>;
>> + compatible = "isa";
>> + ranges = <1 0 0 0 0 0x100>;
>> +
>> + rtc@70 {
>> + compatible = "motorola,mc146818";
>> + interrupts = <8 3>;
>> + interrupt-parent = <&ioapic1>;
>
>If you put an interrupt-parent property in the root node, then it will
>become the default interrupt controller for the system which is
>usually convenient to have.
Okay, I mode it once I have more common devices. I have two interrupt
controller and most devices are attached to the second one (and are
assigned via interrupt-map).
>> + /* Secondary IO-APIC */
>> + ioapic2: pic@bffff000 {
>> + #interrupt-cells = <2>;
>> + compatible = "Intel,ioapic-ce4100", "Intel,ioapic";
>> + interrupt-controller;
>> + device_type = "interrupt-controller";
>
>Drop device_type.
done
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 03/15] x86/dtb: Add a device tree for CE4100
[not found] ` <20101230085122.GE11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-03 11:28 ` Sebastian Andrzej Siewior
2011-01-05 10:01 ` [PATCH " Sebastian Andrzej Siewior
@ 2011-01-05 23:20 ` David Gibson
2 siblings, 0 replies; 42+ messages in thread
From: David Gibson @ 2011-01-05 23:20 UTC (permalink / raw)
To: Grant Likely
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Thu, Dec 30, 2010 at 01:51:22AM -0700, Grant Likely wrote:
> On Fri, Dec 17, 2010 at 04:33:41PM +0100, Sebastian Andrzej Siewior wrote:
[snip]
> > +/dts-v1/;
> > +/ {
> > + model = "Intel,FalconFalls";
> > + compatible = "Intel,FalconFalls";
>
> To-date the convention has been to use all lowercase in compatible
> properties. Ditto throughout this file.
IEEE1275 actually explicitly gives the convention on p164, in the
context of the "name" property. The vendor string can either be all
uppercase, in which case it must be a stock ticker symbol ("AAPL" is
seen in the wild, for example), or it can be another string with no
uppercase.
I'm sure some intel peripheral chips must have been used on existing
OF platforms at various points. It might be worth seeking those out
and double checking what was used in those cases.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 04/15] x86/dtb: add irq domain abstraction
2010-12-17 15:33 ` [PATCH 04/15] x86/dtb: add irq domain abstraction Sebastian Andrzej Siewior
@ 2011-01-11 22:03 ` Grant Likely
[not found] ` <20110111220317.GA2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2011-01-11 22:03 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: linux-kernel, sodaville, x86, devicetree-discuss
On Fri, Dec 17, 2010 at 04:33:42PM +0100, Sebastian Andrzej Siewior wrote:
> 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;
> +};
True, it's not a full implementation, but I'd rather the same
structure be used for both powerpc and x86.
Thomas, this only touches x86, so I have no objection to you merging
it, but I'd like to see a follow up patch to merge the x86 and powerpc
irq_host/irq_domain structures.
However, there is a defect below that must be fixed first....
> unsigned int irq_create_of_mapping(struct device_node *controller,
> const u32 *intspec, unsigned int intsize)
> {
> - return intspec[0];
> + struct irq_domain *ih;
> + u32 virq;
> + u32 type;
> + int ret;
>
> + ih = get_ih_from_node(controller);
> + if (!ih)
> + return -ENODEV;
Return value is an unsigned int. 0 or NO_IRQ is the correct thing to
return if an IRQ cannot be mapped.
> + ret = ih->xlate(ih, intspec, intsize, &virq, &type);
> + if (ret)
> + return ret;
Ditto here. xlate is also supposed to return a virq number, not an
error code, so the failure condition must be "if (!ret)" or
"if (reg == NO_IRQ)". The former is preferred since we're trying to
eliminate references to NO_IRQ, not add more of them.
> + if (type == IRQ_TYPE_NONE)
> + return virq;
> + /* set the mask if it is different from current */
> + if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
> + set_irq_type(virq, type);
> + return virq;
> }
> EXPORT_SYMBOL_GPL(irq_create_of_mapping);
>
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 05/15] x86/dtb: add early parsing of APIC and IO APIC
[not found] ` <20110104132302.GB21359-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
@ 2011-01-11 22:14 ` Grant Likely
[not found] ` <20110111221401.GB2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2011-01-11 22:14 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tue, Jan 04, 2011 at 02:23:02PM +0100, Sebastian Andrzej Siewior wrote:
> 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.
Hi Sebastian,
Some comments below...
>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> ---
> 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
Nit: Personally, I prefer static inlines over preprocessor macros, but
that isn't anything that will block this patch.
> #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>
> #include <linux/list.h>
> #include <linux/of.h>
> +#include <linux/of_address.h>
> #include <linux/of_platform.h>
> #include <linux/slab.h>
>
> #include <asm/irq_controller.h>
> +#include <asm/io_apic.h>
>
> +__initdata u64 initial_dtb;
> char __initdata cmd_line[COMMAND_LINE_SIZE];
> static LIST_HEAD(irq_domains);
> static DEFINE_RAW_SPINLOCK(big_irq_lock);
>
> +int __initdata of_ioapic;
> +
> void add_interrupt_host(struct irq_domain *ih)
> {
> unsigned long flags;
> @@ -93,7 +98,117 @@ u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
>
> void __init add_dtb(u64 data)
> {
> - initial_boot_params = (struct boot_param_header *)
> - phys_to_virt((u64) (u32) data +
> - offsetof(struct setup_data, data));
> + initial_dtb = data + offsetof(struct setup_data, data);
> +}
> +
> +static void __init dtb_lapic_setup(void)
> +{
> +#ifdef CONFIG_X86_LOCAL_APIC
> + if (apic_force_enable())
> + return;
> +
> + smp_found_config = 1;
> + pic_mode = 1;
> + /* Required for ioapic registration */
> + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
> + if (boot_cpu_physical_apicid == -1U)
> + boot_cpu_physical_apicid = read_apic_id();
> +
> + generic_processor_info(boot_cpu_physical_apicid,
> + GET_APIC_VERSION(apic_read(APIC_LVR)));
> +#endif
> +}
> +
> +#ifdef CONFIG_X86_IO_APIC
> +static void __init dtb_add_ioapic(struct device_node *dn)
> +{
> + unsigned int ioapic_id;
> + const __be32 *cell;
> + int len;
> + struct resource r;
> + int ret;
> +
> + cell = of_get_property(dn, "id", &len);
> + if (!cell) {
> + printk(KERN_ERR "Node %s is missing id property.\n",
> + dn->full_name);
> + return;
> + }
> + ioapic_id = of_read_ulong(cell, len / 4);
This looks like poor usage practise for the device tree. 'id' or any
kind of enumeration property in a device tree node is strongly
discouraged. As much as possible, let Linux dynamically enumerate
devices rather than trying to explicitly specify the numbering. Since
you can explicitly describe the relationship between device nodes in
the tree, you should find that explicitly specifying numbers is almost
never required.
If you *really* need to enumerate devices in the device tree, then use
properties in the /aliases node to assign globally unique numbers.
> +
> + ret = of_address_to_resource(dn, 0, &r);
> + if (ret) {
> + printk(KERN_ERR "Can't obtain address from node %s.\n",
> + dn->full_name);
> + return;
> + }
> + mp_register_ioapic(ioapic_id, r.start, gsi_top);
> +}
> +
> +static void __init dtb_ioapic_setup(void)
> +{
> + struct device_node *dn;
> +
> + if (!smp_found_config)
> + return;
> +
> + for_each_compatible_node(dn, NULL, "intel,ioapic")
> + dtb_add_ioapic(dn);
> +
> + if (nr_ioapics) {
> + of_ioapic = 1;
> + return;
> + }
> + printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
> + smp_found_config = 0;
> +}
> +#else
> +static void __init dtb_ioapic_setup(void) {}
> +#endif
> +
> +static void __init dtb_apic_setup(void)
> +{
> + dtb_lapic_setup();
> + dtb_ioapic_setup();
> +}
> +
> +void __init x86_dtb_find_config(void)
> +{
> + if (initial_dtb)
> + smp_found_config = 1;
> + else
> + printk(KERN_ERR "Missing device tree!.\n");
> +}
> +
> +void __init x86_dtb_get_config(unsigned int unused)
> +{
> + u32 size;
> + u32 map_len;
> + void *new_dtb;
> +
> + if (!initial_dtb)
> + return;
> +
> + map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
> + (u64)sizeof(struct boot_param_header));
> +
> + initial_boot_params = early_memremap(initial_dtb, map_len);
> + size = be32_to_cpu(initial_boot_params->totalsize);
> + if (map_len < size) {
> + early_iounmap(initial_boot_params, map_len);
> + initial_boot_params = early_memremap(initial_dtb, size);
> + map_len = size;
> + }
> +
> + new_dtb = alloc_bootmem(size);
> + memcpy(new_dtb, initial_boot_params, size);
> + early_iounmap(initial_boot_params, map_len);
> +
> + initial_boot_params = new_dtb;
> +
> + /* root level address cells */
> + of_scan_flat_dt(early_init_dt_scan_root, NULL);
> +
> + unflatten_device_tree();
> + dtb_apic_setup();
> }
> --
> 1.7.3.2
>
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 06/15] x86/dtb: add support hpet
[not found] ` <1292600033-12271-7-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2011-01-11 22:26 ` Grant Likely
0 siblings, 0 replies; 42+ messages in thread
From: Grant Likely @ 2011-01-11 22:26 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Fri, Dec 17, 2010 at 04:33:44PM +0100, Sebastian Andrzej Siewior wrote:
> Set hpet_address based on information provied form DTB
>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Acked-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> 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
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 07/15] of: move of_irq_map_pci() into generic code
[not found] ` <20110104142754.GD21359-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
@ 2011-01-11 23:27 ` Grant Likely
[not found] ` <20110111232726.GD2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2011-01-11 23:27 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior
On Tue, Jan 04, 2011 at 03:27:54PM +0100, Sebastian Andrzej Siewior wrote:
> From: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
>
> There is a tiny difference between PPC32 and PPC64. Microblaze uses the
> PPC32 variant.
Mostly looks good, but breaks both Sparc and microblaze which is kind
of important to fix before I merge it. :-)
Sparc
-----
CC drivers/of/of_pci.o
/home/grant/hacking/linux-2.6/drivers/of/of_pci.c: In function 'of_irq_map_pci':
/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:20: error: implicit declaration of function 'of_irq_map_one'
/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:44: error: implicit declaration of function 'pci_bus_to_OF_node'
/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:44: warning: assignment makes pointer from integer without a cast
/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:78: error: implicit declaration of function 'of_irq_map_raw'
make[3]: *** [drivers/of/of_pci.o] Error 1
Microblaze
----------
CC arch/microblaze/kernel/prom.o
In file included from /home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci.h:23,
from /home/grant/hacking/linux-2.6/include/linux/pci.h:1230,
from /home/grant/hacking/linux-2.6/arch/microblaze/kernel/prom.c:23:
/home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci-bridge.h: In function 'pci_bus_to_OF_node':
/home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci-bridge.h:117: error: implicit declaration of function 'pci_device_to_OF_node'
/home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci-bridge.h:117: warning: return makes pointer from integer without a cast
make[2]: *** [arch/microblaze/kernel/prom.o] Error 1
make[1]: *** [arch/microblaze/kernel] Error 2
make: *** [sub-make] Error 2
>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
> Signed-off-by: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
> ---
> 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
> +++ 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__ */
> #endif /* __KERNEL__ */
>
> diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
> index 99d9b61..306f41d 100644
> --- a/arch/microblaze/kernel/prom_parse.c
> +++ b/arch/microblaze/kernel/prom_parse.c
> @@ -2,88 +2,11 @@
>
> #include <linux/kernel.h>
> #include <linux/string.h>
> -#include <linux/pci_regs.h>
> #include <linux/module.h>
> #include <linux/ioport.h>
> #include <linux/etherdevice.h>
> #include <linux/of_address.h>
> #include <asm/prom.h>
> -#include <asm/pci-bridge.h>
> -
> -#ifdef CONFIG_PCI
> -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
> -{
> - struct device_node *dn, *ppnode;
> - struct pci_dev *ppdev;
> - u32 lspec;
> - u32 laddr[3];
> - u8 pin;
> - int rc;
> -
> - /* Check if we have a device node, if yes, fallback to standard OF
> - * parsing
> - */
> - dn = pci_device_to_OF_node(pdev);
> - if (dn)
> - return of_irq_map_one(dn, 0, out_irq);
> -
> - /* Ok, we don't, time to have fun. Let's start by building up an
> - * interrupt spec. we assume #interrupt-cells is 1, which is standard
> - * for PCI. If you do different, then don't use that routine.
> - */
> - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
> - if (rc != 0)
> - return rc;
> - /* No pin, exit */
> - if (pin == 0)
> - return -ENODEV;
> -
> - /* Now we walk up the PCI tree */
> - lspec = pin;
> - for (;;) {
> - /* Get the pci_dev of our parent */
> - ppdev = pdev->bus->self;
> -
> - /* Ouch, it's a host bridge... */
> - if (ppdev == NULL) {
> - struct pci_controller *host;
> - host = pci_bus_to_host(pdev->bus);
> - ppnode = host ? host->dn : NULL;
> - /* No node for host bridge ? give up */
> - if (ppnode == NULL)
> - return -EINVAL;
> - } else
> - /* We found a P2P bridge, check if it has a node */
> - ppnode = pci_device_to_OF_node(ppdev);
> -
> - /* Ok, we have found a parent with a device-node, hand over to
> - * the OF parsing code.
> - * We build a unit address from the linux device to be used for
> - * resolution. Note that we use the linux bus number which may
> - * not match your firmware bus numbering.
> - * Fortunately, in most cases, interrupt-map-mask doesn't
> - * include the bus number as part of the matching.
> - * You should still be careful about that though if you intend
> - * to rely on this function (you ship a firmware that doesn't
> - * create device nodes for all PCI devices).
> - */
> - if (ppnode)
> - break;
> -
> - /* We can only get here if we hit a P2P bridge with no node,
> - * let's do standard swizzling and try again
> - */
> - lspec = pci_swizzle_interrupt_pin(pdev, lspec);
> - pdev = ppdev;
> - }
> -
> - laddr[0] = (pdev->bus->number << 16)
> - | (pdev->devfn << 8);
> - laddr[1] = laddr[2] = 0;
> - return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
> -}
> -EXPORT_SYMBOL_GPL(of_irq_map_pci);
> -#endif /* CONFIG_PCI */
>
> void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
> unsigned long *busno, unsigned long *phys, unsigned long *size)
> diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
> index e363615..1e01a12 100644
> --- a/arch/microblaze/pci/pci-common.c
> +++ b/arch/microblaze/pci/pci-common.c
> @@ -29,6 +29,7 @@
> #include <linux/slab.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> +#include <linux/of_pci.h>
>
> #include <asm/processor.h>
> #include <asm/io.h>
> diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
> index 51e9e6f..edeb80f 100644
> --- a/arch/powerpc/include/asm/pci-bridge.h
> +++ b/arch/powerpc/include/asm/pci-bridge.h
> @@ -171,6 +171,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/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
> index ae26f2e..01c3302 100644
> --- a/arch/powerpc/include/asm/prom.h
> +++ b/arch/powerpc/include/asm/prom.h
> @@ -73,21 +73,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
> #endif
> #define of_node_to_nid of_node_to_nid
>
> -/**
> - * 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);
> -
> extern void of_instantiate_rtc(void);
>
> /* These includes are put at the bottom because they may contain things
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> index 10a44e6..eb341be 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -22,6 +22,7 @@
> #include <linux/init.h>
> #include <linux/bootmem.h>
> #include <linux/of_address.h>
> +#include <linux/of_pci.h>
> #include <linux/mm.h>
> #include <linux/list.h>
> #include <linux/syscalls.h>
> diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
> index 88334af..306f41d 100644
> --- a/arch/powerpc/kernel/prom_parse.c
> +++ b/arch/powerpc/kernel/prom_parse.c
> @@ -2,95 +2,11 @@
>
> #include <linux/kernel.h>
> #include <linux/string.h>
> -#include <linux/pci_regs.h>
> #include <linux/module.h>
> #include <linux/ioport.h>
> #include <linux/etherdevice.h>
> #include <linux/of_address.h>
> #include <asm/prom.h>
> -#include <asm/pci-bridge.h>
> -
> -#ifdef CONFIG_PCI
> -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
> -{
> - struct device_node *dn, *ppnode;
> - struct pci_dev *ppdev;
> - u32 lspec;
> - u32 laddr[3];
> - u8 pin;
> - int rc;
> -
> - /* Check if we have a device node, if yes, fallback to standard OF
> - * parsing
> - */
> - dn = pci_device_to_OF_node(pdev);
> - if (dn) {
> - rc = of_irq_map_one(dn, 0, out_irq);
> - if (!rc)
> - return rc;
> - }
> -
> - /* Ok, we don't, time to have fun. Let's start by building up an
> - * interrupt spec. we assume #interrupt-cells is 1, which is standard
> - * for PCI. If you do different, then don't use that routine.
> - */
> - rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
> - if (rc != 0)
> - return rc;
> - /* No pin, exit */
> - if (pin == 0)
> - return -ENODEV;
> -
> - /* Now we walk up the PCI tree */
> - lspec = pin;
> - for (;;) {
> - /* Get the pci_dev of our parent */
> - ppdev = pdev->bus->self;
> -
> - /* Ouch, it's a host bridge... */
> - if (ppdev == NULL) {
> -#ifdef CONFIG_PPC64
> - ppnode = pci_bus_to_OF_node(pdev->bus);
> -#else
> - struct pci_controller *host;
> - host = pci_bus_to_host(pdev->bus);
> - ppnode = host ? host->dn : NULL;
> -#endif
> - /* No node for host bridge ? give up */
> - if (ppnode == NULL)
> - return -EINVAL;
> - } else
> - /* We found a P2P bridge, check if it has a node */
> - ppnode = pci_device_to_OF_node(ppdev);
> -
> - /* Ok, we have found a parent with a device-node, hand over to
> - * the OF parsing code.
> - * We build a unit address from the linux device to be used for
> - * resolution. Note that we use the linux bus number which may
> - * not match your firmware bus numbering.
> - * Fortunately, in most cases, interrupt-map-mask doesn't include
> - * the bus number as part of the matching.
> - * You should still be careful about that though if you intend
> - * to rely on this function (you ship a firmware that doesn't
> - * create device nodes for all PCI devices).
> - */
> - if (ppnode)
> - break;
> -
> - /* We can only get here if we hit a P2P bridge with no node,
> - * let's do standard swizzling and try again
> - */
> - lspec = pci_swizzle_interrupt_pin(pdev, lspec);
> - pdev = ppdev;
> - }
> -
> - laddr[0] = (pdev->bus->number << 16)
> - | (pdev->devfn << 8);
> - laddr[1] = laddr[2] = 0;
> - return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
> -}
> -EXPORT_SYMBOL_GPL(of_irq_map_pci);
> -#endif /* CONFIG_PCI */
>
> void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
> unsigned long *busno, unsigned long *phys, unsigned long *size)
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 7888155..4dcb177 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
> obj-$(CONFIG_OF_I2C) += of_i2c.o
> obj-$(CONFIG_OF_SPI) += of_spi.o
> obj-$(CONFIG_OF_MDIO) += of_mdio.o
> +obj-$(CONFIG_PCI) += of_pci.o
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> new file mode 100644
> index 0000000..dd862d2
> --- /dev/null
> +++ b/drivers/of/of_pci.c
> @@ -0,0 +1,80 @@
> +#include <linux/kernel.h>
> +#include <linux/of_pci.h>
> +#include <asm/prom.h>
> +
> +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
> +{
> + struct device_node *dn, *ppnode;
> + struct pci_dev *ppdev;
> + u32 lspec;
> + __be32 lspec_be;
> + __be32 laddr[3];
> + u8 pin;
> + int rc;
> +
> + /* Check if we have a device node, if yes, fallback to standard OF
> + * parsing
> + */
> + dn = pci_device_to_OF_node(pdev);
> + if (dn) {
> + rc = of_irq_map_one(dn, 0, out_irq);
> + if (!rc)
> + return rc;
> + }
> +
> + /* Ok, we don't, time to have fun. Let's start by building up an
> + * interrupt spec. we assume #interrupt-cells is 1, which is standard
> + * for PCI. If you do different, then don't use that routine.
> + */
> + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
> + if (rc != 0)
> + return rc;
> + /* No pin, exit */
> + if (pin == 0)
> + return -ENODEV;
> +
> + /* Now we walk up the PCI tree */
> + lspec = pin;
> + for (;;) {
> + /* Get the pci_dev of our parent */
> + ppdev = pdev->bus->self;
> +
> + /* Ouch, it's a host bridge... */
> + if (ppdev == NULL) {
> + ppnode = pci_bus_to_OF_node(pdev->bus);
> +
> + /* No node for host bridge ? give up */
> + if (ppnode == NULL)
> + return -EINVAL;
> + } else {
> + /* We found a P2P bridge, check if it has a node */
> + ppnode = pci_device_to_OF_node(ppdev);
> + }
> +
> + /* Ok, we have found a parent with a device-node, hand over to
> + * the OF parsing code.
> + * We build a unit address from the linux device to be used for
> + * resolution. Note that we use the linux bus number which may
> + * not match your firmware bus numbering.
> + * Fortunately, in most cases, interrupt-map-mask doesn't
> + * include the bus number as part of the matching.
> + * You should still be careful about that though if you intend
> + * to rely on this function (you ship a firmware that doesn't
> + * create device nodes for all PCI devices).
> + */
> + if (ppnode)
> + break;
> +
> + /* We can only get here if we hit a P2P bridge with no node,
> + * let's do standard swizzling and try again
> + */
> + lspec = pci_swizzle_interrupt_pin(pdev, lspec);
> + pdev = ppdev;
> + }
> +
> + lspec_be = cpu_to_be32(lspec);
> + laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
> + laddr[1] = laddr[2] = cpu_to_be32(0);
> + return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
> +}
> +EXPORT_SYMBOL_GPL(of_irq_map_pci);
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> new file mode 100644
> index 0000000..9b0ba67
> --- /dev/null
> +++ b/include/linux/of_pci.h
> @@ -0,0 +1,20 @@
> +#ifndef __OF_PCI_H
> +#define __OF_PCI_H
> +
> +#include <linux/pci.h>
> +
> +/**
> + * 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;
> +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
> +#endif
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 08/15] x86/dtb: add support for PCI devices backed by dtb nodes
[not found] ` <1292600033-12271-9-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2011-01-11 23:47 ` Grant Likely
0 siblings, 0 replies; 42+ messages in thread
From: Grant Likely @ 2011-01-11 23:47 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Fri, Dec 17, 2010 at 04:33:46PM +0100, Sebastian Andrzej Siewior wrote:
> 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-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Tested-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> ---
> 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;
> +}
> +
Hmmm, maybe pci_device_to_OF_node() should be checking for
bus->self == NULL. It would probably be safer overall.
Otherwise, the patch looks good to me.
g.
> #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 a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
> index 40ad8c0..a449dc6 100644
> --- a/arch/x86/kernel/prom.c
> +++ b/arch/x86/kernel/prom.c
> @@ -9,10 +9,13 @@
> #include <linux/of_address.h>
> #include <linux/of_platform.h>
> #include <linux/slab.h>
> +#include <linux/pci.h>
> +#include <linux/of_pci.h>
>
> #include <asm/hpet.h>
> #include <asm/irq_controller.h>
> #include <asm/io_apic.h>
> +#include <asm/pci_x86.h>
>
> __initdata u64 initial_dtb;
> char __initdata cmd_line[COMMAND_LINE_SIZE];
> @@ -102,6 +105,83 @@ void __init add_dtb(u64 data)
> initial_dtb = data + offsetof(struct setup_data, data);
> }
>
> +static int x86_of_pci_irq_enable(struct pci_dev *dev)
> +{
> + struct of_irq oirq;
> + u32 virq;
> + int ret;
> + u8 pin;
> +
> + ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> + if (ret)
> + return ret;
> + if (!pin)
> + return 0;
> +
> + ret = of_irq_map_pci(dev, &oirq);
> + if (ret)
> + return ret;
> +
> + virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
> + oirq.size);
> + if (virq == NO_IRQ)
> + return -EINVAL;
> + dev->irq = virq;
> + return 0;
> +}
> +
> +static void x86_of_pci_irq_disable(struct pci_dev *dev)
> +{
> +}
> +
> +void __cpuinit x86_of_pci_init(void)
> +{
> + struct device_node *np;
> +
> + pcibios_enable_irq = x86_of_pci_irq_enable;
> + pcibios_disable_irq = x86_of_pci_irq_disable;
> +
> + for_each_node_by_type(np, "pci") {
> + const void *prop;
> + struct pci_bus *bus;
> + unsigned int bus_min;
> + struct device_node *child;
> +
> + prop = of_get_property(np, "bus-range", NULL);
> + if (!prop)
> + continue;
> + bus_min = be32_to_cpup(prop);
> +
> + bus = pci_find_bus(0, bus_min);
> + if (!bus) {
> + printk(KERN_ERR "Can't find a node for bus %s.\n",
> + np->full_name);
> + continue;
> + }
> +
> + if (bus->self)
> + bus->self->dev.of_node = np;
> + else
> + bus->dev.of_node = np;
> +
> + for_each_child_of_node(np, child) {
> + struct pci_dev *dev;
> + u32 devfn;
> +
> + prop = of_get_property(child, "reg", NULL);
> + if (!prop)
> + continue;
> +
> + devfn = (be32_to_cpup(prop) >> 8) & 0xff;
> + dev = pci_get_slot(bus, devfn);
> + if (!dev)
> + continue;
> + dev->dev.of_node = child;
> + pci_dev_put(dev);
> + }
> + }
> +}
> +
> static void __init dtb_setup_hpet(void)
> {
> struct device_node *dn;
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 09/15] x86/dtb: Add generic bus probe
[not found] ` <1292600033-12271-10-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2011-01-11 23:48 ` Grant Likely
0 siblings, 0 replies; 42+ messages in thread
From: Grant Likely @ 2011-01-11 23:48 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Fri, Dec 17, 2010 at 04:33:47PM +0100, Sebastian Andrzej Siewior wrote:
> For now we probe these busses and we change is to board dependent probes
> once we have to.
>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Acked-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> 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
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC
[not found] ` <1292600033-12271-11-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2011-01-11 23:53 ` Grant Likely
[not found] ` <20110111235353.GG2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2011-01-11 23:53 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Fri, Dec 17, 2010 at 04:33:48PM +0100, Sebastian Andrzej Siewior wrote:
> 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.
One question below, but otherwise looks okay to me.
g.
>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> 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 pci_bus *bus)
>
> #else
> static inline void add_dtb(u64 data) { }
> +static inline void x86_add_irq_domains(void) { }
> 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
> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> index 7eb0027..4dece80 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -43,6 +43,7 @@
> #include <linux/bootmem.h>
> #include <linux/dmar.h>
> #include <linux/hpet.h>
> +#include <linux/of_address.h>
>
> #include <asm/idle.h>
> #include <asm/io.h>
> @@ -60,6 +61,7 @@
> #include <asm/irq_remapping.h>
> #include <asm/hpet.h>
> #include <asm/hw_irq.h>
> +#include <asm/irq_controller.h>
>
> #include <asm/apic.h>
>
> @@ -88,6 +90,10 @@ int nr_ioapics;
> /* IO APIC gsi routing info */
> struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS];
>
> +#ifdef CONFIG_X86_OF
> +/* OF -> IO APIC lookup */
> +struct mp_of_ioapic mp_of_ioapic[MAX_IO_APICS];
> +#endif
> /* The one past the highest gsi number used */
> u32 gsi_top;
>
> @@ -4080,6 +4086,99 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
> nr_ioapics++;
> }
>
> +#ifdef CONFIG_X86_OF
> +static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
> + u32 *out_hwirq, u32 *out_type)
> +{
> + u32 line;
> + u32 idx;
> + u32 type;
> + u32 trigger;
> + u32 polarity;
> + struct irq_cfg *cfg;
> + struct irq_desc *desc;
> +
> + if (intsize < 1)
> + return -EINVAL;
> +
> + line = *intspec;
> + idx = (u32) id->priv;
> + *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
> + if (intsize > 1) {
> + intspec++;
> + type = *intspec;
> + switch (type) {
> + case 0:
> + *out_type = IRQ_TYPE_EDGE_RISING;
> + trigger = IOAPIC_EDGE;
> + polarity = 1;
> + break;
> + case 1:
> + *out_type = IRQ_TYPE_LEVEL_LOW;
> + trigger = IOAPIC_LEVEL;
> + polarity = 0;
> + break;
> + case 2:
> + *out_type = IRQ_TYPE_LEVEL_HIGH;
> + trigger = IOAPIC_LEVEL;
> + polarity = 1;
> + break;
> + case 3:
> + *out_type = IRQ_TYPE_EDGE_FALLING;
> + trigger = IOAPIC_EDGE;
> + polarity = 0;
> + break;
> + default:
> + *out_type = IRQ_TYPE_NONE;
> + trigger = IOAPIC_AUTO;
> + polarity = 0;
> + break;
> + };
> + } else {
> + *out_type = IRQ_TYPE_NONE;
> + trigger = IOAPIC_AUTO;
> + polarity = 0;
> + }
> + /* And now tell the IO APIC to make the line ready */
> + desc = irq_to_desc_alloc_node(*out_hwirq, 0);
> + cfg = irq_cfg(*out_hwirq);
> + add_pin_to_irq_node(cfg, 0, idx, line);
> + /* make it edge by default, settype will update it */
> + setup_ioapic_irq(idx, line, *out_hwirq, cfg, trigger, polarity);
> + return 0;
> +}
> +
> +void __init ioapic_add_ofnode(struct device_node *np)
> +{
> + int i;
> + int ret;
> + struct resource r;
> +
> + ret = of_address_to_resource(np, 0, &r);
> + if (ret) {
> + printk(KERN_ERR "Failed to obtain address for %s\n",
> + np->full_name);
> + return;
> + }
> +
> + for (i = 0; i < nr_ioapics; i++) {
> + if (r.start == mp_ioapics[i].apicaddr) {
> + struct irq_domain *id;
> +
> + mp_of_ioapic[i].node = np;
> + id = kzalloc(sizeof(*id), GFP_KERNEL);
> + BUG_ON(!id);
> + id->controller = np;
> + id->xlate = ioapic_xlate;
> + id->priv = (void *)i;
> + add_interrupt_host(id);
> + return;
> + }
I'm confused here. Are there multiple ioapic's described by a single
device tree node?
> + }
> + printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
> +}
> +#endif
> +
> /* Enable IOAPIC early just for system timer */
> void __init pre_init_apic_IRQ0(void)
> {
> diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
> index 4cadf86..9f76f89 100644
> --- a/arch/x86/kernel/irqinit.c
> +++ b/arch/x86/kernel/irqinit.c
> @@ -119,6 +119,12 @@ void __init init_IRQ(void)
> int i;
>
> /*
> + * We probably need a better place for this, but it works for
> + * now ...
> + */
> + x86_add_irq_domains();
> +
> + /*
> * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
> * If these IRQ's are handled by legacy interrupt-controllers like PIC,
> * then this configuration will likely be static after the boot. If
> diff --git a/arch/x86/kernel/prom.c b/arch/x86/kernel/prom.c
> index 6eddafd..edcaf1b 100644
> --- a/arch/x86/kernel/prom.c
> +++ b/arch/x86/kernel/prom.c
> @@ -11,9 +11,11 @@
> #include <linux/slab.h>
> #include <linux/pci.h>
> #include <linux/of_pci.h>
> +#include <linux/of_fdt.h>
>
> #include <asm/hpet.h>
> #include <asm/irq_controller.h>
> +#include <asm/apic.h>
> #include <asm/io_apic.h>
> #include <asm/pci_x86.h>
>
> @@ -332,3 +334,16 @@ void __init x86_dtb_get_config(unsigned int unused)
> dtb_setup_hpet();
> dtb_apic_setup();
> }
> +
> +void __init x86_add_irq_domains(void)
> +{
> + struct device_node *dp;
> +
> + if (!initial_boot_params)
> + return;
> +
> + for_each_node_by_type(dp, "interrupt-controller") {
> + if (of_device_is_compatible(dp, "intel,ioapic"))
> + ioapic_add_ofnode(dp);
> + }
> +}
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 14/15] rtc/cmos: add OF bindings
[not found] ` <1292600033-12271-15-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
@ 2011-01-12 0:04 ` Grant Likely
[not found] ` <20110112000442.GJ2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Grant Likely @ 2011-01-12 0:04 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Alessandro Zummo, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ
On Fri, Dec 17, 2010 at 04:33:52PM +0100, Sebastian Andrzej Siewior wrote:
> 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
> Cc: Alessandro Zummo <a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> 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 5856167..8cf0049 100644
> --- a/drivers/rtc/rtc-cmos.c
> +++ b/drivers/rtc/rtc-cmos.c
> @@ -36,6 +36,8 @@
> #include <linux/platform_device.h>
> #include <linux/mod_devicetable.h>
> #include <linux/log2.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
>
> /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
> #include <asm-generic/rtc.h>
> @@ -1121,6 +1123,15 @@ static struct pnp_driver cmos_pnp_driver = {
>
> #endif /* CONFIG_PNP */
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id of_cmos_match[] = {
> + {
> + .compatible = "motorola,mc146818",
> + },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, of_cmos_match);
> +#endif
> /*----------------------------------------------------------------*/
>
> /* Platform setup should have set up an RTC device, when PNP is
> @@ -1129,6 +1140,32 @@ static struct pnp_driver cmos_pnp_driver = {
>
> static int __init cmos_platform_probe(struct platform_device *pdev)
> {
> +#ifdef CONFIG_OF
> + if (pdev->dev.of_node) {
> + struct device_node *node = pdev->dev.of_node;
> + struct rtc_time time;
> + int ret;
> + const __be32 *val;
> +
> + val = of_get_property(node, "ctrl-reg", NULL);
> + if (val)
> + CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL);
> +
> + val = of_get_property(node, "freq-reg", NULL);
> + if (val)
> + CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
> +
> + get_rtc_time(&time);
> + ret = rtc_valid_tm(&time);
> + if (ret) {
> + struct rtc_time def_time = {
> + .tm_year = 1,
> + .tm_mday = 1,
> + };
> + set_rtc_time(&def_time);
> + }
> + }
> +#endif
It's usually cleaner to break the of-specific probe stuff into a
separate function that can be #ifdef'ed out as a whole instead of
having #ifdef blocks inside the probe functions. Aside from that this
patch looks good to me.
> cmos_wake_setup(&pdev->dev);
> return cmos_do_probe(&pdev->dev,
> platform_get_resource(pdev, IORESOURCE_IO, 0),
> @@ -1157,6 +1194,9 @@ static struct platform_driver cmos_platform_driver = {
> .shutdown = cmos_platform_shutdown,
> .driver = {
> .name = (char *) driver_name,
> +#if defined(CONFIG_OF)
> + .of_match_table = of_cmos_match,
> +#endif
> .suspend = cmos_suspend,
> .resume = cmos_resume,
> }
> --
> 1.7.3.2
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC
[not found] ` <20110111235353.GG2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-12 17:07 ` Sebastian Andrzej Siewior
[not found] ` <20110112170707.GA6907-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-12 17:07 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
* Grant Likely | 2011-01-11 16:53:53 [-0700]:
>> +void __init ioapic_add_ofnode(struct device_node *np)
>> +{
>> + int i;
>> + int ret;
>> + struct resource r;
>> +
>> + ret = of_address_to_resource(np, 0, &r);
>> + if (ret) {
>> + printk(KERN_ERR "Failed to obtain address for %s\n",
>> + np->full_name);
>> + return;
>> + }
>> +
>> + for (i = 0; i < nr_ioapics; i++) {
>> + if (r.start == mp_ioapics[i].apicaddr) {
>> + struct irq_domain *id;
>> +
>> + mp_of_ioapic[i].node = np;
>> + id = kzalloc(sizeof(*id), GFP_KERNEL);
>> + BUG_ON(!id);
>> + id->controller = np;
>> + id->xlate = ioapic_xlate;
>> + id->priv = (void *)i;
>> + add_interrupt_host(id);
>> + return;
>> + }
>
>I'm confused here. Are there multiple ioapic's described by a single
>device tree node?
Yes, the CE4100 has two IO-APICs. It looks like the first one is
responsible for the "legacy devices" (like RTC) and the second one is
used for the "extra devices" like SPI controller, USB, ... The UART
however is not on the first IO-APIC but on the second.
Those two IO-APICs are not cascaded. The device tree contains the line
number of device to the io apic. The kernel computes then interrupt
number based on gsi_base + line_number where gsi_base is incremented by
the number of entries[0]. This interrupt number (gsi_base + line) is then
sent via apic bus to lapic which reports it as the active interrupt
source.
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [sodaville] [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC
[not found] ` <20110112170707.GA6907-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
@ 2011-01-12 17:19 ` H. Peter Anvin
[not found] ` <4D2DE2B9.2000607-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
0 siblings, 1 reply; 42+ messages in thread
From: H. Peter Anvin @ 2011-01-12 17:19 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 01/12/2011 09:07 AM, Sebastian Andrzej Siewior wrote:
>>
>> I'm confused here. Are there multiple ioapic's described by a single
>> device tree node?
>
> Yes, the CE4100 has two IO-APICs. It looks like the first one is
> responsible for the "legacy devices" (like RTC) and the second one is
> used for the "extra devices" like SPI controller, USB, ... The UART
> however is not on the first IO-APIC but on the second.
>
> Those two IO-APICs are not cascaded. The device tree contains the line
> number of device to the io apic. The kernel computes then interrupt
> number based on gsi_base + line_number where gsi_base is incremented by
> the number of entries[0]. This interrupt number (gsi_base + line) is then
> sent via apic bus to lapic which reports it as the active interrupt
> source.
>
That's normal multiple IOAPIC behavior (and multiple IOAPICs is a common
thing), but why use the same device tree node for both?
-hpa
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 07/15] of: move of_irq_map_pci() into generic code
[not found] ` <20110111232726.GD2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-12 18:21 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-12 18:21 UTC (permalink / raw)
To: Grant Likely
Cc: Sebastian Andrzej Siewior, x86-DgEjT+Ai2ygdnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
>From 558ec33d76f6f0f4ec7398e6f3af1ea8892d981f Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
Date: Wed, 1 Dec 2010 21:55:12 +0100
Subject: [PATCH] of: move of_irq_map_pci() into generic code
There is a tiny difference between PPC32 and PPC64. Microblaze uses the
PPC32 variant.
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
Signed-off-by: Sebastian Andrzej Siewior <sebastian-E0PNVn5OA6ohrxcnuTQ+TQ@public.gmane.org>
---
* Grant Likely | 2011-01-11 16:27:26 [-0700]:
>Mostly looks good, but breaks both Sparc and microblaze which is kind
>of important to fix before I merge it. :-)
You could note that ppc32/ppc64 built because now it looks like I did
not test it all :)
>Sparc
>-----
> CC drivers/of/of_pci.o
>/home/grant/hacking/linux-2.6/drivers/of/of_pci.c: In function 'of_irq_map_pci':
>/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:20: error: implicit declaration of function 'of_irq_map_one'
>/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:44: error: implicit declaration of function 'pci_bus_to_OF_node'
>/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:44: warning: assignment makes pointer from integer without a cast
>/home/grant/hacking/linux-2.6/drivers/of/of_pci.c:78: error: implicit declaration of function 'of_irq_map_raw'
>make[3]: *** [drivers/of/of_pci.o] Error 1
Yeah, I did not expect that. I add some Kconfig magic like that for I2C
and others in order to exclude it on sparc.
>Microblaze
>----------
> CC arch/microblaze/kernel/prom.o
>In file included from /home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci.h:23,
> from /home/grant/hacking/linux-2.6/include/linux/pci.h:1230,
> from /home/grant/hacking/linux-2.6/arch/microblaze/kernel/prom.c:23:
>/home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci-bridge.h: In function 'pci_bus_to_OF_node':
>/home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci-bridge.h:117: error: implicit declaration of function 'pci_device_to_OF_node'
>/home/grant/hacking/linux-2.6/arch/microblaze/include/asm/pci-bridge.h:117: warning: return makes pointer from integer without a cast
>make[2]: *** [arch/microblaze/kernel/prom.o] Error 1
>make[1]: *** [arch/microblaze/kernel] Error 2
>make: *** [sub-make] Error 2
The non-pci case of course. CONFIG_PCI is around pci_device_to_OF_node()
pci.h. I add some of those around the three static inline in
pci-bridge.h. I looks kinda wrong to export all this PCI stuff even that
we don't have PCI around.
arch/microblaze/include/asm/pci-bridge.h | 12 ++++
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/Kconfig | 6 ++
drivers/of/Makefile | 1 +
drivers/of/of_pci.c | 80 ++++++++++++++++++++++++++++
include/linux/of_pci.h | 20 +++++++
12 files changed, 131 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..c2a40a4 100644
--- a/arch/microblaze/include/asm/pci-bridge.h
+++ b/arch/microblaze/include/asm/pci-bridge.h
@@ -104,11 +104,22 @@ struct pci_controller {
int global_number; /* PCI domain number */
};
+#ifdef CONFIG_PCI
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
@@ -116,6 +127,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
*/
return 0;
}
+#endif
/* These are used for config access before all the PCI probing
has been done. */
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__ */
#endif /* __KERNEL__ */
diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
index 99d9b61..306f41d 100644
--- a/arch/microblaze/kernel/prom_parse.c
+++ b/arch/microblaze/kernel/prom_parse.c
@@ -2,88 +2,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- u32 laddr[3];
- u8 pin;
- int rc;
-
- /* Check if we have a device node, if yes, fallback to standard OF
- * parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn)
- return of_irq_map_one(dn, 0, out_irq);
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
- struct pci_controller *host;
- host = pci_bus_to_host(pdev->bus);
- ppnode = host ? host->dn : NULL;
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't
- * include the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
-
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
- */
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
- }
-
- laddr[0] = (pdev->bus->number << 16)
- | (pdev->devfn << 8);
- laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index e363615..1e01a12 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <asm/processor.h>
#include <asm/io.h>
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 51e9e6f..edeb80f 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -171,6 +171,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/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index ae26f2e..01c3302 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -73,21 +73,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
#endif
#define of_node_to_nid of_node_to_nid
-/**
- * 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);
-
extern void of_instantiate_rtc(void);
/* These includes are put at the bottom because they may contain things
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 10a44e6..eb341be 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/syscalls.h>
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 88334af..306f41d 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -2,95 +2,11 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
- struct device_node *dn, *ppnode;
- struct pci_dev *ppdev;
- u32 lspec;
- u32 laddr[3];
- u8 pin;
- int rc;
-
- /* Check if we have a device node, if yes, fallback to standard OF
- * parsing
- */
- dn = pci_device_to_OF_node(pdev);
- if (dn) {
- rc = of_irq_map_one(dn, 0, out_irq);
- if (!rc)
- return rc;
- }
-
- /* Ok, we don't, time to have fun. Let's start by building up an
- * interrupt spec. we assume #interrupt-cells is 1, which is standard
- * for PCI. If you do different, then don't use that routine.
- */
- rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
- if (rc != 0)
- return rc;
- /* No pin, exit */
- if (pin == 0)
- return -ENODEV;
-
- /* Now we walk up the PCI tree */
- lspec = pin;
- for (;;) {
- /* Get the pci_dev of our parent */
- ppdev = pdev->bus->self;
-
- /* Ouch, it's a host bridge... */
- if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
- ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
- struct pci_controller *host;
- host = pci_bus_to_host(pdev->bus);
- ppnode = host ? host->dn : NULL;
-#endif
- /* No node for host bridge ? give up */
- if (ppnode == NULL)
- return -EINVAL;
- } else
- /* We found a P2P bridge, check if it has a node */
- ppnode = pci_device_to_OF_node(ppdev);
-
- /* Ok, we have found a parent with a device-node, hand over to
- * the OF parsing code.
- * We build a unit address from the linux device to be used for
- * resolution. Note that we use the linux bus number which may
- * not match your firmware bus numbering.
- * Fortunately, in most cases, interrupt-map-mask doesn't include
- * the bus number as part of the matching.
- * You should still be careful about that though if you intend
- * to rely on this function (you ship a firmware that doesn't
- * create device nodes for all PCI devices).
- */
- if (ppnode)
- break;
-
- /* We can only get here if we hit a P2P bridge with no node,
- * let's do standard swizzling and try again
- */
- lspec = pci_swizzle_interrupt_pin(pdev, lspec);
- pdev = ppdev;
- }
-
- laddr[0] = (pdev->bus->number << 16)
- | (pdev->devfn << 8);
- laddr[1] = laddr[2] = 0;
- return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index aa675eb..9379a74 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -61,4 +61,10 @@ config OF_MDIO
help
OpenFirmware MDIO bus (Ethernet PHY) accessors
+config OF_PCI
+ def_tristate PCI
+ depends on PCI && !SPARC
+ help
+ OpenFirmware PCI bus accessors
+
endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 7888155..4e0c1ef 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_SPI) += of_spi.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
+obj-$(CONFIG_OF_PCI) += of_pci.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 0000000..dd862d2
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,80 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <asm/prom.h>
+
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+ struct device_node *dn, *ppnode;
+ struct pci_dev *ppdev;
+ u32 lspec;
+ __be32 lspec_be;
+ __be32 laddr[3];
+ u8 pin;
+ int rc;
+
+ /* Check if we have a device node, if yes, fallback to standard OF
+ * parsing
+ */
+ dn = pci_device_to_OF_node(pdev);
+ if (dn) {
+ rc = of_irq_map_one(dn, 0, out_irq);
+ if (!rc)
+ return rc;
+ }
+
+ /* Ok, we don't, time to have fun. Let's start by building up an
+ * interrupt spec. we assume #interrupt-cells is 1, which is standard
+ * for PCI. If you do different, then don't use that routine.
+ */
+ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+ if (rc != 0)
+ return rc;
+ /* No pin, exit */
+ if (pin == 0)
+ return -ENODEV;
+
+ /* Now we walk up the PCI tree */
+ lspec = pin;
+ for (;;) {
+ /* Get the pci_dev of our parent */
+ ppdev = pdev->bus->self;
+
+ /* Ouch, it's a host bridge... */
+ if (ppdev == NULL) {
+ ppnode = pci_bus_to_OF_node(pdev->bus);
+
+ /* No node for host bridge ? give up */
+ if (ppnode == NULL)
+ return -EINVAL;
+ } else {
+ /* We found a P2P bridge, check if it has a node */
+ ppnode = pci_device_to_OF_node(ppdev);
+ }
+
+ /* Ok, we have found a parent with a device-node, hand over to
+ * the OF parsing code.
+ * We build a unit address from the linux device to be used for
+ * resolution. Note that we use the linux bus number which may
+ * not match your firmware bus numbering.
+ * Fortunately, in most cases, interrupt-map-mask doesn't
+ * include the bus number as part of the matching.
+ * You should still be careful about that though if you intend
+ * to rely on this function (you ship a firmware that doesn't
+ * create device nodes for all PCI devices).
+ */
+ if (ppnode)
+ break;
+
+ /* We can only get here if we hit a P2P bridge with no node,
+ * let's do standard swizzling and try again
+ */
+ lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+ pdev = ppdev;
+ }
+
+ lspec_be = cpu_to_be32(lspec);
+ laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+ laddr[1] = laddr[2] = cpu_to_be32(0);
+ return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
new file mode 100644
index 0000000..9b0ba67
--- /dev/null
+++ b/include/linux/of_pci.h
@@ -0,0 +1,20 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+/**
+ * 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;
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+#endif
--
1.7.3.2
Sebastian
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [sodaville] [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC
[not found] ` <4D2DE2B9.2000607-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2011-01-13 10:38 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-13 10:38 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Sebastian Andrzej Siewior, x86-DgEjT+Ai2ygdnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
* H. Peter Anvin | 2011-01-12 09:19:53 [-0800]:
>On 01/12/2011 09:07 AM, Sebastian Andrzej Siewior wrote:
>>>
>>> I'm confused here. Are there multiple ioapic's described by a single
>>> device tree node?
>
>That's normal multiple IOAPIC behavior (and multiple IOAPICs is a common
>thing), but why use the same device tree node for both?
I'm sorry, I miss understood Grant's question. The two io apics in the
system are described by two nodes. ioapic_add_ofnode() is called for one
node:
> + for (i = 0; i < nr_ioapics; i++) {
> + if (r.start == mp_ioapics[i].apicaddr) {
> + struct irq_domain *id;
> +
> + mp_of_ioapic[i].node = np;
> + id = kzalloc(sizeof(*id), GFP_KERNEL);
> + BUG_ON(!id);
> + id->controller = np;
> + id->xlate = ioapic_xlate;
> + id->priv = (void *)i;
> + add_interrupt_host(id);
> + return;
> + }
and once it matches the previously registered io apic it calls
add_interrupt_host() on it and returns. x86_add_irq_domains() calls it
for every io apic node so it calls add_interrupt_host() twice.
> -hpa
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2] rtc/cmos: add OF bindings
[not found] ` <20110112000442.GJ2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-13 10:50 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-13 10:50 UTC (permalink / raw)
To: Grant Likely
Cc: Alessandro Zummo, rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
Sebastian Andrzej Siewior, x86-DgEjT+Ai2ygdnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
Cc: Alessandro Zummo <a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Signed-off-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Dirk Brandewie <dirk.brandewie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
* Grant Likely | 2011-01-11 17:04:42 [-0700]:
>It's usually cleaner to break the of-specific probe stuff into a
>separate function that can be #ifdef'ed out as a whole instead of
>having #ifdef blocks inside the probe functions. Aside from that this
>patch looks good to me.
Done.
Documentation/powerpc/dts-bindings/rtc-cmos.txt | 28 ++++++++++++++
drivers/rtc/rtc-cmos.c | 46 +++++++++++++++++++++++
2 files changed, 74 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 5856167..95a08dd 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -36,6 +36,8 @@
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
@@ -1121,6 +1123,46 @@ static struct pnp_driver cmos_pnp_driver = {
#endif /* CONFIG_PNP */
+#ifdef CONFIG_OF
+static const struct of_device_id of_cmos_match[] = {
+ {
+ .compatible = "motorola,mc146818",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, of_cmos_match);
+
+static __init void cmos_of_init(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct rtc_time time;
+ int ret;
+ const __be32 *val;
+
+ if (!node)
+ return;
+
+ val = of_get_property(node, "ctrl-reg", NULL);
+ if (val)
+ CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL);
+
+ val = of_get_property(node, "freq-reg", NULL);
+ if (val)
+ CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
+
+ get_rtc_time(&time);
+ ret = rtc_valid_tm(&time);
+ if (ret) {
+ struct rtc_time def_time = {
+ .tm_year = 1,
+ .tm_mday = 1,
+ };
+ set_rtc_time(&def_time);
+ }
+}
+#else
+static inline void cmos_of_init(struct platform_device *pdev) {}
+#endif
/*----------------------------------------------------------------*/
/* Platform setup should have set up an RTC device, when PNP is
@@ -1129,6 +1171,7 @@ static struct pnp_driver cmos_pnp_driver = {
static int __init cmos_platform_probe(struct platform_device *pdev)
{
+ cmos_of_init(pdev);
cmos_wake_setup(&pdev->dev);
return cmos_do_probe(&pdev->dev,
platform_get_resource(pdev, IORESOURCE_IO, 0),
@@ -1157,6 +1200,9 @@ static struct platform_driver cmos_platform_driver = {
.shutdown = cmos_platform_shutdown,
.driver = {
.name = (char *) driver_name,
+#if defined(CONFIG_OF)
+ .of_match_table = of_cmos_match,
+#endif
.suspend = cmos_suspend,
.resume = cmos_resume,
}
--
1.7.3.2
Sebastian
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH v2 05/15] x86/dtb: add early parsing of APIC and IO APIC
[not found] ` <20110111221401.GB2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-18 14:56 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-18 14:56 UTC (permalink / raw)
To: Grant Likely
Cc: sodaville-hfZtesqFncYOwBW4kG4KsQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Grant Likely wrote:
> Hi Sebastian,
Hi Grant,
>> 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
>
> Nit: Personally, I prefer static inlines over preprocessor macros, but
> that isn't anything that will block this patch.
Right. x86 does similar for ioapic function callbacks for CONFIG_IOAPIC
case. So I keep this unless x86 folks want it different.
>> +#ifdef CONFIG_X86_IO_APIC
>> +static void __init dtb_add_ioapic(struct device_node *dn)
>> +{
>> + unsigned int ioapic_id;
>> + const __be32 *cell;
>> + int len;
>> + struct resource r;
>> + int ret;
>> +
>> + cell = of_get_property(dn, "id", &len);
>> + if (!cell) {
>> + printk(KERN_ERR "Node %s is missing id property.\n",
>> + dn->full_name);
>> + return;
>> + }
>> + ioapic_id = of_read_ulong(cell, len / 4);
>
> This looks like poor usage practise for the device tree. 'id' or any
> kind of enumeration property in a device tree node is strongly
> discouraged. As much as possible, let Linux dynamically enumerate
> devices rather than trying to explicitly specify the numbering. Since
> you can explicitly describe the relationship between device nodes in
> the tree, you should find that explicitly specifying numbers is almost
> never required.
Good point. I removed the id property and let linux statically enumerate
it. I don't see any relationship and spec. says only to keep it unique.
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 04/15] x86/dtb: add irq domain abstraction
[not found] ` <20110111220317.GA2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
@ 2011-01-23 13:06 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 42+ messages in thread
From: Sebastian Andrzej Siewior @ 2011-01-23 13:06 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
sodaville-hfZtesqFncYOwBW4kG4KsQ, Sebastian Andrzej Siewior,
x86-DgEjT+Ai2ygdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA
* Grant Likely | 2011-01-11 15:03:17 [-0700]:
>> unsigned int irq_create_of_mapping(struct device_node *controller,
>> const u32 *intspec, unsigned int intsize)
>> {
>> - return intspec[0];
>> + struct irq_domain *ih;
>> + u32 virq;
>> + u32 type;
>> + int ret;
>>
>> + ih = get_ih_from_node(controller);
>> + if (!ih)
>> + return -ENODEV;
>
>Return value is an unsigned int. 0 or NO_IRQ is the correct thing to
>return if an IRQ cannot be mapped.
fixed.
>> + ret = ih->xlate(ih, intspec, intsize, &virq, &type);
>> + if (ret)
>> + return ret;
>
>Ditto here. xlate is also supposed to return a virq number, not an
>error code, so the failure condition must be "if (!ret)" or
are you sure on that? The relevant part of powerpc's
irq_create_of_mapping() looks like:
| if (host->ops->xlate(host, controller, intspec, intsize,
| &hwirq, &type))
| return NO_IRQ;
so xlate here returns 0 on success and hwirq via a pointer. I do the
same thing here except I return directly virq instead of
irq_hw_number_t. I add powerpc's irq_create_mapping() including virq <->
hwirq mapping once it is generic. I shouldn't need unless we use
non-ioapics are irq controllers.
>"if (reg == NO_IRQ)". The former is preferred since we're trying to
>eliminate references to NO_IRQ, not add more of them.
Okay. So try to get rid of NO_IRQ in my series.
Sebastian
^ permalink raw reply [flat|nested] 42+ messages in thread
end of thread, other threads:[~2011-01-23 13:06 UTC | newest]
Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1292600033-12271-1-git-send-email-bigeasy@linutronix.de>
[not found] ` <1292600033-12271-1-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-17 15:33 ` [PATCH 02/15] x86: Add device tree support Sebastian Andrzej Siewior
2010-12-30 8:43 ` Grant Likely
[not found] ` <20101230084311.GD11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2010-12-30 21:01 ` Grant Likely
[not found] ` <AANLkTi=EFewaizO=1FLALE0eQPUmaFPfTmgoeF+JRpkt-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-01-02 0:40 ` H. Peter Anvin
2011-01-03 12:20 ` Sebastian Andrzej Siewior
2011-01-03 18:05 ` [sodaville] " H. Peter Anvin
2010-12-17 15:33 ` [PATCH 03/15] x86/dtb: Add a device tree for CE4100 Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-4-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-30 8:51 ` Grant Likely
[not found] ` <20101230085122.GE11721-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-03 11:28 ` Sebastian Andrzej Siewior
2011-01-03 17:45 ` Grant Likely
[not found] ` <20110103174500.GC2522-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-05 9:48 ` [PATCH v2 " Sebastian Andrzej Siewior
2011-01-05 10:01 ` [PATCH " Sebastian Andrzej Siewior
2011-01-05 23:20 ` David Gibson
2010-12-17 15:33 ` [PATCH 04/15] x86/dtb: add irq domain abstraction Sebastian Andrzej Siewior
2011-01-11 22:03 ` Grant Likely
[not found] ` <20110111220317.GA2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-23 13:06 ` Sebastian Andrzej Siewior
2010-12-17 15:33 ` [PATCH 05/15] x86/dtb: add early parsing of APIC and IO APIC Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-6-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2010-12-30 8:54 ` Grant Likely
2011-01-04 13:23 ` [PATCH v2 " Sebastian Andrzej Siewior
[not found] ` <20110104132302.GB21359-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
2011-01-11 22:14 ` Grant Likely
[not found] ` <20110111221401.GB2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-18 14:56 ` Sebastian Andrzej Siewior
2010-12-17 15:33 ` [PATCH 06/15] x86/dtb: add support hpet Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-7-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2011-01-11 22:26 ` Grant Likely
2010-12-17 15:33 ` [PATCH 07/15] of: move of_irq_map_pci() into generic code Sebastian Andrzej Siewior
2010-12-17 21:16 ` Benjamin Herrenschmidt
2011-01-04 14:27 ` [PATCH v2 " Sebastian Andrzej Siewior
[not found] ` <20110104142754.GD21359-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
2011-01-11 23:27 ` Grant Likely
[not found] ` <20110111232726.GD2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-12 18:21 ` Sebastian Andrzej Siewior
2010-12-17 15:33 ` [PATCH 08/15] x86/dtb: add support for PCI devices backed by dtb nodes Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-9-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2011-01-11 23:47 ` Grant Likely
2010-12-17 15:33 ` [PATCH 09/15] x86/dtb: Add generic bus probe Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-10-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2011-01-11 23:48 ` Grant Likely
2010-12-17 15:33 ` [PATCH 10/15] x86/ioapic: Add OF bindings for IO-APIC Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-11-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2011-01-11 23:53 ` Grant Likely
[not found] ` <20110111235353.GG2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-12 17:07 ` Sebastian Andrzej Siewior
[not found] ` <20110112170707.GA6907-Hfxr4Dq0UpYb1SvskN2V4Q@public.gmane.org>
2011-01-12 17:19 ` [sodaville] " H. Peter Anvin
[not found] ` <4D2DE2B9.2000607-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2011-01-13 10:38 ` Sebastian Andrzej Siewior
2010-12-17 15:33 ` [PATCH 12/15] of/address: use propper endianess in get_flags Sebastian Andrzej Siewior
2010-12-30 9:05 ` Grant Likely
2010-12-17 15:33 ` [PATCH 14/15] rtc/cmos: add OF bindings Sebastian Andrzej Siewior
[not found] ` <1292600033-12271-15-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
2011-01-12 0:04 ` Grant Likely
[not found] ` <20110112000442.GJ2131-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-01-13 10:50 ` [PATCH v2] " Sebastian Andrzej Siewior
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).