mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
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
This commit is contained in:
commit
d10902812c
93
Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
Normal file
93
Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
Normal file
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
28
Documentation/devicetree/bindings/rtc/rtc-cmos.txt
Normal file
28
Documentation/devicetree/bindings/rtc/rtc-cmos.txt
Normal file
@ -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>;
|
||||
};
|
38
Documentation/devicetree/bindings/x86/ce4100.txt
Normal file
38
Documentation/devicetree/bindings/x86/ce4100.txt
Normal file
@ -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".
|
26
Documentation/devicetree/bindings/x86/interrupt.txt
Normal file
26
Documentation/devicetree/bindings/x86/interrupt.txt
Normal file
@ -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";
|
6
Documentation/devicetree/bindings/x86/timer.txt
Normal file
6
Documentation/devicetree/bindings/x86/timer.txt
Normal file
@ -0,0 +1,6 @@
|
||||
Timers
|
||||
------
|
||||
|
||||
* High Precision Event Timer (HPET)
|
||||
Required property:
|
||||
compatible = "intel,ce4100-hpet";
|
@ -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
|
||||
========================
|
||||
|
@ -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. */
|
||||
|
@ -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__ */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -386,6 +386,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
|
||||
@ -2070,9 +2072,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.
|
||||
@ -2083,21 +2086,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
|
||||
|
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
12
arch/x86/include/asm/irq_controller.h
Normal file
12
arch/x86/include/asm/irq_controller.h
Normal file
@ -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
|
@ -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 */
|
||||
|
||||
#endif /* !CONFIG_OLPC_OPENFIRMWARE */
|
||||
|
||||
#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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
unsigned long current_count;
|
||||
|
||||
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;
|
||||
current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
|
||||
return (cycle_t)~current_count;
|
||||
}
|
||||
|
||||
static int apbt_clocksource_register(void)
|
||||
|
@ -93,7 +93,7 @@ DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID);
|
||||
*
|
||||
* +1=force-enable
|
||||
*/
|
||||
static int force_enable_local_apic;
|
||||
static int force_enable_local_apic __initdata;
|
||||
/*
|
||||
* APIC command line parameters
|
||||
*/
|
||||
@ -163,7 +163,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);
|
||||
@ -187,29 +187,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;
|
||||
|
||||
/*
|
||||
@ -248,7 +227,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;
|
||||
@ -292,23 +271,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
|
||||
@ -518,6 +480,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.
|
||||
@ -1560,7 +1539,7 @@ static int __init detect_init_APIC(void)
|
||||
}
|
||||
#else
|
||||
|
||||
static int apic_verify(void)
|
||||
static int __init apic_verify(void)
|
||||
{
|
||||
u32 features, h, l;
|
||||
|
||||
@ -1585,7 +1564,7 @@ static int apic_verify(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apic_force_enable(void)
|
||||
int __init apic_force_enable(unsigned long addr)
|
||||
{
|
||||
u32 h, l;
|
||||
|
||||
@ -1601,7 +1580,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;
|
||||
}
|
||||
@ -1642,7 +1621,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())
|
||||
|
441
arch/x86/kernel/devicetree.c
Normal file
441
arch/x86/kernel/devicetree.c
Normal file
@ -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
|
@ -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");
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -223,15 +223,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)
|
||||
|
@ -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:
|
||||
@ -119,6 +120,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,
|
||||
@ -308,7 +315,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
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
@ -453,16 +454,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1030,8 +1045,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:
|
||||
@ -1065,6 +1080,8 @@ void __init setup_arch(char **cmdline_p)
|
||||
#endif
|
||||
x86_init.oem.banner();
|
||||
|
||||
x86_init.timers.wallclock_init();
|
||||
|
||||
mcheck_init();
|
||||
|
||||
local_irq_save(flags);
|
||||
|
@ -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 = {
|
||||
|
@ -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,
|
||||
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++) {
|
||||
|
@ -16,21 +16,19 @@
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/ce4100.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;
|
||||
@ -119,6 +117,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.
|
||||
@ -129,6 +136,11 @@ 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;
|
||||
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
|
||||
}
|
||||
|
428
arch/x86/platform/ce4100/falconfalls.dts
Normal file
428
arch/x86/platform/ce4100/falconfalls.dts
Normal file
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
92
drivers/of/of_pci.c
Normal file
92
drivers/of/of_pci.c
Normal file
@ -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);
|
@ -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>
|
||||
@ -1057,6 +1059,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
|
||||
@ -1065,6 +1108,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),
|
||||
@ -1096,6 +1140,7 @@ static struct platform_driver cmos_platform_driver = {
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &cmos_pm_ops,
|
||||
#endif
|
||||
.of_match_table = of_cmos_match,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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" */
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
9
include/linux/of_pci.h
Normal file
9
include/linux/of_pci.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user