* [GIT PULL] x86/platform changes for v2.6.39
@ 2011-03-15 21:32 Ingo Molnar
2011-03-15 23:09 ` Grant Likely
0 siblings, 1 reply; 3+ messages in thread
From: Ingo Molnar @ 2011-03-15 21:32 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, Thomas Gleixner, Andrew Morton
Linus,
Please pull the latest x86-platform-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git x86-platform-for-linus
out-of-topic modifications in x86-platform-for-linus:
-----------------------------------------------------
arch/microblaze/include/asm/pci-bridge.h# 04bea68: of/pci: move of_irq_map_pci() int
arch/microblaze/include/asm/prom.h # 04bea68: of/pci: move of_irq_map_pci() int
arch/microblaze/kernel/prom_parse.c# 04bea68: of/pci: move of_irq_map_pci() int
arch/microblaze/pci/pci-common.c # 04bea68: of/pci: move of_irq_map_pci() int
arch/powerpc/include/asm/pci-bridge.h# 04bea68: of/pci: move of_irq_map_pci() int
arch/powerpc/include/asm/prom.h # 04bea68: of/pci: move of_irq_map_pci() int
arch/powerpc/kernel/pci-common.c # 04bea68: of/pci: move of_irq_map_pci() int
arch/powerpc/kernel/prom_parse.c # 04bea68: of/pci: move of_irq_map_pci() int
drivers/i2c/busses/i2c-ocores.c # c9e358d: driver-core: remove conditionals
drivers/i2c/i2c-core.c # c9e358d: driver-core: remove conditionals
drivers/mmc/host/mmc_spi.c # c9e358d: driver-core: remove conditionals
drivers/net/ethoc.c # c9e358d: driver-core: remove conditionals
drivers/of/Kconfig # 96e0a07: x86: dtb: Add support for PCI dev
# 04bea68: of/pci: move of_irq_map_pci() int
drivers/of/Makefile # 04bea68: of/pci: move of_irq_map_pci() int
drivers/of/of_pci.c # 96e0a07: x86: dtb: Add support for PCI dev
# 04bea68: of/pci: move of_irq_map_pci() int
drivers/rtc/rtc-cmos.c # 3bcbaf6: rtc: cmos: Add OF bindings
drivers/rtc/rtc-mrst.c # 168202c: mrst/vrtc: Avoid using cmos rtc o
drivers/spi/pxa2xx_spi.c # c9e358d: driver-core: remove conditionals
drivers/spi/pxa2xx_spi_pci.c # c9e358d: driver-core: remove conditionals
drivers/spi/xilinx_spi.c # c9e358d: driver-core: remove conditionals
include/linux/device.h # c9e358d: driver-core: remove conditionals
include/linux/i2c.h # c9e358d: driver-core: remove conditionals
include/linux/of.h # 3bcbaf6: rtc: cmos: Add OF bindings
# c9e358d: driver-core: remove conditionals
include/linux/of_pci.h # 04bea68: of/pci: move of_irq_map_pci() int
Thanks,
Ingo
------------------>
Feng Tang (2):
x86/platform: Add a wallclock_init func to x86_init.timers ops
mrst/vrtc: Avoid using cmos rtc ops
Grant Likely (1):
driver-core: remove conditionals around devicetree pointers
Henrik Kretzschmar (7):
x86: Move ioapic_irq_destination_types to apicdef.h
x86: Add dummy mp_save_irq()
x86: Rework arch_disable_smp_support() for x86
x86: Add dummy functions for compiling without IOAPIC
x86: Fix deps of X86_UP_IOAPIC
x86: Remove superflous goal definition of tsc_sync
x86: Clean up apic.c and apic.h
Sebastian Andrzej Siewior (15):
of/pci: move of_irq_map_pci() into generic code
x86/pci: Remove unused variable
x86: e820: Remove conditional early mapping in parse_e820_ext
x86: Add device tree support
x86: dtb: Add a device tree for CE4100
x86: dtb: Add irq domain abstraction
x86: dtb: Add early parsing of IO_APIC
x86: dtb: Add device tree support for HPET
x86: dtb: Add support for PCI devices backed by dtb nodes
x86: dtb: Add generic bus probe
x86: ioapic: Add OF bindings for IO_APIC
x86: ce4100: Use OF to setup devices
rtc: cmos: Add OF bindings
x86: dt: Fix OLPC=y/INTEL_CE=n build
x86: dt: Correct local apic documentation in device tree bindings
Thomas Gleixner (17):
x86: OLPC: Remove redundant !X64_64 config dependency
x86: OLPC: Hide OLPC_OPENFIRMWARE config switch
x86: OLPC: Cleanup config maze completely
x86: OLPC: Remove extra OLPC_OPENFIRMWARE_DT indirection
x86: OLPC: Make OLPC=n build again
x86: ioapic: Remove silly debug bloat in setup_IOAPIC_irqs()
x86: ioapic: Split out the nested loop in setup_IO_APIC_irqs()
x86: ioapic: Add io_apic_setup_irq_pin()
x86: ioapic: Use new setup function in pre_init_apic_IRQ0()
x86: ioapic: Use setup function in __io_apic_set_pci_routing()
x86: ioapic: Use setup function in __io_apic_setup_irqs()
x86: ioapic: Use setup function in setup_IO_APIC_irq_extra()
x86: ioapic: Make a few functions static
x86: ioapic: Remove useless inlines
x86: ioapic: Implement and use io_apic_setup_irq_pin_once()
x86: ioapic: Move trigger defines to io_apic.h
x86: dt: Cleanup local apic setup
jacob.jun.pan@linux.intel.com (1):
x86: mrst: Remove apb timer read workaround
.../devicetree/bindings/i2c/ce4100-i2c.txt | 93 ++++
Documentation/devicetree/bindings/rtc/rtc-cmos.txt | 28 ++
Documentation/devicetree/bindings/x86/ce4100.txt | 38 ++
.../devicetree/bindings/x86/interrupt.txt | 26 ++
Documentation/devicetree/bindings/x86/timer.txt | 6 +
Documentation/devicetree/booting-without-of.txt | 20 +
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 ----
arch/x86/Kconfig | 24 +-
arch/x86/include/asm/apic.h | 6 +-
arch/x86/include/asm/apicdef.h | 12 +
arch/x86/include/asm/bootparam.h | 1 +
arch/x86/include/asm/e820.h | 2 +-
arch/x86/include/asm/io_apic.h | 44 ++-
arch/x86/include/asm/irq.h | 3 -
arch/x86/include/asm/irq_controller.h | 12 +
arch/x86/include/asm/olpc_ofw.h | 14 +-
arch/x86/include/asm/prom.h | 70 +++-
arch/x86/include/asm/x86_init.h | 2 +
arch/x86/kernel/Makefile | 5 +-
arch/x86/kernel/apb_timer.c | 60 +---
arch/x86/kernel/apic/apic.c | 74 ++--
arch/x86/kernel/apic/io_apic.c | 265 +++++-------
arch/x86/kernel/devicetree.c | 441 ++++++++++++++++++++
arch/x86/kernel/e820.c | 8 +-
arch/x86/kernel/head_32.S | 2 +-
arch/x86/kernel/irq.c | 9 -
arch/x86/kernel/irqinit.c | 9 +-
arch/x86/kernel/rtc.c | 3 +
arch/x86/kernel/setup.c | 25 +-
arch/x86/kernel/smpboot.c | 11 +-
arch/x86/kernel/x86_init.c | 1 +
arch/x86/pci/ce4100.c | 2 +-
arch/x86/platform/ce4100/ce4100.c | 24 +-
arch/x86/platform/ce4100/falconfalls.dts | 428 +++++++++++++++++++
arch/x86/platform/mrst/mrst.c | 2 +
arch/x86/platform/mrst/vrtc.c | 16 +-
arch/x86/platform/olpc/Makefile | 4 +-
drivers/i2c/busses/i2c-ocores.c | 14 +-
drivers/i2c/i2c-core.c | 2 -
drivers/mmc/host/mmc_spi.c | 4 -
drivers/net/ethoc.c | 8 +-
drivers/of/Kconfig | 6 +
drivers/of/Makefile | 1 +
drivers/of/of_pci.c | 92 ++++
drivers/rtc/rtc-cmos.c | 45 ++
drivers/rtc/rtc-mrst.c | 13 +-
drivers/spi/pxa2xx_spi.c | 2 -
drivers/spi/pxa2xx_spi_pci.c | 2 -
drivers/spi/xilinx_spi.c | 6 -
include/linux/device.h | 7 +-
include/linux/i2c.h | 2 -
include/linux/of.h | 16 +-
include/linux/of_pci.h | 9 +
60 files changed, 1641 insertions(+), 593 deletions(-)
create mode 100644 Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
create mode 100644 Documentation/devicetree/bindings/rtc/rtc-cmos.txt
create mode 100644 Documentation/devicetree/bindings/x86/ce4100.txt
create mode 100644 Documentation/devicetree/bindings/x86/interrupt.txt
create mode 100644 Documentation/devicetree/bindings/x86/timer.txt
create mode 100644 arch/x86/include/asm/irq_controller.h
create mode 100644 arch/x86/kernel/devicetree.c
create mode 100644 arch/x86/platform/ce4100/falconfalls.dts
create mode 100644 drivers/of/of_pci.c
create mode 100644 include/linux/of_pci.h
diff --git a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
new file mode 100644
index 0000000..569b162
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
@@ -0,0 +1,93 @@
+CE4100 I2C
+----------
+
+CE4100 has one PCI device which is described as the I2C-Controller. This
+PCI device has three PCI-bars, each bar contains a complete I2C
+controller. So we have a total of three independent I2C-Controllers
+which share only an interrupt line.
+The driver is probed via the PCI-ID and is gathering the information of
+attached devices from the devices tree.
+Grant Likely recommended to use the ranges property to map the PCI-Bar
+number to its physical address and to use this to find the child nodes
+of the specific I2C controller. This were his exact words:
+
+ 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 is an example which is used on FalconFalls:
+------------------------------------------------
+ i2c-controller@b,2 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "pci8086,2e68.2",
+ "pci8086,2e68",
+ "pciclass,ff0000",
+ "pciclass,ff00";
+
+ reg = <0x15a00 0x0 0x0 0x0 0x0>;
+ interrupts = <16 1>;
+
+ /* as described by Grant, the first number in the group of
+ * three is the bar number followed by the 64bit bar address
+ * followed by size of the mapping. The bar address
+ * requires also a valid translation in parents ranges
+ * property.
+ */
+ 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";
+
+ /* The first number in the reg property is the
+ * number of the bar
+ */
+ reg = <0 0 0x100>;
+
+ /* This I2C controller has no devices */
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ce4100-i2c-controller";
+ reg = <1 0 0x100>;
+
+ /* This I2C controller has one gpio controller */
+ gpio@26 {
+ #gpio-cells = <2>;
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ gpio-controller;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ce4100-i2c-controller";
+ reg = <2 0 0x100>;
+
+ gpio@26 {
+ #gpio-cells = <2>;
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ gpio-controller;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.txt b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
new file mode 100644
index 0000000..7382989
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/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/Documentation/devicetree/bindings/x86/ce4100.txt b/Documentation/devicetree/bindings/x86/ce4100.txt
new file mode 100644
index 0000000..b49ae59
--- /dev/null
+++ b/Documentation/devicetree/bindings/x86/ce4100.txt
@@ -0,0 +1,38 @@
+CE4100 Device Tree Bindings
+---------------------------
+
+The CE4100 SoC uses for in core peripherals the following compatible
+format: <vendor>,<chip>-<device>.
+Many of the "generic" devices like HPET or IO APIC have the ce4100
+name in their compatible property because they first appeared in this
+SoC.
+
+The CPU node
+------------
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "intel,ce4100";
+ reg = <0>;
+ lapic = <&lapic0>;
+ };
+
+The reg property describes the CPU number. The lapic property points to
+the local APIC timer.
+
+The SoC node
+------------
+
+This node describes the in-core peripherals. Required property:
+ compatible = "intel,ce4100-cp";
+
+The PCI node
+------------
+This node describes the PCI bus on the SoC. Its property should be
+ compatible = "intel,ce4100-pci", "pci";
+
+If the OS is using the IO-APIC for interrupt routing then the reported
+interrupt numbers for devices is no longer true. In order to obtain the
+correct interrupt number, the child node which represents the device has
+to contain the interrupt property. Besides the interrupt property it has
+to contain at least the reg property containing the PCI bus address and
+compatible property according to "PCI Bus Binding Revision 2.1".
diff --git a/Documentation/devicetree/bindings/x86/interrupt.txt b/Documentation/devicetree/bindings/x86/interrupt.txt
new file mode 100644
index 0000000..7d19f49
--- /dev/null
+++ b/Documentation/devicetree/bindings/x86/interrupt.txt
@@ -0,0 +1,26 @@
+Interrupt chips
+---------------
+
+* Intel I/O Advanced Programmable Interrupt Controller (IO APIC)
+
+ Required properties:
+ --------------------
+ compatible = "intel,ce4100-ioapic";
+ #interrupt-cells = <2>;
+
+ Device's interrupt property:
+
+ interrupts = <P S>;
+
+ The first number (P) represents the interrupt pin which is wired to the
+ IO APIC. The second number (S) represents the sense of interrupt which
+ should be configured and can be one of:
+ 0 - Edge Rising
+ 1 - Level Low
+ 2 - Level High
+ 3 - Edge Falling
+
+* Local APIC
+ Required property:
+
+ compatible = "intel,ce4100-lapic";
diff --git a/Documentation/devicetree/bindings/x86/timer.txt b/Documentation/devicetree/bindings/x86/timer.txt
new file mode 100644
index 0000000..c688af5
--- /dev/null
+++ b/Documentation/devicetree/bindings/x86/timer.txt
@@ -0,0 +1,6 @@
+Timers
+------
+
+* High Precision Event Timer (HPET)
+ Required property:
+ compatible = "intel,ce4100-hpet";
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt
index 28b1c9d..55fd262 100644
--- a/Documentation/devicetree/booting-without-of.txt
+++ b/Documentation/devicetree/booting-without-of.txt
@@ -13,6 +13,7 @@ Table of Contents
I - Introduction
1) Entry point for arch/powerpc
+ 2) Entry point for arch/x86
II - The DT block format
1) Header
@@ -225,6 +226,25 @@ it with special cases.
cannot support both configurations with Book E and configurations
with classic Powerpc architectures.
+2) Entry point for arch/x86
+-------------------------------
+
+ There is one single 32bit entry point to the kernel at code32_start,
+ the decompressor (the real mode entry point goes to the same 32bit
+ entry point once it switched into protected mode). That entry point
+ supports one calling convention which is documented in
+ Documentation/x86/boot.txt
+ The physical pointer to the device-tree block (defined in chapter II)
+ is passed via setup_data which requires at least boot protocol 2.09.
+ The type filed is defined as
+
+ #define SETUP_DTB 2
+
+ This device-tree is used as an extension to the "boot page". As such it
+ does not parse / consider data which is already covered by the boot
+ page. This includes memory size, reserved ranges, 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.
II - The DT block format
========================
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
index 0c68764..1071766 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 /* CONFIG_PCI */
/* 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 2e72af0..d0890d3 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void);
/* CPU OF node matching */
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
-/**
- * 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 9ae24f4..47187cc 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 d727575..c189aa5 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -70,21 +70,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 c2b7a07..47187cc 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/arch/x86/Kconfig b/arch/x86/Kconfig
index d5ed94d..b4c2e9c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -382,6 +382,8 @@ config X86_INTEL_CE
depends on X86_32
depends on X86_EXTENDED_PLATFORM
select X86_REBOOTFIXUPS
+ select OF
+ select OF_EARLY_FLATTREE
---help---
Select for the Intel CE media processor (CE4100) SOC.
This option compiles in support for the CE4100 SOC for settop
@@ -811,7 +813,7 @@ config X86_LOCAL_APIC
config X86_IO_APIC
def_bool y
- depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
+ depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
config X86_VISWS_APIC
def_bool y
@@ -2066,9 +2068,10 @@ config SCx200HR_TIMER
config OLPC
bool "One Laptop Per Child support"
+ depends on !X86_PAE
select GPIOLIB
- select OLPC_OPENFIRMWARE
- depends on !X86_64 && !X86_PAE
+ select OF
+ select OF_PROMTREE if PROC_DEVICETREE
---help---
Add support for detecting the unique features of the OLPC
XO hardware.
@@ -2079,21 +2082,6 @@ config OLPC_XO1
---help---
Add support for non-essential features of the OLPC XO-1 laptop.
-config OLPC_OPENFIRMWARE
- bool "Support for OLPC's Open Firmware"
- depends on !X86_64 && !X86_PAE
- default n
- select OF
- help
- This option adds support for the implementation of Open Firmware
- that is used on the OLPC XO-1 Children's Machine.
- If unsure, say N here.
-
-config OLPC_OPENFIRMWARE_DT
- bool
- default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
- select OF_PROMTREE
-
endif # X86_32
config AMD_NB
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 3c89694..5b7d513 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -220,7 +220,6 @@ extern void enable_IR_x2apic(void);
extern int get_physical_broadcast(void);
-extern void apic_disable(void);
extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC(void);
@@ -228,7 +227,6 @@ extern void disconnect_bsp_APIC(int virt_wire_setup);
extern void disable_local_APIC(void);
extern void lapic_shutdown(void);
extern int verify_local_APIC(void);
-extern void cache_APIC_registers(void);
extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
extern void setup_local_APIC(void);
@@ -239,8 +237,7 @@ void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void);
extern int APIC_init_uniprocessor(void);
-extern void enable_NMI_through_LVT0(void);
-extern int apic_force_enable(void);
+extern int apic_force_enable(unsigned long addr);
/*
* On 32bit this is mach-xxx local
@@ -261,7 +258,6 @@ static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }
-static inline void apic_disable(void) { }
# define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop
#endif /* !CONFIG_X86_LOCAL_APIC */
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 47a30ff..d87988b 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -426,4 +426,16 @@ struct local_apic {
#else
#define BAD_APICID 0xFFFFu
#endif
+
+enum ioapic_irq_destination_types {
+ dest_Fixed = 0,
+ dest_LowestPrio = 1,
+ dest_SMI = 2,
+ dest__reserved_1 = 3,
+ dest_NMI = 4,
+ dest_INIT = 5,
+ dest__reserved_2 = 6,
+ dest_ExtINT = 7
+};
+
#endif /* _ASM_X86_APICDEF_H */
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/e820.h b/arch/x86/include/asm/e820.h
index e99d55d..908b969 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -96,7 +96,7 @@ extern void e820_setup_gap(void);
extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
unsigned long start_addr, unsigned long long end_addr);
struct setup_data;
-extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data);
+extern void parse_e820_ext(struct setup_data *data);
#if defined(CONFIG_X86_64) || \
(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index f327d38..c4bd267 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -63,17 +63,6 @@ union IO_APIC_reg_03 {
} __attribute__ ((packed)) bits;
};
-enum ioapic_irq_destination_types {
- dest_Fixed = 0,
- dest_LowestPrio = 1,
- dest_SMI = 2,
- dest__reserved_1 = 3,
- dest_NMI = 4,
- dest_INIT = 5,
- dest__reserved_2 = 6,
- dest_ExtINT = 7
-};
-
struct IO_APIC_route_entry {
__u32 vector : 8,
delivery_mode : 3, /* 000: FIXED
@@ -106,6 +95,10 @@ struct IR_IO_APIC_route_entry {
index : 15;
} __attribute__ ((packed));
+#define IOAPIC_AUTO -1
+#define IOAPIC_EDGE 0
+#define IOAPIC_LEVEL 1
+
#ifdef CONFIG_X86_IO_APIC
/*
@@ -150,11 +143,6 @@ extern int timer_through_8259;
#define io_apic_assign_pci_irqs \
(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
-extern u8 io_apic_unique_id(u8 id);
-extern int io_apic_get_unique_id(int ioapic, int apic_id);
-extern int io_apic_get_version(int ioapic);
-extern int io_apic_get_redir_entries(int ioapic);
-
struct io_apic_irq_attr;
extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr);
@@ -162,6 +150,8 @@ void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_and_gsi_init(void);
extern void ioapic_insert_resources(void);
+int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
@@ -186,6 +176,8 @@ extern void __init pre_init_apic_IRQ0(void);
extern void mp_save_irq(struct mpc_intsrc *m);
+extern void disable_ioapic_support(void);
+
#else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0
@@ -199,6 +191,26 @@ static inline int mp_find_ioapic(u32 gsi) { return 0; }
struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr) { return 0; }
+
+static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+{
+ return NULL;
+}
+
+static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { }
+static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent)
+{
+ return -ENOMEM;
+}
+
+static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { }
+static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent)
+{
+ return -ENOMEM;
+}
+
+static inline void mp_save_irq(struct mpc_intsrc *m) { };
+static inline void disable_ioapic_support(void) { }
#endif
#endif /* _ASM_X86_IO_APIC_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index c704b38..ba870bb 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -10,9 +10,6 @@
#include <asm/apicdef.h>
#include <asm/irq_vectors.h>
-/* Even though we don't support this, supply it to appease OF */
-static inline void irq_dispose_mapping(unsigned int virq) { }
-
static inline int irq_canonicalize(int irq)
{
return ((irq == 2) ? 9 : irq);
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/olpc_ofw.h b/arch/x86/include/asm/olpc_ofw.h
index 641988e..c5d3a5a 100644
--- a/arch/x86/include/asm/olpc_ofw.h
+++ b/arch/x86/include/asm/olpc_ofw.h
@@ -6,7 +6,7 @@
#define OLPC_OFW_SIG 0x2057464F /* aka "OFW " */
-#ifdef CONFIG_OLPC_OPENFIRMWARE
+#ifdef CONFIG_OLPC
extern bool olpc_ofw_is_installed(void);
@@ -26,19 +26,15 @@ extern void setup_olpc_ofw_pgd(void);
/* check if OFW was detected during boot */
extern bool olpc_ofw_present(void);
-#else /* !CONFIG_OLPC_OPENFIRMWARE */
-
-static inline bool olpc_ofw_is_installed(void) { return false; }
+#else /* !CONFIG_OLPC */
static inline void olpc_ofw_detect(void) { }
static inline void setup_olpc_ofw_pgd(void) { }
-static inline bool olpc_ofw_present(void) { return false; }
-
-#endif /* !CONFIG_OLPC_OPENFIRMWARE */
+#endif /* !CONFIG_OLPC */
-#ifdef CONFIG_OLPC_OPENFIRMWARE_DT
+#ifdef CONFIG_OF_PROMTREE
extern void olpc_dt_build_devicetree(void);
#else
static inline void olpc_dt_build_devicetree(void) { }
-#endif /* CONFIG_OLPC_OPENFIRMWARE_DT */
+#endif
#endif /* _ASM_X86_OLPC_OFW_H */
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index b4ec95f..971e0b4 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -1 +1,69 @@
-/* dummy prom.h; here to make linux/of.h's #includes happy */
+/*
+ * 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 <linux/pci.h>
+
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/setup.h>
+#include <asm/irq_controller.h>
+
+#ifdef CONFIG_OF
+extern int of_ioapic;
+extern u64 initial_dtb;
+extern void add_dtb(u64 data);
+extern void x86_add_irq_domains(void);
+void __cpuinit x86_of_pci_init(void);
+void x86_dtb_init(void);
+
+static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+ return pdev ? pdev->dev.of_node : NULL;
+}
+
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+ return pci_device_to_OF_node(bus->self);
+}
+
+#else
+static inline void add_dtb(u64 data) { }
+static inline void x86_add_irq_domains(void) { }
+static inline void x86_of_pci_init(void) { }
+static inline void x86_dtb_init(void) { }
+#define of_ioapic 0
+#endif
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+
+#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__ */
+#endif
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 64642ad..643ebf2 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -83,11 +83,13 @@ struct x86_init_paging {
* boot cpu
* @tsc_pre_init: platform function called before TSC init
* @timer_init: initialize the platform timer (default PIT/HPET)
+ * @wallclock_init: init the wallclock device
*/
struct x86_init_timers {
void (*setup_percpu_clockev)(void);
void (*tsc_pre_init)(void);
void (*timer_init)(void);
+ void (*wallclock_init)(void);
};
/**
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 34244b2..62445ba 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -66,9 +66,9 @@ obj-$(CONFIG_PCI) += early-quirks.o
apm-y := apm_32.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_SMP) += smpboot.o tsc_sync.o
+obj-$(CONFIG_SMP) += smpboot.o
+obj-$(CONFIG_SMP) += tsc_sync.o
obj-$(CONFIG_SMP) += setup_percpu.o
-obj-$(CONFIG_X86_64_SMP) += tsc_sync.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-y += apic/
@@ -109,6 +109,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
+obj-$(CONFIG_OF) += devicetree.o
###
# 64 bit specific files
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 51ef31a..671d5aa 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta,
return 0;
}
-/*
- * APB timer clock is not in sync with pclk on Langwell, which translates to
- * unreliable read value caused by sampling error. the error does not add up
- * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
- * would go backwards. the following code is trying to prevent time traveling
- * backwards. little bit paranoid.
- */
static cycle_t apbt_read_clocksource(struct clocksource *cs)
{
- unsigned long t0, t1, t2;
- static unsigned long last_read;
-
-bad_count:
- t1 = apbt_readl(phy_cs_timer_id,
- APBTMR_N_CURRENT_VALUE);
- t2 = apbt_readl(phy_cs_timer_id,
- APBTMR_N_CURRENT_VALUE);
- if (unlikely(t1 < t2)) {
- pr_debug("APBT: read current count error %lx:%lx:%lx\n",
- t1, t2, t2 - t1);
- goto bad_count;
- }
- /*
- * check against cached last read, makes sure time does not go back.
- * it could be a normal rollover but we will do tripple check anyway
- */
- if (unlikely(t2 > last_read)) {
- /* check if we have a normal rollover */
- unsigned long raw_intr_status =
- apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
- /*
- * cs timer interrupt is masked but raw intr bit is set if
- * rollover occurs. then we read EOI reg to clear it.
- */
- if (raw_intr_status & (1 << phy_cs_timer_id)) {
- apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
- goto out;
- }
- pr_debug("APB CS going back %lx:%lx:%lx ",
- t2, last_read, t2 - last_read);
-bad_count_x3:
- pr_debug("triple check enforced\n");
- t0 = apbt_readl(phy_cs_timer_id,
- APBTMR_N_CURRENT_VALUE);
- udelay(1);
- t1 = apbt_readl(phy_cs_timer_id,
- APBTMR_N_CURRENT_VALUE);
- udelay(1);
- t2 = apbt_readl(phy_cs_timer_id,
- APBTMR_N_CURRENT_VALUE);
- if ((t2 > t1) || (t1 > t0)) {
- printk(KERN_ERR "Error: APB CS tripple check failed\n");
- goto bad_count_x3;
- }
- }
-out:
- last_read = t2;
- return (cycle_t)~t2;
+ unsigned long current_count;
+
+ current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
+ return (cycle_t)~current_count;
}
static int apbt_clocksource_register(void)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 76b96d7..ffbf7c2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -43,6 +43,7 @@
#include <asm/i8259.h>
#include <asm/proto.h>
#include <asm/apic.h>
+#include <asm/io_apic.h>
#include <asm/desc.h>
#include <asm/hpet.h>
#include <asm/idle.h>
@@ -83,7 +84,7 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
*
* +1=force-enable
*/
-static int force_enable_local_apic;
+static int force_enable_local_apic __initdata;
/*
* APIC command line parameters
*/
@@ -153,7 +154,7 @@ early_param("nox2apic", setup_nox2apic);
unsigned long mp_lapic_addr;
int disable_apic;
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
-static int disable_apic_timer __cpuinitdata;
+static int disable_apic_timer __initdata;
/* Local APIC timer works in C2 */
int local_apic_timer_c2_ok;
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
@@ -177,29 +178,8 @@ static struct resource lapic_resource = {
static unsigned int calibration_result;
-static int lapic_next_event(unsigned long delta,
- struct clock_event_device *evt);
-static void lapic_timer_setup(enum clock_event_mode mode,
- struct clock_event_device *evt);
-static void lapic_timer_broadcast(const struct cpumask *mask);
static void apic_pm_activate(void);
-/*
- * The local apic timer can be used for any function which is CPU local.
- */
-static struct clock_event_device lapic_clockevent = {
- .name = "lapic",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
- | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
- .shift = 32,
- .set_mode = lapic_timer_setup,
- .set_next_event = lapic_next_event,
- .broadcast = lapic_timer_broadcast,
- .rating = 100,
- .irq = -1,
-};
-static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
-
static unsigned long apic_phys;
/*
@@ -238,7 +218,7 @@ static int modern_apic(void)
* right after this call apic become NOOP driven
* so apic->write/read doesn't do anything
*/
-void apic_disable(void)
+static void __init apic_disable(void)
{
pr_info("APIC: switched to apic NOOP\n");
apic = &apic_noop;
@@ -282,23 +262,6 @@ u64 native_apic_icr_read(void)
return icr1 | ((u64)icr2 << 32);
}
-/**
- * enable_NMI_through_LVT0 - enable NMI through local vector table 0
- */
-void __cpuinit enable_NMI_through_LVT0(void)
-{
- unsigned int v;
-
- /* unmask and set to NMI */
- v = APIC_DM_NMI;
-
- /* Level triggered for 82489DX (32bit mode) */
- if (!lapic_is_integrated())
- v |= APIC_LVT_LEVEL_TRIGGER;
-
- apic_write(APIC_LVT0, v);
-}
-
#ifdef CONFIG_X86_32
/**
* get_physical_broadcast - Get number of physical broadcast IDs
@@ -508,6 +471,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
#endif
}
+
+/*
+ * The local apic timer can be used for any function which is CPU local.
+ */
+static struct clock_event_device lapic_clockevent = {
+ .name = "lapic",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
+ | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
+ .shift = 32,
+ .set_mode = lapic_timer_setup,
+ .set_next_event = lapic_next_event,
+ .broadcast = lapic_timer_broadcast,
+ .rating = 100,
+ .irq = -1,
+};
+static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+
/*
* Setup the local APIC timer for this CPU. Copy the initialized values
* of the boot CPU and register the clock event in the framework.
@@ -1209,7 +1189,7 @@ void __cpuinit setup_local_APIC(void)
rdtscll(tsc);
if (disable_apic) {
- arch_disable_smp_support();
+ disable_ioapic_support();
return;
}
@@ -1448,7 +1428,7 @@ int __init enable_IR(void)
void __init enable_IR_x2apic(void)
{
unsigned long flags;
- struct IO_APIC_route_entry **ioapic_entries = NULL;
+ struct IO_APIC_route_entry **ioapic_entries;
int ret, x2apic_enabled = 0;
int dmar_table_init_ret;
@@ -1537,7 +1517,7 @@ static int __init detect_init_APIC(void)
}
#else
-static int apic_verify(void)
+static int __init apic_verify(void)
{
u32 features, h, l;
@@ -1562,7 +1542,7 @@ static int apic_verify(void)
return 0;
}
-int apic_force_enable(void)
+int __init apic_force_enable(unsigned long addr)
{
u32 h, l;
@@ -1578,7 +1558,7 @@ int apic_force_enable(void)
if (!(l & MSR_IA32_APICBASE_ENABLE)) {
pr_info("Local APIC disabled by BIOS -- reenabling.\n");
l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | addr;
wrmsr(MSR_IA32_APICBASE, l, h);
enabled_via_apicbase = 1;
}
@@ -1619,7 +1599,7 @@ static int __init detect_init_APIC(void)
"you can enable it with \"lapic\"\n");
return -1;
}
- if (apic_force_enable())
+ if (apic_force_enable(APIC_DEFAULT_PHYS_BASE))
return -1;
} else {
if (apic_verify())
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index ca9e2a3..8d23e83 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -108,7 +108,10 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
int skip_ioapic_setup;
-void arch_disable_smp_support(void)
+/**
+ * disable_ioapic_support() - disables ioapic support at runtime
+ */
+void disable_ioapic_support(void)
{
#ifdef CONFIG_PCI
noioapicquirk = 1;
@@ -120,11 +123,14 @@ void arch_disable_smp_support(void)
static int __init parse_noapic(char *str)
{
/* disable IO-APIC */
- arch_disable_smp_support();
+ disable_ioapic_support();
return 0;
}
early_param("noapic", parse_noapic);
+static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+ struct io_apic_irq_attr *attr);
+
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
void mp_save_irq(struct mpc_intsrc *m)
{
@@ -818,7 +824,7 @@ static int EISA_ELCR(unsigned int irq)
#define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) default_ISA_polarity(idx)
-static int MPBIOS_polarity(int idx)
+static int irq_polarity(int idx)
{
int bus = mp_irqs[idx].srcbus;
int polarity;
@@ -860,7 +866,7 @@ static int MPBIOS_polarity(int idx)
return polarity;
}
-static int MPBIOS_trigger(int idx)
+static int irq_trigger(int idx)
{
int bus = mp_irqs[idx].srcbus;
int trigger;
@@ -932,16 +938,6 @@ static int MPBIOS_trigger(int idx)
return trigger;
}
-static inline int irq_polarity(int idx)
-{
- return MPBIOS_polarity(idx);
-}
-
-static inline int irq_trigger(int idx)
-{
- return MPBIOS_trigger(idx);
-}
-
static int pin_2_irq(int idx, int apic, int pin)
{
int irq;
@@ -1220,10 +1216,6 @@ void __setup_vector_irq(int cpu)
static struct irq_chip ioapic_chip;
static struct irq_chip ir_ioapic_chip;
-#define IOAPIC_AUTO -1
-#define IOAPIC_EDGE 0
-#define IOAPIC_LEVEL 1
-
#ifdef CONFIG_X86_32
static inline int IO_APIC_irq_trigger(int irq)
{
@@ -1385,33 +1377,26 @@ static struct {
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} mp_ioapic_routing[MAX_IO_APICS];
-static void __init setup_IO_APIC_irqs(void)
+static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
{
- int apic_id, pin, idx, irq, notcon = 0;
- int node = cpu_to_node(0);
- struct irq_cfg *cfg;
+ if (idx != -1)
+ return false;
- apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
+ mp_ioapics[apic_id].apicid, pin);
+ return true;
+}
+
+static void __init __io_apic_setup_irqs(unsigned int apic_id)
+{
+ int idx, node = cpu_to_node(0);
+ struct io_apic_irq_attr attr;
+ unsigned int pin, irq;
- for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
idx = find_irq_entry(apic_id, pin, mp_INT);
- if (idx == -1) {
- if (!notcon) {
- notcon = 1;
- apic_printk(APIC_VERBOSE,
- KERN_DEBUG " %d-%d",
- mp_ioapics[apic_id].apicid, pin);
- } else
- apic_printk(APIC_VERBOSE, " %d-%d",
- mp_ioapics[apic_id].apicid, pin);
+ if (io_apic_pin_not_connected(idx, apic_id, pin))
continue;
- }
- if (notcon) {
- apic_printk(APIC_VERBOSE,
- " (apicid-pin) not connected\n");
- notcon = 0;
- }
irq = pin_2_irq(idx, apic_id, pin);
@@ -1423,25 +1408,24 @@ static void __init setup_IO_APIC_irqs(void)
* installed and if it returns 1:
*/
if (apic->multi_timer_check &&
- apic->multi_timer_check(apic_id, irq))
+ apic->multi_timer_check(apic_id, irq))
continue;
- cfg = alloc_irq_and_cfg_at(irq, node);
- if (!cfg)
- continue;
+ set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+ irq_polarity(idx));
- add_pin_to_irq_node(cfg, node, apic_id, pin);
- /*
- * don't mark it in pin_programmed, so later acpi could
- * set it correctly when irq < 16
- */
- setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
- irq_polarity(idx));
+ io_apic_setup_irq_pin(irq, node, &attr);
}
+}
- if (notcon)
- apic_printk(APIC_VERBOSE,
- " (apicid-pin) not connected\n");
+static void __init setup_IO_APIC_irqs(void)
+{
+ unsigned int apic_id;
+
+ apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+ for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
+ __io_apic_setup_irqs(apic_id);
}
/*
@@ -1452,7 +1436,7 @@ static void __init setup_IO_APIC_irqs(void)
void setup_IO_APIC_irq_extra(u32 gsi)
{
int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
- struct irq_cfg *cfg;
+ struct io_apic_irq_attr attr;
/*
* Convert 'gsi' to 'ioapic.pin'.
@@ -1472,21 +1456,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
if (apic_id == 0 || irq < NR_IRQS_LEGACY)
return;
- cfg = alloc_irq_and_cfg_at(irq, node);
- if (!cfg)
- return;
-
- add_pin_to_irq_node(cfg, node, apic_id, pin);
-
- if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
- pr_debug("Pin %d-%d already programmed\n",
- mp_ioapics[apic_id].apicid, pin);
- return;
- }
- set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+ set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+ irq_polarity(idx));
- setup_ioapic_irq(apic_id, pin, irq, cfg,
- irq_trigger(idx), irq_polarity(idx));
+ io_apic_setup_irq_pin_once(irq, node, &attr);
}
/*
@@ -3605,7 +3578,40 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
}
#endif /* CONFIG_HT_IRQ */
-int __init io_apic_get_redir_entries (int ioapic)
+int
+io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
+{
+ struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
+ int ret;
+
+ if (!cfg)
+ return -EINVAL;
+ ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
+ if (!ret)
+ setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
+ attr->trigger, attr->polarity);
+ return ret;
+}
+
+static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+ struct io_apic_irq_attr *attr)
+{
+ unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
+ int ret;
+
+ /* Avoid redundant programming */
+ if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
+ pr_debug("Pin %d-%d already programmed\n",
+ mp_ioapics[id].apicid, pin);
+ return 0;
+ }
+ ret = io_apic_setup_irq_pin(irq, node, attr);
+ if (!ret)
+ set_bit(pin, mp_ioapic_routing[id].pin_programmed);
+ return ret;
+}
+
+static int __init io_apic_get_redir_entries(int ioapic)
{
union IO_APIC_reg_01 reg_01;
unsigned long flags;
@@ -3659,96 +3665,24 @@ int __init arch_probe_nr_irqs(void)
}
#endif
-static int __io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr)
+int io_apic_set_pci_routing(struct device *dev, int irq,
+ struct io_apic_irq_attr *irq_attr)
{
- struct irq_cfg *cfg;
int node;
- int ioapic, pin;
- int trigger, polarity;
- ioapic = irq_attr->ioapic;
if (!IO_APIC_IRQ(irq)) {
apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
- ioapic);
+ irq_attr->ioapic);
return -EINVAL;
}
- if (dev)
- node = dev_to_node(dev);
- else
- node = cpu_to_node(0);
-
- cfg = alloc_irq_and_cfg_at(irq, node);
- if (!cfg)
- return 0;
-
- pin = irq_attr->ioapic_pin;
- trigger = irq_attr->trigger;
- polarity = irq_attr->polarity;
-
- /*
- * IRQs < 16 are already in the irq_2_pin[] map
- */
- if (irq >= legacy_pic->nr_legacy_irqs) {
- if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
- printk(KERN_INFO "can not add pin %d for irq %d\n",
- pin, irq);
- return 0;
- }
- }
-
- setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
+ node = dev ? dev_to_node(dev) : cpu_to_node(0);
- return 0;
+ return io_apic_setup_irq_pin_once(irq, node, irq_attr);
}
-int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr)
-{
- int ioapic, pin;
- /*
- * Avoid pin reprogramming. PRTs typically include entries
- * with redundant pin->gsi mappings (but unique PCI devices);
- * we only program the IOAPIC on the first.
- */
- ioapic = irq_attr->ioapic;
- pin = irq_attr->ioapic_pin;
- if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
- pr_debug("Pin %d-%d already programmed\n",
- mp_ioapics[ioapic].apicid, pin);
- return 0;
- }
- set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
-
- return __io_apic_set_pci_routing(dev, irq, irq_attr);
-}
-
-u8 __init io_apic_unique_id(u8 id)
-{
#ifdef CONFIG_X86_32
- if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
- !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
- return io_apic_get_unique_id(nr_ioapics, id);
- else
- return id;
-#else
- int i;
- DECLARE_BITMAP(used, 256);
-
- bitmap_zero(used, 256);
- for (i = 0; i < nr_ioapics; i++) {
- struct mpc_ioapic *ia = &mp_ioapics[i];
- __set_bit(ia->apicid, used);
- }
- if (!test_bit(id, used))
- return id;
- return find_first_zero_bit(used, 256);
-#endif
-}
-
-#ifdef CONFIG_X86_32
-int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int __init io_apic_get_unique_id(int ioapic, int apic_id)
{
union IO_APIC_reg_00 reg_00;
static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3821,9 +3755,33 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
return apic_id;
}
+
+static u8 __init io_apic_unique_id(u8 id)
+{
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+ !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+ return io_apic_get_unique_id(nr_ioapics, id);
+ else
+ return id;
+}
+#else
+static u8 __init io_apic_unique_id(u8 id)
+{
+ int i;
+ DECLARE_BITMAP(used, 256);
+
+ bitmap_zero(used, 256);
+ for (i = 0; i < nr_ioapics; i++) {
+ struct mpc_ioapic *ia = &mp_ioapics[i];
+ __set_bit(ia->apicid, used);
+ }
+ if (!test_bit(id, used))
+ return id;
+ return find_first_zero_bit(used, 256);
+}
#endif
-int __init io_apic_get_version(int ioapic)
+static int __init io_apic_get_version(int ioapic)
{
union IO_APIC_reg_01 reg_01;
unsigned long flags;
@@ -4026,7 +3984,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
return gsi - mp_gsi_routing[ioapic].gsi_base;
}
-static int bad_ioapic(unsigned long address)
+static __init int bad_ioapic(unsigned long address)
{
if (nr_ioapics >= MAX_IO_APICS) {
printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
@@ -4086,20 +4044,15 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{
- struct irq_cfg *cfg;
+ struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
printk(KERN_INFO "Early APIC setup for system timer0\n");
#ifndef CONFIG_SMP
physid_set_mask_of_physid(boot_cpu_physical_apicid,
&phys_cpu_present_map);
#endif
- /* Make sure the irq descriptor is set up */
- cfg = alloc_irq_and_cfg_at(0, 0);
-
setup_local_APIC();
- add_pin_to_irq_node(cfg, 0, 0, 0);
+ io_apic_setup_irq_pin(0, 0, &attr);
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
-
- setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
}
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
new file mode 100644
index 0000000..7a8cebc
--- /dev/null
+++ b/arch/x86/kernel/devicetree.c
@@ -0,0 +1,441 @@
+/*
+ * Architecture specific OF callbacks.
+ */
+#include <linux/bootmem.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.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/apic.h>
+#include <asm/pci_x86.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;
+
+#ifdef CONFIG_X86_IO_APIC
+static 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);
+}
+#endif
+
+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)
+{
+ struct irq_domain *ih;
+ u32 virq, type;
+ int ret;
+
+ ih = get_ih_from_node(controller);
+ if (!ih)
+ return 0;
+ 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);
+
+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();
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+ return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
+}
+
+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[] = {
+ { .compatible = "intel,ce4100-cp", },
+ { .compatible = "isa", },
+ { .compatible = "pci", },
+ {},
+};
+
+static int __init add_bus_probe(void)
+{
+ if (!of_have_populated_dt())
+ return 0;
+
+ return of_platform_bus_probe(NULL, ce4100_ids, NULL);
+}
+module_init(add_bus_probe);
+
+#ifdef CONFIG_PCI
+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 == 0)
+ 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);
+ }
+ }
+}
+#endif
+
+static void __init dtb_setup_hpet(void)
+{
+#ifdef CONFIG_HPET_TIMER
+ struct device_node *dn;
+ struct resource r;
+ int ret;
+
+ dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
+ if (!dn)
+ return;
+ ret = of_address_to_resource(dn, 0, &r);
+ if (ret) {
+ WARN_ON(1);
+ return;
+ }
+ hpet_address = r.start;
+#endif
+}
+
+static void __init dtb_lapic_setup(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ struct device_node *dn;
+ struct resource r;
+ int ret;
+
+ dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
+ if (!dn)
+ return;
+
+ ret = of_address_to_resource(dn, 0, &r);
+ if (WARN_ON(ret))
+ return;
+
+ /* Did the boot loader setup the local APIC ? */
+ if (!cpu_has_apic) {
+ if (apic_force_enable(r.start))
+ return;
+ }
+ smp_found_config = 1;
+ pic_mode = 1;
+ register_lapic_address(r.start);
+ generic_processor_info(boot_cpu_physical_apicid,
+ GET_APIC_VERSION(apic_read(APIC_LVR)));
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+static unsigned int ioapic_id;
+
+static void __init dtb_add_ioapic(struct device_node *dn)
+{
+ struct resource r;
+ int ret;
+
+ 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;
+
+ for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+ dtb_add_ioapic(dn);
+
+ if (nr_ioapics) {
+ of_ioapic = 1;
+ return;
+ }
+ printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
+
+static void __init dtb_apic_setup(void)
+{
+ dtb_lapic_setup();
+ dtb_ioapic_setup();
+}
+
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
+{
+ u32 size, 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();
+}
+#else
+static inline void x86_flattree_get_config(void) { }
+#endif
+
+void __init x86_dtb_init(void)
+{
+ x86_flattree_get_config();
+
+ if (!of_have_populated_dt())
+ return;
+
+ dtb_setup_hpet();
+ dtb_apic_setup();
+}
+
+#ifdef CONFIG_X86_IO_APIC
+
+struct of_ioapic_type {
+ u32 out_type;
+ u32 trigger;
+ u32 polarity;
+};
+
+static struct of_ioapic_type of_ioapic_type[] =
+{
+ {
+ .out_type = IRQ_TYPE_EDGE_RISING,
+ .trigger = IOAPIC_EDGE,
+ .polarity = 1,
+ },
+ {
+ .out_type = IRQ_TYPE_LEVEL_LOW,
+ .trigger = IOAPIC_LEVEL,
+ .polarity = 0,
+ },
+ {
+ .out_type = IRQ_TYPE_LEVEL_HIGH,
+ .trigger = IOAPIC_LEVEL,
+ .polarity = 1,
+ },
+ {
+ .out_type = IRQ_TYPE_EDGE_FALLING,
+ .trigger = IOAPIC_EDGE,
+ .polarity = 0,
+ },
+};
+
+static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
+ u32 *out_hwirq, u32 *out_type)
+{
+ struct io_apic_irq_attr attr;
+ struct of_ioapic_type *it;
+ u32 line, idx, type;
+
+ if (intsize < 2)
+ return -EINVAL;
+
+ line = *intspec;
+ idx = (u32) id->priv;
+ *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
+
+ intspec++;
+ type = *intspec;
+
+ if (type >= ARRAY_SIZE(of_ioapic_type))
+ return -EINVAL;
+
+ it = of_ioapic_type + type;
+ *out_type = it->out_type;
+
+ set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
+
+ return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
+}
+
+static void __init ioapic_add_ofnode(struct device_node *np)
+{
+ struct resource r;
+ int i, ret;
+
+ 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;
+
+ 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);
+}
+
+void __init x86_add_irq_domains(void)
+{
+ struct device_node *dp;
+
+ if (!of_have_populated_dt())
+ return;
+
+ for_each_node_with_property(dp, "interrupt-controller") {
+ if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
+ ioapic_add_ofnode(dp);
+ }
+}
+#else
+void __init x86_add_irq_domains(void) { }
+#endif
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 294f26d..5fad626 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -667,21 +667,15 @@ __init void e820_setup_gap(void)
* boot_params.e820_map, others are passed via SETUP_E820_EXT node of
* linked list of struct setup_data, which is parsed here.
*/
-void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
+void __init parse_e820_ext(struct setup_data *sdata)
{
- u32 map_len;
int entries;
struct e820entry *extmap;
entries = sdata->len / sizeof(struct e820entry);
- map_len = sdata->len + sizeof(struct setup_data);
- if (map_len > PAGE_SIZE)
- sdata = early_ioremap(pa_data, map_len);
extmap = (struct e820entry *)(sdata->data);
__append_e820_map(extmap, entries);
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
- if (map_len > PAGE_SIZE)
- early_iounmap(sdata, map_len);
printk(KERN_INFO "extended physical RAM map:\n");
e820_print_map("extended");
}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 767d6c4..d8cc18a 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -137,7 +137,7 @@ ENTRY(startup_32)
movsl
1:
-#ifdef CONFIG_OLPC_OPENFIRMWARE
+#ifdef CONFIG_OLPC
/* save OFW's pgdir table for later use when calling into OFW */
movl %cr3, %eax
movl %eax, pa(olpc_ofw_pgd)
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 387b6a0..7531360 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -276,15 +276,6 @@ void smp_x86_platform_ipi(struct pt_regs *regs)
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
-#ifdef CONFIG_OF
-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);
-#endif
-
#ifdef CONFIG_HOTPLUG_CPU
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
void fixup_irqs(void)
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index c752e97..9f76f89 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:
@@ -118,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
@@ -243,7 +250,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/rtc.c b/arch/x86/kernel/rtc.c
index 6f39cab..3f2ad26 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bcd.h>
#include <linux/pnp.h>
+#include <linux/of.h>
#include <asm/vsyscall.h>
#include <asm/x86_init.h>
@@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void)
}
}
#endif
+ if (of_have_populated_dt())
+ return 0;
platform_device_register(&rtc_device);
dev_info(&rtc_device.dev,
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index d3cfe26..b3143bc 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.
@@ -429,16 +430,30 @@ static void __init parse_setup_data(void)
return;
pa_data = boot_params.hdr.setup_data;
while (pa_data) {
- data = early_memremap(pa_data, PAGE_SIZE);
+ u32 data_len, map_len;
+
+ map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK),
+ (u64)sizeof(struct setup_data));
+ data = early_memremap(pa_data, map_len);
+ data_len = data->len + sizeof(struct setup_data);
+ if (data_len > map_len) {
+ early_iounmap(data, map_len);
+ data = early_memremap(pa_data, data_len);
+ map_len = data_len;
+ }
+
switch (data->type) {
case SETUP_E820_EXT:
- parse_e820_ext(data, pa_data);
+ parse_e820_ext(data);
+ break;
+ case SETUP_DTB:
+ add_dtb(pa_data);
break;
default:
break;
}
pa_data = data->next;
- early_iounmap(data, PAGE_SIZE);
+ early_iounmap(data, map_len);
}
}
@@ -1029,8 +1044,8 @@ void __init setup_arch(char **cmdline_p)
* Read APIC and some other early information from ACPI tables.
*/
acpi_boot_init();
-
sfi_init();
+ x86_dtb_init();
/*
* get boot-time SMP configuration:
@@ -1066,6 +1081,8 @@ void __init setup_arch(char **cmdline_p)
#endif
x86_init.oem.banner();
+ x86_init.timers.wallclock_init();
+
mcheck_init();
local_irq_save(flags);
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 08776a9..09d0172 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -64,6 +64,7 @@
#include <asm/mtrr.h>
#include <asm/mwait.h>
#include <asm/apic.h>
+#include <asm/io_apic.h>
#include <asm/setup.h>
#include <asm/uv/uv.h>
#include <linux/mc146818rtc.h>
@@ -945,6 +946,14 @@ int __cpuinit native_cpu_up(unsigned int cpu)
return 0;
}
+/**
+ * arch_disable_smp_support() - disables SMP support for x86 at runtime
+ */
+void arch_disable_smp_support(void)
+{
+ disable_ioapic_support();
+}
+
/*
* Fall back to non SMP mode after errors.
*
@@ -1045,7 +1054,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
"(tell your hw vendor)\n");
}
smpboot_clear_io_apic();
- arch_disable_smp_support();
+ disable_ioapic_support();
return -1;
}
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index ceb2911..c11514e 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = {
.setup_percpu_clockev = setup_boot_APIC_clock,
.tsc_pre_init = x86_init_noop,
.timer_init = hpet_time_init,
+ .wallclock_init = x86_init_noop,
},
.iommu = {
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index 85b68ef..c63c6d3 100644
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -254,7 +254,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
static int ce4100_conf_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
- int i, retval = 1;
+ int i;
if (bus == 1) {
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index d2c0d51..68c0dbc 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -15,21 +15,19 @@
#include <linux/serial_reg.h>
#include <linux/serial_8250.h>
+#include <asm/prom.h>
#include <asm/setup.h>
+#include <asm/i8259.h>
#include <asm/io.h>
+#include <asm/io_apic.h>
static int ce4100_i8042_detect(void)
{
return 0;
}
-static void __init sdv_find_smp_config(void)
-{
-}
-
#ifdef CONFIG_SERIAL_8250
-
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@@ -118,6 +116,15 @@ static void __init sdv_arch_setup(void)
sdv_serial_fixup();
}
+#ifdef CONFIG_X86_IO_APIC
+static void __cpuinit sdv_pci_init(void)
+{
+ x86_of_pci_init();
+ /* We can't set this earlier, because we need to calibrate the timer */
+ legacy_pic = &null_legacy_pic;
+}
+#endif
+
/*
* CE4100 specific x86_init function overrides and early setup
* calls.
@@ -128,5 +135,10 @@ void __init x86_ce4100_early_setup(void)
x86_platform.i8042_detect = ce4100_i8042_detect;
x86_init.resources.probe_roms = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
- x86_init.mpparse.find_smp_config = sdv_find_smp_config;
+ x86_init.mpparse.find_smp_config = x86_init_noop;
+
+#ifdef CONFIG_X86_IO_APIC
+ x86_init.pci.init_irq = sdv_pci_init;
+ x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
+#endif
}
diff --git a/arch/x86/platform/ce4100/falconfalls.dts b/arch/x86/platform/ce4100/falconfalls.dts
new file mode 100644
index 0000000..dc701ea
--- /dev/null
+++ b/arch/x86/platform/ce4100/falconfalls.dts
@@ -0,0 +1,428 @@
+/*
+ * 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-cp";
+ ranges;
+
+ ioapic1: interrupt-controller@fec00000 {
+ #interrupt-cells = <2>;
+ compatible = "intel,ce4100-ioapic";
+ interrupt-controller;
+ reg = <0xfec00000 0x1000>;
+ };
+
+ timer@fed00000 {
+ compatible = "intel,ce4100-hpet";
+ reg = <0xfed00000 0x200>;
+ };
+
+ lapic0: interrupt-controller@fee00000 {
+ compatible = "intel,ce4100-lapic";
+ reg = <0xfee00000 0x1000>;
+ };
+
+ pci@3fc {
+ #address-cells = <3>;
+ #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>;
+
+ /* Secondary IO-APIC */
+ ioapic2: interrupt-controller@0,1 {
+ #interrupt-cells = <2>;
+ compatible = "intel,ce4100-ioapic";
+ interrupt-controller;
+ reg = <0x100 0x0 0x0 0x0 0x0>;
+ assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+ };
+
+ pci@1,0 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ compatible = "intel,ce4100-pci", "pci";
+ device_type = "pci";
+ bus-range = <1 1>;
+ ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
+
+ interrupt-parent = <&ioapic2>;
+
+ display@2,0 {
+ compatible = "pci8086,2e5b.2",
+ "pci8086,2e5b",
+ "pciclass038000",
+ "pciclass0380";
+
+ reg = <0x11000 0x0 0x0 0x0 0x0>;
+ interrupts = <0 1>;
+ };
+
+ multimedia@3,0 {
+ compatible = "pci8086,2e5c.2",
+ "pci8086,2e5c",
+ "pciclass048000",
+ "pciclass0480";
+
+ reg = <0x11800 0x0 0x0 0x0 0x0>;
+ interrupts = <2 1>;
+ };
+
+ multimedia@4,0 {
+ compatible = "pci8086,2e5d.2",
+ "pci8086,2e5d",
+ "pciclass048000",
+ "pciclass0480";
+
+ reg = <0x12000 0x0 0x0 0x0 0x0>;
+ interrupts = <4 1>;
+ };
+
+ multimedia@4,1 {
+ compatible = "pci8086,2e5e.2",
+ "pci8086,2e5e",
+ "pciclass048000",
+ "pciclass0480";
+
+ reg = <0x12100 0x0 0x0 0x0 0x0>;
+ interrupts = <5 1>;
+ };
+
+ sound@6,0 {
+ compatible = "pci8086,2e5f.2",
+ "pci8086,2e5f",
+ "pciclass040100",
+ "pciclass0401";
+
+ reg = <0x13000 0x0 0x0 0x0 0x0>;
+ interrupts = <6 1>;
+ };
+
+ sound@6,1 {
+ compatible = "pci8086,2e5f.2",
+ "pci8086,2e5f",
+ "pciclass040100",
+ "pciclass0401";
+
+ reg = <0x13100 0x0 0x0 0x0 0x0>;
+ interrupts = <7 1>;
+ };
+
+ sound@6,2 {
+ compatible = "pci8086,2e60.2",
+ "pci8086,2e60",
+ "pciclass040100",
+ "pciclass0401";
+
+ reg = <0x13200 0x0 0x0 0x0 0x0>;
+ interrupts = <8 1>;
+ };
+
+ display@8,0 {
+ compatible = "pci8086,2e61.2",
+ "pci8086,2e61",
+ "pciclass038000",
+ "pciclass0380";
+
+ reg = <0x14000 0x0 0x0 0x0 0x0>;
+ interrupts = <9 1>;
+ };
+
+ display@8,1 {
+ compatible = "pci8086,2e62.2",
+ "pci8086,2e62",
+ "pciclass038000",
+ "pciclass0380";
+
+ reg = <0x14100 0x0 0x0 0x0 0x0>;
+ interrupts = <10 1>;
+ };
+
+ multimedia@8,2 {
+ compatible = "pci8086,2e63.2",
+ "pci8086,2e63",
+ "pciclass048000",
+ "pciclass0480";
+
+ reg = <0x14200 0x0 0x0 0x0 0x0>;
+ interrupts = <11 1>;
+ };
+
+ entertainment-encryption@9,0 {
+ compatible = "pci8086,2e64.2",
+ "pci8086,2e64",
+ "pciclass101000",
+ "pciclass1010";
+
+ reg = <0x14800 0x0 0x0 0x0 0x0>;
+ interrupts = <12 1>;
+ };
+
+ localbus@a,0 {
+ compatible = "pci8086,2e65.2",
+ "pci8086,2e65",
+ "pciclassff0000",
+ "pciclassff00";
+
+ reg = <0x15000 0x0 0x0 0x0 0x0>;
+ };
+
+ serial@b,0 {
+ compatible = "pci8086,2e66.2",
+ "pci8086,2e66",
+ "pciclass070003",
+ "pciclass0700";
+
+ reg = <0x15800 0x0 0x0 0x0 0x0>;
+ interrupts = <14 1>;
+ };
+
+ gpio@b,1 {
+ compatible = "pci8086,2e67.2",
+ "pci8086,2e67",
+ "pciclassff0000",
+ "pciclassff00";
+
+ #gpio-cells = <2>;
+ reg = <0x15900 0x0 0x0 0x0 0x0>;
+ interrupts = <15 1>;
+ gpio-controller;
+ };
+
+ i2c-controller@b,2 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "pci8086,2e68.2",
+ "pci8086,2e68",
+ "pciclass,ff0000",
+ "pciclass,ff00";
+
+ reg = <0x15a00 0x0 0x0 0x0 0x0>;
+ interrupts = <16 1>;
+ 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 {
+ #gpio-cells = <2>;
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ gpio-controller;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "intel,ce4100-i2c-controller";
+ reg = <2 0 0x100>;
+
+ gpio@26 {
+ #gpio-cells = <2>;
+ compatible = "ti,pcf8575";
+ reg = <0x26>;
+ gpio-controller;
+ };
+ };
+ };
+
+ smard-card@b,3 {
+ compatible = "pci8086,2e69.2",
+ "pci8086,2e69",
+ "pciclass070500",
+ "pciclass0705";
+
+ reg = <0x15b00 0x0 0x0 0x0 0x0>;
+ interrupts = <15 1>;
+ };
+
+ spi-controller@b,4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible =
+ "pci8086,2e6a.2",
+ "pci8086,2e6a",
+ "pciclass,ff0000",
+ "pciclass,ff00";
+
+ reg = <0x15c00 0x0 0x0 0x0 0x0>;
+ interrupts = <15 1>;
+
+ 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>;
+ };
+ };
+
+ multimedia@b,7 {
+ compatible = "pci8086,2e6d.2",
+ "pci8086,2e6d",
+ "pciclassff0000",
+ "pciclassff00";
+
+ reg = <0x15f00 0x0 0x0 0x0 0x0>;
+ };
+
+ ethernet@c,0 {
+ compatible = "pci8086,2e6e.2",
+ "pci8086,2e6e",
+ "pciclass020000",
+ "pciclass0200";
+
+ reg = <0x16000 0x0 0x0 0x0 0x0>;
+ interrupts = <21 1>;
+ };
+
+ clock@c,1 {
+ compatible = "pci8086,2e6f.2",
+ "pci8086,2e6f",
+ "pciclassff0000",
+ "pciclassff00";
+
+ reg = <0x16100 0x0 0x0 0x0 0x0>;
+ interrupts = <3 1>;
+ };
+
+ usb@d,0 {
+ compatible = "pci8086,2e70.2",
+ "pci8086,2e70",
+ "pciclass0c0320",
+ "pciclass0c03";
+
+ reg = <0x16800 0x0 0x0 0x0 0x0>;
+ interrupts = <22 3>;
+ };
+
+ usb@d,1 {
+ compatible = "pci8086,2e70.2",
+ "pci8086,2e70",
+ "pciclass0c0320",
+ "pciclass0c03";
+
+ reg = <0x16900 0x0 0x0 0x0 0x0>;
+ interrupts = <22 3>;
+ };
+
+ sata@e,0 {
+ compatible = "pci8086,2e71.0",
+ "pci8086,2e71",
+ "pciclass010601",
+ "pciclass0106";
+
+ reg = <0x17000 0x0 0x0 0x0 0x0>;
+ interrupts = <23 3>;
+ };
+
+ flash@f,0 {
+ compatible = "pci8086,701.1",
+ "pci8086,701",
+ "pciclass050100",
+ "pciclass0501";
+
+ reg = <0x17800 0x0 0x0 0x0 0x0>;
+ interrupts = <13 1>;
+ };
+
+ entertainment-encryption@10,0 {
+ compatible = "pci8086,702.1",
+ "pci8086,702",
+ "pciclass101000",
+ "pciclass1010";
+
+ reg = <0x18000 0x0 0x0 0x0 0x0>;
+ };
+
+ co-processor@11,0 {
+ compatible = "pci8086,703.1",
+ "pci8086,703",
+ "pciclass0b4000",
+ "pciclass0b40";
+
+ reg = <0x18800 0x0 0x0 0x0 0x0>;
+ interrupts = <1 1>;
+ };
+
+ multimedia@12,0 {
+ compatible = "pci8086,704.0",
+ "pci8086,704",
+ "pciclass048000",
+ "pciclass0480";
+
+ reg = <0x19000 0x0 0x0 0x0 0x0>;
+ };
+ };
+
+ isa@1f,0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "isa";
+ ranges = <1 0 0 0 0 0x100>;
+
+ rtc@70 {
+ compatible = "intel,ce4100-rtc", "motorola,mc146818";
+ interrupts = <8 3>;
+ interrupt-parent = <&ioapic1>;
+ ctrl-reg = <2>;
+ freq-reg = <0x26>;
+ reg = <1 0x70 2>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index ea6529e..5c0207b 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -31,6 +31,7 @@
#include <asm/apic.h>
#include <asm/io_apic.h>
#include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
#include <asm/io.h>
#include <asm/i8259.h>
#include <asm/intel_scu_ipc.h>
@@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void)
x86_platform.calibrate_tsc = mrst_calibrate_tsc;
x86_platform.i8042_detect = mrst_i8042_detect;
+ x86_init.timers.wallclock_init = mrst_rtc_init;
x86_init.pci.init = pci_mrst_init;
x86_init.pci.fixup_irqs = x86_init_noop;
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
index 32cd7ed..04cf645 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -100,22 +100,14 @@ int vrtc_set_mmss(unsigned long nowtime)
void __init mrst_rtc_init(void)
{
- unsigned long rtc_paddr;
- void __iomem *virt_base;
+ unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr;
sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
- if (!sfi_mrtc_num)
+ if (!sfi_mrtc_num || !vrtc_paddr)
return;
- rtc_paddr = sfi_mrtc_array[0].phys_addr;
-
- /* vRTC's register address may not be page aligned */
- set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
-
- virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
- virt_base += rtc_paddr & ~PAGE_MASK;
- vrtc_virt_base = virt_base;
-
+ vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
+ vrtc_paddr);
x86_platform.get_wallclock = vrtc_get_time;
x86_platform.set_wallclock = vrtc_set_mmss;
}
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
index e797428..c2a8cab 100644
--- a/arch/x86/platform/olpc/Makefile
+++ b/arch/x86/platform/olpc/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_OLPC) += olpc.o
obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o
-obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o
-obj-$(CONFIG_OLPC_OPENFIRMWARE_DT) += olpc_dt.o
+obj-$(CONFIG_OLPC) += olpc_ofw.o
+obj-$(CONFIG_OF_PROMTREE) += olpc_dt.o
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index ef3bcb1..c2ef5ce 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -330,9 +330,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
i2c->adap = ocores_adapter;
i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev;
-#ifdef CONFIG_OF
i2c->adap.dev.of_node = pdev->dev.of_node;
-#endif
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
@@ -390,15 +388,11 @@ static int ocores_i2c_resume(struct platform_device *pdev)
#define ocores_i2c_resume NULL
#endif
-#ifdef CONFIG_OF
static struct of_device_id ocores_i2c_match[] = {
- {
- .compatible = "opencores,i2c-ocores",
- },
- {},
+ { .compatible = "opencores,i2c-ocores", },
+ {},
};
MODULE_DEVICE_TABLE(of, ocores_i2c_match);
-#endif
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:ocores-i2c");
@@ -411,9 +405,7 @@ static struct platform_driver ocores_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "ocores-i2c",
-#ifdef CONFIG_OF
- .of_match_table = ocores_i2c_match,
-#endif
+ .of_match_table = ocores_i2c_match,
},
};
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index f0bd5bc..045ba6e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -537,9 +537,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
-#ifdef CONFIG_OF
client->dev.of_node = info->of_node;
-#endif
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
client->addr);
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index fd877f6..2f7fc0c 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1516,21 +1516,17 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
return 0;
}
-#if defined(CONFIG_OF)
static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
{ .compatible = "mmc-spi-slot", },
{},
};
-#endif
static struct spi_driver mmc_spi_driver = {
.driver = {
.name = "mmc_spi",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
-#if defined(CONFIG_OF)
.of_match_table = mmc_spi_of_match_table,
-#endif
},
.probe = mmc_spi_probe,
.remove = __devexit_p(mmc_spi_remove),
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index b79d7e1..db0290f 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -1163,15 +1163,11 @@ static int ethoc_resume(struct platform_device *pdev)
# define ethoc_resume NULL
#endif
-#ifdef CONFIG_OF
static struct of_device_id ethoc_match[] = {
- {
- .compatible = "opencores,ethoc",
- },
+ { .compatible = "opencores,ethoc", },
{},
};
MODULE_DEVICE_TABLE(of, ethoc_match);
-#endif
static struct platform_driver ethoc_driver = {
.probe = ethoc_probe,
@@ -1181,9 +1177,7 @@ static struct platform_driver ethoc_driver = {
.driver = {
.name = "ethoc",
.owner = THIS_MODULE,
-#ifdef CONFIG_OF
.of_match_table = ethoc_match,
-#endif
},
};
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 3c6e100..d06a637 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -69,4 +69,10 @@ config OF_MDIO
help
OpenFirmware MDIO bus (Ethernet PHY) accessors
+config OF_PCI
+ def_tristate PCI
+ depends on PCI && (PPC || MICROBLAZE || X86)
+ help
+ OpenFirmware PCI bus accessors
+
endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 3ab21a0..f7861ed 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_NET) += of_net.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..ac1ec54
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,92 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <asm/prom.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.
+ */
+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
+ * device tree 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/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index c7ff8df..159b95e 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -37,6 +37,8 @@
#include <linux/mod_devicetable.h>
#include <linux/log2.h>
#include <linux/pm.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>
@@ -1123,6 +1125,47 @@ 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) {}
+#define of_cmos_match NULL
+#endif
/*----------------------------------------------------------------*/
/* Platform setup should have set up an RTC device, when PNP is
@@ -1131,6 +1174,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),
@@ -1162,6 +1206,7 @@ static struct platform_driver cmos_platform_driver = {
#ifdef CONFIG_PM
.pm = &cmos_pm_ops,
#endif
+ .of_match_table = of_cmos_match,
}
};
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 1db62db..8d2cf60 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr)
return rtc_intr & RTC_IRQMASK;
}
+static inline unsigned char vrtc_is_updating(void)
+{
+ unsigned char uip;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return uip;
+}
+
/*
* rtc_time's year contains the increment over 1900, but vRTC's YEAR
* register can't be programmed to value larger than 0x64, so vRTC
@@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
{
unsigned long flags;
- if (rtc_is_updating())
+ if (vrtc_is_updating())
mdelay(20);
spin_lock_irqsave(&rtc_lock, flags);
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 9592883..a429b01 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1557,9 +1557,7 @@ static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->ssp = ssp;
master->dev.parent = &pdev->dev;
-#ifdef CONFIG_OF
master->dev.of_node = pdev->dev.of_node;
-#endif
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
index 19752b0..378e504 100644
--- a/drivers/spi/pxa2xx_spi_pci.c
+++ b/drivers/spi/pxa2xx_spi_pci.c
@@ -89,9 +89,7 @@ static int __devinit ce4100_spi_probe(struct pci_dev *dev,
goto err_nomem;
pdev->dev.parent = &dev->dev;
-#ifdef CONFIG_OF
pdev->dev.of_node = dev->dev.of_node;
-#endif
ssp = &spi_info->ssp;
ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = ioremap(phys_beg, phys_len);
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 7adaef6..4d2c75d 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -351,14 +351,12 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#ifdef CONFIG_OF
static const struct of_device_id xilinx_spi_of_match[] = {
{ .compatible = "xlnx,xps-spi-2.00.a", },
{ .compatible = "xlnx,xps-spi-2.00.b", },
{}
};
MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-#endif
struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
@@ -394,9 +392,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
master->bus_num = bus_num;
master->num_chipselect = num_cs;
-#ifdef CONFIG_OF
master->dev.of_node = dev->of_node;
-#endif
xspi->mem = *mem;
xspi->irq = irq;
@@ -539,9 +535,7 @@ static struct platform_driver xilinx_spi_driver = {
.driver = {
.name = XILINX_SPI_NAME,
.owner = THIS_MODULE,
-#ifdef CONFIG_OF
.of_match_table = xilinx_spi_of_match,
-#endif
},
};
diff --git a/include/linux/device.h b/include/linux/device.h
index 1bf5cf0..ca5d252 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -128,9 +128,7 @@ struct device_driver {
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
-#if defined(CONFIG_OF)
const struct of_device_id *of_match_table;
-#endif
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
@@ -441,9 +439,8 @@ struct device {
override */
/* arch specific additions */
struct dev_archdata archdata;
-#ifdef CONFIG_OF
- struct device_node *of_node;
-#endif
+
+ struct device_node *of_node; /* associated device tree node */
dev_t devt; /* dev_t, creates the sysfs "dev" */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 903576d..06a8d9c 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -258,9 +258,7 @@ struct i2c_board_info {
unsigned short addr;
void *platform_data;
struct dev_archdata *archdata;
-#ifdef CONFIG_OF
struct device_node *of_node;
-#endif
int irq;
};
diff --git a/include/linux/of.h b/include/linux/of.h
index cad7cf0..266db1d 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -23,8 +23,6 @@
#include <asm/byteorder.h>
-#ifdef CONFIG_OF
-
typedef u32 phandle;
typedef u32 ihandle;
@@ -65,11 +63,18 @@ struct device_node {
#endif
};
+#ifdef CONFIG_OF
+
/* Pointer for first entry in chain of all nodes. */
extern struct device_node *allnodes;
extern struct device_node *of_chosen;
extern rwlock_t devtree_lock;
+static inline bool of_have_populated_dt(void)
+{
+ return allnodes != NULL;
+}
+
static inline bool of_node_is_root(const struct device_node *node)
{
return node && (node->parent == NULL);
@@ -222,5 +227,12 @@ extern void of_attach_node(struct device_node *);
extern void of_detach_node(struct device_node *);
#endif
+#else
+
+static inline bool of_have_populated_dt(void)
+{
+ return false;
+}
+
#endif /* CONFIG_OF */
#endif /* _LINUX_OF_H */
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
new file mode 100644
index 0000000..85a27b6
--- /dev/null
+++ b/include/linux/of_pci.h
@@ -0,0 +1,9 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+struct pci_dev;
+struct of_irq;
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+#endif
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [GIT PULL] x86/platform changes for v2.6.39
2011-03-15 21:32 [GIT PULL] x86/platform changes for v2.6.39 Ingo Molnar
@ 2011-03-15 23:09 ` Grant Likely
2011-03-16 12:07 ` Ingo Molnar
0 siblings, 1 reply; 3+ messages in thread
From: Grant Likely @ 2011-03-15 23:09 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Linus Torvalds, linux-kernel, Thomas Gleixner, Andrew Morton
On Tue, Mar 15, 2011 at 10:32:23PM +0100, Ingo Molnar wrote:
> Linus,
>
> Please pull the latest x86-platform-for-linus git tree from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git x86-platform-for-linus
>
>
> out-of-topic modifications in x86-platform-for-linus:
> -----------------------------------------------------
... all merged in from my devicetree/next branch which Thomas and I
discussed before hand. I agree with this pull.
g.
> arch/microblaze/include/asm/pci-bridge.h# 04bea68: of/pci: move of_irq_map_pci() int
> arch/microblaze/include/asm/prom.h # 04bea68: of/pci: move of_irq_map_pci() int
> arch/microblaze/kernel/prom_parse.c# 04bea68: of/pci: move of_irq_map_pci() int
> arch/microblaze/pci/pci-common.c # 04bea68: of/pci: move of_irq_map_pci() int
> arch/powerpc/include/asm/pci-bridge.h# 04bea68: of/pci: move of_irq_map_pci() int
> arch/powerpc/include/asm/prom.h # 04bea68: of/pci: move of_irq_map_pci() int
> arch/powerpc/kernel/pci-common.c # 04bea68: of/pci: move of_irq_map_pci() int
> arch/powerpc/kernel/prom_parse.c # 04bea68: of/pci: move of_irq_map_pci() int
> drivers/i2c/busses/i2c-ocores.c # c9e358d: driver-core: remove conditionals
> drivers/i2c/i2c-core.c # c9e358d: driver-core: remove conditionals
> drivers/mmc/host/mmc_spi.c # c9e358d: driver-core: remove conditionals
> drivers/net/ethoc.c # c9e358d: driver-core: remove conditionals
> drivers/of/Kconfig # 96e0a07: x86: dtb: Add support for PCI dev
> # 04bea68: of/pci: move of_irq_map_pci() int
> drivers/of/Makefile # 04bea68: of/pci: move of_irq_map_pci() int
> drivers/of/of_pci.c # 96e0a07: x86: dtb: Add support for PCI dev
> # 04bea68: of/pci: move of_irq_map_pci() int
> drivers/rtc/rtc-cmos.c # 3bcbaf6: rtc: cmos: Add OF bindings
> drivers/rtc/rtc-mrst.c # 168202c: mrst/vrtc: Avoid using cmos rtc o
> drivers/spi/pxa2xx_spi.c # c9e358d: driver-core: remove conditionals
> drivers/spi/pxa2xx_spi_pci.c # c9e358d: driver-core: remove conditionals
> drivers/spi/xilinx_spi.c # c9e358d: driver-core: remove conditionals
> include/linux/device.h # c9e358d: driver-core: remove conditionals
> include/linux/i2c.h # c9e358d: driver-core: remove conditionals
> include/linux/of.h # 3bcbaf6: rtc: cmos: Add OF bindings
> # c9e358d: driver-core: remove conditionals
> include/linux/of_pci.h # 04bea68: of/pci: move of_irq_map_pci() int
>
> Thanks,
>
> Ingo
>
> ------------------>
> Feng Tang (2):
> x86/platform: Add a wallclock_init func to x86_init.timers ops
> mrst/vrtc: Avoid using cmos rtc ops
>
> Grant Likely (1):
> driver-core: remove conditionals around devicetree pointers
>
> Henrik Kretzschmar (7):
> x86: Move ioapic_irq_destination_types to apicdef.h
> x86: Add dummy mp_save_irq()
> x86: Rework arch_disable_smp_support() for x86
> x86: Add dummy functions for compiling without IOAPIC
> x86: Fix deps of X86_UP_IOAPIC
> x86: Remove superflous goal definition of tsc_sync
> x86: Clean up apic.c and apic.h
>
> Sebastian Andrzej Siewior (15):
> of/pci: move of_irq_map_pci() into generic code
> x86/pci: Remove unused variable
> x86: e820: Remove conditional early mapping in parse_e820_ext
> x86: Add device tree support
> x86: dtb: Add a device tree for CE4100
> x86: dtb: Add irq domain abstraction
> x86: dtb: Add early parsing of IO_APIC
> x86: dtb: Add device tree support for HPET
> x86: dtb: Add support for PCI devices backed by dtb nodes
> x86: dtb: Add generic bus probe
> x86: ioapic: Add OF bindings for IO_APIC
> x86: ce4100: Use OF to setup devices
> rtc: cmos: Add OF bindings
> x86: dt: Fix OLPC=y/INTEL_CE=n build
> x86: dt: Correct local apic documentation in device tree bindings
>
> Thomas Gleixner (17):
> x86: OLPC: Remove redundant !X64_64 config dependency
> x86: OLPC: Hide OLPC_OPENFIRMWARE config switch
> x86: OLPC: Cleanup config maze completely
> x86: OLPC: Remove extra OLPC_OPENFIRMWARE_DT indirection
> x86: OLPC: Make OLPC=n build again
> x86: ioapic: Remove silly debug bloat in setup_IOAPIC_irqs()
> x86: ioapic: Split out the nested loop in setup_IO_APIC_irqs()
> x86: ioapic: Add io_apic_setup_irq_pin()
> x86: ioapic: Use new setup function in pre_init_apic_IRQ0()
> x86: ioapic: Use setup function in __io_apic_set_pci_routing()
> x86: ioapic: Use setup function in __io_apic_setup_irqs()
> x86: ioapic: Use setup function in setup_IO_APIC_irq_extra()
> x86: ioapic: Make a few functions static
> x86: ioapic: Remove useless inlines
> x86: ioapic: Implement and use io_apic_setup_irq_pin_once()
> x86: ioapic: Move trigger defines to io_apic.h
> x86: dt: Cleanup local apic setup
>
> jacob.jun.pan@linux.intel.com (1):
> x86: mrst: Remove apb timer read workaround
>
>
> .../devicetree/bindings/i2c/ce4100-i2c.txt | 93 ++++
> Documentation/devicetree/bindings/rtc/rtc-cmos.txt | 28 ++
> Documentation/devicetree/bindings/x86/ce4100.txt | 38 ++
> .../devicetree/bindings/x86/interrupt.txt | 26 ++
> Documentation/devicetree/bindings/x86/timer.txt | 6 +
> Documentation/devicetree/booting-without-of.txt | 20 +
> 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 ----
> arch/x86/Kconfig | 24 +-
> arch/x86/include/asm/apic.h | 6 +-
> arch/x86/include/asm/apicdef.h | 12 +
> arch/x86/include/asm/bootparam.h | 1 +
> arch/x86/include/asm/e820.h | 2 +-
> arch/x86/include/asm/io_apic.h | 44 ++-
> arch/x86/include/asm/irq.h | 3 -
> arch/x86/include/asm/irq_controller.h | 12 +
> arch/x86/include/asm/olpc_ofw.h | 14 +-
> arch/x86/include/asm/prom.h | 70 +++-
> arch/x86/include/asm/x86_init.h | 2 +
> arch/x86/kernel/Makefile | 5 +-
> arch/x86/kernel/apb_timer.c | 60 +---
> arch/x86/kernel/apic/apic.c | 74 ++--
> arch/x86/kernel/apic/io_apic.c | 265 +++++-------
> arch/x86/kernel/devicetree.c | 441 ++++++++++++++++++++
> arch/x86/kernel/e820.c | 8 +-
> arch/x86/kernel/head_32.S | 2 +-
> arch/x86/kernel/irq.c | 9 -
> arch/x86/kernel/irqinit.c | 9 +-
> arch/x86/kernel/rtc.c | 3 +
> arch/x86/kernel/setup.c | 25 +-
> arch/x86/kernel/smpboot.c | 11 +-
> arch/x86/kernel/x86_init.c | 1 +
> arch/x86/pci/ce4100.c | 2 +-
> arch/x86/platform/ce4100/ce4100.c | 24 +-
> arch/x86/platform/ce4100/falconfalls.dts | 428 +++++++++++++++++++
> arch/x86/platform/mrst/mrst.c | 2 +
> arch/x86/platform/mrst/vrtc.c | 16 +-
> arch/x86/platform/olpc/Makefile | 4 +-
> drivers/i2c/busses/i2c-ocores.c | 14 +-
> drivers/i2c/i2c-core.c | 2 -
> drivers/mmc/host/mmc_spi.c | 4 -
> drivers/net/ethoc.c | 8 +-
> drivers/of/Kconfig | 6 +
> drivers/of/Makefile | 1 +
> drivers/of/of_pci.c | 92 ++++
> drivers/rtc/rtc-cmos.c | 45 ++
> drivers/rtc/rtc-mrst.c | 13 +-
> drivers/spi/pxa2xx_spi.c | 2 -
> drivers/spi/pxa2xx_spi_pci.c | 2 -
> drivers/spi/xilinx_spi.c | 6 -
> include/linux/device.h | 7 +-
> include/linux/i2c.h | 2 -
> include/linux/of.h | 16 +-
> include/linux/of_pci.h | 9 +
> 60 files changed, 1641 insertions(+), 593 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
> create mode 100644 Documentation/devicetree/bindings/rtc/rtc-cmos.txt
> create mode 100644 Documentation/devicetree/bindings/x86/ce4100.txt
> create mode 100644 Documentation/devicetree/bindings/x86/interrupt.txt
> create mode 100644 Documentation/devicetree/bindings/x86/timer.txt
> create mode 100644 arch/x86/include/asm/irq_controller.h
> create mode 100644 arch/x86/kernel/devicetree.c
> create mode 100644 arch/x86/platform/ce4100/falconfalls.dts
> create mode 100644 drivers/of/of_pci.c
> create mode 100644 include/linux/of_pci.h
>
> diff --git a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
> new file mode 100644
> index 0000000..569b162
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
> @@ -0,0 +1,93 @@
> +CE4100 I2C
> +----------
> +
> +CE4100 has one PCI device which is described as the I2C-Controller. This
> +PCI device has three PCI-bars, each bar contains a complete I2C
> +controller. So we have a total of three independent I2C-Controllers
> +which share only an interrupt line.
> +The driver is probed via the PCI-ID and is gathering the information of
> +attached devices from the devices tree.
> +Grant Likely recommended to use the ranges property to map the PCI-Bar
> +number to its physical address and to use this to find the child nodes
> +of the specific I2C controller. This were his exact words:
> +
> + 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 is an example which is used on FalconFalls:
> +------------------------------------------------
> + i2c-controller@b,2 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "pci8086,2e68.2",
> + "pci8086,2e68",
> + "pciclass,ff0000",
> + "pciclass,ff00";
> +
> + reg = <0x15a00 0x0 0x0 0x0 0x0>;
> + interrupts = <16 1>;
> +
> + /* as described by Grant, the first number in the group of
> + * three is the bar number followed by the 64bit bar address
> + * followed by size of the mapping. The bar address
> + * requires also a valid translation in parents ranges
> + * property.
> + */
> + 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";
> +
> + /* The first number in the reg property is the
> + * number of the bar
> + */
> + reg = <0 0 0x100>;
> +
> + /* This I2C controller has no devices */
> + };
> +
> + i2c@1 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "intel,ce4100-i2c-controller";
> + reg = <1 0 0x100>;
> +
> + /* This I2C controller has one gpio controller */
> + gpio@26 {
> + #gpio-cells = <2>;
> + compatible = "ti,pcf8575";
> + reg = <0x26>;
> + gpio-controller;
> + };
> + };
> +
> + i2c@2 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "intel,ce4100-i2c-controller";
> + reg = <2 0 0x100>;
> +
> + gpio@26 {
> + #gpio-cells = <2>;
> + compatible = "ti,pcf8575";
> + reg = <0x26>;
> + gpio-controller;
> + };
> + };
> + };
> diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.txt b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
> new file mode 100644
> index 0000000..7382989
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/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/Documentation/devicetree/bindings/x86/ce4100.txt b/Documentation/devicetree/bindings/x86/ce4100.txt
> new file mode 100644
> index 0000000..b49ae59
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/x86/ce4100.txt
> @@ -0,0 +1,38 @@
> +CE4100 Device Tree Bindings
> +---------------------------
> +
> +The CE4100 SoC uses for in core peripherals the following compatible
> +format: <vendor>,<chip>-<device>.
> +Many of the "generic" devices like HPET or IO APIC have the ce4100
> +name in their compatible property because they first appeared in this
> +SoC.
> +
> +The CPU node
> +------------
> + cpu@0 {
> + device_type = "cpu";
> + compatible = "intel,ce4100";
> + reg = <0>;
> + lapic = <&lapic0>;
> + };
> +
> +The reg property describes the CPU number. The lapic property points to
> +the local APIC timer.
> +
> +The SoC node
> +------------
> +
> +This node describes the in-core peripherals. Required property:
> + compatible = "intel,ce4100-cp";
> +
> +The PCI node
> +------------
> +This node describes the PCI bus on the SoC. Its property should be
> + compatible = "intel,ce4100-pci", "pci";
> +
> +If the OS is using the IO-APIC for interrupt routing then the reported
> +interrupt numbers for devices is no longer true. In order to obtain the
> +correct interrupt number, the child node which represents the device has
> +to contain the interrupt property. Besides the interrupt property it has
> +to contain at least the reg property containing the PCI bus address and
> +compatible property according to "PCI Bus Binding Revision 2.1".
> diff --git a/Documentation/devicetree/bindings/x86/interrupt.txt b/Documentation/devicetree/bindings/x86/interrupt.txt
> new file mode 100644
> index 0000000..7d19f49
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/x86/interrupt.txt
> @@ -0,0 +1,26 @@
> +Interrupt chips
> +---------------
> +
> +* Intel I/O Advanced Programmable Interrupt Controller (IO APIC)
> +
> + Required properties:
> + --------------------
> + compatible = "intel,ce4100-ioapic";
> + #interrupt-cells = <2>;
> +
> + Device's interrupt property:
> +
> + interrupts = <P S>;
> +
> + The first number (P) represents the interrupt pin which is wired to the
> + IO APIC. The second number (S) represents the sense of interrupt which
> + should be configured and can be one of:
> + 0 - Edge Rising
> + 1 - Level Low
> + 2 - Level High
> + 3 - Edge Falling
> +
> +* Local APIC
> + Required property:
> +
> + compatible = "intel,ce4100-lapic";
> diff --git a/Documentation/devicetree/bindings/x86/timer.txt b/Documentation/devicetree/bindings/x86/timer.txt
> new file mode 100644
> index 0000000..c688af5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/x86/timer.txt
> @@ -0,0 +1,6 @@
> +Timers
> +------
> +
> +* High Precision Event Timer (HPET)
> + Required property:
> + compatible = "intel,ce4100-hpet";
> diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt
> index 28b1c9d..55fd262 100644
> --- a/Documentation/devicetree/booting-without-of.txt
> +++ b/Documentation/devicetree/booting-without-of.txt
> @@ -13,6 +13,7 @@ Table of Contents
>
> I - Introduction
> 1) Entry point for arch/powerpc
> + 2) Entry point for arch/x86
>
> II - The DT block format
> 1) Header
> @@ -225,6 +226,25 @@ it with special cases.
> cannot support both configurations with Book E and configurations
> with classic Powerpc architectures.
>
> +2) Entry point for arch/x86
> +-------------------------------
> +
> + There is one single 32bit entry point to the kernel at code32_start,
> + the decompressor (the real mode entry point goes to the same 32bit
> + entry point once it switched into protected mode). That entry point
> + supports one calling convention which is documented in
> + Documentation/x86/boot.txt
> + The physical pointer to the device-tree block (defined in chapter II)
> + is passed via setup_data which requires at least boot protocol 2.09.
> + The type filed is defined as
> +
> + #define SETUP_DTB 2
> +
> + This device-tree is used as an extension to the "boot page". As such it
> + does not parse / consider data which is already covered by the boot
> + page. This includes memory size, reserved ranges, 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.
>
> II - The DT block format
> ========================
> diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
> index 0c68764..1071766 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 /* CONFIG_PCI */
>
> /* 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 2e72af0..d0890d3 100644
> --- a/arch/microblaze/include/asm/prom.h
> +++ b/arch/microblaze/include/asm/prom.h
> @@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void);
> /* CPU OF node matching */
> struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
>
> -/**
> - * 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 9ae24f4..47187cc 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 d727575..c189aa5 100644
> --- a/arch/powerpc/include/asm/prom.h
> +++ b/arch/powerpc/include/asm/prom.h
> @@ -70,21 +70,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 c2b7a07..47187cc 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/arch/x86/Kconfig b/arch/x86/Kconfig
> index d5ed94d..b4c2e9c 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -382,6 +382,8 @@ config X86_INTEL_CE
> depends on X86_32
> depends on X86_EXTENDED_PLATFORM
> select X86_REBOOTFIXUPS
> + select OF
> + select OF_EARLY_FLATTREE
> ---help---
> Select for the Intel CE media processor (CE4100) SOC.
> This option compiles in support for the CE4100 SOC for settop
> @@ -811,7 +813,7 @@ config X86_LOCAL_APIC
>
> config X86_IO_APIC
> def_bool y
> - depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
> + depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
>
> config X86_VISWS_APIC
> def_bool y
> @@ -2066,9 +2068,10 @@ config SCx200HR_TIMER
>
> config OLPC
> bool "One Laptop Per Child support"
> + depends on !X86_PAE
> select GPIOLIB
> - select OLPC_OPENFIRMWARE
> - depends on !X86_64 && !X86_PAE
> + select OF
> + select OF_PROMTREE if PROC_DEVICETREE
> ---help---
> Add support for detecting the unique features of the OLPC
> XO hardware.
> @@ -2079,21 +2082,6 @@ config OLPC_XO1
> ---help---
> Add support for non-essential features of the OLPC XO-1 laptop.
>
> -config OLPC_OPENFIRMWARE
> - bool "Support for OLPC's Open Firmware"
> - depends on !X86_64 && !X86_PAE
> - default n
> - select OF
> - help
> - This option adds support for the implementation of Open Firmware
> - that is used on the OLPC XO-1 Children's Machine.
> - If unsure, say N here.
> -
> -config OLPC_OPENFIRMWARE_DT
> - bool
> - default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
> - select OF_PROMTREE
> -
> endif # X86_32
>
> config AMD_NB
> diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
> index 3c89694..5b7d513 100644
> --- a/arch/x86/include/asm/apic.h
> +++ b/arch/x86/include/asm/apic.h
> @@ -220,7 +220,6 @@ extern void enable_IR_x2apic(void);
>
> extern int get_physical_broadcast(void);
>
> -extern void apic_disable(void);
> extern int lapic_get_maxlvt(void);
> extern void clear_local_APIC(void);
> extern void connect_bsp_APIC(void);
> @@ -228,7 +227,6 @@ extern void disconnect_bsp_APIC(int virt_wire_setup);
> extern void disable_local_APIC(void);
> extern void lapic_shutdown(void);
> extern int verify_local_APIC(void);
> -extern void cache_APIC_registers(void);
> extern void sync_Arb_IDs(void);
> extern void init_bsp_APIC(void);
> extern void setup_local_APIC(void);
> @@ -239,8 +237,7 @@ void register_lapic_address(unsigned long address);
> extern void setup_boot_APIC_clock(void);
> extern void setup_secondary_APIC_clock(void);
> extern int APIC_init_uniprocessor(void);
> -extern void enable_NMI_through_LVT0(void);
> -extern int apic_force_enable(void);
> +extern int apic_force_enable(unsigned long addr);
>
> /*
> * On 32bit this is mach-xxx local
> @@ -261,7 +258,6 @@ static inline void lapic_shutdown(void) { }
> #define local_apic_timer_c2_ok 1
> static inline void init_apic_mappings(void) { }
> static inline void disable_local_APIC(void) { }
> -static inline void apic_disable(void) { }
> # define setup_boot_APIC_clock x86_init_noop
> # define setup_secondary_APIC_clock x86_init_noop
> #endif /* !CONFIG_X86_LOCAL_APIC */
> diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
> index 47a30ff..d87988b 100644
> --- a/arch/x86/include/asm/apicdef.h
> +++ b/arch/x86/include/asm/apicdef.h
> @@ -426,4 +426,16 @@ struct local_apic {
> #else
> #define BAD_APICID 0xFFFFu
> #endif
> +
> +enum ioapic_irq_destination_types {
> + dest_Fixed = 0,
> + dest_LowestPrio = 1,
> + dest_SMI = 2,
> + dest__reserved_1 = 3,
> + dest_NMI = 4,
> + dest_INIT = 5,
> + dest__reserved_2 = 6,
> + dest_ExtINT = 7
> +};
> +
> #endif /* _ASM_X86_APICDEF_H */
> 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/e820.h b/arch/x86/include/asm/e820.h
> index e99d55d..908b969 100644
> --- a/arch/x86/include/asm/e820.h
> +++ b/arch/x86/include/asm/e820.h
> @@ -96,7 +96,7 @@ extern void e820_setup_gap(void);
> extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
> unsigned long start_addr, unsigned long long end_addr);
> struct setup_data;
> -extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data);
> +extern void parse_e820_ext(struct setup_data *data);
>
> #if defined(CONFIG_X86_64) || \
> (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
> diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
> index f327d38..c4bd267 100644
> --- a/arch/x86/include/asm/io_apic.h
> +++ b/arch/x86/include/asm/io_apic.h
> @@ -63,17 +63,6 @@ union IO_APIC_reg_03 {
> } __attribute__ ((packed)) bits;
> };
>
> -enum ioapic_irq_destination_types {
> - dest_Fixed = 0,
> - dest_LowestPrio = 1,
> - dest_SMI = 2,
> - dest__reserved_1 = 3,
> - dest_NMI = 4,
> - dest_INIT = 5,
> - dest__reserved_2 = 6,
> - dest_ExtINT = 7
> -};
> -
> struct IO_APIC_route_entry {
> __u32 vector : 8,
> delivery_mode : 3, /* 000: FIXED
> @@ -106,6 +95,10 @@ struct IR_IO_APIC_route_entry {
> index : 15;
> } __attribute__ ((packed));
>
> +#define IOAPIC_AUTO -1
> +#define IOAPIC_EDGE 0
> +#define IOAPIC_LEVEL 1
> +
> #ifdef CONFIG_X86_IO_APIC
>
> /*
> @@ -150,11 +143,6 @@ extern int timer_through_8259;
> #define io_apic_assign_pci_irqs \
> (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
>
> -extern u8 io_apic_unique_id(u8 id);
> -extern int io_apic_get_unique_id(int ioapic, int apic_id);
> -extern int io_apic_get_version(int ioapic);
> -extern int io_apic_get_redir_entries(int ioapic);
> -
> struct io_apic_irq_attr;
> extern int io_apic_set_pci_routing(struct device *dev, int irq,
> struct io_apic_irq_attr *irq_attr);
> @@ -162,6 +150,8 @@ void setup_IO_APIC_irq_extra(u32 gsi);
> extern void ioapic_and_gsi_init(void);
> extern void ioapic_insert_resources(void);
>
> +int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr);
> +
> extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
> extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
> extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
> @@ -186,6 +176,8 @@ extern void __init pre_init_apic_IRQ0(void);
>
> extern void mp_save_irq(struct mpc_intsrc *m);
>
> +extern void disable_ioapic_support(void);
> +
> #else /* !CONFIG_X86_IO_APIC */
>
> #define io_apic_assign_pci_irqs 0
> @@ -199,6 +191,26 @@ static inline int mp_find_ioapic(u32 gsi) { return 0; }
> struct io_apic_irq_attr;
> static inline int io_apic_set_pci_routing(struct device *dev, int irq,
> struct io_apic_irq_attr *irq_attr) { return 0; }
> +
> +static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void)
> +{
> + return NULL;
> +}
> +
> +static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { }
> +static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent)
> +{
> + return -ENOMEM;
> +}
> +
> +static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { }
> +static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent)
> +{
> + return -ENOMEM;
> +}
> +
> +static inline void mp_save_irq(struct mpc_intsrc *m) { };
> +static inline void disable_ioapic_support(void) { }
> #endif
>
> #endif /* _ASM_X86_IO_APIC_H */
> diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
> index c704b38..ba870bb 100644
> --- a/arch/x86/include/asm/irq.h
> +++ b/arch/x86/include/asm/irq.h
> @@ -10,9 +10,6 @@
> #include <asm/apicdef.h>
> #include <asm/irq_vectors.h>
>
> -/* Even though we don't support this, supply it to appease OF */
> -static inline void irq_dispose_mapping(unsigned int virq) { }
> -
> static inline int irq_canonicalize(int irq)
> {
> return ((irq == 2) ? 9 : irq);
> 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/olpc_ofw.h b/arch/x86/include/asm/olpc_ofw.h
> index 641988e..c5d3a5a 100644
> --- a/arch/x86/include/asm/olpc_ofw.h
> +++ b/arch/x86/include/asm/olpc_ofw.h
> @@ -6,7 +6,7 @@
>
> #define OLPC_OFW_SIG 0x2057464F /* aka "OFW " */
>
> -#ifdef CONFIG_OLPC_OPENFIRMWARE
> +#ifdef CONFIG_OLPC
>
> extern bool olpc_ofw_is_installed(void);
>
> @@ -26,19 +26,15 @@ extern void setup_olpc_ofw_pgd(void);
> /* check if OFW was detected during boot */
> extern bool olpc_ofw_present(void);
>
> -#else /* !CONFIG_OLPC_OPENFIRMWARE */
> -
> -static inline bool olpc_ofw_is_installed(void) { return false; }
> +#else /* !CONFIG_OLPC */
> static inline void olpc_ofw_detect(void) { }
> static inline void setup_olpc_ofw_pgd(void) { }
> -static inline bool olpc_ofw_present(void) { return false; }
> -
> -#endif /* !CONFIG_OLPC_OPENFIRMWARE */
> +#endif /* !CONFIG_OLPC */
>
> -#ifdef CONFIG_OLPC_OPENFIRMWARE_DT
> +#ifdef CONFIG_OF_PROMTREE
> extern void olpc_dt_build_devicetree(void);
> #else
> static inline void olpc_dt_build_devicetree(void) { }
> -#endif /* CONFIG_OLPC_OPENFIRMWARE_DT */
> +#endif
>
> #endif /* _ASM_X86_OLPC_OFW_H */
> diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
> index b4ec95f..971e0b4 100644
> --- a/arch/x86/include/asm/prom.h
> +++ b/arch/x86/include/asm/prom.h
> @@ -1 +1,69 @@
> -/* dummy prom.h; here to make linux/of.h's #includes happy */
> +/*
> + * 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 <linux/pci.h>
> +
> +#include <asm/irq.h>
> +#include <asm/atomic.h>
> +#include <asm/setup.h>
> +#include <asm/irq_controller.h>
> +
> +#ifdef CONFIG_OF
> +extern int of_ioapic;
> +extern u64 initial_dtb;
> +extern void add_dtb(u64 data);
> +extern void x86_add_irq_domains(void);
> +void __cpuinit x86_of_pci_init(void);
> +void x86_dtb_init(void);
> +
> +static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
> +{
> + return pdev ? pdev->dev.of_node : NULL;
> +}
> +
> +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
> +{
> + return pci_device_to_OF_node(bus->self);
> +}
> +
> +#else
> +static inline void add_dtb(u64 data) { }
> +static inline void x86_add_irq_domains(void) { }
> +static inline void x86_of_pci_init(void) { }
> +static inline void x86_dtb_init(void) { }
> +#define of_ioapic 0
> +#endif
> +
> +extern char cmd_line[COMMAND_LINE_SIZE];
> +
> +#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__ */
> +#endif
> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> index 64642ad..643ebf2 100644
> --- a/arch/x86/include/asm/x86_init.h
> +++ b/arch/x86/include/asm/x86_init.h
> @@ -83,11 +83,13 @@ struct x86_init_paging {
> * boot cpu
> * @tsc_pre_init: platform function called before TSC init
> * @timer_init: initialize the platform timer (default PIT/HPET)
> + * @wallclock_init: init the wallclock device
> */
> struct x86_init_timers {
> void (*setup_percpu_clockev)(void);
> void (*tsc_pre_init)(void);
> void (*timer_init)(void);
> + void (*wallclock_init)(void);
> };
>
> /**
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index 34244b2..62445ba 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -66,9 +66,9 @@ obj-$(CONFIG_PCI) += early-quirks.o
> apm-y := apm_32.o
> obj-$(CONFIG_APM) += apm.o
> obj-$(CONFIG_SMP) += smp.o
> -obj-$(CONFIG_SMP) += smpboot.o tsc_sync.o
> +obj-$(CONFIG_SMP) += smpboot.o
> +obj-$(CONFIG_SMP) += tsc_sync.o
> obj-$(CONFIG_SMP) += setup_percpu.o
> -obj-$(CONFIG_X86_64_SMP) += tsc_sync.o
> obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
> obj-$(CONFIG_X86_MPPARSE) += mpparse.o
> obj-y += apic/
> @@ -109,6 +109,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
> obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
>
> obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
> +obj-$(CONFIG_OF) += devicetree.o
>
> ###
> # 64 bit specific files
> diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
> index 51ef31a..671d5aa 100644
> --- a/arch/x86/kernel/apb_timer.c
> +++ b/arch/x86/kernel/apb_timer.c
> @@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta,
> return 0;
> }
>
> -/*
> - * APB timer clock is not in sync with pclk on Langwell, which translates to
> - * unreliable read value caused by sampling error. the error does not add up
> - * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
> - * would go backwards. the following code is trying to prevent time traveling
> - * backwards. little bit paranoid.
> - */
> static cycle_t apbt_read_clocksource(struct clocksource *cs)
> {
> - unsigned long t0, t1, t2;
> - static unsigned long last_read;
> -
> -bad_count:
> - t1 = apbt_readl(phy_cs_timer_id,
> - APBTMR_N_CURRENT_VALUE);
> - t2 = apbt_readl(phy_cs_timer_id,
> - APBTMR_N_CURRENT_VALUE);
> - if (unlikely(t1 < t2)) {
> - pr_debug("APBT: read current count error %lx:%lx:%lx\n",
> - t1, t2, t2 - t1);
> - goto bad_count;
> - }
> - /*
> - * check against cached last read, makes sure time does not go back.
> - * it could be a normal rollover but we will do tripple check anyway
> - */
> - if (unlikely(t2 > last_read)) {
> - /* check if we have a normal rollover */
> - unsigned long raw_intr_status =
> - apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
> - /*
> - * cs timer interrupt is masked but raw intr bit is set if
> - * rollover occurs. then we read EOI reg to clear it.
> - */
> - if (raw_intr_status & (1 << phy_cs_timer_id)) {
> - apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
> - goto out;
> - }
> - pr_debug("APB CS going back %lx:%lx:%lx ",
> - t2, last_read, t2 - last_read);
> -bad_count_x3:
> - pr_debug("triple check enforced\n");
> - t0 = apbt_readl(phy_cs_timer_id,
> - APBTMR_N_CURRENT_VALUE);
> - udelay(1);
> - t1 = apbt_readl(phy_cs_timer_id,
> - APBTMR_N_CURRENT_VALUE);
> - udelay(1);
> - t2 = apbt_readl(phy_cs_timer_id,
> - APBTMR_N_CURRENT_VALUE);
> - if ((t2 > t1) || (t1 > t0)) {
> - printk(KERN_ERR "Error: APB CS tripple check failed\n");
> - goto bad_count_x3;
> - }
> - }
> -out:
> - last_read = t2;
> - return (cycle_t)~t2;
> + unsigned long current_count;
> +
> + current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
> + return (cycle_t)~current_count;
> }
>
> static int apbt_clocksource_register(void)
> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
> index 76b96d7..ffbf7c2 100644
> --- a/arch/x86/kernel/apic/apic.c
> +++ b/arch/x86/kernel/apic/apic.c
> @@ -43,6 +43,7 @@
> #include <asm/i8259.h>
> #include <asm/proto.h>
> #include <asm/apic.h>
> +#include <asm/io_apic.h>
> #include <asm/desc.h>
> #include <asm/hpet.h>
> #include <asm/idle.h>
> @@ -83,7 +84,7 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
> *
> * +1=force-enable
> */
> -static int force_enable_local_apic;
> +static int force_enable_local_apic __initdata;
> /*
> * APIC command line parameters
> */
> @@ -153,7 +154,7 @@ early_param("nox2apic", setup_nox2apic);
> unsigned long mp_lapic_addr;
> int disable_apic;
> /* Disable local APIC timer from the kernel commandline or via dmi quirk */
> -static int disable_apic_timer __cpuinitdata;
> +static int disable_apic_timer __initdata;
> /* Local APIC timer works in C2 */
> int local_apic_timer_c2_ok;
> EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
> @@ -177,29 +178,8 @@ static struct resource lapic_resource = {
>
> static unsigned int calibration_result;
>
> -static int lapic_next_event(unsigned long delta,
> - struct clock_event_device *evt);
> -static void lapic_timer_setup(enum clock_event_mode mode,
> - struct clock_event_device *evt);
> -static void lapic_timer_broadcast(const struct cpumask *mask);
> static void apic_pm_activate(void);
>
> -/*
> - * The local apic timer can be used for any function which is CPU local.
> - */
> -static struct clock_event_device lapic_clockevent = {
> - .name = "lapic",
> - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
> - | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
> - .shift = 32,
> - .set_mode = lapic_timer_setup,
> - .set_next_event = lapic_next_event,
> - .broadcast = lapic_timer_broadcast,
> - .rating = 100,
> - .irq = -1,
> -};
> -static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
> -
> static unsigned long apic_phys;
>
> /*
> @@ -238,7 +218,7 @@ static int modern_apic(void)
> * right after this call apic become NOOP driven
> * so apic->write/read doesn't do anything
> */
> -void apic_disable(void)
> +static void __init apic_disable(void)
> {
> pr_info("APIC: switched to apic NOOP\n");
> apic = &apic_noop;
> @@ -282,23 +262,6 @@ u64 native_apic_icr_read(void)
> return icr1 | ((u64)icr2 << 32);
> }
>
> -/**
> - * enable_NMI_through_LVT0 - enable NMI through local vector table 0
> - */
> -void __cpuinit enable_NMI_through_LVT0(void)
> -{
> - unsigned int v;
> -
> - /* unmask and set to NMI */
> - v = APIC_DM_NMI;
> -
> - /* Level triggered for 82489DX (32bit mode) */
> - if (!lapic_is_integrated())
> - v |= APIC_LVT_LEVEL_TRIGGER;
> -
> - apic_write(APIC_LVT0, v);
> -}
> -
> #ifdef CONFIG_X86_32
> /**
> * get_physical_broadcast - Get number of physical broadcast IDs
> @@ -508,6 +471,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
> #endif
> }
>
> +
> +/*
> + * The local apic timer can be used for any function which is CPU local.
> + */
> +static struct clock_event_device lapic_clockevent = {
> + .name = "lapic",
> + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
> + | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
> + .shift = 32,
> + .set_mode = lapic_timer_setup,
> + .set_next_event = lapic_next_event,
> + .broadcast = lapic_timer_broadcast,
> + .rating = 100,
> + .irq = -1,
> +};
> +static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
> +
> /*
> * Setup the local APIC timer for this CPU. Copy the initialized values
> * of the boot CPU and register the clock event in the framework.
> @@ -1209,7 +1189,7 @@ void __cpuinit setup_local_APIC(void)
> rdtscll(tsc);
>
> if (disable_apic) {
> - arch_disable_smp_support();
> + disable_ioapic_support();
> return;
> }
>
> @@ -1448,7 +1428,7 @@ int __init enable_IR(void)
> void __init enable_IR_x2apic(void)
> {
> unsigned long flags;
> - struct IO_APIC_route_entry **ioapic_entries = NULL;
> + struct IO_APIC_route_entry **ioapic_entries;
> int ret, x2apic_enabled = 0;
> int dmar_table_init_ret;
>
> @@ -1537,7 +1517,7 @@ static int __init detect_init_APIC(void)
> }
> #else
>
> -static int apic_verify(void)
> +static int __init apic_verify(void)
> {
> u32 features, h, l;
>
> @@ -1562,7 +1542,7 @@ static int apic_verify(void)
> return 0;
> }
>
> -int apic_force_enable(void)
> +int __init apic_force_enable(unsigned long addr)
> {
> u32 h, l;
>
> @@ -1578,7 +1558,7 @@ int apic_force_enable(void)
> if (!(l & MSR_IA32_APICBASE_ENABLE)) {
> pr_info("Local APIC disabled by BIOS -- reenabling.\n");
> l &= ~MSR_IA32_APICBASE_BASE;
> - l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
> + l |= MSR_IA32_APICBASE_ENABLE | addr;
> wrmsr(MSR_IA32_APICBASE, l, h);
> enabled_via_apicbase = 1;
> }
> @@ -1619,7 +1599,7 @@ static int __init detect_init_APIC(void)
> "you can enable it with \"lapic\"\n");
> return -1;
> }
> - if (apic_force_enable())
> + if (apic_force_enable(APIC_DEFAULT_PHYS_BASE))
> return -1;
> } else {
> if (apic_verify())
> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> index ca9e2a3..8d23e83 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -108,7 +108,10 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
>
> int skip_ioapic_setup;
>
> -void arch_disable_smp_support(void)
> +/**
> + * disable_ioapic_support() - disables ioapic support at runtime
> + */
> +void disable_ioapic_support(void)
> {
> #ifdef CONFIG_PCI
> noioapicquirk = 1;
> @@ -120,11 +123,14 @@ void arch_disable_smp_support(void)
> static int __init parse_noapic(char *str)
> {
> /* disable IO-APIC */
> - arch_disable_smp_support();
> + disable_ioapic_support();
> return 0;
> }
> early_param("noapic", parse_noapic);
>
> +static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
> + struct io_apic_irq_attr *attr);
> +
> /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
> void mp_save_irq(struct mpc_intsrc *m)
> {
> @@ -818,7 +824,7 @@ static int EISA_ELCR(unsigned int irq)
> #define default_MCA_trigger(idx) (1)
> #define default_MCA_polarity(idx) default_ISA_polarity(idx)
>
> -static int MPBIOS_polarity(int idx)
> +static int irq_polarity(int idx)
> {
> int bus = mp_irqs[idx].srcbus;
> int polarity;
> @@ -860,7 +866,7 @@ static int MPBIOS_polarity(int idx)
> return polarity;
> }
>
> -static int MPBIOS_trigger(int idx)
> +static int irq_trigger(int idx)
> {
> int bus = mp_irqs[idx].srcbus;
> int trigger;
> @@ -932,16 +938,6 @@ static int MPBIOS_trigger(int idx)
> return trigger;
> }
>
> -static inline int irq_polarity(int idx)
> -{
> - return MPBIOS_polarity(idx);
> -}
> -
> -static inline int irq_trigger(int idx)
> -{
> - return MPBIOS_trigger(idx);
> -}
> -
> static int pin_2_irq(int idx, int apic, int pin)
> {
> int irq;
> @@ -1220,10 +1216,6 @@ void __setup_vector_irq(int cpu)
> static struct irq_chip ioapic_chip;
> static struct irq_chip ir_ioapic_chip;
>
> -#define IOAPIC_AUTO -1
> -#define IOAPIC_EDGE 0
> -#define IOAPIC_LEVEL 1
> -
> #ifdef CONFIG_X86_32
> static inline int IO_APIC_irq_trigger(int irq)
> {
> @@ -1385,33 +1377,26 @@ static struct {
> DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
> } mp_ioapic_routing[MAX_IO_APICS];
>
> -static void __init setup_IO_APIC_irqs(void)
> +static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
> {
> - int apic_id, pin, idx, irq, notcon = 0;
> - int node = cpu_to_node(0);
> - struct irq_cfg *cfg;
> + if (idx != -1)
> + return false;
>
> - apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
> + apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
> + mp_ioapics[apic_id].apicid, pin);
> + return true;
> +}
> +
> +static void __init __io_apic_setup_irqs(unsigned int apic_id)
> +{
> + int idx, node = cpu_to_node(0);
> + struct io_apic_irq_attr attr;
> + unsigned int pin, irq;
>
> - for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
> for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
> idx = find_irq_entry(apic_id, pin, mp_INT);
> - if (idx == -1) {
> - if (!notcon) {
> - notcon = 1;
> - apic_printk(APIC_VERBOSE,
> - KERN_DEBUG " %d-%d",
> - mp_ioapics[apic_id].apicid, pin);
> - } else
> - apic_printk(APIC_VERBOSE, " %d-%d",
> - mp_ioapics[apic_id].apicid, pin);
> + if (io_apic_pin_not_connected(idx, apic_id, pin))
> continue;
> - }
> - if (notcon) {
> - apic_printk(APIC_VERBOSE,
> - " (apicid-pin) not connected\n");
> - notcon = 0;
> - }
>
> irq = pin_2_irq(idx, apic_id, pin);
>
> @@ -1423,25 +1408,24 @@ static void __init setup_IO_APIC_irqs(void)
> * installed and if it returns 1:
> */
> if (apic->multi_timer_check &&
> - apic->multi_timer_check(apic_id, irq))
> + apic->multi_timer_check(apic_id, irq))
> continue;
>
> - cfg = alloc_irq_and_cfg_at(irq, node);
> - if (!cfg)
> - continue;
> + set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
> + irq_polarity(idx));
>
> - add_pin_to_irq_node(cfg, node, apic_id, pin);
> - /*
> - * don't mark it in pin_programmed, so later acpi could
> - * set it correctly when irq < 16
> - */
> - setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
> - irq_polarity(idx));
> + io_apic_setup_irq_pin(irq, node, &attr);
> }
> +}
>
> - if (notcon)
> - apic_printk(APIC_VERBOSE,
> - " (apicid-pin) not connected\n");
> +static void __init setup_IO_APIC_irqs(void)
> +{
> + unsigned int apic_id;
> +
> + apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
> +
> + for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
> + __io_apic_setup_irqs(apic_id);
> }
>
> /*
> @@ -1452,7 +1436,7 @@ static void __init setup_IO_APIC_irqs(void)
> void setup_IO_APIC_irq_extra(u32 gsi)
> {
> int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
> - struct irq_cfg *cfg;
> + struct io_apic_irq_attr attr;
>
> /*
> * Convert 'gsi' to 'ioapic.pin'.
> @@ -1472,21 +1456,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
> if (apic_id == 0 || irq < NR_IRQS_LEGACY)
> return;
>
> - cfg = alloc_irq_and_cfg_at(irq, node);
> - if (!cfg)
> - return;
> -
> - add_pin_to_irq_node(cfg, node, apic_id, pin);
> -
> - if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
> - pr_debug("Pin %d-%d already programmed\n",
> - mp_ioapics[apic_id].apicid, pin);
> - return;
> - }
> - set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
> + set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
> + irq_polarity(idx));
>
> - setup_ioapic_irq(apic_id, pin, irq, cfg,
> - irq_trigger(idx), irq_polarity(idx));
> + io_apic_setup_irq_pin_once(irq, node, &attr);
> }
>
> /*
> @@ -3605,7 +3578,40 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
> }
> #endif /* CONFIG_HT_IRQ */
>
> -int __init io_apic_get_redir_entries (int ioapic)
> +int
> +io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
> +{
> + struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
> + int ret;
> +
> + if (!cfg)
> + return -EINVAL;
> + ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
> + if (!ret)
> + setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
> + attr->trigger, attr->polarity);
> + return ret;
> +}
> +
> +static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
> + struct io_apic_irq_attr *attr)
> +{
> + unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
> + int ret;
> +
> + /* Avoid redundant programming */
> + if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
> + pr_debug("Pin %d-%d already programmed\n",
> + mp_ioapics[id].apicid, pin);
> + return 0;
> + }
> + ret = io_apic_setup_irq_pin(irq, node, attr);
> + if (!ret)
> + set_bit(pin, mp_ioapic_routing[id].pin_programmed);
> + return ret;
> +}
> +
> +static int __init io_apic_get_redir_entries(int ioapic)
> {
> union IO_APIC_reg_01 reg_01;
> unsigned long flags;
> @@ -3659,96 +3665,24 @@ int __init arch_probe_nr_irqs(void)
> }
> #endif
>
> -static int __io_apic_set_pci_routing(struct device *dev, int irq,
> - struct io_apic_irq_attr *irq_attr)
> +int io_apic_set_pci_routing(struct device *dev, int irq,
> + struct io_apic_irq_attr *irq_attr)
> {
> - struct irq_cfg *cfg;
> int node;
> - int ioapic, pin;
> - int trigger, polarity;
>
> - ioapic = irq_attr->ioapic;
> if (!IO_APIC_IRQ(irq)) {
> apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
> - ioapic);
> + irq_attr->ioapic);
> return -EINVAL;
> }
>
> - if (dev)
> - node = dev_to_node(dev);
> - else
> - node = cpu_to_node(0);
> -
> - cfg = alloc_irq_and_cfg_at(irq, node);
> - if (!cfg)
> - return 0;
> -
> - pin = irq_attr->ioapic_pin;
> - trigger = irq_attr->trigger;
> - polarity = irq_attr->polarity;
> -
> - /*
> - * IRQs < 16 are already in the irq_2_pin[] map
> - */
> - if (irq >= legacy_pic->nr_legacy_irqs) {
> - if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
> - printk(KERN_INFO "can not add pin %d for irq %d\n",
> - pin, irq);
> - return 0;
> - }
> - }
> -
> - setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
> + node = dev ? dev_to_node(dev) : cpu_to_node(0);
>
> - return 0;
> + return io_apic_setup_irq_pin_once(irq, node, irq_attr);
> }
>
> -int io_apic_set_pci_routing(struct device *dev, int irq,
> - struct io_apic_irq_attr *irq_attr)
> -{
> - int ioapic, pin;
> - /*
> - * Avoid pin reprogramming. PRTs typically include entries
> - * with redundant pin->gsi mappings (but unique PCI devices);
> - * we only program the IOAPIC on the first.
> - */
> - ioapic = irq_attr->ioapic;
> - pin = irq_attr->ioapic_pin;
> - if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
> - pr_debug("Pin %d-%d already programmed\n",
> - mp_ioapics[ioapic].apicid, pin);
> - return 0;
> - }
> - set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
> -
> - return __io_apic_set_pci_routing(dev, irq, irq_attr);
> -}
> -
> -u8 __init io_apic_unique_id(u8 id)
> -{
> #ifdef CONFIG_X86_32
> - if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
> - !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
> - return io_apic_get_unique_id(nr_ioapics, id);
> - else
> - return id;
> -#else
> - int i;
> - DECLARE_BITMAP(used, 256);
> -
> - bitmap_zero(used, 256);
> - for (i = 0; i < nr_ioapics; i++) {
> - struct mpc_ioapic *ia = &mp_ioapics[i];
> - __set_bit(ia->apicid, used);
> - }
> - if (!test_bit(id, used))
> - return id;
> - return find_first_zero_bit(used, 256);
> -#endif
> -}
> -
> -#ifdef CONFIG_X86_32
> -int __init io_apic_get_unique_id(int ioapic, int apic_id)
> +static int __init io_apic_get_unique_id(int ioapic, int apic_id)
> {
> union IO_APIC_reg_00 reg_00;
> static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
> @@ -3821,9 +3755,33 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
>
> return apic_id;
> }
> +
> +static u8 __init io_apic_unique_id(u8 id)
> +{
> + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
> + !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
> + return io_apic_get_unique_id(nr_ioapics, id);
> + else
> + return id;
> +}
> +#else
> +static u8 __init io_apic_unique_id(u8 id)
> +{
> + int i;
> + DECLARE_BITMAP(used, 256);
> +
> + bitmap_zero(used, 256);
> + for (i = 0; i < nr_ioapics; i++) {
> + struct mpc_ioapic *ia = &mp_ioapics[i];
> + __set_bit(ia->apicid, used);
> + }
> + if (!test_bit(id, used))
> + return id;
> + return find_first_zero_bit(used, 256);
> +}
> #endif
>
> -int __init io_apic_get_version(int ioapic)
> +static int __init io_apic_get_version(int ioapic)
> {
> union IO_APIC_reg_01 reg_01;
> unsigned long flags;
> @@ -4026,7 +3984,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
> return gsi - mp_gsi_routing[ioapic].gsi_base;
> }
>
> -static int bad_ioapic(unsigned long address)
> +static __init int bad_ioapic(unsigned long address)
> {
> if (nr_ioapics >= MAX_IO_APICS) {
> printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
> @@ -4086,20 +4044,15 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
> /* Enable IOAPIC early just for system timer */
> void __init pre_init_apic_IRQ0(void)
> {
> - struct irq_cfg *cfg;
> + struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
>
> printk(KERN_INFO "Early APIC setup for system timer0\n");
> #ifndef CONFIG_SMP
> physid_set_mask_of_physid(boot_cpu_physical_apicid,
> &phys_cpu_present_map);
> #endif
> - /* Make sure the irq descriptor is set up */
> - cfg = alloc_irq_and_cfg_at(0, 0);
> -
> setup_local_APIC();
>
> - add_pin_to_irq_node(cfg, 0, 0, 0);
> + io_apic_setup_irq_pin(0, 0, &attr);
> set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
> -
> - setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
> }
> diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
> new file mode 100644
> index 0000000..7a8cebc
> --- /dev/null
> +++ b/arch/x86/kernel/devicetree.c
> @@ -0,0 +1,441 @@
> +/*
> + * Architecture specific OF callbacks.
> + */
> +#include <linux/bootmem.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/list.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_irq.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/apic.h>
> +#include <asm/pci_x86.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;
> +
> +#ifdef CONFIG_X86_IO_APIC
> +static 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);
> +}
> +#endif
> +
> +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)
> +{
> + struct irq_domain *ih;
> + u32 virq, type;
> + int ret;
> +
> + ih = get_ih_from_node(controller);
> + if (!ih)
> + return 0;
> + 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);
> +
> +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();
> +}
> +
> +void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
> +{
> + return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
> +}
> +
> +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[] = {
> + { .compatible = "intel,ce4100-cp", },
> + { .compatible = "isa", },
> + { .compatible = "pci", },
> + {},
> +};
> +
> +static int __init add_bus_probe(void)
> +{
> + if (!of_have_populated_dt())
> + return 0;
> +
> + return of_platform_bus_probe(NULL, ce4100_ids, NULL);
> +}
> +module_init(add_bus_probe);
> +
> +#ifdef CONFIG_PCI
> +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 == 0)
> + 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);
> + }
> + }
> +}
> +#endif
> +
> +static void __init dtb_setup_hpet(void)
> +{
> +#ifdef CONFIG_HPET_TIMER
> + struct device_node *dn;
> + struct resource r;
> + int ret;
> +
> + dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
> + if (!dn)
> + return;
> + ret = of_address_to_resource(dn, 0, &r);
> + if (ret) {
> + WARN_ON(1);
> + return;
> + }
> + hpet_address = r.start;
> +#endif
> +}
> +
> +static void __init dtb_lapic_setup(void)
> +{
> +#ifdef CONFIG_X86_LOCAL_APIC
> + struct device_node *dn;
> + struct resource r;
> + int ret;
> +
> + dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
> + if (!dn)
> + return;
> +
> + ret = of_address_to_resource(dn, 0, &r);
> + if (WARN_ON(ret))
> + return;
> +
> + /* Did the boot loader setup the local APIC ? */
> + if (!cpu_has_apic) {
> + if (apic_force_enable(r.start))
> + return;
> + }
> + smp_found_config = 1;
> + pic_mode = 1;
> + register_lapic_address(r.start);
> + generic_processor_info(boot_cpu_physical_apicid,
> + GET_APIC_VERSION(apic_read(APIC_LVR)));
> +#endif
> +}
> +
> +#ifdef CONFIG_X86_IO_APIC
> +static unsigned int ioapic_id;
> +
> +static void __init dtb_add_ioapic(struct device_node *dn)
> +{
> + struct resource r;
> + int ret;
> +
> + 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;
> +
> + for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
> + dtb_add_ioapic(dn);
> +
> + if (nr_ioapics) {
> + of_ioapic = 1;
> + return;
> + }
> + printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
> +}
> +#else
> +static void __init dtb_ioapic_setup(void) {}
> +#endif
> +
> +static void __init dtb_apic_setup(void)
> +{
> + dtb_lapic_setup();
> + dtb_ioapic_setup();
> +}
> +
> +#ifdef CONFIG_OF_FLATTREE
> +static void __init x86_flattree_get_config(void)
> +{
> + u32 size, 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();
> +}
> +#else
> +static inline void x86_flattree_get_config(void) { }
> +#endif
> +
> +void __init x86_dtb_init(void)
> +{
> + x86_flattree_get_config();
> +
> + if (!of_have_populated_dt())
> + return;
> +
> + dtb_setup_hpet();
> + dtb_apic_setup();
> +}
> +
> +#ifdef CONFIG_X86_IO_APIC
> +
> +struct of_ioapic_type {
> + u32 out_type;
> + u32 trigger;
> + u32 polarity;
> +};
> +
> +static struct of_ioapic_type of_ioapic_type[] =
> +{
> + {
> + .out_type = IRQ_TYPE_EDGE_RISING,
> + .trigger = IOAPIC_EDGE,
> + .polarity = 1,
> + },
> + {
> + .out_type = IRQ_TYPE_LEVEL_LOW,
> + .trigger = IOAPIC_LEVEL,
> + .polarity = 0,
> + },
> + {
> + .out_type = IRQ_TYPE_LEVEL_HIGH,
> + .trigger = IOAPIC_LEVEL,
> + .polarity = 1,
> + },
> + {
> + .out_type = IRQ_TYPE_EDGE_FALLING,
> + .trigger = IOAPIC_EDGE,
> + .polarity = 0,
> + },
> +};
> +
> +static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
> + u32 *out_hwirq, u32 *out_type)
> +{
> + struct io_apic_irq_attr attr;
> + struct of_ioapic_type *it;
> + u32 line, idx, type;
> +
> + if (intsize < 2)
> + return -EINVAL;
> +
> + line = *intspec;
> + idx = (u32) id->priv;
> + *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
> +
> + intspec++;
> + type = *intspec;
> +
> + if (type >= ARRAY_SIZE(of_ioapic_type))
> + return -EINVAL;
> +
> + it = of_ioapic_type + type;
> + *out_type = it->out_type;
> +
> + set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
> +
> + return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
> +}
> +
> +static void __init ioapic_add_ofnode(struct device_node *np)
> +{
> + struct resource r;
> + int i, ret;
> +
> + 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;
> +
> + 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);
> +}
> +
> +void __init x86_add_irq_domains(void)
> +{
> + struct device_node *dp;
> +
> + if (!of_have_populated_dt())
> + return;
> +
> + for_each_node_with_property(dp, "interrupt-controller") {
> + if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
> + ioapic_add_ofnode(dp);
> + }
> +}
> +#else
> +void __init x86_add_irq_domains(void) { }
> +#endif
> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
> index 294f26d..5fad626 100644
> --- a/arch/x86/kernel/e820.c
> +++ b/arch/x86/kernel/e820.c
> @@ -667,21 +667,15 @@ __init void e820_setup_gap(void)
> * boot_params.e820_map, others are passed via SETUP_E820_EXT node of
> * linked list of struct setup_data, which is parsed here.
> */
> -void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
> +void __init parse_e820_ext(struct setup_data *sdata)
> {
> - u32 map_len;
> int entries;
> struct e820entry *extmap;
>
> entries = sdata->len / sizeof(struct e820entry);
> - map_len = sdata->len + sizeof(struct setup_data);
> - if (map_len > PAGE_SIZE)
> - sdata = early_ioremap(pa_data, map_len);
> extmap = (struct e820entry *)(sdata->data);
> __append_e820_map(extmap, entries);
> sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
> - if (map_len > PAGE_SIZE)
> - early_iounmap(sdata, map_len);
> printk(KERN_INFO "extended physical RAM map:\n");
> e820_print_map("extended");
> }
> diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
> index 767d6c4..d8cc18a 100644
> --- a/arch/x86/kernel/head_32.S
> +++ b/arch/x86/kernel/head_32.S
> @@ -137,7 +137,7 @@ ENTRY(startup_32)
> movsl
> 1:
>
> -#ifdef CONFIG_OLPC_OPENFIRMWARE
> +#ifdef CONFIG_OLPC
> /* save OFW's pgdir table for later use when calling into OFW */
> movl %cr3, %eax
> movl %eax, pa(olpc_ofw_pgd)
> diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
> index 387b6a0..7531360 100644
> --- a/arch/x86/kernel/irq.c
> +++ b/arch/x86/kernel/irq.c
> @@ -276,15 +276,6 @@ void smp_x86_platform_ipi(struct pt_regs *regs)
>
> EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
>
> -#ifdef CONFIG_OF
> -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);
> -#endif
> -
> #ifdef CONFIG_HOTPLUG_CPU
> /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
> void fixup_irqs(void)
> diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
> index c752e97..9f76f89 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:
> @@ -118,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
> @@ -243,7 +250,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/rtc.c b/arch/x86/kernel/rtc.c
> index 6f39cab..3f2ad26 100644
> --- a/arch/x86/kernel/rtc.c
> +++ b/arch/x86/kernel/rtc.c
> @@ -6,6 +6,7 @@
> #include <linux/acpi.h>
> #include <linux/bcd.h>
> #include <linux/pnp.h>
> +#include <linux/of.h>
>
> #include <asm/vsyscall.h>
> #include <asm/x86_init.h>
> @@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void)
> }
> }
> #endif
> + if (of_have_populated_dt())
> + return 0;
>
> platform_device_register(&rtc_device);
> dev_info(&rtc_device.dev,
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index d3cfe26..b3143bc 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.
> @@ -429,16 +430,30 @@ static void __init parse_setup_data(void)
> return;
> pa_data = boot_params.hdr.setup_data;
> while (pa_data) {
> - data = early_memremap(pa_data, PAGE_SIZE);
> + u32 data_len, map_len;
> +
> + map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK),
> + (u64)sizeof(struct setup_data));
> + data = early_memremap(pa_data, map_len);
> + data_len = data->len + sizeof(struct setup_data);
> + if (data_len > map_len) {
> + early_iounmap(data, map_len);
> + data = early_memremap(pa_data, data_len);
> + map_len = data_len;
> + }
> +
> switch (data->type) {
> case SETUP_E820_EXT:
> - parse_e820_ext(data, pa_data);
> + parse_e820_ext(data);
> + break;
> + case SETUP_DTB:
> + add_dtb(pa_data);
> break;
> default:
> break;
> }
> pa_data = data->next;
> - early_iounmap(data, PAGE_SIZE);
> + early_iounmap(data, map_len);
> }
> }
>
> @@ -1029,8 +1044,8 @@ void __init setup_arch(char **cmdline_p)
> * Read APIC and some other early information from ACPI tables.
> */
> acpi_boot_init();
> -
> sfi_init();
> + x86_dtb_init();
>
> /*
> * get boot-time SMP configuration:
> @@ -1066,6 +1081,8 @@ void __init setup_arch(char **cmdline_p)
> #endif
> x86_init.oem.banner();
>
> + x86_init.timers.wallclock_init();
> +
> mcheck_init();
>
> local_irq_save(flags);
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 08776a9..09d0172 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -64,6 +64,7 @@
> #include <asm/mtrr.h>
> #include <asm/mwait.h>
> #include <asm/apic.h>
> +#include <asm/io_apic.h>
> #include <asm/setup.h>
> #include <asm/uv/uv.h>
> #include <linux/mc146818rtc.h>
> @@ -945,6 +946,14 @@ int __cpuinit native_cpu_up(unsigned int cpu)
> return 0;
> }
>
> +/**
> + * arch_disable_smp_support() - disables SMP support for x86 at runtime
> + */
> +void arch_disable_smp_support(void)
> +{
> + disable_ioapic_support();
> +}
> +
> /*
> * Fall back to non SMP mode after errors.
> *
> @@ -1045,7 +1054,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
> "(tell your hw vendor)\n");
> }
> smpboot_clear_io_apic();
> - arch_disable_smp_support();
> + disable_ioapic_support();
> return -1;
> }
>
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index ceb2911..c11514e 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = {
> .setup_percpu_clockev = setup_boot_APIC_clock,
> .tsc_pre_init = x86_init_noop,
> .timer_init = hpet_time_init,
> + .wallclock_init = x86_init_noop,
> },
>
> .iommu = {
> diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
> index 85b68ef..c63c6d3 100644
> --- a/arch/x86/pci/ce4100.c
> +++ b/arch/x86/pci/ce4100.c
> @@ -254,7 +254,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
> static int ce4100_conf_read(unsigned int seg, unsigned int bus,
> unsigned int devfn, int reg, int len, u32 *value)
> {
> - int i, retval = 1;
> + int i;
>
> if (bus == 1) {
> for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
> diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
> index d2c0d51..68c0dbc 100644
> --- a/arch/x86/platform/ce4100/ce4100.c
> +++ b/arch/x86/platform/ce4100/ce4100.c
> @@ -15,21 +15,19 @@
> #include <linux/serial_reg.h>
> #include <linux/serial_8250.h>
>
> +#include <asm/prom.h>
> #include <asm/setup.h>
> +#include <asm/i8259.h>
> #include <asm/io.h>
> +#include <asm/io_apic.h>
>
> static int ce4100_i8042_detect(void)
> {
> return 0;
> }
>
> -static void __init sdv_find_smp_config(void)
> -{
> -}
> -
> #ifdef CONFIG_SERIAL_8250
>
> -
> static unsigned int mem_serial_in(struct uart_port *p, int offset)
> {
> offset = offset << p->regshift;
> @@ -118,6 +116,15 @@ static void __init sdv_arch_setup(void)
> sdv_serial_fixup();
> }
>
> +#ifdef CONFIG_X86_IO_APIC
> +static void __cpuinit sdv_pci_init(void)
> +{
> + x86_of_pci_init();
> + /* We can't set this earlier, because we need to calibrate the timer */
> + legacy_pic = &null_legacy_pic;
> +}
> +#endif
> +
> /*
> * CE4100 specific x86_init function overrides and early setup
> * calls.
> @@ -128,5 +135,10 @@ void __init x86_ce4100_early_setup(void)
> x86_platform.i8042_detect = ce4100_i8042_detect;
> x86_init.resources.probe_roms = x86_init_noop;
> x86_init.mpparse.get_smp_config = x86_init_uint_noop;
> - x86_init.mpparse.find_smp_config = sdv_find_smp_config;
> + x86_init.mpparse.find_smp_config = x86_init_noop;
> +
> +#ifdef CONFIG_X86_IO_APIC
> + x86_init.pci.init_irq = sdv_pci_init;
> + x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
> +#endif
> }
> diff --git a/arch/x86/platform/ce4100/falconfalls.dts b/arch/x86/platform/ce4100/falconfalls.dts
> new file mode 100644
> index 0000000..dc701ea
> --- /dev/null
> +++ b/arch/x86/platform/ce4100/falconfalls.dts
> @@ -0,0 +1,428 @@
> +/*
> + * 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-cp";
> + ranges;
> +
> + ioapic1: interrupt-controller@fec00000 {
> + #interrupt-cells = <2>;
> + compatible = "intel,ce4100-ioapic";
> + interrupt-controller;
> + reg = <0xfec00000 0x1000>;
> + };
> +
> + timer@fed00000 {
> + compatible = "intel,ce4100-hpet";
> + reg = <0xfed00000 0x200>;
> + };
> +
> + lapic0: interrupt-controller@fee00000 {
> + compatible = "intel,ce4100-lapic";
> + reg = <0xfee00000 0x1000>;
> + };
> +
> + pci@3fc {
> + #address-cells = <3>;
> + #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>;
> +
> + /* Secondary IO-APIC */
> + ioapic2: interrupt-controller@0,1 {
> + #interrupt-cells = <2>;
> + compatible = "intel,ce4100-ioapic";
> + interrupt-controller;
> + reg = <0x100 0x0 0x0 0x0 0x0>;
> + assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
> + };
> +
> + pci@1,0 {
> + #address-cells = <3>;
> + #size-cells = <2>;
> + compatible = "intel,ce4100-pci", "pci";
> + device_type = "pci";
> + bus-range = <1 1>;
> + ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
> +
> + interrupt-parent = <&ioapic2>;
> +
> + display@2,0 {
> + compatible = "pci8086,2e5b.2",
> + "pci8086,2e5b",
> + "pciclass038000",
> + "pciclass0380";
> +
> + reg = <0x11000 0x0 0x0 0x0 0x0>;
> + interrupts = <0 1>;
> + };
> +
> + multimedia@3,0 {
> + compatible = "pci8086,2e5c.2",
> + "pci8086,2e5c",
> + "pciclass048000",
> + "pciclass0480";
> +
> + reg = <0x11800 0x0 0x0 0x0 0x0>;
> + interrupts = <2 1>;
> + };
> +
> + multimedia@4,0 {
> + compatible = "pci8086,2e5d.2",
> + "pci8086,2e5d",
> + "pciclass048000",
> + "pciclass0480";
> +
> + reg = <0x12000 0x0 0x0 0x0 0x0>;
> + interrupts = <4 1>;
> + };
> +
> + multimedia@4,1 {
> + compatible = "pci8086,2e5e.2",
> + "pci8086,2e5e",
> + "pciclass048000",
> + "pciclass0480";
> +
> + reg = <0x12100 0x0 0x0 0x0 0x0>;
> + interrupts = <5 1>;
> + };
> +
> + sound@6,0 {
> + compatible = "pci8086,2e5f.2",
> + "pci8086,2e5f",
> + "pciclass040100",
> + "pciclass0401";
> +
> + reg = <0x13000 0x0 0x0 0x0 0x0>;
> + interrupts = <6 1>;
> + };
> +
> + sound@6,1 {
> + compatible = "pci8086,2e5f.2",
> + "pci8086,2e5f",
> + "pciclass040100",
> + "pciclass0401";
> +
> + reg = <0x13100 0x0 0x0 0x0 0x0>;
> + interrupts = <7 1>;
> + };
> +
> + sound@6,2 {
> + compatible = "pci8086,2e60.2",
> + "pci8086,2e60",
> + "pciclass040100",
> + "pciclass0401";
> +
> + reg = <0x13200 0x0 0x0 0x0 0x0>;
> + interrupts = <8 1>;
> + };
> +
> + display@8,0 {
> + compatible = "pci8086,2e61.2",
> + "pci8086,2e61",
> + "pciclass038000",
> + "pciclass0380";
> +
> + reg = <0x14000 0x0 0x0 0x0 0x0>;
> + interrupts = <9 1>;
> + };
> +
> + display@8,1 {
> + compatible = "pci8086,2e62.2",
> + "pci8086,2e62",
> + "pciclass038000",
> + "pciclass0380";
> +
> + reg = <0x14100 0x0 0x0 0x0 0x0>;
> + interrupts = <10 1>;
> + };
> +
> + multimedia@8,2 {
> + compatible = "pci8086,2e63.2",
> + "pci8086,2e63",
> + "pciclass048000",
> + "pciclass0480";
> +
> + reg = <0x14200 0x0 0x0 0x0 0x0>;
> + interrupts = <11 1>;
> + };
> +
> + entertainment-encryption@9,0 {
> + compatible = "pci8086,2e64.2",
> + "pci8086,2e64",
> + "pciclass101000",
> + "pciclass1010";
> +
> + reg = <0x14800 0x0 0x0 0x0 0x0>;
> + interrupts = <12 1>;
> + };
> +
> + localbus@a,0 {
> + compatible = "pci8086,2e65.2",
> + "pci8086,2e65",
> + "pciclassff0000",
> + "pciclassff00";
> +
> + reg = <0x15000 0x0 0x0 0x0 0x0>;
> + };
> +
> + serial@b,0 {
> + compatible = "pci8086,2e66.2",
> + "pci8086,2e66",
> + "pciclass070003",
> + "pciclass0700";
> +
> + reg = <0x15800 0x0 0x0 0x0 0x0>;
> + interrupts = <14 1>;
> + };
> +
> + gpio@b,1 {
> + compatible = "pci8086,2e67.2",
> + "pci8086,2e67",
> + "pciclassff0000",
> + "pciclassff00";
> +
> + #gpio-cells = <2>;
> + reg = <0x15900 0x0 0x0 0x0 0x0>;
> + interrupts = <15 1>;
> + gpio-controller;
> + };
> +
> + i2c-controller@b,2 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "pci8086,2e68.2",
> + "pci8086,2e68",
> + "pciclass,ff0000",
> + "pciclass,ff00";
> +
> + reg = <0x15a00 0x0 0x0 0x0 0x0>;
> + interrupts = <16 1>;
> + 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 {
> + #gpio-cells = <2>;
> + compatible = "ti,pcf8575";
> + reg = <0x26>;
> + gpio-controller;
> + };
> + };
> +
> + i2c@2 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "intel,ce4100-i2c-controller";
> + reg = <2 0 0x100>;
> +
> + gpio@26 {
> + #gpio-cells = <2>;
> + compatible = "ti,pcf8575";
> + reg = <0x26>;
> + gpio-controller;
> + };
> + };
> + };
> +
> + smard-card@b,3 {
> + compatible = "pci8086,2e69.2",
> + "pci8086,2e69",
> + "pciclass070500",
> + "pciclass0705";
> +
> + reg = <0x15b00 0x0 0x0 0x0 0x0>;
> + interrupts = <15 1>;
> + };
> +
> + spi-controller@b,4 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible =
> + "pci8086,2e6a.2",
> + "pci8086,2e6a",
> + "pciclass,ff0000",
> + "pciclass,ff00";
> +
> + reg = <0x15c00 0x0 0x0 0x0 0x0>;
> + interrupts = <15 1>;
> +
> + 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>;
> + };
> + };
> +
> + multimedia@b,7 {
> + compatible = "pci8086,2e6d.2",
> + "pci8086,2e6d",
> + "pciclassff0000",
> + "pciclassff00";
> +
> + reg = <0x15f00 0x0 0x0 0x0 0x0>;
> + };
> +
> + ethernet@c,0 {
> + compatible = "pci8086,2e6e.2",
> + "pci8086,2e6e",
> + "pciclass020000",
> + "pciclass0200";
> +
> + reg = <0x16000 0x0 0x0 0x0 0x0>;
> + interrupts = <21 1>;
> + };
> +
> + clock@c,1 {
> + compatible = "pci8086,2e6f.2",
> + "pci8086,2e6f",
> + "pciclassff0000",
> + "pciclassff00";
> +
> + reg = <0x16100 0x0 0x0 0x0 0x0>;
> + interrupts = <3 1>;
> + };
> +
> + usb@d,0 {
> + compatible = "pci8086,2e70.2",
> + "pci8086,2e70",
> + "pciclass0c0320",
> + "pciclass0c03";
> +
> + reg = <0x16800 0x0 0x0 0x0 0x0>;
> + interrupts = <22 3>;
> + };
> +
> + usb@d,1 {
> + compatible = "pci8086,2e70.2",
> + "pci8086,2e70",
> + "pciclass0c0320",
> + "pciclass0c03";
> +
> + reg = <0x16900 0x0 0x0 0x0 0x0>;
> + interrupts = <22 3>;
> + };
> +
> + sata@e,0 {
> + compatible = "pci8086,2e71.0",
> + "pci8086,2e71",
> + "pciclass010601",
> + "pciclass0106";
> +
> + reg = <0x17000 0x0 0x0 0x0 0x0>;
> + interrupts = <23 3>;
> + };
> +
> + flash@f,0 {
> + compatible = "pci8086,701.1",
> + "pci8086,701",
> + "pciclass050100",
> + "pciclass0501";
> +
> + reg = <0x17800 0x0 0x0 0x0 0x0>;
> + interrupts = <13 1>;
> + };
> +
> + entertainment-encryption@10,0 {
> + compatible = "pci8086,702.1",
> + "pci8086,702",
> + "pciclass101000",
> + "pciclass1010";
> +
> + reg = <0x18000 0x0 0x0 0x0 0x0>;
> + };
> +
> + co-processor@11,0 {
> + compatible = "pci8086,703.1",
> + "pci8086,703",
> + "pciclass0b4000",
> + "pciclass0b40";
> +
> + reg = <0x18800 0x0 0x0 0x0 0x0>;
> + interrupts = <1 1>;
> + };
> +
> + multimedia@12,0 {
> + compatible = "pci8086,704.0",
> + "pci8086,704",
> + "pciclass048000",
> + "pciclass0480";
> +
> + reg = <0x19000 0x0 0x0 0x0 0x0>;
> + };
> + };
> +
> + isa@1f,0 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "isa";
> + ranges = <1 0 0 0 0 0x100>;
> +
> + rtc@70 {
> + compatible = "intel,ce4100-rtc", "motorola,mc146818";
> + interrupts = <8 3>;
> + interrupt-parent = <&ioapic1>;
> + ctrl-reg = <2>;
> + freq-reg = <0x26>;
> + reg = <1 0x70 2>;
> + };
> + };
> + };
> + };
> +};
> diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
> index ea6529e..5c0207b 100644
> --- a/arch/x86/platform/mrst/mrst.c
> +++ b/arch/x86/platform/mrst/mrst.c
> @@ -31,6 +31,7 @@
> #include <asm/apic.h>
> #include <asm/io_apic.h>
> #include <asm/mrst.h>
> +#include <asm/mrst-vrtc.h>
> #include <asm/io.h>
> #include <asm/i8259.h>
> #include <asm/intel_scu_ipc.h>
> @@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void)
>
> x86_platform.calibrate_tsc = mrst_calibrate_tsc;
> x86_platform.i8042_detect = mrst_i8042_detect;
> + x86_init.timers.wallclock_init = mrst_rtc_init;
> x86_init.pci.init = pci_mrst_init;
> x86_init.pci.fixup_irqs = x86_init_noop;
>
> diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
> index 32cd7ed..04cf645 100644
> --- a/arch/x86/platform/mrst/vrtc.c
> +++ b/arch/x86/platform/mrst/vrtc.c
> @@ -100,22 +100,14 @@ int vrtc_set_mmss(unsigned long nowtime)
>
> void __init mrst_rtc_init(void)
> {
> - unsigned long rtc_paddr;
> - void __iomem *virt_base;
> + unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr;
>
> sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
> - if (!sfi_mrtc_num)
> + if (!sfi_mrtc_num || !vrtc_paddr)
> return;
>
> - rtc_paddr = sfi_mrtc_array[0].phys_addr;
> -
> - /* vRTC's register address may not be page aligned */
> - set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
> -
> - virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
> - virt_base += rtc_paddr & ~PAGE_MASK;
> - vrtc_virt_base = virt_base;
> -
> + vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
> + vrtc_paddr);
> x86_platform.get_wallclock = vrtc_get_time;
> x86_platform.set_wallclock = vrtc_set_mmss;
> }
> diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
> index e797428..c2a8cab 100644
> --- a/arch/x86/platform/olpc/Makefile
> +++ b/arch/x86/platform/olpc/Makefile
> @@ -1,4 +1,4 @@
> obj-$(CONFIG_OLPC) += olpc.o
> obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o
> -obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o
> -obj-$(CONFIG_OLPC_OPENFIRMWARE_DT) += olpc_dt.o
> +obj-$(CONFIG_OLPC) += olpc_ofw.o
> +obj-$(CONFIG_OF_PROMTREE) += olpc_dt.o
> diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
> index ef3bcb1..c2ef5ce 100644
> --- a/drivers/i2c/busses/i2c-ocores.c
> +++ b/drivers/i2c/busses/i2c-ocores.c
> @@ -330,9 +330,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
> i2c->adap = ocores_adapter;
> i2c_set_adapdata(&i2c->adap, i2c);
> i2c->adap.dev.parent = &pdev->dev;
> -#ifdef CONFIG_OF
> i2c->adap.dev.of_node = pdev->dev.of_node;
> -#endif
>
> /* add i2c adapter to i2c tree */
> ret = i2c_add_adapter(&i2c->adap);
> @@ -390,15 +388,11 @@ static int ocores_i2c_resume(struct platform_device *pdev)
> #define ocores_i2c_resume NULL
> #endif
>
> -#ifdef CONFIG_OF
> static struct of_device_id ocores_i2c_match[] = {
> - {
> - .compatible = "opencores,i2c-ocores",
> - },
> - {},
> + { .compatible = "opencores,i2c-ocores", },
> + {},
> };
> MODULE_DEVICE_TABLE(of, ocores_i2c_match);
> -#endif
>
> /* work with hotplug and coldplug */
> MODULE_ALIAS("platform:ocores-i2c");
> @@ -411,9 +405,7 @@ static struct platform_driver ocores_i2c_driver = {
> .driver = {
> .owner = THIS_MODULE,
> .name = "ocores-i2c",
> -#ifdef CONFIG_OF
> - .of_match_table = ocores_i2c_match,
> -#endif
> + .of_match_table = ocores_i2c_match,
> },
> };
>
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index f0bd5bc..045ba6e 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -537,9 +537,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
> client->dev.parent = &client->adapter->dev;
> client->dev.bus = &i2c_bus_type;
> client->dev.type = &i2c_client_type;
> -#ifdef CONFIG_OF
> client->dev.of_node = info->of_node;
> -#endif
>
> dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
> client->addr);
> diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
> index fd877f6..2f7fc0c 100644
> --- a/drivers/mmc/host/mmc_spi.c
> +++ b/drivers/mmc/host/mmc_spi.c
> @@ -1516,21 +1516,17 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
> return 0;
> }
>
> -#if defined(CONFIG_OF)
> static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
> { .compatible = "mmc-spi-slot", },
> {},
> };
> -#endif
>
> static struct spi_driver mmc_spi_driver = {
> .driver = {
> .name = "mmc_spi",
> .bus = &spi_bus_type,
> .owner = THIS_MODULE,
> -#if defined(CONFIG_OF)
> .of_match_table = mmc_spi_of_match_table,
> -#endif
> },
> .probe = mmc_spi_probe,
> .remove = __devexit_p(mmc_spi_remove),
> diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
> index b79d7e1..db0290f 100644
> --- a/drivers/net/ethoc.c
> +++ b/drivers/net/ethoc.c
> @@ -1163,15 +1163,11 @@ static int ethoc_resume(struct platform_device *pdev)
> # define ethoc_resume NULL
> #endif
>
> -#ifdef CONFIG_OF
> static struct of_device_id ethoc_match[] = {
> - {
> - .compatible = "opencores,ethoc",
> - },
> + { .compatible = "opencores,ethoc", },
> {},
> };
> MODULE_DEVICE_TABLE(of, ethoc_match);
> -#endif
>
> static struct platform_driver ethoc_driver = {
> .probe = ethoc_probe,
> @@ -1181,9 +1177,7 @@ static struct platform_driver ethoc_driver = {
> .driver = {
> .name = "ethoc",
> .owner = THIS_MODULE,
> -#ifdef CONFIG_OF
> .of_match_table = ethoc_match,
> -#endif
> },
> };
>
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index 3c6e100..d06a637 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -69,4 +69,10 @@ config OF_MDIO
> help
> OpenFirmware MDIO bus (Ethernet PHY) accessors
>
> +config OF_PCI
> + def_tristate PCI
> + depends on PCI && (PPC || MICROBLAZE || X86)
> + help
> + OpenFirmware PCI bus accessors
> +
> endmenu # OF
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 3ab21a0..f7861ed 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C) += of_i2c.o
> obj-$(CONFIG_OF_NET) += of_net.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..ac1ec54
> --- /dev/null
> +++ b/drivers/of/of_pci.c
> @@ -0,0 +1,92 @@
> +#include <linux/kernel.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_irq.h>
> +#include <asm/prom.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.
> + */
> +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
> + * device tree 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/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
> index c7ff8df..159b95e 100644
> --- a/drivers/rtc/rtc-cmos.c
> +++ b/drivers/rtc/rtc-cmos.c
> @@ -37,6 +37,8 @@
> #include <linux/mod_devicetable.h>
> #include <linux/log2.h>
> #include <linux/pm.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>
> @@ -1123,6 +1125,47 @@ 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) {}
> +#define of_cmos_match NULL
> +#endif
> /*----------------------------------------------------------------*/
>
> /* Platform setup should have set up an RTC device, when PNP is
> @@ -1131,6 +1174,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),
> @@ -1162,6 +1206,7 @@ static struct platform_driver cmos_platform_driver = {
> #ifdef CONFIG_PM
> .pm = &cmos_pm_ops,
> #endif
> + .of_match_table = of_cmos_match,
> }
> };
>
> diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
> index 1db62db..8d2cf60 100644
> --- a/drivers/rtc/rtc-mrst.c
> +++ b/drivers/rtc/rtc-mrst.c
> @@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr)
> return rtc_intr & RTC_IRQMASK;
> }
>
> +static inline unsigned char vrtc_is_updating(void)
> +{
> + unsigned char uip;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&rtc_lock, flags);
> + uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
> + spin_unlock_irqrestore(&rtc_lock, flags);
> + return uip;
> +}
> +
> /*
> * rtc_time's year contains the increment over 1900, but vRTC's YEAR
> * register can't be programmed to value larger than 0x64, so vRTC
> @@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
> {
> unsigned long flags;
>
> - if (rtc_is_updating())
> + if (vrtc_is_updating())
> mdelay(20);
>
> spin_lock_irqsave(&rtc_lock, flags);
> diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
> index 9592883..a429b01 100644
> --- a/drivers/spi/pxa2xx_spi.c
> +++ b/drivers/spi/pxa2xx_spi.c
> @@ -1557,9 +1557,7 @@ static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
> drv_data->ssp = ssp;
>
> master->dev.parent = &pdev->dev;
> -#ifdef CONFIG_OF
> master->dev.of_node = pdev->dev.of_node;
> -#endif
> /* the spi->mode bits understood by this driver: */
> master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
>
> diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
> index 19752b0..378e504 100644
> --- a/drivers/spi/pxa2xx_spi_pci.c
> +++ b/drivers/spi/pxa2xx_spi_pci.c
> @@ -89,9 +89,7 @@ static int __devinit ce4100_spi_probe(struct pci_dev *dev,
> goto err_nomem;
>
> pdev->dev.parent = &dev->dev;
> -#ifdef CONFIG_OF
> pdev->dev.of_node = dev->dev.of_node;
> -#endif
> ssp = &spi_info->ssp;
> ssp->phys_base = pci_resource_start(dev, 0);
> ssp->mmio_base = ioremap(phys_beg, phys_len);
> diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
> index 7adaef6..4d2c75d 100644
> --- a/drivers/spi/xilinx_spi.c
> +++ b/drivers/spi/xilinx_spi.c
> @@ -351,14 +351,12 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> -#ifdef CONFIG_OF
> static const struct of_device_id xilinx_spi_of_match[] = {
> { .compatible = "xlnx,xps-spi-2.00.a", },
> { .compatible = "xlnx,xps-spi-2.00.b", },
> {}
> };
> MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
> -#endif
>
> struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
> u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
> @@ -394,9 +392,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
>
> master->bus_num = bus_num;
> master->num_chipselect = num_cs;
> -#ifdef CONFIG_OF
> master->dev.of_node = dev->of_node;
> -#endif
>
> xspi->mem = *mem;
> xspi->irq = irq;
> @@ -539,9 +535,7 @@ static struct platform_driver xilinx_spi_driver = {
> .driver = {
> .name = XILINX_SPI_NAME,
> .owner = THIS_MODULE,
> -#ifdef CONFIG_OF
> .of_match_table = xilinx_spi_of_match,
> -#endif
> },
> };
>
> diff --git a/include/linux/device.h b/include/linux/device.h
> index 1bf5cf0..ca5d252 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -128,9 +128,7 @@ struct device_driver {
>
> bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
>
> -#if defined(CONFIG_OF)
> const struct of_device_id *of_match_table;
> -#endif
>
> int (*probe) (struct device *dev);
> int (*remove) (struct device *dev);
> @@ -441,9 +439,8 @@ struct device {
> override */
> /* arch specific additions */
> struct dev_archdata archdata;
> -#ifdef CONFIG_OF
> - struct device_node *of_node;
> -#endif
> +
> + struct device_node *of_node; /* associated device tree node */
>
> dev_t devt; /* dev_t, creates the sysfs "dev" */
>
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index 903576d..06a8d9c 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -258,9 +258,7 @@ struct i2c_board_info {
> unsigned short addr;
> void *platform_data;
> struct dev_archdata *archdata;
> -#ifdef CONFIG_OF
> struct device_node *of_node;
> -#endif
> int irq;
> };
>
> diff --git a/include/linux/of.h b/include/linux/of.h
> index cad7cf0..266db1d 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -23,8 +23,6 @@
>
> #include <asm/byteorder.h>
>
> -#ifdef CONFIG_OF
> -
> typedef u32 phandle;
> typedef u32 ihandle;
>
> @@ -65,11 +63,18 @@ struct device_node {
> #endif
> };
>
> +#ifdef CONFIG_OF
> +
> /* Pointer for first entry in chain of all nodes. */
> extern struct device_node *allnodes;
> extern struct device_node *of_chosen;
> extern rwlock_t devtree_lock;
>
> +static inline bool of_have_populated_dt(void)
> +{
> + return allnodes != NULL;
> +}
> +
> static inline bool of_node_is_root(const struct device_node *node)
> {
> return node && (node->parent == NULL);
> @@ -222,5 +227,12 @@ extern void of_attach_node(struct device_node *);
> extern void of_detach_node(struct device_node *);
> #endif
>
> +#else
> +
> +static inline bool of_have_populated_dt(void)
> +{
> + return false;
> +}
> +
> #endif /* CONFIG_OF */
> #endif /* _LINUX_OF_H */
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> new file mode 100644
> index 0000000..85a27b6
> --- /dev/null
> +++ b/include/linux/of_pci.h
> @@ -0,0 +1,9 @@
> +#ifndef __OF_PCI_H
> +#define __OF_PCI_H
> +
> +#include <linux/pci.h>
> +
> +struct pci_dev;
> +struct of_irq;
> +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
> +#endif
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [GIT PULL] x86/platform changes for v2.6.39
2011-03-15 23:09 ` Grant Likely
@ 2011-03-16 12:07 ` Ingo Molnar
0 siblings, 0 replies; 3+ messages in thread
From: Ingo Molnar @ 2011-03-16 12:07 UTC (permalink / raw)
To: Grant Likely; +Cc: Linus Torvalds, linux-kernel, Thomas Gleixner, Andrew Morton
* Grant Likely <grant.likely@secretlab.ca> wrote:
> On Tue, Mar 15, 2011 at 10:32:23PM +0100, Ingo Molnar wrote:
> > Linus,
> >
> > Please pull the latest x86-platform-for-linus git tree from:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git x86-platform-for-linus
> >
> >
> > out-of-topic modifications in x86-platform-for-linus:
> > -----------------------------------------------------
>
> ... all merged in from my devicetree/next branch which Thomas and I
> discussed before hand.
Yeah. We auto-generate these notifiers for all arch/x86/ pull requests that come
from -tip, to not surprise Linus with any modification he might not expect from an
x86 topic, and to give us a final chance to catch any unintended out-of-tree
modifications ourselves.
The sha1's can be used to check the individual commits easily and as you say they
come with acks from affected maintainers.
> [...] I agree with this pull.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-03-16 12:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-15 21:32 [GIT PULL] x86/platform changes for v2.6.39 Ingo Molnar
2011-03-15 23:09 ` Grant Likely
2011-03-16 12:07 ` Ingo Molnar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®