Commit d1090281 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-platform-for-linus' of...

Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (27 commits)
  x86: Clean up apic.c and apic.h
  x86: Remove superflous goal definition of tsc_sync
  x86: dt: Correct local apic documentation in device tree bindings
  x86: dt: Cleanup local apic setup
  x86: dt: Fix OLPC=y/INTEL_CE=n build
  rtc: cmos: Add OF bindings
  x86: ce4100: Use OF to setup devices
  x86: ioapic: Add OF bindings for IO_APIC
  x86: dtb: Add generic bus probe
  x86: dtb: Add support for PCI devices backed by dtb nodes
  x86: dtb: Add device tree support for HPET
  x86: dtb: Add early parsing of IO_APIC
  x86: dtb: Add irq domain abstraction
  x86: dtb: Add a device tree for CE4100
  x86: Add device tree support
  x86: e820: Remove conditional early mapping in parse_e820_ext
  x86: OLPC: Make OLPC=n build again
  x86: OLPC: Remove extra OLPC_OPENFIRMWARE_DT indirection
  x86: OLPC: Cleanup config maze completely
  x86: OLPC: Hide OLPC_OPENFIRMWARE config switch
  ...

Fix up conflicts in arch/x86/platform/ce4100/ce4100.c
parents 181f977d 25874a29
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;
};
};
};
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>;
};
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".
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";
Timers
------
* High Precision Event Timer (HPET)
Required property:
compatible = "intel,ce4100-hpet";
...@@ -13,6 +13,7 @@ Table of Contents ...@@ -13,6 +13,7 @@ Table of Contents
I - Introduction I - Introduction
1) Entry point for arch/powerpc 1) Entry point for arch/powerpc
2) Entry point for arch/x86
II - The DT block format II - The DT block format
1) Header 1) Header
...@@ -225,6 +226,25 @@ it with special cases. ...@@ -225,6 +226,25 @@ it with special cases.
cannot support both configurations with Book E and configurations cannot support both configurations with Book E and configurations
with classic Powerpc architectures. 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 II - The DT block format
======================== ========================
......
...@@ -104,11 +104,22 @@ struct pci_controller { ...@@ -104,11 +104,22 @@ struct pci_controller {
int global_number; /* PCI domain number */ int global_number; /* PCI domain number */
}; };
#ifdef CONFIG_PCI
static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
{ {
return bus->sysdata; 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) static inline int isa_vaddr_is_ioport(void __iomem *address)
{ {
/* No specific ISA handling on ppc32 at this stage, it /* No specific ISA handling on ppc32 at this stage, it
...@@ -116,6 +127,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address) ...@@ -116,6 +127,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
*/ */
return 0; return 0;
} }
#endif /* CONFIG_PCI */
/* These are used for config access before all the PCI probing /* These are used for config access before all the PCI probing
has been done. */ has been done. */
......
...@@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void); ...@@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void);
/* CPU OF node matching */ /* CPU OF node matching */
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); 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 /* __ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -2,88 +2,11 @@ ...@@ -2,88 +2,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci_regs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <asm/prom.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, void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size) unsigned long *busno, unsigned long *phys, unsigned long *size)
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_pci.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -171,6 +171,16 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) ...@@ -171,6 +171,16 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
return bus->sysdata; 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) static inline int isa_vaddr_is_ioport(void __iomem *address)
{ {
/* No specific ISA handling on ppc32 at this stage, it /* No specific ISA handling on ppc32 at this stage, it
......
...@@ -70,21 +70,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; } ...@@ -70,21 +70,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
#endif #endif
#define of_node_to_nid of_node_to_nid #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); extern void of_instantiate_rtc(void);
/* These includes are put at the bottom because they may contain things /* These includes are put at the bottom because they may contain things
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
......
...@@ -2,95 +2,11 @@ ...@@ -2,95 +2,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci_regs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <asm/prom.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, void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size) unsigned long *busno, unsigned long *phys, unsigned long *size)
......
...@@ -386,6 +386,8 @@ config X86_INTEL_CE ...@@ -386,6 +386,8 @@ config X86_INTEL_CE
depends on X86_32 depends on X86_32
depends on X86_EXTENDED_PLATFORM depends on X86_EXTENDED_PLATFORM
select X86_REBOOTFIXUPS select X86_REBOOTFIXUPS
select OF
select OF_EARLY_FLATTREE
---help--- ---help---
Select for the Intel CE media processor (CE4100) SOC. Select for the Intel CE media processor (CE4100) SOC.
This option compiles in support for the CE4100 SOC for settop This option compiles in support for the CE4100 SOC for settop
...@@ -2070,9 +2072,10 @@ config SCx200HR_TIMER ...@@ -2070,9 +2072,10 @@ config SCx200HR_TIMER
config OLPC config OLPC
bool "One Laptop Per Child support" bool "One Laptop Per Child support"
depends on !X86_PAE
select GPIOLIB select GPIOLIB
select OLPC_OPENFIRMWARE select OF
depends on !X86_64 && !X86_PAE select OF_PROMTREE if PROC_DEVICETREE
---help--- ---help---
Add support for detecting the unique features of the OLPC Add support for detecting the unique features of the OLPC
XO hardware. XO hardware.
...@@ -2083,21 +2086,6 @@ config OLPC_XO1 ...@@ -2083,21 +2086,6 @@ config OLPC_XO1
---help--- ---help---
Add support for non-essential features of the OLPC XO-1 laptop. 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 endif # X86_32
config AMD_NB config AMD_NB
......
...@@ -220,7 +220,6 @@ extern void enable_IR_x2apic(void); ...@@ -220,7 +220,6 @@ extern void enable_IR_x2apic(void);
extern int get_physical_broadcast(void); extern int get_physical_broadcast(void);
extern void apic_disable(void);
extern int lapic_get_maxlvt(void); extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void); extern void clear_local_APIC(void);
extern void connect_bsp_APIC(void); extern void connect_bsp_APIC(void);
...@@ -228,7 +227,6 @@ extern void disconnect_bsp_APIC(int virt_wire_setup); ...@@ -228,7 +227,6 @@ extern void disconnect_bsp_APIC(int virt_wire_setup);
extern void disable_local_APIC(void); extern void disable_local_APIC(void);
extern void lapic_shutdown(void); extern void lapic_shutdown(void);
extern int verify_local_APIC(void); extern int verify_local_APIC(void);
extern void cache_APIC_registers(void);
extern void sync_Arb_IDs(void); extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void); extern void init_bsp_APIC(void);
extern void setup_local_APIC(void); extern void setup_local_APIC(void);
...@@ -239,8 +237,7 @@ void register_lapic_address(unsigned long address); ...@@ -239,8 +237,7 @@ void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void); extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void); extern void setup_secondary_APIC_clock(void);
extern int APIC_init_uniprocessor(void); extern int APIC_init_uniprocessor(void);
extern void enable_NMI_through_LVT0(void); extern int apic_force_enable(unsigned long addr);
extern int apic_force_enable(void);
/* /*
* On 32bit this is mach-xxx local * On 32bit this is mach-xxx local
...@@ -261,7 +258,6 @@ static inline void lapic_shutdown(void) { } ...@@ -261,7 +258,6 @@ static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1 #define local_apic_timer_c2_ok 1
static inline void init_apic_mappings(void) { } static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { } static inline void disable_local_APIC(void) { }
static inline void apic_disable(void) { }
# define setup_boot_APIC_clock x86_init_noop # define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop # define setup_secondary_APIC_clock x86_init_noop
#endif /* !CONFIG_X86_LOCAL_APIC */ #endif /* !CONFIG_X86_LOCAL_APIC */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
/* setup data types */ /* setup data types */
#define SETUP_NONE 0 #define SETUP_NONE 0
#define SETUP_E820_EXT 1 #define SETUP_E820_EXT 1
#define SETUP_DTB 2
/* extensible setup data list node */ /* extensible setup data list node */
struct setup_data { struct setup_data {
......
...@@ -96,7 +96,7 @@ extern void e820_setup_gap(void); ...@@ -96,7 +96,7 @@ extern void e820_setup_gap(void);
extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
unsigned long start_addr, unsigned long long end_addr); unsigned long start_addr, unsigned long long end_addr);
struct setup_data; 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) || \ #if defined(CONFIG_X86_64) || \
(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
......
...@@ -10,9 +10,6 @@ ...@@ -10,9 +10,6 @@
#include <asm/apicdef.h> #include <asm/apicdef.h>
#include <asm/irq_vectors.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) static inline int irq_canonicalize(int irq)
{ {
return ((irq == 2) ? 9 : irq); return ((irq == 2) ? 9 : irq);
......
#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
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define OLPC_OFW_SIG 0x2057464F /* aka "OFW " */ #define OLPC_OFW_SIG 0x2057464F /* aka "OFW " */
#ifdef CONFIG_OLPC_OPENFIRMWARE #ifdef CONFIG_OLPC
extern bool olpc_ofw_is_installed(void); extern bool olpc_ofw_is_installed(void);
...@@ -26,19 +26,15 @@ extern void setup_olpc_ofw_pgd(void); ...@@ -26,19 +26,15 @@ extern void setup_olpc_ofw_pgd(void);
/* check if OFW was detected during boot */ /* check if OFW was detected during boot */
extern bool olpc_ofw_present(void); extern bool olpc_ofw_present(void);
#else /* !CONFIG_OLPC_OPENFIRMWARE */ #else /* !CONFIG_OLPC */
static inline bool olpc_ofw_is_installed(void) { return false; }
static inline void olpc_ofw_detect(void) { } static inline void olpc_ofw_detect(void) { }
static inline void setup_olpc_ofw_pgd(void) { } static inline void setup_olpc_ofw_pgd(void) { }
static inline bool olpc_ofw_present(void) { return false; } #endif /* !CONFIG_OLPC */
#endif /* !CONFIG_OLPC_OPENFIRMWARE */
#ifdef CONFIG_OLPC_OPENFIRMWARE_DT #ifdef CONFIG_OF_PROMTREE
extern void olpc_dt_build_devicetree(void); extern void olpc_dt_build_devicetree(void);
#else #else
static inline void olpc_dt_build_devicetree(void) { } static inline void olpc_dt_build_devicetree(void) { }
#endif /* CONFIG_OLPC_OPENFIRMWARE_DT */ #endif
#endif /* _ASM_X86_OLPC_OFW_H */ #endif /* _ASM_X86_OLPC_OFW_H */
/* 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
...@@ -83,11 +83,13 @@ struct x86_init_paging { ...@@ -83,11 +83,13 @@ struct x86_init_paging {
* boot cpu * boot cpu
* @tsc_pre_init: platform function called before TSC init * @tsc_pre_init: platform function called before TSC init
* @timer_init: initialize the platform timer (default PIT/HPET) * @timer_init: initialize the platform timer (default PIT/HPET)
* @wallclock_init: init the wallclock device
*/ */
struct x86_init_timers { struct x86_init_timers {
void (*setup_percpu_clockev)(void); void (*setup_percpu_clockev)(void);
void (*tsc_pre_init)(void); void (*tsc_pre_init)(void);
void (*timer_init)(void); void (*timer_init)(void);
void (*wallclock_init)(void);
}; };
/** /**
......
...@@ -66,9 +66,9 @@ obj-$(CONFIG_PCI) += early-quirks.o ...@@ -66,9 +66,9 @@ obj-$(CONFIG_PCI) += early-quirks.o
apm-y := apm_32.o apm-y := apm_32.o
obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_SMP) += smp.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_SMP) += setup_percpu.o
obj-$(CONFIG_X86_64_SMP) += tsc_sync.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-y += apic/ obj-y += apic/
...@@ -109,6 +109,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o ...@@ -109,6 +109,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
obj-$(CONFIG_OF) += devicetree.o
### ###
# 64 bit specific files # 64 bit specific files
......
...@@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta, ...@@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta,
return 0; 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) static cycle_t apbt_read_clocksource(struct clocksource *cs)
{ {
unsigned long t0, t1, t2; unsigned long current_count;
static unsigned long last_read;
current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
bad_count: return (cycle_t)~current_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;
} }
static int apbt_clocksource_register(void) static int apbt_clocksource_register(void)
......
...@@ -93,7 +93,7 @@ DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID); ...@@ -93,7 +93,7 @@ DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID);
* *
* +1=force-enable * +1=force-enable
*/ */
static int force_enable_local_apic; static int force_enable_local_apic __initdata;
/* /*
* APIC command line parameters * APIC command line parameters
*/ */
...@@ -163,7 +163,7 @@ early_param("nox2apic", setup_nox2apic); ...@@ -163,7 +163,7 @@ early_param("nox2apic", setup_nox2apic);
unsigned long mp_lapic_addr; unsigned long mp_lapic_addr;
int disable_apic; int disable_apic;
/* Disable local APIC timer from the kernel commandline or via dmi quirk */ /* 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 */ /* Local APIC timer works in C2 */
int local_apic_timer_c2_ok; int local_apic_timer_c2_ok;
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
...@@ -187,29 +187,8 @@ static struct resource lapic_resource = { ...@@ -187,29 +187,8 @@ static struct resource lapic_resource = {
static unsigned int calibration_result; 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); 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; static unsigned long apic_phys;
/* /*
...@@ -248,7 +227,7 @@ static int modern_apic(void) ...@@ -248,7 +227,7 @@ static int modern_apic(void)
* right after this call apic become NOOP driven * right after this call apic become NOOP driven
* so apic->write/read doesn't do anything * 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"); pr_info("APIC: switched to apic NOOP\n");
apic = &apic_noop; apic = &apic_noop;
...@@ -292,23 +271,6 @@ u64 native_apic_icr_read(void) ...@@ -292,23 +271,6 @@ u64 native_apic_icr_read(void)
return icr1 | ((u64)icr2 << 32); 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 #ifdef CONFIG_X86_32
/** /**
* get_physical_broadcast - Get number of physical broadcast IDs * get_physical_broadcast - Get number of physical broadcast IDs
...@@ -518,6 +480,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask) ...@@ -518,6 +480,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
#endif #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 * Setup the local APIC timer for this CPU. Copy the initialized values
* of the boot CPU and register the clock event in the framework. * of the boot CPU and register the clock event in the framework.
...@@ -1560,7 +1539,7 @@ static int __init detect_init_APIC(void) ...@@ -1560,7 +1539,7 @@ static int __init detect_init_APIC(void)
} }
#else #else
static int apic_verify(void) static int __init apic_verify(void)
{ {
u32 features, h, l; u32 features, h, l;
...@@ -1585,7 +1564,7 @@ static int apic_verify(void) ...@@ -1585,7 +1564,7 @@ static int apic_verify(void)
return 0; return 0;
} }
int apic_force_enable(void) int __init apic_force_enable(unsigned long addr)
{ {
u32 h, l; u32 h, l;
...@@ -1601,7 +1580,7 @@ int apic_force_enable(void) ...@@ -1601,7 +1580,7 @@ int apic_force_enable(void)
if (!(l & MSR_IA32_APICBASE_ENABLE)) { if (!(l & MSR_IA32_APICBASE_ENABLE)) {
pr_info("Local APIC disabled by BIOS -- reenabling.\n"); pr_info("Local APIC disabled by BIOS -- reenabling.\n");
l &= ~MSR_IA32_APICBASE_BASE; 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); wrmsr(MSR_IA32_APICBASE, l, h);
enabled_via_apicbase = 1; enabled_via_apicbase = 1;
} }
...@@ -1642,7 +1621,7 @@ static int __init detect_init_APIC(void) ...@@ -1642,7 +1621,7 @@ static int __init detect_init_APIC(void)
"you can enable it with \"lapic\"\n"); "you can enable it with \"lapic\"\n");
return -1; return -1;
} }
if (apic_force_enable()) if (apic_force_enable(APIC_DEFAULT_PHYS_BASE))
return -1; return -1;
} else { } else {
if (apic_verify()) if (apic_verify())
......
/*
* 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
...@@ -667,21 +667,15 @@ __init void e820_setup_gap(void) ...@@ -667,21 +667,15 @@ __init void e820_setup_gap(void)
* boot_params.e820_map, others are passed via SETUP_E820_EXT node of * boot_params.e820_map, others are passed via SETUP_E820_EXT node of
* linked list of struct setup_data, which is parsed here. * 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; int entries;
struct e820entry *extmap; struct e820entry *extmap;
entries = sdata->len / sizeof(struct e820entry); 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); extmap = (struct e820entry *)(sdata->data);
__append_e820_map(extmap, entries); __append_e820_map(extmap, entries);
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); 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"); printk(KERN_INFO "extended physical RAM map:\n");
e820_print_map("extended"); e820_print_map("extended");
} }
......
...@@ -137,7 +137,7 @@ ENTRY(startup_32) ...@@ -137,7 +137,7 @@ ENTRY(startup_32)
movsl movsl
1: 1:
#ifdef CONFIG_OLPC_OPENFIRMWARE #ifdef CONFIG_OLPC
/* save OFW's pgdir table for later use when calling into OFW */ /* save OFW's pgdir table for later use when calling into OFW */
movl %cr3, %eax movl %cr3, %eax
movl %eax, pa(olpc_ofw_pgd) movl %eax, pa(olpc_ofw_pgd)
......
...@@ -223,15 +223,6 @@ void smp_x86_platform_ipi(struct pt_regs *regs) ...@@ -223,15 +223,6 @@ void smp_x86_platform_ipi(struct pt_regs *regs)
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); 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 #ifdef CONFIG_HOTPLUG_CPU
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
void fixup_irqs(void) void fixup_irqs(void)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/i8259.h> #include <asm/i8259.h>
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/prom.h>
/* /*
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
...@@ -119,6 +120,12 @@ void __init init_IRQ(void) ...@@ -119,6 +120,12 @@ void __init init_IRQ(void)
{ {
int i; 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. * 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, * If these IRQ's are handled by legacy interrupt-controllers like PIC,
...@@ -308,7 +315,7 @@ void __init native_init_IRQ(void) ...@@ -308,7 +315,7 @@ void __init native_init_IRQ(void)
set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
} }
if (!acpi_ioapic) if (!acpi_ioapic && !of_ioapic)
setup_irq(2, &irq2); setup_irq(2, &irq2);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/of.h>
#include <asm/vsyscall.h> #include <asm/vsyscall.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
...@@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void) ...@@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void)
} }
} }
#endif #endif
if (of_have_populated_dt())
return 0;
platform_device_register(&rtc_device); platform_device_register(&rtc_device);
dev_info(&rtc_device.dev, dev_info(&rtc_device.dev,
......
...@@ -113,6 +113,7 @@ ...@@ -113,6 +113,7 @@
#endif #endif
#include <asm/mce.h> #include <asm/mce.h>
#include <asm/alternative.h> #include <asm/alternative.h>
#include <asm/prom.h>
/* /*
* end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
...@@ -453,16 +454,30 @@ static void __init parse_setup_data(void) ...@@ -453,16 +454,30 @@ static void __init parse_setup_data(void)
return; return;
pa_data = boot_params.hdr.setup_data; pa_data = boot_params.hdr.setup_data;
while (pa_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) { switch (data->type) {
case SETUP_E820_EXT: case SETUP_E820_EXT:
parse_e820_ext(data, pa_data); parse_e820_ext(data);
break;
case SETUP_DTB:
add_dtb(pa_data);
break; break;
default: default:
break; break;
} }
pa_data = data->next; pa_data = data->next;
early_iounmap(data, PAGE_SIZE); early_iounmap(data, map_len);
} }
} }
...@@ -1030,8 +1045,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -1030,8 +1045,8 @@ void __init setup_arch(char **cmdline_p)
* Read APIC and some other early information from ACPI tables. * Read APIC and some other early information from ACPI tables.
*/ */
acpi_boot_init(); acpi_boot_init();
sfi_init(); sfi_init();
x86_dtb_init();
/* /*
* get boot-time SMP configuration: * get boot-time SMP configuration:
...@@ -1065,6 +1080,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -1065,6 +1080,8 @@ void __init setup_arch(char **cmdline_p)
#endif #endif
x86_init.oem.banner(); x86_init.oem.banner();
x86_init.timers.wallclock_init();
mcheck_init(); mcheck_init();
local_irq_save(flags); local_irq_save(flags);
......
...@@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = { ...@@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = {
.setup_percpu_clockev = setup_boot_APIC_clock, .setup_percpu_clockev = setup_boot_APIC_clock,
.tsc_pre_init = x86_init_noop, .tsc_pre_init = x86_init_noop,
.timer_init = hpet_time_init, .timer_init = hpet_time_init,
.wallclock_init = x86_init_noop,
}, },
.iommu = { .iommu = {
......
...@@ -255,7 +255,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value) ...@@ -255,7 +255,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
static int ce4100_conf_read(unsigned int seg, unsigned int bus, static int ce4100_conf_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value) unsigned int devfn, int reg, int len, u32 *value)
{ {
int i, retval = 1; int i;
if (bus == 1) { if (bus == 1) {
for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
......
...@@ -16,21 +16,19 @@ ...@@ -16,21 +16,19 @@
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <asm/ce4100.h> #include <asm/ce4100.h>
#include <asm/prom.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/i8259.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/io_apic.h>
static int ce4100_i8042_detect(void) static int ce4100_i8042_detect(void)
{ {
return 0; return 0;
} }
static void __init sdv_find_smp_config(void)
{
}
#ifdef CONFIG_SERIAL_8250 #ifdef CONFIG_SERIAL_8250
static unsigned int mem_serial_in(struct uart_port *p, int offset) static unsigned int mem_serial_in(struct uart_port *p, int offset)
{ {
offset = offset << p->regshift; offset = offset << p->regshift;
...@@ -119,6 +117,15 @@ static void __init sdv_arch_setup(void) ...@@ -119,6 +117,15 @@ static void __init sdv_arch_setup(void)
sdv_serial_fixup(); 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 * CE4100 specific x86_init function overrides and early setup
* calls. * calls.
...@@ -129,6 +136,11 @@ void __init x86_ce4100_early_setup(void) ...@@ -129,6 +136,11 @@ void __init x86_ce4100_early_setup(void)
x86_platform.i8042_detect = ce4100_i8042_detect; x86_platform.i8042_detect = ce4100_i8042_detect;
x86_init.resources.probe_roms = x86_init_noop; x86_init.resources.probe_roms = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_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;
x86_init.pci.init = ce4100_pci_init; x86_init.pci.init = ce4100_pci_init;
#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
} }
/*
* 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>;
};
};
};
};
};
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/io_apic.h> #include <asm/io_apic.h>
#include <asm/mrst.h> #include <asm/mrst.h>
#include <asm/mrst-vrtc.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/i8259.h> #include <asm/i8259.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
...@@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void) ...@@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void)
x86_platform.calibrate_tsc = mrst_calibrate_tsc; x86_platform.calibrate_tsc = mrst_calibrate_tsc;
x86_platform.i8042_detect = mrst_i8042_detect; 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.init = pci_mrst_init;
x86_init.pci.fixup_irqs = x86_init_noop; x86_init.pci.fixup_irqs = x86_init_noop;
......
...@@ -100,22 +100,14 @@ int vrtc_set_mmss(unsigned long nowtime) ...@@ -100,22 +100,14 @@ int vrtc_set_mmss(unsigned long nowtime)
void __init mrst_rtc_init(void) void __init mrst_rtc_init(void)
{ {
unsigned long rtc_paddr; unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr;
void __iomem *virt_base;
sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
if (!sfi_mrtc_num) if (!sfi_mrtc_num || !vrtc_paddr)
return; return;
rtc_paddr = sfi_mrtc_array[0].phys_addr; vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
vrtc_paddr);
/* 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;
x86_platform.get_wallclock = vrtc_get_time; x86_platform.get_wallclock = vrtc_get_time;
x86_platform.set_wallclock = vrtc_set_mmss; x86_platform.set_wallclock = vrtc_set_mmss;
} }
......
obj-$(CONFIG_OLPC) += olpc.o obj-$(CONFIG_OLPC) += olpc.o
obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o
obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o obj-$(CONFIG_OLPC) += olpc_ofw.o
obj-$(CONFIG_OLPC_OPENFIRMWARE_DT) += olpc_dt.o obj-$(CONFIG_OF_PROMTREE) += olpc_dt.o
...@@ -330,9 +330,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) ...@@ -330,9 +330,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
i2c->adap = ocores_adapter; i2c->adap = ocores_adapter;
i2c_set_adapdata(&i2c->adap, i2c); i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
#ifdef CONFIG_OF
i2c->adap.dev.of_node = pdev->dev.of_node; i2c->adap.dev.of_node = pdev->dev.of_node;
#endif
/* add i2c adapter to i2c tree */ /* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap); ret = i2c_add_adapter(&i2c->adap);
...@@ -390,15 +388,11 @@ static int ocores_i2c_resume(struct platform_device *pdev) ...@@ -390,15 +388,11 @@ static int ocores_i2c_resume(struct platform_device *pdev)
#define ocores_i2c_resume NULL #define ocores_i2c_resume NULL
#endif #endif
#ifdef CONFIG_OF
static struct of_device_id ocores_i2c_match[] = { static struct of_device_id ocores_i2c_match[] = {
{ { .compatible = "opencores,i2c-ocores", },
.compatible = "opencores,i2c-ocores", {},
},
{},
}; };
MODULE_DEVICE_TABLE(of, ocores_i2c_match); MODULE_DEVICE_TABLE(of, ocores_i2c_match);
#endif
/* work with hotplug and coldplug */ /* work with hotplug and coldplug */
MODULE_ALIAS("platform:ocores-i2c"); MODULE_ALIAS("platform:ocores-i2c");
...@@ -411,9 +405,7 @@ static struct platform_driver ocores_i2c_driver = { ...@@ -411,9 +405,7 @@ static struct platform_driver ocores_i2c_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ocores-i2c", .name = "ocores-i2c",
#ifdef CONFIG_OF .of_match_table = ocores_i2c_match,
.of_match_table = ocores_i2c_match,
#endif
}, },
}; };
......
...@@ -537,9 +537,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) ...@@ -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.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type; client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type; client->dev.type = &i2c_client_type;
#ifdef CONFIG_OF
client->dev.of_node = info->of_node; client->dev.of_node = info->of_node;
#endif
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
client->addr); client->addr);
......
...@@ -1516,21 +1516,17 @@ static int __devexit mmc_spi_remove(struct spi_device *spi) ...@@ -1516,21 +1516,17 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
return 0; return 0;
} }
#if defined(CONFIG_OF)
static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
{ .compatible = "mmc-spi-slot", }, { .compatible = "mmc-spi-slot", },
{}, {},
}; };
#endif
static struct spi_driver mmc_spi_driver = { static struct spi_driver mmc_spi_driver = {
.driver = { .driver = {
.name = "mmc_spi", .name = "mmc_spi",
.bus = &spi_bus_type, .bus = &spi_bus_type,
.owner = THIS_MODULE, .owner = THIS_MODULE,
#if defined(CONFIG_OF)
.of_match_table = mmc_spi_of_match_table, .of_match_table = mmc_spi_of_match_table,
#endif
}, },
.probe = mmc_spi_probe, .probe = mmc_spi_probe,
.remove = __devexit_p(mmc_spi_remove), .remove = __devexit_p(mmc_spi_remove),
......
...@@ -1163,15 +1163,11 @@ static int ethoc_resume(struct platform_device *pdev) ...@@ -1163,15 +1163,11 @@ static int ethoc_resume(struct platform_device *pdev)
# define ethoc_resume NULL # define ethoc_resume NULL
#endif #endif
#ifdef CONFIG_OF
static struct of_device_id ethoc_match[] = { static struct of_device_id ethoc_match[] = {
{ { .compatible = "opencores,ethoc", },
.compatible = "opencores,ethoc",
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, ethoc_match); MODULE_DEVICE_TABLE(of, ethoc_match);
#endif
static struct platform_driver ethoc_driver = { static struct platform_driver ethoc_driver = {
.probe = ethoc_probe, .probe = ethoc_probe,
...@@ -1181,9 +1177,7 @@ static struct platform_driver ethoc_driver = { ...@@ -1181,9 +1177,7 @@ static struct platform_driver ethoc_driver = {
.driver = { .driver = {
.name = "ethoc", .name = "ethoc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = ethoc_match, .of_match_table = ethoc_match,
#endif
}, },
}; };
......
...@@ -69,4 +69,10 @@ config OF_MDIO ...@@ -69,4 +69,10 @@ config OF_MDIO
help help
OpenFirmware MDIO bus (Ethernet PHY) accessors 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 endmenu # OF
...@@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C) += of_i2c.o ...@@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C) += of_i2c.o
obj-$(CONFIG_OF_NET) += of_net.o obj-$(CONFIG_OF_NET) += of_net.o
obj-$(CONFIG_OF_SPI) += of_spi.o obj-$(CONFIG_OF_SPI) += of_spi.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
#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);
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/pm.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 */ /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h> #include <asm-generic/rtc.h>
...@@ -1057,6 +1059,47 @@ static struct pnp_driver cmos_pnp_driver = { ...@@ -1057,6 +1059,47 @@ static struct pnp_driver cmos_pnp_driver = {
#endif /* CONFIG_PNP */ #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 /* Platform setup should have set up an RTC device, when PNP is
...@@ -1065,6 +1108,7 @@ static struct pnp_driver cmos_pnp_driver = { ...@@ -1065,6 +1108,7 @@ static struct pnp_driver cmos_pnp_driver = {
static int __init cmos_platform_probe(struct platform_device *pdev) static int __init cmos_platform_probe(struct platform_device *pdev)
{ {
cmos_of_init(pdev);
cmos_wake_setup(&pdev->dev); cmos_wake_setup(&pdev->dev);
return cmos_do_probe(&pdev->dev, return cmos_do_probe(&pdev->dev,
platform_get_resource(pdev, IORESOURCE_IO, 0), platform_get_resource(pdev, IORESOURCE_IO, 0),
...@@ -1096,6 +1140,7 @@ static struct platform_driver cmos_platform_driver = { ...@@ -1096,6 +1140,7 @@ static struct platform_driver cmos_platform_driver = {
#ifdef CONFIG_PM #ifdef CONFIG_PM
.pm = &cmos_pm_ops, .pm = &cmos_pm_ops,
#endif #endif
.of_match_table = of_cmos_match,
} }
}; };
......
...@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr) ...@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr)
return rtc_intr & RTC_IRQMASK; 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 * 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 * 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) ...@@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
{ {
unsigned long flags; unsigned long flags;
if (rtc_is_updating()) if (vrtc_is_updating())
mdelay(20); mdelay(20);
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
......
...@@ -1557,9 +1557,7 @@ static int __devinit pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1557,9 +1557,7 @@ static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->ssp = ssp; drv_data->ssp = ssp;
master->dev.parent = &pdev->dev; master->dev.parent = &pdev->dev;
#ifdef CONFIG_OF
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
#endif
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
......
...@@ -89,9 +89,7 @@ static int __devinit ce4100_spi_probe(struct pci_dev *dev, ...@@ -89,9 +89,7 @@ static int __devinit ce4100_spi_probe(struct pci_dev *dev,
goto err_nomem; goto err_nomem;
pdev->dev.parent = &dev->dev; pdev->dev.parent = &dev->dev;
#ifdef CONFIG_OF
pdev->dev.of_node = dev->dev.of_node; pdev->dev.of_node = dev->dev.of_node;
#endif
ssp = &spi_info->ssp; ssp = &spi_info->ssp;
ssp->phys_base = pci_resource_start(dev, 0); ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = ioremap(phys_beg, phys_len); ssp->mmio_base = ioremap(phys_beg, phys_len);
......
...@@ -351,14 +351,12 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) ...@@ -351,14 +351,12 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
#ifdef CONFIG_OF
static const struct of_device_id xilinx_spi_of_match[] = { static const struct of_device_id xilinx_spi_of_match[] = {
{ .compatible = "xlnx,xps-spi-2.00.a", }, { .compatible = "xlnx,xps-spi-2.00.a", },
{ .compatible = "xlnx,xps-spi-2.00.b", }, { .compatible = "xlnx,xps-spi-2.00.b", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
#endif
struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, 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) 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, ...@@ -394,9 +392,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
master->bus_num = bus_num; master->bus_num = bus_num;
master->num_chipselect = num_cs; master->num_chipselect = num_cs;
#ifdef CONFIG_OF
master->dev.of_node = dev->of_node; master->dev.of_node = dev->of_node;
#endif
xspi->mem = *mem; xspi->mem = *mem;
xspi->irq = irq; xspi->irq = irq;
...@@ -539,9 +535,7 @@ static struct platform_driver xilinx_spi_driver = { ...@@ -539,9 +535,7 @@ static struct platform_driver xilinx_spi_driver = {
.driver = { .driver = {
.name = XILINX_SPI_NAME, .name = XILINX_SPI_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = xilinx_spi_of_match, .of_match_table = xilinx_spi_of_match,
#endif
}, },
}; };
......
...@@ -128,9 +128,7 @@ struct device_driver { ...@@ -128,9 +128,7 @@ struct device_driver {
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
#if defined(CONFIG_OF)
const struct of_device_id *of_match_table; const struct of_device_id *of_match_table;
#endif
int (*probe) (struct device *dev); int (*probe) (struct device *dev);
int (*remove) (struct device *dev); int (*remove) (struct device *dev);
...@@ -441,9 +439,8 @@ struct device { ...@@ -441,9 +439,8 @@ struct device {
override */ override */
/* arch specific additions */ /* arch specific additions */
struct dev_archdata archdata; struct dev_archdata archdata;
#ifdef CONFIG_OF
struct device_node *of_node; struct device_node *of_node; /* associated device tree node */
#endif
dev_t devt; /* dev_t, creates the sysfs "dev" */ dev_t devt; /* dev_t, creates the sysfs "dev" */
......
...@@ -258,9 +258,7 @@ struct i2c_board_info { ...@@ -258,9 +258,7 @@ struct i2c_board_info {
unsigned short addr; unsigned short addr;
void *platform_data; void *platform_data;
struct dev_archdata *archdata; struct dev_archdata *archdata;
#ifdef CONFIG_OF
struct device_node *of_node; struct device_node *of_node;
#endif
int irq; int irq;
}; };
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#ifdef CONFIG_OF
typedef u32 phandle; typedef u32 phandle;
typedef u32 ihandle; typedef u32 ihandle;
...@@ -65,11 +63,18 @@ struct device_node { ...@@ -65,11 +63,18 @@ struct device_node {
#endif #endif
}; };
#ifdef CONFIG_OF
/* Pointer for first entry in chain of all nodes. */ /* Pointer for first entry in chain of all nodes. */
extern struct device_node *allnodes; extern struct device_node *allnodes;
extern struct device_node *of_chosen; extern struct device_node *of_chosen;
extern rwlock_t devtree_lock; 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) static inline bool of_node_is_root(const struct device_node *node)
{ {
return node && (node->parent == NULL); return node && (node->parent == NULL);
...@@ -222,5 +227,12 @@ extern void of_attach_node(struct device_node *); ...@@ -222,5 +227,12 @@ extern void of_attach_node(struct device_node *);
extern void of_detach_node(struct device_node *); extern void of_detach_node(struct device_node *);
#endif #endif
#else
static inline bool of_have_populated_dt(void)
{
return false;
}
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
#endif /* _LINUX_OF_H */ #endif /* _LINUX_OF_H */
#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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment