[kernel] Update kernel-arm64.patch from git.

Kyle McMartin kyle at fedoraproject.org
Mon Sep 29 22:10:33 UTC 2014


commit 8462484ef2e9db49c8435ac67821f8b97e96159c
Author: Kyle McMartin <kmcmarti at redhat.com>
Date:   Mon Sep 29 14:14:17 2014 -0400

    Update kernel-arm64.patch from git.

 config-arm64       |   18 +
 config-generic     |    2 +
 kernel-arm64.patch | 6526 +++++++++++++++++++++++++++++++++++++++++-----------
 kernel.spec        |    3 +
 4 files changed, 5193 insertions(+), 1356 deletions(-)
---
diff --git a/config-arm64 b/config-arm64
index f6c244e..c9b8861 100644
--- a/config-arm64
+++ b/config-arm64
@@ -117,3 +117,21 @@ CONFIG_HOTPLUG_PCI=y
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 
 # CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set
+
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+CONFIG_NET_SB1000=y
+CONFIG_SBSAUART_TTY=y
+CONFIG_I2C_SCMI=m
+CONFIG_SENSORS_ACPI_POWER=m
+CONFIG_IMX_THERMAL=m
+CONFIG_PWM_LPSS=m
+CONFIG_ACPI=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_IPMI=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_CUSTOM_METHOD=m
diff --git a/config-generic b/config-generic
index 3f12961..414db23 100644
--- a/config-generic
+++ b/config-generic
@@ -5390,3 +5390,5 @@ CONFIG_FMC_CHARDEV=m
 # CONFIG_NET_XGENE is not set
 
 # CONFIG_GLOB_SELFTEST is not set
+
+# CONFIG_SBSAUART_TTY is not set
diff --git a/kernel-arm64.patch b/kernel-arm64.patch
index 5334f72..a8813c1 100644
--- a/kernel-arm64.patch
+++ b/kernel-arm64.patch
@@ -1,42 +1,329 @@
- .../devicetree/bindings/pci/xgene-pci.txt          |  52 ++
- MAINTAINERS                                        |   7 +
- arch/arm64/Kconfig                                 |  19 +-
+ Documentation/arm64/arm-acpi.txt                   | 218 +++++++
+ .../devicetree/bindings/pci/xgene-pci.txt          |  57 ++
+ Documentation/kernel-parameters.txt                |   3 +-
+ MAINTAINERS                                        |   8 +
+ arch/arm/include/asm/io.h                          |   1 +
+ arch/arm/include/asm/kvm_mmu.h                     |  13 +
+ arch/arm/kvm/arm.c                                 |  23 +-
+ arch/arm/mach-integrator/pci_v3.c                  |  23 +-
+ arch/arm64/Kconfig                                 |  28 +-
+ arch/arm64/Makefile                                |   1 +
  arch/arm64/boot/dts/apm-mustang.dts                |   8 +
- arch/arm64/boot/dts/apm-storm.dtsi                 | 180 ++++-
+ arch/arm64/boot/dts/apm-storm.dtsi                 | 165 ++++++
  arch/arm64/include/asm/Kbuild                      |   1 +
+ arch/arm64/include/asm/acenv.h                     |  18 +
+ arch/arm64/include/asm/acpi.h                      |  99 ++++
+ arch/arm64/include/asm/cpu_ops.h                   |   1 +
  arch/arm64/include/asm/elf.h                       |   3 +-
  arch/arm64/include/asm/io.h                        |   3 +-
- arch/arm64/include/asm/pci.h                       |  49 ++
- arch/arm64/kernel/Makefile                         |   1 +
+ arch/arm64/include/asm/kvm_arm.h                   |  17 +-
+ arch/arm64/include/asm/kvm_mmu.h                   |  75 +++
+ arch/arm64/include/asm/pci.h                       |  37 ++
+ arch/arm64/include/asm/pgtable.h                   |   2 +
+ arch/arm64/include/asm/psci.h                      |   3 +-
+ arch/arm64/include/asm/smp.h                       |  10 +-
+ arch/arm64/kernel/Makefile                         |   5 +-
+ arch/arm64/kernel/acpi.c                           | 397 +++++++++++++
+ arch/arm64/kernel/cpu_ops.c                        |   8 +-
  arch/arm64/kernel/efi-stub.c                       |  16 +-
  arch/arm64/kernel/efi.c                            |  11 +
  arch/arm64/kernel/head.S                           |   6 +-
- arch/arm64/kernel/pci.c                            |  38 ++
+ arch/arm64/kernel/pci.c                            |  70 +++
  arch/arm64/kernel/process.c                        |   6 +
- arch/arm64/kernel/smp_spin_table.c                 |  21 +-
- drivers/ata/ahci_xgene.c                           |   3 +-
- drivers/irqchip/irq-gic.c                          |  32 +-
- drivers/of/address.c                               | 108 +++
- drivers/of/of_pci.c                                | 136 ++++
- drivers/pci/host-bridge.c                          |  18 +-
+ arch/arm64/kernel/psci.c                           |  78 ++-
+ arch/arm64/kernel/setup.c                          |  42 +-
+ arch/arm64/kernel/smp.c                            |   2 +-
+ arch/arm64/kernel/smp_parking_protocol.c           | 110 ++++
+ arch/arm64/kernel/smp_spin_table.c                 |  22 +-
+ arch/arm64/kernel/time.c                           |   7 +
+ arch/arm64/kvm/hyp-init.S                          |  20 +-
+ arch/arm64/mm/dma-mapping.c                        |  65 +++
+ arch/arm64/pci/Makefile                            |   1 +
+ arch/arm64/pci/pci.c                               |  28 +
+ drivers/acpi/Kconfig                               |   6 +-
+ drivers/acpi/Makefile                              |   6 +-
+ drivers/acpi/acpica/utresrc.c                      |   4 +-
+ drivers/acpi/bus.c                                 |   3 +
+ drivers/acpi/internal.h                            |   5 +
+ drivers/acpi/osl.c                                 |   6 +-
+ drivers/acpi/processor_core.c                      |  37 ++
+ drivers/acpi/sleep-arm.c                           |  28 +
+ drivers/acpi/tables.c                              | 115 +++-
+ drivers/acpi/utils.c                               |  26 +
+ drivers/ata/Kconfig                                |   2 +-
+ drivers/ata/ahci_platform.c                        |  13 +
+ drivers/ata/ahci_xgene.c                           |  30 +-
+ drivers/clocksource/arm_arch_timer.c               | 120 +++-
+ drivers/irqchip/irq-gic-v3.c                       |  10 +
+ drivers/irqchip/irq-gic.c                          | 116 ++++
+ drivers/irqchip/irqchip.c                          |   3 +
+ drivers/of/address.c                               | 154 +++++
+ drivers/of/of_pci.c                                | 142 +++++
  drivers/pci/host/Kconfig                           |  10 +
  drivers/pci/host/Makefile                          |   1 +
- drivers/pci/host/pci-xgene.c                       | 725 +++++++++++++++++++++
- drivers/pci/pci.c                                  |  37 ++
- drivers/pci/probe.c                                |  68 +-
+ drivers/pci/host/pci-tegra.c                       |  10 +-
+ drivers/pci/host/pci-xgene.c                       | 646 +++++++++++++++++++++
+ drivers/pci/host/pcie-rcar.c                       |  21 +-
+ drivers/pci/pci.c                                  |  40 ++
+ drivers/pci/probe.c                                |  46 +-
+ drivers/pnp/resource.c                             |   2 +
+ drivers/tty/Kconfig                                |   6 +
+ drivers/tty/Makefile                               |   1 +
+ drivers/tty/sbsauart.c                             | 355 +++++++++++
+ drivers/tty/serial/8250/8250_dw.c                  |   9 +
+ include/acpi/acnames.h                             |   4 +
+ include/acpi/acpi_bus.h                            |   2 +
+ include/acpi/acpi_io.h                             |   6 +
+ include/acpi/acpixf.h                              |   2 +-
+ include/acpi/actbl1.h                              |  19 +-
+ include/acpi/actbl3.h                              |   9 +-
  include/asm-generic/io.h                           |   2 +-
- include/linux/of_address.h                         |  14 +-
- include/linux/of_pci.h                             |  10 +
- include/linux/pci.h                                |  15 +
+ include/asm-generic/pgtable.h                      |   4 +
+ include/kvm/arm_vgic.h                             |  20 +-
+ include/linux/acpi.h                               |   5 +
+ include/linux/clocksource.h                        |   6 +
+ include/linux/irqchip/arm-gic-acpi.h               |  31 +
+ include/linux/irqchip/arm-gic.h                    |   2 +
+ include/linux/of_address.h                         |  17 +-
+ include/linux/of_pci.h                             |  13 +
+ include/linux/pci.h                                |  64 +-
  tools/perf/arch/arm64/include/perf_regs.h          |   2 +
- 31 files changed, 1533 insertions(+), 69 deletions(-)
+ virt/kvm/arm/arch_timer.c                          | 108 ++--
+ virt/kvm/arm/vgic-v2.c                             |  75 ++-
+ virt/kvm/arm/vgic-v3.c                             |   8 +-
+ virt/kvm/arm/vgic.c                                |  32 +-
+ 94 files changed, 3840 insertions(+), 275 deletions(-)
 
+diff --git a/Documentation/arm64/arm-acpi.txt b/Documentation/arm64/arm-acpi.txt
+new file mode 100644
+index 0000000..b7dc826
+--- /dev/null
++++ b/Documentation/arm64/arm-acpi.txt
+@@ -0,0 +1,218 @@
++ACPI on ARMv8 Servers
++---------------------
++
++ACPI can be used for ARMv8 general purpose servers designed to follow
++the SBSA specification (currently available to people with an ARM login at
++http://silver.arm.com).
++
++The kernel will implement minimum ACPI version is 5.1 + errata as released by
++the UEFI Forum, which is available at <http://www.uefi.org/acpi/specs>.
++
++If the machine does not meet the requirements of the SBSA, or cannot be
++described in the required ACPI specifications then it is likely that Device Tree
++(DT) is more suitable for the hardware.
++
++Relationship with Device Tree
++-----------------------------
++
++ACPI support in drivers and subsystems for ARMv8 should never be mutually
++exclusive with DT support at compile time.
++
++At boot time the kernel will only use one description method depending on
++parameters passed from the bootloader (including kernel bootargs).
++
++Regardless of whether DT or ACPI is used, the kernel must always be capable
++of booting with either scheme (in kernels with both schemes enabled at compile
++time).
++
++When booting using ACPI tables the /chosen node in DT will still be parsed
++to extract the kernel command line and initrd path. No other section of
++the DT will be used.
++
++Booting using ACPI tables
++-------------------------
++
++Currently, the only defined method to pass ACPI tables to the kernel on ARMv8
++is via the UEFI system configuration table.
++
++The UEFI implementation MUST set the ACPI_20_TABLE_GUID to point to the
++RSDP table (the table with the ACPI signature "RSD PTR ").
++
++The pointer to the RSDP table will be retrieved from EFI by the ACPI core.
++
++Processing of ACPI tables may be disabled by passing acpi=off on the kernel
++command line.
++
++DO use an XSDT; RSDTs are deprecated and should not be used on arm64. They
++only allow for 32-bit addresses.
++
++DO NOT use the 32-bit address fields in the FADT; they are deprecated. The
++64-bit alternatives MUST be used.
++
++The minimum set of tables MUST include RSDP, XSDT, FACS, FADT, DSDT, MADT
++and GTDT. If PCI is used the MCFG table MUST also be present.
++
++ACPI Detection
++--------------
++
++Drivers should determine their probe() type by checking for ACPI_HANDLE,
++or .of_node, or other information in the device structure. This is
++detailed further in the "Driver Recommendations" section.
++
++In non-driver code If the presence of ACPI needs to be detected at runtime,
++then check the value of acpi_disabled. If CONFIG_ACPI is not set,
++acpi_disabled will always be 1.
++
++Device Enumeration
++------------------
++
++Device descriptions in ACPI should use standard recognized ACPI interfaces.
++These are far simpler than the information provided via Device Tree. Drivers
++should take into account this simplicity and work with sensible defaults.
++
++On no account should a Device Tree attempt to be replicated in ASL using such
++constructs as Name(KEY0, "Value1") type constructs. Additional driver specific
++data should be represented with the appropriate _DSD (ACPI Section 6.2.5)
++structure. _DSM (ACPI Section 9.14.1) should only be used if _DSD cannot
++represent the data required.
++
++This data should be rare and not OS specific. For x86 ACPI has taken to
++identifying itself as Windows because it was found that only one path was
++routinely tested. For ARMv8 it would be preferable to have only one well
++tested path.
++
++_DSD covers more than the generic server case and care should be taken not to
++replicate highly specific embedded behaviour from DT into generic servers.
++
++Common _DSD bindings should be submitted to ASWG to be included in the
++document :-
++
++http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
++
++If these bindings are mirrored from DT care should be taken to ensure they are
++reviewed as DT bindings before submission to limit divergance in bindings.
++
++Programmable Power Control Resources
++------------------------------------
++
++Programmable power control resources include such resources as voltage/current
++providers (regulators) and clock sources.
++
++For power control of these resources they should be represented with Power
++Resource Objects (ACPI Section 7.1). The ACPI core will then handle correctly
++enabling/disabling of resources as they are needed.
++
++The ACPI 5.1 specification does not contain any standard binding for these
++objects to enable programmable levels or rates so this should be avoided if
++possible and the resources set to appropriate levels by the firmware. If this is
++not possible then any manipulation should be abstracted in ASL.
++
++Each device in ACPI has D-states and these can be controlled through
++the optional methods _PS0..._PS3 where _PS0 is full on and _PS3 is full off.
++
++If either _PS0 or _PS3 is implemented, then the other method must also be
++implemented.
++
++If a device requires usage or setup of a power resource when on, the ASL
++should organize that it is allocated/enabled using the _PS0 method.
++
++Resources allocated/enabled in the _PS0 method should be disabled/de-allocated
++in the _PS3 method.
++
++Such code in _PS? methods will of course be very platform specific but
++should allow the driver to operate the device without special non-standard
++values being read from ASL. Further, abstracting the use of these resources
++allows hardware revisions without requiring updates to the kernel.
++
++Clocks
++------
++
++Like clocks that are part of the power resources there is no standard way
++to represent a clock tree in ACPI 5.1 in a similar manner to how it is
++described in DT.
++
++Devices affected by this include things like UARTs, SoC driven LCD displays,
++etc.
++
++The firmware (for example, UEFI) should initialize these clocks to fixed working
++values before the kernel is executed.
++
++Driver Recommendations
++----------------------
++
++DO NOT remove any FDT handling when adding ACPI support for a driver. Different
++systems may use the same device.
++
++DO try and keep complex sections of ACPI and DT functionality separate. This
++may mean a patch to break out some complex DT to another function before
++the patch to add ACPI. This may happen in other functions but is most likely
++in probe function. This gives a clearer flow of data for reviewing driver
++source.
++
++probe() :-
++
++static int device_probe_dt(struct platform_device *pdev)
++{
++	/* DT specific functionality */
++	...
++}
++
++static int device_probe_acpi(struct platform_device *pdev)
++{
++	/* ACPI specific functionality */
++	...
++}
++
++static int device_probe(stuct platform_device *pdev)
++{
++	...
++	struct device_node node = pdev->dev.of_node;
++	...
++
++	if (node)
++		ret = device_probe_dt(pdev);
++	else if (ACPI_HANDLE(&pdev->dev))
++		ret = device_probe_acpi(pdev);
++	else
++		/* other initialization */
++		...
++	/* Continue with any generic probe operations */
++	...
++}
++
++DO keep the MODULE_DEVICE_TABLE entries together in the driver to make it clear
++the different names the driver is probed for, both from DT and from ACPI.
++
++module device tables :-
++
++static struct of_device_id virtio_mmio_match[] = {
++        { .compatible = "virtio,mmio", },
++        { }
++};
++MODULE_DEVICE_TABLE(of, virtio_mmio_match);
++
++static const struct acpi_device_id virtio_mmio_acpi_match[] = {
++        { "LNRO0005", },
++        { }
++};
++MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match);
++
++ASWG
++----
++
++The following areas are not yet well defined for ARM in the current ACPI
++specification and are expected to be worked through in the UEFI ACPI
++Specification Working Group (ASWG) <http://www.uefi.org/workinggroups>.
++Participation in this group is open to all UEFI members.
++
++	- ACPI based CPU topology
++	- ACPI based Power management
++	- CPU idle control based on PSCI
++	- CPU performance control (CPPC)
++	- ACPI based SMMU
++	- ITS support for GIC in MADT
++
++No code shall be accepted into the kernel unless it complies with the released
++standards from UEFI ASWG. If there are features missing from ACPI to make it
++function on a platform, ECRs should be submitted to ASWG and go through the
++approval process.
 diff --git a/Documentation/devicetree/bindings/pci/xgene-pci.txt b/Documentation/devicetree/bindings/pci/xgene-pci.txt
 new file mode 100644
-index 0000000..e19fdb8
+index 0000000..1070b06
 --- /dev/null
 +++ b/Documentation/devicetree/bindings/pci/xgene-pci.txt
-@@ -0,0 +1,52 @@
+@@ -0,0 +1,57 @@
 +* AppliedMicro X-Gene PCIe interface
 +
 +Required properties:
@@ -60,10 +347,12 @@ index 0000000..e19fdb8
 +
 +Optional properties:
 +- status: Either "ok" or "disabled".
++- dma-coherent: Present if dma operations are coherent
 +
 +Example:
 +
 +SoC specific DT Entry:
++
 +	pcie0: pcie at 1f2b0000 {
 +		status = "disabled";
 +		device_type = "pci";
@@ -72,28 +361,52 @@ index 0000000..e19fdb8
 +		#size-cells = <2>;
 +		#address-cells = <3>;
 +		reg = < 0x00 0x1f2b0000 0x0 0x00010000   /* Controller registers */
-+			0xe0 0xd0000000 0x0 0x00200000>; /* PCI config space */
++			0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */
 +		reg-names = "csr", "cfg";
-+		ranges = <0x01000000 0x00 0x00000000 0xe0 0x00000000 0x00 0x00010000   /* io */
-+			  0x02000000 0x00 0x10000000 0xe0 0x10000000 0x00 0x80000000>; /* mem */
-+		dma-ranges = <0x42000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
++		ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000   /* io */
++			  0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */
++		dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
++			      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
 +		interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 +		interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1
 +				 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1
 +				 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1
 +				 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>;
++		dma-coherent;
 +		clocks = <&pcie0clk 0>;
 +	};
 +
++
 +Board specific DT Entry:
 +	&pcie0 {
 +		status = "ok";
 +	};
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 10d51c2..9464c6d 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -165,7 +165,7 @@ multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
+ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 
+ 
+-	acpi=		[HW,ACPI,X86]
++	acpi=		[HW,ACPI,X86,ARM]
+ 			Advanced Configuration and Power Interface
+ 			Format: { force | off | strict | noirq | rsdt }
+ 			force -- enable ACPI if default was off
+@@ -175,6 +175,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ 				strictly ACPI specification compliant.
+ 			rsdt -- prefer RSDT over (default) XSDT
+ 			copy_dsdt -- copy DSDT to memory
++			For ARM64, ONLY "acpi=off" is available.
+ 
+ 			See also Documentation/power/runtime_pm.txt, pci=noacpi
+ 
 diff --git a/MAINTAINERS b/MAINTAINERS
-index 2f85f55..8980971 100644
+index 670b3dc..b18bc49 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -6894,6 +6894,13 @@ L:	linux-pci at vger.kernel.org
+@@ -6942,6 +6942,14 @@ L:	linux-pci at vger.kernel.org
  S:	Maintained
  F:	drivers/pci/host/*spear*
  
@@ -102,16 +415,202 @@ index 2f85f55..8980971 100644
 +L:	linux-pci at vger.kernel.org
 +L:	linux-arm-kernel at lists.infradead.org
 +S:	Maintained
++F:	Documentation/devicetree/bindings/pci/xgene-pci.txt
 +F:	drivers/pci/host/pci-xgene.c
 +
  PCMCIA SUBSYSTEM
  P:	Linux PCMCIA Team
  L:	linux-pcmcia at lists.infradead.org
+diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
+index 3d23418..22b7529 100644
+--- a/arch/arm/include/asm/io.h
++++ b/arch/arm/include/asm/io.h
+@@ -178,6 +178,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
+ 
+ /* PCI fixed i/o mapping */
+ #define PCI_IO_VIRT_BASE	0xfee00000
++#define PCI_IOBASE		PCI_IO_VIRT_BASE
+ 
+ #if defined(CONFIG_PCI)
+ void pci_ioremap_set_mem_type(int mem_type);
+diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
+index 5cc0b0f..03a08bb 100644
+--- a/arch/arm/include/asm/kvm_mmu.h
++++ b/arch/arm/include/asm/kvm_mmu.h
+@@ -21,6 +21,7 @@
+ 
+ #include <asm/memory.h>
+ #include <asm/page.h>
++#include <asm/kvm_arm.h>
+ 
+ /*
+  * We directly use the kernel VA for the HYP, as we can directly share
+@@ -178,6 +179,18 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
+ 
+ void stage2_flush_vm(struct kvm *kvm);
+ 
++static inline int kvm_get_phys_addr_shift(void)
++{
++	return KVM_PHYS_SHIFT;
++}
++
++
++static inline u32 get_vttbr_baddr_mask(void)
++{
++	return VTTBR_BADDR_MASK;
++}
++
++
+ #endif	/* !__ASSEMBLY__ */
+ 
+ #endif /* __ARM_KVM_MMU_H__ */
+diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
+index a99e0cd..d0fca8f 100644
+--- a/arch/arm/kvm/arm.c
++++ b/arch/arm/kvm/arm.c
+@@ -37,6 +37,7 @@
+ #include <asm/mman.h>
+ #include <asm/tlbflush.h>
+ #include <asm/cacheflush.h>
++#include <asm/cputype.h>
+ #include <asm/virt.h>
+ #include <asm/kvm_arm.h>
+ #include <asm/kvm_asm.h>
+@@ -61,6 +62,12 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
+ static u8 kvm_next_vmid;
+ static DEFINE_SPINLOCK(kvm_vmid_lock);
+ 
++#ifdef CONFIG_ARM64
++static u64 vttbr_baddr_mask;
++#else
++static u32 vttbr_baddr_mask;
++#endif
++
+ static bool vgic_present;
+ 
+ static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
+@@ -429,8 +436,14 @@ static void update_vttbr(struct kvm *kvm)
+ 	/* update vttbr to be used with the new vmid */
+ 	pgd_phys = virt_to_phys(kvm->arch.pgd);
+ 	vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK;
+-	kvm->arch.vttbr = pgd_phys & VTTBR_BADDR_MASK;
+-	kvm->arch.vttbr |= vmid;
++
++	/*
++	 * If the VTTBR isn't aligned there is something wrong with the system
++	 * or kernel.
++	 */
++	BUG_ON(pgd_phys & ~vttbr_baddr_mask);
++
++	kvm->arch.vttbr = pgd_phys | vmid;
+ 
+ 	spin_unlock(&kvm_vmid_lock);
+ }
+@@ -1015,6 +1028,12 @@ int kvm_arch_init(void *opaque)
+ 		}
+ 	}
+ 
++	vttbr_baddr_mask = get_vttbr_baddr_mask();
++	if (vttbr_baddr_mask == ~0) {
++		kvm_err("Cannot set vttbr_baddr_mask\n");
++		return -EINVAL;
++	}
++
+ 	cpu_notifier_register_begin();
+ 
+ 	err = init_hyp_mode();
+diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
+index 05e1f73..c186a17 100644
+--- a/arch/arm/mach-integrator/pci_v3.c
++++ b/arch/arm/mach-integrator/pci_v3.c
+@@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
+ {
+ 	unsigned long flags;
+ 	unsigned int temp;
++	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
+ 
+ 	pcibios_min_mem = 0x00100000;
+ 
+@@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
+ 	/*
+ 	 * Setup window 2 - PCI IO
+ 	 */
+-	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
++	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
+ 			V3_LB_BASE_ENABLE);
+ 	v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
+ 
+@@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
+ static void __init pci_v3_postinit(void)
+ {
+ 	unsigned int pci_cmd;
++	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
+ 
+ 	pci_cmd = PCI_COMMAND_MEMORY |
+ 		  PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
+@@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
+ 		       "interrupt: %d\n", ret);
+ #endif
+ 
+-	register_isa_ports(non_mem.start, io_mem.start, 0);
++	register_isa_ports(non_mem.start, io_address, 0);
+ }
+ 
+ /*
+@@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
+ 
+ 	for_each_of_pci_range(&parser, &range) {
+ 		if (!range.flags) {
+-			of_pci_range_to_resource(&range, np, &conf_mem);
++			ret = of_pci_range_to_resource(&range, np, &conf_mem);
+ 			conf_mem.name = "PCIv3 config";
+ 		}
+ 		if (range.flags & IORESOURCE_IO) {
+-			of_pci_range_to_resource(&range, np, &io_mem);
++			ret = of_pci_range_to_resource(&range, np, &io_mem);
+ 			io_mem.name = "PCIv3 I/O";
+ 		}
+ 		if ((range.flags & IORESOURCE_MEM) &&
+ 			!(range.flags & IORESOURCE_PREFETCH)) {
+ 			non_mem_pci = range.pci_addr;
+ 			non_mem_pci_sz = range.size;
+-			of_pci_range_to_resource(&range, np, &non_mem);
++			ret = of_pci_range_to_resource(&range, np, &non_mem);
+ 			non_mem.name = "PCIv3 non-prefetched mem";
+ 		}
+ 		if ((range.flags & IORESOURCE_MEM) &&
+ 			(range.flags & IORESOURCE_PREFETCH)) {
+ 			pre_mem_pci = range.pci_addr;
+ 			pre_mem_pci_sz = range.size;
+-			of_pci_range_to_resource(&range, np, &pre_mem);
++			ret = of_pci_range_to_resource(&range, np, &pre_mem);
+ 			pre_mem.name = "PCIv3 prefetched mem";
+ 		}
+-	}
+ 
+-	if (!conf_mem.start || !io_mem.start ||
+-	    !non_mem.start || !pre_mem.start) {
+-		dev_err(&pdev->dev, "missing ranges in device node\n");
+-		return -EINVAL;
++		if (ret < 0) {
++			dev_err(&pdev->dev, "missing ranges in device node\n");
++			return ret;
++		}
+ 	}
+ 
+ 	pci_v3.map_irq = of_irq_parse_and_map_pci;
 diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index fd4e81a..e8559bb 100644
+index fd4e81a..e57b91a 100644
 --- a/arch/arm64/Kconfig
 +++ b/arch/arm64/Kconfig
-@@ -81,7 +81,7 @@ config MMU
+@@ -1,5 +1,6 @@
+ config ARM64
+ 	def_bool y
++	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+ 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+ 	select ARCH_HAS_SG_CHAIN
+ 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+@@ -81,7 +82,7 @@ config MMU
  	def_bool y
  
  config NO_IOPORT_MAP
@@ -120,20 +619,23 @@ index fd4e81a..e8559bb 100644
  
  config STACKTRACE_SUPPORT
  	def_bool y
-@@ -156,6 +156,23 @@ menu "Bus support"
+@@ -156,6 +157,26 @@ menu "Bus support"
  config ARM_AMBA
  	bool
  
 +config PCI
 +	bool "PCI support"
 +	help
-+	  This feature enables support for PCIe bus system. If you say Y
++	  This feature enables support for PCI bus system. If you say Y
 +	  here, the kernel will include drivers and infrastructure code
-+	  to support PCIe bus devices.
++	  to support PCI bus devices.
 +
 +config PCI_DOMAINS
 +	def_bool PCI
 +
++config PCI_DOMAINS_GENERIC
++	def_bool PCI
++
 +config PCI_SYSCALL
 +	def_bool PCI
 +
@@ -144,15 +646,45 @@ index fd4e81a..e8559bb 100644
  endmenu
  
  menu "Kernel Features"
+@@ -235,6 +256,9 @@ config SMP
+ 
+ 	  If you don't know what to do here, say N.
+ 
++config ARM_PARKING_PROTOCOL
++	def_bool y if SMP
++
+ config SCHED_MC
+ 	bool "Multi-core scheduler support"
+ 	depends on SMP
+@@ -421,6 +445,8 @@ source "drivers/Kconfig"
+ 
+ source "drivers/firmware/Kconfig"
+ 
++source "drivers/acpi/Kconfig"
++
+ source "fs/Kconfig"
+ 
+ source "arch/arm64/kvm/Kconfig"
+diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
+index 2df5e5d..bddd4e3 100644
+--- a/arch/arm64/Makefile
++++ b/arch/arm64/Makefile
+@@ -50,6 +50,7 @@ core-y		+= arch/arm64/kernel/ arch/arm64/mm/
+ core-$(CONFIG_KVM) += arch/arm64/kvm/
+ core-$(CONFIG_XEN) += arch/arm64/xen/
+ core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
++drivers-$(CONFIG_PCI)	+= arch/arm64/pci/
+ libs-y		:= arch/arm64/lib/ $(libs-y)
+ libs-y		+= $(LIBGCC)
+ libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/
 diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
-index b2f5622..0cb67fc 100644
+index b2f5622..f649000 100644
 --- a/arch/arm64/boot/dts/apm-mustang.dts
 +++ b/arch/arm64/boot/dts/apm-mustang.dts
-@@ -32,3 +32,11 @@
- &menet {
- 	status = "ok";
+@@ -25,6 +25,14 @@
+ 	};
  };
-+
+ 
 +&pcie0clk {
 +	status = "ok";
 +};
@@ -160,88 +692,15 @@ index b2f5622..0cb67fc 100644
 +&pcie0 {
 +	status = "ok";
 +};
++
+ &serial0 {
+ 	status = "ok";
+ };
 diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
-index c0aceef..fb2ee54 100644
+index c0aceef..403197a 100644
 --- a/arch/arm64/boot/dts/apm-storm.dtsi
 +++ b/arch/arm64/boot/dts/apm-storm.dtsi
-@@ -24,56 +24,56 @@
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x000>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 001 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x001>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 100 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x100>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 101 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x101>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 200 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x200>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 201 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x201>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 300 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x300>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 		cpu at 301 {
- 			device_type = "cpu";
- 			compatible = "apm,potenza", "arm,armv8";
- 			reg = <0x0 0x301>;
- 			enable-method = "spin-table";
--			cpu-release-addr = <0x1 0x0000fff8>;
-+			cpu-release-addr = <0x40 0x0000f000>;
- 		};
- 	};
- 
-@@ -97,6 +97,11 @@
- 		clock-frequency = <50000000>;
- 	};
- 
-+	pmu {
-+		compatible = "arm,armv8-pmuv3";
-+		interrupts = <1 12 0xff04>;
-+	};
-+
- 	soc {
- 		compatible = "simple-bus";
- 		#address-cells = <2>;
-@@ -269,6 +274,161 @@
+@@ -269,6 +269,171 @@
  				enable-mask = <0x2>;
  				clock-output-names = "rtcclk";
  			};
@@ -305,16 +764,18 @@ index c0aceef..fb2ee54 100644
 +			#size-cells = <2>;
 +			#address-cells = <3>;
 +			reg = < 0x00 0x1f2b0000 0x0 0x00010000   /* Controller registers */
-+				0xe0 0xd0000000 0x0 0x00200000>; /* PCI config space */
++				0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */
 +			reg-names = "csr", "cfg";
-+			ranges = <0x01000000 0x00 0x00000000 0xe0 0x00000000 0x00 0x00010000   /* io */
-+				  0x02000000 0x00 0x10000000 0xe0 0x10000000 0x00 0x80000000>; /* mem */
-+			dma-ranges = <0x42000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
++			ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000   /* io */
++				  0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */
++			dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
++				      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
 +			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 +			interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1
 +					 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1
 +					 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1
 +					 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>;
++			dma-coherent;
 +			clocks = <&pcie0clk 0>;
 +		};
 +
@@ -326,16 +787,18 @@ index c0aceef..fb2ee54 100644
 +			#size-cells = <2>;
 +			#address-cells = <3>;
 +			reg = < 0x00 0x1f2c0000 0x0 0x00010000   /* Controller registers */
-+				0xd0 0xd0000000 0x0 0x00200000>; /* PCI config space */
++				0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */
 +			reg-names = "csr", "cfg";
-+			ranges = <0x01000000 0x0 0x00000000 0xd0 0x00000000 0x00 0x00010000   /* io  */
-+				  0x02000000 0x0 0x10000000 0xd0 0x10000000 0x00 0x80000000>; /* mem */
-+			dma-ranges = <0x42000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
++			ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
++				  0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */
++			dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
++				      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
 +			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 +			interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1
 +					 0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1
 +					 0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1
 +					 0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>;
++			dma-coherent;
 +			clocks = <&pcie1clk 0>;
 +		};
 +
@@ -347,16 +810,18 @@ index c0aceef..fb2ee54 100644
 +			#size-cells = <2>;
 +			#address-cells = <3>;
 +			reg =  < 0x00 0x1f2d0000 0x0 0x00010000   /* Controller registers */
-+				 0x90 0xd0000000 0x0 0x00200000>; /* PCI config space */
++				 0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */
 +			reg-names = "csr", "cfg";
-+			ranges = <0x01000000 0x0 0x00000000 0x90 0x00000000 0x0 0x00010000   /* io  */
-+				  0x02000000 0x0 0x10000000 0x90 0x10000000 0x0 0x80000000>; /* mem */
-+			dma-ranges = <0x42000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
++			ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000   /* io  */
++				  0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */
++			dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
++				      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
 +			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 +			interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1
 +					 0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1
 +					 0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1
 +					 0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>;
++			dma-coherent;
 +			clocks = <&pcie2clk 0>;
 +		};
 +
@@ -368,16 +833,18 @@ index c0aceef..fb2ee54 100644
 +			#size-cells = <2>;
 +			#address-cells = <3>;
 +			reg = < 0x00 0x1f500000 0x0 0x00010000   /* Controller registers */
-+				0xa0 0xd0000000 0x0 0x00200000>; /* PCI config space */
++				0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */
 +			reg-names = "csr", "cfg";
-+			ranges = <0x01000000 0x0 0x00000000 0xa0 0x00000000 0x0 0x00010000  /* io */
-+				  0x02000000 0x0 0x10000000 0xa0 0x10000000 0x0 0x80000000>; /* mem  */
-+			dma-ranges = <0x42000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
++			ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000   /* io   */
++				  0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem  */
++			dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
++				      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
 +			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 +			interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1
 +					 0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1
 +					 0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1
 +					 0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>;
++			dma-coherent;
 +			clocks = <&pcie3clk 0>;
 +		};
 +
@@ -391,36 +858,20 @@ index c0aceef..fb2ee54 100644
 +			reg = < 0x00 0x1f510000 0x0 0x00010000   /* Controller registers */
 +				0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */
 +			reg-names = "csr", "cfg";
-+			ranges = <0x01000000 0x0 0x00000000 0xc0 0x00000000 0x0 0x00010000   /* io  */
-+				  0x02000000 0x0 0x10000000 0xc0 0x10000000 0x0 0x80000000>; /* mem */
-+			dma-ranges = <0x42000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
++			ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000   /* io  */
++				  0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */
++			dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
++				      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
 +			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 +			interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1
 +					 0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1
 +					 0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1
 +					 0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>;
++			dma-coherent;
 +			clocks = <&pcie4clk 0>;
  		};
  
  		serial0: serial at 1c020000 {
-@@ -277,7 +437,7 @@
- 			compatible = "ns16550a";
- 			reg = <0 0x1c020000 0x0 0x1000>;
- 			reg-shift = <2>;
--			clock-frequency = <10000000>; /* Updated by bootloader */
-+			clock-frequency = <50000000>; /* Updated by bootloader */
- 			interrupt-parent = <&gic>;
- 			interrupts = <0x0 0x4c 0x4>;
- 		};
-@@ -407,7 +567,7 @@
- 			interrupts = <0x0 0x3c 0x4>;
- 			dma-coherent;
- 			clocks = <&menetclk 0>;
--			local-mac-address = [00 01 73 00 00 01];
-+			local-mac-address = [00 00 00 00 00 00];
- 			phy-connection-type = "rgmii";
- 			phy-handle = <&menetphy>;
- 			mdio {
 diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
 index 0b3fcf8..07cb417 100644
 --- a/arch/arm64/include/asm/Kbuild
@@ -433,6 +884,147 @@ index 0b3fcf8..07cb417 100644
  generic-y += poll.h
  generic-y += preempt.h
  generic-y += resource.h
+diff --git a/arch/arm64/include/asm/acenv.h b/arch/arm64/include/asm/acenv.h
+new file mode 100644
+index 0000000..b49166f
+--- /dev/null
++++ b/arch/arm64/include/asm/acenv.h
+@@ -0,0 +1,18 @@
++/*
++ * ARM64 specific ACPICA environments and implementation
++ *
++ * Copyright (C) 2014, Linaro Ltd.
++ *   Author: Hanjun Guo <hanjun.guo at linaro.org>
++ *   Author: Graeme Gregory <graeme.gregory at linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _ASM_ACENV_H
++#define _ASM_ACENV_H
++
++/* It is required unconditionally by ACPI core, update it when needed. */
++
++#endif /* _ASM_ACENV_H */
+diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
+new file mode 100644
+index 0000000..7f6cd91
+--- /dev/null
++++ b/arch/arm64/include/asm/acpi.h
+@@ -0,0 +1,99 @@
++/*
++ *  Copyright (C) 2013-2014, Linaro Ltd.
++ *	Author: Al Stone <al.stone at linaro.org>
++ *	Author: Graeme Gregory <graeme.gregory at linaro.org>
++ *	Author: Hanjun Guo <hanjun.guo at linaro.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation;
++ */
++
++#ifndef _ASM_ACPI_H
++#define _ASM_ACPI_H
++
++#include <asm/smp_plat.h>
++
++/* Basic configuration for ACPI */
++#ifdef	CONFIG_ACPI
++#define acpi_strict 1	/* No out-of-spec workarounds on ARM64 */
++extern int acpi_disabled;
++extern int acpi_noirq;
++extern int acpi_pci_disabled;
++
++/* 1 to indicate PSCI 0.2+ is implemented */
++static inline bool acpi_psci_present(void)
++{
++	return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;
++}
++
++/* 1 to indicate HVC must be used instead of SMC as the PSCI conduit */
++static inline bool acpi_psci_use_hvc(void)
++{
++	return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
++}
++
++static inline void disable_acpi(void)
++{
++	acpi_disabled = 1;
++	acpi_pci_disabled = 1;
++	acpi_noirq = 1;
++}
++
++/* MPIDR value provided in GICC structure is 64 bits, but
++ * the acpi processor driver use the 32 bits cpu hardware
++ * ID (apic_id on intel platform) everywhere, it is pretty
++ * hard to modify the acpi processor driver to accept the
++ * 64 bits MPIDR value, at the same time, only 32 bits of
++ * the MPIDR is used in the 64 bits MPIDR, just pack the
++ * Affx fields into a single 32 bit identifier to accommodate
++ * the acpi processor drivers.
++ */
++static inline u32 pack_mpidr_into_32_bits(u64 mpidr)
++{
++	/*
++	 * Bits [0:7] Aff0;
++	 * Bits [8:15] Aff1;
++	 * Bits [16:23] Aff2;
++	 * Bits [32:39] Aff3;
++	 */
++	return (u32) ((mpidr & 0xff00000000) >> 8) | mpidr;
++}
++
++/*
++ * The ACPI processor driver for ACPI core code needs this macro
++ * to find out this cpu was already mapped (mapping from CPU hardware
++ * ID to CPU logical ID) or not.
++ *
++ * cpu_logical_map(cpu) is the mapping of MPIDR and the logical cpu,
++ * and MPIDR is the cpu hardware ID we needed to pack.
++ */
++#define cpu_physical_id(cpu) pack_mpidr_into_32_bits(cpu_logical_map(cpu))
++
++/*
++ * It's used from ACPI core in kdump to boot UP system with SMP kernel,
++ * with this check the ACPI core will not override the CPU index
++ * obtained from GICC with 0 and not print some error message as well.
++ * Since MADT must provide at least one GICC structure for GIC
++ * initialization, CPU will be always available in MADT on ARM64.
++ */
++static inline bool acpi_has_cpu_in_madt(void)
++{
++	return true;
++}
++
++static inline void arch_fix_phys_package_id(int num, u32 slot) { }
++void __init acpi_smp_init_cpus(void);
++
++extern int acpi_get_cpu_parked_address(int cpu, u64 *addr);
++
++#else
++
++static inline bool acpi_psci_present(void) { return false; }
++static inline bool acpi_psci_use_hvc(void) { return false; }
++static inline void acpi_smp_init_cpus(void) { }
++static inline int  acpi_get_cpu_parked_address(int cpu, u64 *addr) { return  -EOPNOTSUPP; }
++
++#endif /* CONFIG_ACPI */
++
++#endif /*_ASM_ACPI_H*/
+diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
+index d7b4b38..d149580 100644
+--- a/arch/arm64/include/asm/cpu_ops.h
++++ b/arch/arm64/include/asm/cpu_ops.h
+@@ -61,6 +61,7 @@ struct cpu_operations {
+ };
+ 
+ extern const struct cpu_operations *cpu_ops[NR_CPUS];
++const struct cpu_operations *cpu_get_ops(const char *name);
+ extern int __init cpu_read_ops(struct device_node *dn, int cpu);
+ extern void __init cpu_read_bootcpu_ops(void);
+ 
 diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
 index 01d3aab..8186df6 100644
 --- a/arch/arm64/include/asm/elf.h
@@ -448,7 +1040,7 @@ index 01d3aab..8186df6 100644
  #define CORE_DUMP_USE_REGSET
  #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
-index e0ecdcf..dc34039 100644
+index e0ecdcf..f998d90 100644
 --- a/arch/arm64/include/asm/io.h
 +++ b/arch/arm64/include/asm/io.h
 @@ -121,7 +121,8 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
@@ -457,16 +1049,162 @@ index e0ecdcf..dc34039 100644
   */
 -#define IO_SPACE_LIMIT		0xffff
 +#define arch_has_dev_port()	(1)
-+#define IO_SPACE_LIMIT		0x1ffffff
++#define IO_SPACE_LIMIT		(SZ_32M - 1)
  #define PCI_IOBASE		((void __iomem *)(MODULES_VADDR - SZ_32M))
  
  static inline u8 inb(unsigned long addr)
+diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
+index cc83520..ff4a4fa 100644
+--- a/arch/arm64/include/asm/kvm_arm.h
++++ b/arch/arm64/include/asm/kvm_arm.h
+@@ -95,7 +95,6 @@
+ /* TCR_EL2 Registers bits */
+ #define TCR_EL2_TBI	(1 << 20)
+ #define TCR_EL2_PS	(7 << 16)
+-#define TCR_EL2_PS_40B	(2 << 16)
+ #define TCR_EL2_TG0	(1 << 14)
+ #define TCR_EL2_SH0	(3 << 12)
+ #define TCR_EL2_ORGN0	(3 << 10)
+@@ -104,8 +103,6 @@
+ #define TCR_EL2_MASK	(TCR_EL2_TG0 | TCR_EL2_SH0 | \
+ 			 TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ)
+ 
+-#define TCR_EL2_FLAGS	(TCR_EL2_PS_40B)
+-
+ /* VTCR_EL2 Registers bits */
+ #define VTCR_EL2_PS_MASK	(7 << 16)
+ #define VTCR_EL2_TG0_MASK	(1 << 14)
+@@ -120,36 +117,28 @@
+ #define VTCR_EL2_SL0_MASK	(3 << 6)
+ #define VTCR_EL2_SL0_LVL1	(1 << 6)
+ #define VTCR_EL2_T0SZ_MASK	0x3f
+-#define VTCR_EL2_T0SZ_40B	24
++#define VTCR_EL2_T0SZ(bits)	(64 - (bits))
+ 
+ #ifdef CONFIG_ARM64_64K_PAGES
+ /*
+  * Stage2 translation configuration:
+- * 40bits output (PS = 2)
+- * 40bits input  (T0SZ = 24)
+  * 64kB pages (TG0 = 1)
+  * 2 level page tables (SL = 1)
+  */
+ #define VTCR_EL2_FLAGS		(VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \
+ 				 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
+-				 VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B)
+-#define VTTBR_X		(38 - VTCR_EL2_T0SZ_40B)
++				 VTCR_EL2_SL0_LVL1)
+ #else
+ /*
+  * Stage2 translation configuration:
+- * 40bits output (PS = 2)
+- * 40bits input  (T0SZ = 24)
+  * 4kB pages (TG0 = 0)
+  * 3 level page tables (SL = 1)
+  */
+ #define VTCR_EL2_FLAGS		(VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \
+ 				 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
+-				 VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B)
+-#define VTTBR_X		(37 - VTCR_EL2_T0SZ_40B)
++				 VTCR_EL2_SL0_LVL1)
+ #endif
+ 
+-#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
+-#define VTTBR_BADDR_MASK  (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
+ #define VTTBR_VMID_SHIFT  (48LLU)
+ #define VTTBR_VMID_MASK	  (0xffLLU << VTTBR_VMID_SHIFT)
+ 
+diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
+index 8e138c7..1c70b2f 100644
+--- a/arch/arm64/include/asm/kvm_mmu.h
++++ b/arch/arm64/include/asm/kvm_mmu.h
+@@ -167,5 +167,80 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
+ 
+ void stage2_flush_vm(struct kvm *kvm);
+ 
++/*
++ * ARMv8 64K architecture limitations:
++ * 16 <= T0SZ <= 21 is valid under 3 level of translation tables
++ * 18 <= T0SZ <= 34 is valid under 2 level of translation tables
++ * 31 <= T0SZ <= 39 is valid under 1 level of transltaion tables
++ *
++ * ARMv8 4K architecture limitations:
++ * 16 <= T0SZ <= 24 is valid under 4 level of translation tables
++ * 21 <= T0SZ <= 33 is valid under 3 level of translation tables
++ * 30 <= T0SZ <= 39 is valid under 2 level of translation tables
++ *
++ * For 4K pages we only support 3 or 4 level, giving T0SZ a range of 16 to 33.
++ * For 64K pages we only support 2 or 3 level, giving T0SZ a range of 16 to 34.
++ *
++ * See Table D4-23 and Table D4-25 in ARM DDI 0487A.b to figure out
++ * the origin of the hardcoded values, 38 and 37.
++ */
++
++#ifdef CONFIG_ARM64_64K_PAGES
++static inline int t0sz_to_vttbr_x(int t0sz)
++{
++	if (t0sz < 16 || t0sz > 34) {
++		kvm_err("Cannot support %d-bit address space\n", 64 - t0sz);
++		return -EINVAL;
++	}
++
++	return 38 - t0sz;
++}
++#else /* 4K pages */
++static inline int t0sz_to_vttbr_x(int t0sz)
++{
++	if (t0sz < 16 || t0sz > 33) {
++		kvm_err("Cannot support %d-bit address space\n", 64 - t0sz);
++		return -EINVAL;
++	}
++	return 37 - t0sz;
++}
++#endif
++static inline int kvm_get_phys_addr_shift(void)
++{
++	int pa_range = read_cpuid(ID_AA64MMFR0_EL1) & 0xf;
++
++	switch (pa_range) {
++	case 0: return 32;
++	case 1: return 36;
++	case 2: return 40;
++	case 3: return 42;
++	case 4: return 44;
++	case 5: return 48;
++	default:
++		BUG();
++		return 0;
++	}
++}
++
++/**
++ * get_vttbr_baddr_mask - get mask value for vttbr base address
++ *
++ * In ARMv8, vttbr_baddr_mask cannot be determined in compile time since the
++ * stage2 input address size depends on hardware capability. Thus, we first
++ * need to read ID_AA64MMFR0_EL1.PARange and then set vttbr_baddr_mask with
++ * consideration of both the granule size and the level of translation tables.
++ */
++static inline u64 get_vttbr_baddr_mask(void)
++{
++	int t0sz, vttbr_x;
++
++	t0sz = VTCR_EL2_T0SZ(kvm_get_phys_addr_shift());
++	vttbr_x = t0sz_to_vttbr_x(t0sz);
++	if (vttbr_x < 0)
++		return ~0;
++	return GENMASK_ULL(48, (vttbr_x - 1));
++
++}
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* __ARM64_KVM_MMU_H__ */
 diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
 new file mode 100644
-index 0000000..3f7856e
+index 0000000..872ba93
 --- /dev/null
 +++ b/arch/arm64/include/asm/pci.h
-@@ -0,0 +1,49 @@
+@@ -0,0 +1,37 @@
 +#ifndef __ASM_PCI_H
 +#define __ASM_PCI_H
 +#ifdef __KERNEL__
@@ -482,8 +1220,6 @@ index 0000000..3f7856e
 +#define PCIBIOS_MIN_IO		0x1000
 +#define PCIBIOS_MIN_MEM		0
 +
-+struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus);
-+
 +/*
 + * Set to 1 if the kernel should re-assign all PCI bus numbers
 + */
@@ -498,17 +1234,7 @@ index 0000000..3f7856e
 +extern int isa_dma_bridge_buggy;
 +
 +#ifdef CONFIG_PCI
-+static inline int pci_domain_nr(struct pci_bus *bus)
-+{
-+	struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
-+
-+	if (bridge)
-+		return bridge->domain_nr;
-+
-+	return 0;
-+}
-+
-+static inline int pci_proc_domain(struct pci_bus *bus)
++static inline int pci_proc_domain(struct pci_bus *bus)
 +{
 +	return 1;
 +}
@@ -516,18 +1242,517 @@ index 0000000..3f7856e
 +
 +#endif  /* __KERNEL__ */
 +#endif  /* __ASM_PCI_H */
+diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
+index ffe1ba0..a968523 100644
+--- a/arch/arm64/include/asm/pgtable.h
++++ b/arch/arm64/include/asm/pgtable.h
+@@ -296,6 +296,8 @@ static inline int has_transparent_hugepage(void)
+ 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
+ #define pgprot_writecombine(prot) \
+ 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
++#define pgprot_device(prot) \
++	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN)
+ #define __HAVE_PHYS_MEM_ACCESS_PROT
+ struct file;
+ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
+index e5312ea..2454bc5 100644
+--- a/arch/arm64/include/asm/psci.h
++++ b/arch/arm64/include/asm/psci.h
+@@ -14,6 +14,7 @@
+ #ifndef __ASM_PSCI_H
+ #define __ASM_PSCI_H
+ 
+-int psci_init(void);
++int psci_dt_init(void);
++int psci_acpi_init(void);
+ 
+ #endif /* __ASM_PSCI_H */
+diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
+index a498f2c..2ebbd55 100644
+--- a/arch/arm64/include/asm/smp.h
++++ b/arch/arm64/include/asm/smp.h
+@@ -39,9 +39,10 @@ extern void show_ipi_list(struct seq_file *p, int prec);
+ extern void handle_IPI(int ipinr, struct pt_regs *regs);
+ 
+ /*
+- * Setup the set of possible CPUs (via set_cpu_possible)
++ * Discover the set of possible CPUs and determine their
++ * SMP operations.
+  */
+-extern void smp_init_cpus(void);
++extern void of_smp_init_cpus(void);
+ 
+ /*
+  * Provide a function to raise an IPI cross call on CPUs in callmap.
+@@ -49,6 +50,11 @@ extern void smp_init_cpus(void);
+ extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
+ 
+ /*
++ * Provide a function to signal a parked secondary CPU.
++ */
++extern void set_smp_boot_wakeup_call(void (*)(int cpu));
++
++/*
+  * Called from the secondary holding pen, this is the secondary CPU entry point.
+  */
+ asmlinkage void secondary_start_kernel(void);
 diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
-index df7ef87..1ed5a06 100644
+index df7ef87..b0bad2e 100644
 --- a/arch/arm64/kernel/Makefile
 +++ b/arch/arm64/kernel/Makefile
-@@ -29,6 +29,7 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
+@@ -21,7 +21,8 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
+ 					   sys_compat.o
+ arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
+ arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+-arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o topology.o
++arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o topology.o \
++					   smp_parking_protocol.o
+ arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
+ arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
+ arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
+@@ -29,6 +30,8 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)	+= sleep.o suspend.o
  arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
  arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
  arm64-obj-$(CONFIG_EFI)			+= efi.o efi-stub.o efi-entry.o
 +arm64-obj-$(CONFIG_PCI)			+= pci.o
++arm64-obj-$(CONFIG_ACPI)		+= acpi.o
  
  obj-y					+= $(arm64-obj-y) vdso/
  obj-m					+= $(arm64-obj-m)
+diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
+new file mode 100644
+index 0000000..5486426
+--- /dev/null
++++ b/arch/arm64/kernel/acpi.c
+@@ -0,0 +1,397 @@
++/*
++ *  ARM64 Specific Low-Level ACPI Boot Support
++ *
++ *  Copyright (C) 2013-2014, Linaro Ltd.
++ *	Author: Al Stone <al.stone at linaro.org>
++ *	Author: Graeme Gregory <graeme.gregory at linaro.org>
++ *	Author: Hanjun Guo <hanjun.guo at linaro.org>
++ *	Author: Tomasz Nowicki <tomasz.nowicki at linaro.org>
++ *	Author: Naresh Bhat <naresh.bhat at linaro.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#define pr_fmt(fmt) "ACPI: " fmt
++
++#include <linux/init.h>
++#include <linux/acpi.h>
++#include <linux/cpumask.h>
++#include <linux/memblock.h>
++#include <linux/irq.h>
++#include <linux/irqdomain.h>
++#include <linux/bootmem.h>
++#include <linux/smp.h>
++#include <linux/irqchip/arm-gic-acpi.h>
++
++#include <asm/cputype.h>
++#include <asm/cpu_ops.h>
++
++#define ARM64_ACPI_DISABLED_DEFAULT 1
++
++int acpi_noirq;			/* skip ACPI IRQ initialization */
++int acpi_disabled = ARM64_ACPI_DISABLED_DEFAULT;
++EXPORT_SYMBOL(acpi_disabled);
++
++int acpi_pci_disabled;		/* skip ACPI PCI scan and IRQ initialization */
++EXPORT_SYMBOL(acpi_pci_disabled);
++
++static int enabled_cpus;	/* Processors (GICC) with enabled flag in MADT */
++
++static char *boot_method;
++static u64 parked_address[NR_CPUS];
++
++/*
++ * Since we're on ARM, the default interrupt routing model
++ * clearly has to be GIC.
++ */
++enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_GIC;
++
++/*
++ * __acpi_map_table() will be called before page_init(), so early_ioremap()
++ * or early_memremap() should be called here to for ACPI table mapping.
++ */
++char *__init __acpi_map_table(unsigned long phys, unsigned long size)
++{
++	if (!phys || !size)
++		return NULL;
++
++	return early_memremap(phys, size);
++}
++
++void __init __acpi_unmap_table(char *map, unsigned long size)
++{
++	if (!map || !size)
++		return;
++
++	early_memunmap(map, size);
++}
++
++/**
++ * acpi_map_gic_cpu_interface - generates a logical cpu number
++ * and map to MPIDR represented by GICC structure
++ * @mpidr: CPU's hardware id to register, MPIDR represented in MADT
++ * @enabled: this cpu is enabled or not
++ *
++ * Returns the logical cpu number which maps to MPIDR
++ */
++static int acpi_map_gic_cpu_interface(u64 mpidr, u64 parked_addr, u8 enabled)
++{
++	int cpu;
++
++	if (mpidr == INVALID_HWID) {
++		pr_info("Skip invalid cpu hardware ID\n");
++		return -EINVAL;
++	}
++
++	total_cpus++;
++	if (!enabled)
++		return -EINVAL;
++
++	if (enabled_cpus >=  NR_CPUS) {
++		pr_warn("NR_CPUS limit of %d reached, Processor %d/0x%llx ignored.\n",
++			NR_CPUS, total_cpus, mpidr);
++		return -EINVAL;
++	}
++
++	/* No need to check duplicate MPIDRs for the first CPU */
++	if (enabled_cpus) {
++		/*
++		 * Duplicate MPIDRs are a recipe for disaster. Scan
++		 * all initialized entries and check for
++		 * duplicates. If any is found just ignore the CPU.
++		 */
++		for_each_possible_cpu(cpu) {
++			if (cpu_logical_map(cpu) == mpidr) {
++				pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n",
++				mpidr);
++				return -EINVAL;
++			}
++		}
++		
++		/* allocate a logical cpu id for the new comer */
++		cpu = cpumask_next_zero(-1, cpu_possible_mask);
++	} else {
++		/* First GICC entry must be BSP as ACPI spec said */
++		if  (cpu_logical_map(0) != mpidr) {
++			pr_err("First GICC entry with MPIDR 0x%llx is not BSP\n",
++			       mpidr);
++			return -EINVAL;
++		}
++
++		/*
++		 * boot_cpu_init() already hold bit 0 in cpu_present_mask
++		 * for BSP, no need to allocate again.
++		 */
++		cpu = 0;
++	}
++
++	parked_address[cpu] = parked_addr;
++
++	/* CPU 0 was already initialized */
++	if (cpu) {
++		cpu_ops[cpu] = cpu_get_ops(boot_method);
++		if (!cpu_ops[cpu])
++			return -EINVAL;
++
++		if (cpu_ops[cpu]->cpu_init(NULL, cpu))
++			return -EOPNOTSUPP;
++
++		/* map the logical cpu id to cpu MPIDR */
++		cpu_logical_map(cpu) = mpidr;
++
++		set_cpu_possible(cpu, true);
++	} else {
++		/* get cpu0's ops, no need to return if ops is null */
++		cpu_ops[0] = cpu_get_ops(boot_method);
++	}
++
++	enabled_cpus++;
++	return cpu;
++}
++
++static int __init
++acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
++				const unsigned long end)
++{
++	struct acpi_madt_generic_interrupt *processor;
++
++	processor = (struct acpi_madt_generic_interrupt *)header;
++
++	if (BAD_MADT_ENTRY(processor, end))
++		return -EINVAL;
++
++	acpi_table_print_madt_entry(header);
++
++	acpi_map_gic_cpu_interface(processor->arm_mpidr & MPIDR_HWID_BITMASK,
++		processor->parked_address, processor->flags & ACPI_MADT_ENABLED);
++
++	return 0;
++}
++
++/* Parse GIC cpu interface entries in MADT for SMP init */
++void __init acpi_smp_init_cpus(void)
++{
++	int count;
++
++	/*
++	 * do a partial walk of MADT to determine how many CPUs
++	 * we have including disabled CPUs, and get information
++	 * we need for SMP init
++	 */
++	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
++			acpi_parse_gic_cpu_interface, 0);
++
++	if (!count) {
++		pr_err("No GIC CPU interface entries present\n");
++		return;
++	} else if (count < 0) {
++		pr_err("Error parsing GIC CPU interface entry\n");
++		return;
++	}
++
++	/* Make boot-up look pretty */
++	pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus);
++}
++
++int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
++{
++	*irq = irq_find_mapping(NULL, gsi);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
++
++/*
++ * success: return IRQ number (>0)
++ * failure: return =< 0
++ */
++int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
++{
++	unsigned int irq;
++	unsigned int irq_type;
++
++	/*
++	 * ACPI have no bindings to indicate SPI or PPI, so we
++	 * use different mappings from DT in ACPI.
++	 *
++	 * For FDT
++	 * PPI interrupt: in the range [0, 15];
++	 * SPI interrupt: in the range [0, 987];
++	 *
++	 * For ACPI, GSI should be unique so using
++	 * the hwirq directly for the mapping:
++	 * PPI interrupt: in the range [16, 31];
++	 * SPI interrupt: in the range [32, 1019];
++	 */
++
++	if (trigger == ACPI_EDGE_SENSITIVE &&
++				polarity == ACPI_ACTIVE_LOW)
++		irq_type = IRQ_TYPE_EDGE_FALLING;
++	else if (trigger == ACPI_EDGE_SENSITIVE &&
++				polarity == ACPI_ACTIVE_HIGH)
++		irq_type = IRQ_TYPE_EDGE_RISING;
++	else if (trigger == ACPI_LEVEL_SENSITIVE &&
++				polarity == ACPI_ACTIVE_LOW)
++		irq_type = IRQ_TYPE_LEVEL_LOW;
++	else if (trigger == ACPI_LEVEL_SENSITIVE &&
++				polarity == ACPI_ACTIVE_HIGH)
++		irq_type = IRQ_TYPE_LEVEL_HIGH;
++	else
++		irq_type = IRQ_TYPE_NONE;
++
++	/*
++	 * Since only one GIC is supported in ACPI 5.0, we can
++	 * create mapping refer to the default domain
++	 */
++	irq = irq_create_mapping(NULL, gsi);
++	if (!irq)
++		return irq;
++
++	/* Set irq type if specified and different than the current one */
++	if (irq_type != IRQ_TYPE_NONE &&
++		irq_type != irq_get_trigger_type(irq))
++		irq_set_irq_type(irq, irq_type);
++	return irq;
++}
++EXPORT_SYMBOL_GPL(acpi_register_gsi);
++
++void acpi_unregister_gsi(u32 gsi)
++{
++}
++EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
++
++static int __init acpi_parse_fadt(struct acpi_table_header *table)
++{
++	struct acpi_table_fadt *fadt = (struct acpi_table_fadt *)table;
++
++	/*
++	 * Revision in table header is the FADT Major revision,
++	 * and there is a minor revision of FADT which was introduced
++	 * by ACPI 5.1, we only deal with ACPI 5.1 or higher revision
++	 * to get arm boot flags, or we will disable ACPI.
++	 */
++	if (table->revision > 5 ||
++	    (table->revision == 5 && fadt->minor_revision >= 1)) {
++		/*
++		 * ACPI 5.1 only has two explicit methods to boot up SMP,
++		 * PSCI and Parking protocol, but the Parking protocol is
++		 * only specified for ARMv7 now, so make PSCI as the only
++		 * way for the SMP boot protocol before some updates for
++		 * the ACPI spec or the Parking protocol spec.
++		 */
++		if (acpi_psci_present())
++			boot_method = "psci";
++		else if (IS_ENABLED(CONFIG_ARM_PARKING_PROTOCOL))
++			boot_method = "parking-protocol";
++
++		if (!boot_method)
++			pr_warn("has no boot support, will not bring up secondary CPUs\n");
++		return -EOPNOTSUPP;
++	}
++
++	pr_warn("Unsupported FADT revision %d.%d, should be 5.1+, will disable ACPI\n",
++		table->revision, fadt->minor_revision);
++	disable_acpi();
++
++	return -EINVAL;
++}
++
++/*
++ * acpi_boot_table_init() called from setup_arch(), always.
++ *	1. find RSDP and get its address, and then find XSDT
++ *	2. extract all tables and checksums them all
++ *	3. check ACPI FADT revisoin
++ *
++ * We can parse ACPI boot-time tables such as MADT after
++ * this function is called.
++ */
++void __init acpi_boot_table_init(void)
++{
++	/* If acpi_disabled, bail out */
++	if (acpi_disabled)
++		return;
++
++	/* Initialize the ACPI boot-time table parser. */
++	if (acpi_table_init()) {
++		disable_acpi();
++		return;
++	}
++
++	if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
++		pr_err("Can't find FADT or error happened during parsing FADT\n");
++}
++
++void __init acpi_gic_init(void)
++{
++	struct acpi_table_header *table;
++	acpi_status status;
++	acpi_size tbl_size;
++	int err;
++
++	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
++	if (ACPI_FAILURE(status)) {
++		const char *msg = acpi_format_exception(status);
++
++		pr_err("Failed to get MADT table, %s\n", msg);
++		return;
++	}
++
++	err = gic_v2_acpi_init(table);
++	if (err)
++		pr_err("Failed to initialize GIC IRQ controller");
++
++	early_acpi_os_unmap_memory((char *)table, tbl_size);
++}
++
++/*
++ * Parked Address in ACPI GIC structure will be used as the CPU
++ * release address
++ */
++int acpi_get_cpu_parked_address(int cpu, u64 *addr)
++{
++	if (!addr || !parked_address[cpu])
++		return -EINVAL;
++
++	*addr = parked_address[cpu];
++
++	return 0;
++}
++
++static int __init parse_acpi(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
++
++	/* "acpi=off" disables both ACPI table parsing and interpreter */
++	if (strcmp(arg, "off") == 0)
++		acpi_disabled = 1;
++	else if (strcmp(arg, "on") == 0)
++		acpi_disabled = 0;
++	else
++		return -EINVAL;	/* Core will print when we return error */
++
++	return 0;
++}
++early_param("acpi", parse_acpi);
++
++int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
++{
++	return -1;
++}
++
++int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
++{
++	/* TBD */
++	return -EINVAL;
++}
++EXPORT_SYMBOL(acpi_register_ioapic);
++
++int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
++{
++	/* TBD */
++	return -EINVAL;
++}
++EXPORT_SYMBOL(acpi_unregister_ioapic);
++
+diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
+index cce9524..1d90f31 100644
+--- a/arch/arm64/kernel/cpu_ops.c
++++ b/arch/arm64/kernel/cpu_ops.c
+@@ -23,19 +23,23 @@
+ #include <linux/string.h>
+ 
+ extern const struct cpu_operations smp_spin_table_ops;
++extern const struct cpu_operations smp_parking_protocol_ops;
+ extern const struct cpu_operations cpu_psci_ops;
+ 
+ const struct cpu_operations *cpu_ops[NR_CPUS];
+ 
+-static const struct cpu_operations *supported_cpu_ops[] __initconst = {
++static const struct cpu_operations *supported_cpu_ops[] = {
+ #ifdef CONFIG_SMP
+ 	&smp_spin_table_ops,
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++	&smp_parking_protocol_ops,
++#endif
+ #endif
+ 	&cpu_psci_ops,
+ 	NULL,
+ };
+ 
+-static const struct cpu_operations * __init cpu_get_ops(const char *name)
++const struct cpu_operations *cpu_get_ops(const char *name)
+ {
+ 	const struct cpu_operations **ops = supported_cpu_ops;
+ 
 diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
 index 1317fef..d27dd98 100644
 --- a/arch/arm64/kernel/efi-stub.c
@@ -560,10 +1785,10 @@ index 1317fef..d27dd98 100644
  
  
 diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
-index e72f310..72ee260 100644
+index 03aaa99..6c4de44 100644
 --- a/arch/arm64/kernel/efi.c
 +++ b/arch/arm64/kernel/efi.c
-@@ -475,3 +475,14 @@ err_unmap:
+@@ -479,3 +479,14 @@ err_unmap:
  	return -1;
  }
  early_initcall(arm64_enter_virtual_mode);
@@ -579,7 +1804,7 @@ index e72f310..72ee260 100644
 +	return pm_power_off == NULL;
 +}
 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
-index 144f105..b6ca95a 100644
+index 8730690..0a6e4f9 100644
 --- a/arch/arm64/kernel/head.S
 +++ b/arch/arm64/kernel/head.S
 @@ -151,7 +151,7 @@ optional_header:
@@ -611,10 +1836,10 @@ index 144f105..b6ca95a 100644
  	.long	stext - efi_head	// PointerToRawData
 diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
 new file mode 100644
-index 0000000..955d6d1
+index 0000000..ce5836c
 --- /dev/null
 +++ b/arch/arm64/kernel/pci.c
-@@ -0,0 +1,38 @@
+@@ -0,0 +1,70 @@
 +/*
 + * Code borrowed from powerpc/kernel/pci-common.c
 + *
@@ -653,8 +1878,40 @@ index 0000000..955d6d1
 +{
 +	return res->start;
 +}
++
++/*
++ * Try to assign the IRQ number from DT when adding a new device
++ */
++int pcibios_add_device(struct pci_dev *dev)
++{
++	dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
++
++	return 0;
++}
++
++
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++static bool dt_domain_found = false;
++
++void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
++{
++	int domain = of_get_pci_domain_nr(parent->of_node);
++
++	if (domain >= 0) {
++		dt_domain_found = true;
++	} else if (dt_domain_found == true) {
++		dev_err(parent, "Node %s is missing \"linux,pci-domain\" property in DT\n",
++			parent->of_node->full_name);
++		return;
++	} else {
++		domain = pci_get_new_domain_nr();
++	}
++
++	bus->domain_nr = domain;
++}
++#endif
 diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
-index 1309d64..8ff5208 100644
+index 29d4869..c0427bc 100644
 --- a/arch/arm64/kernel/process.c
 +++ b/arch/arm64/kernel/process.c
 @@ -43,6 +43,7 @@
@@ -677,29 +1934,366 @@ index 1309d64..8ff5208 100644
  	 * Whoops - the architecture was unable to reboot.
  	 */
  	printk("Reboot failed -- System halted\n");
-diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
-index 0347d38..70181c1 100644
---- a/arch/arm64/kernel/smp_spin_table.c
-+++ b/arch/arm64/kernel/smp_spin_table.c
-@@ -20,6 +20,7 @@
+diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
+index 5539547..15ba470 100644
+--- a/arch/arm64/kernel/psci.c
++++ b/arch/arm64/kernel/psci.c
+@@ -15,6 +15,7 @@
+ 
+ #define pr_fmt(fmt) "psci: " fmt
+ 
++#include <linux/acpi.h>
  #include <linux/init.h>
  #include <linux/of.h>
  #include <linux/smp.h>
-+#include <linux/types.h>
+@@ -23,6 +24,7 @@
+ #include <linux/delay.h>
+ #include <uapi/linux/psci.h>
  
- #include <asm/cacheflush.h>
++#include <asm/acpi.h>
+ #include <asm/compiler.h>
  #include <asm/cpu_ops.h>
-@@ -65,12 +66,21 @@ static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
+ #include <asm/errno.h>
+@@ -231,6 +233,33 @@ static void psci_sys_poweroff(void)
+ 	invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+ }
  
- static int smp_spin_table_cpu_prepare(unsigned int cpu)
- {
--	void **release_addr;
-+	__le64 __iomem *release_addr;
++static void psci_0_2_set_functions(void)
++{
++	pr_info("Using standard PSCI v0.2 function IDs\n");
++	psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
++	psci_ops.cpu_suspend = psci_cpu_suspend;
++
++	psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
++	psci_ops.cpu_off = psci_cpu_off;
++
++	psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
++	psci_ops.cpu_on = psci_cpu_on;
++
++	psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
++	psci_ops.migrate = psci_migrate;
++
++	psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
++	psci_ops.affinity_info = psci_affinity_info;
++
++	psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
++		PSCI_0_2_FN_MIGRATE_INFO_TYPE;
++	psci_ops.migrate_info_type = psci_migrate_info_type;
++
++	arm_pm_restart = psci_sys_reset;
++
++	pm_power_off = psci_sys_poweroff;
++}
++
+ /*
+  * PSCI Function IDs for v0.2+ are well defined so use
+  * standard values.
+@@ -264,29 +293,7 @@ static int __init psci_0_2_init(struct device_node *np)
+ 		}
+ 	}
  
- 	if (!cpu_release_addr[cpu])
- 		return -ENODEV;
+-	pr_info("Using standard PSCI v0.2 function IDs\n");
+-	psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
+-	psci_ops.cpu_suspend = psci_cpu_suspend;
+-
+-	psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
+-	psci_ops.cpu_off = psci_cpu_off;
+-
+-	psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
+-	psci_ops.cpu_on = psci_cpu_on;
+-
+-	psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN64_MIGRATE;
+-	psci_ops.migrate = psci_migrate;
+-
+-	psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN64_AFFINITY_INFO;
+-	psci_ops.affinity_info = psci_affinity_info;
+-
+-	psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] =
+-		PSCI_0_2_FN_MIGRATE_INFO_TYPE;
+-	psci_ops.migrate_info_type = psci_migrate_info_type;
+-
+-	arm_pm_restart = psci_sys_reset;
+-
+-	pm_power_off = psci_sys_poweroff;
++	psci_0_2_set_functions();
  
--	release_addr = __va(cpu_release_addr[cpu]);
+ out_put_node:
+ 	of_node_put(np);
+@@ -339,7 +346,7 @@ static const struct of_device_id psci_of_match[] __initconst = {
+ 	{},
+ };
+ 
+-int __init psci_init(void)
++int __init psci_dt_init(void)
+ {
+ 	struct device_node *np;
+ 	const struct of_device_id *matched_np;
+@@ -354,6 +361,29 @@ int __init psci_init(void)
+ 	return init_fn(np);
+ }
+ 
++/*
++ * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
++ * explicitly clarified in SBBR
++ */
++int __init psci_acpi_init(void)
++{
++	if (!acpi_psci_present()) {
++		pr_info("is not implemented in ACPI.\n");
++		return -EOPNOTSUPP;
++	}
++
++	pr_info("probing for conduit method from ACPI.\n");
++
++	if (acpi_psci_use_hvc())
++		invoke_psci_fn = __invoke_psci_fn_hvc;
++	else
++		invoke_psci_fn = __invoke_psci_fn_smc;
++
++	psci_0_2_set_functions();
++
++	return 0;
++}
++
+ #ifdef CONFIG_SMP
+ 
+ static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
+diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
+index edb146d..4758443 100644
+--- a/arch/arm64/kernel/setup.c
++++ b/arch/arm64/kernel/setup.c
+@@ -43,6 +43,7 @@
+ #include <linux/of_fdt.h>
+ #include <linux/of_platform.h>
+ #include <linux/efi.h>
++#include <linux/acpi.h>
+ 
+ #include <asm/fixmap.h>
+ #include <asm/cpu.h>
+@@ -59,6 +60,10 @@
+ #include <asm/memblock.h>
+ #include <asm/psci.h>
+ #include <asm/efi.h>
++#include <asm/acpi.h>
++
++int acadia_kvm_acpi=0;
++EXPORT_SYMBOL(acadia_kvm_acpi);
+ 
+ unsigned int processor_id;
+ EXPORT_SYMBOL(processor_id);
+@@ -385,22 +390,34 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	parse_early_param();
+ 
++	if (acpi_disabled)
++		disable_acpi();
++
+ 	efi_init();
+ 	arm64_memblock_init();
+ 
++	/* Parse the ACPI tables for possible boot-time configuration */
++	acpi_boot_table_init();
++
+ 	paging_init();
+ 	request_standard_resources();
+ 
+ 	efi_idmap_init();
+ 
+-	unflatten_device_tree();
+-
+-	psci_init();
+-
+ 	cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
+-	cpu_read_bootcpu_ops();
++	if (acpi_disabled) {
++		unflatten_device_tree();
++		psci_dt_init();
++		cpu_read_bootcpu_ops();
++#ifdef CONFIG_SMP
++		of_smp_init_cpus();
++#endif
++	} else {
++		psci_acpi_init();
++		acpi_smp_init_cpus();
++	}
++
+ #ifdef CONFIG_SMP
+-	smp_init_cpus();
+ 	smp_build_mpidr_hash();
+ #endif
+ 
+@@ -413,6 +430,19 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ }
+ 
++static int __init parse_kvm_acpi(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
++	
++	if (strcmp(arg, "on") == 0) {
++		acadia_kvm_acpi = 1;
++	}
++
++	return 0;
++}
++early_param("kvmacpi", parse_kvm_acpi);
++
+ static int __init arm64_device_init(void)
+ {
+ 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
+index 4743397..4e390ac 100644
+--- a/arch/arm64/kernel/smp.c
++++ b/arch/arm64/kernel/smp.c
+@@ -321,7 +321,7 @@ void __init smp_prepare_boot_cpu(void)
+  * cpu logical map array containing MPIDR values related to logical
+  * cpus. Assumes that cpu_logical_map(0) has already been initialized.
+  */
+-void __init smp_init_cpus(void)
++void __init of_smp_init_cpus(void)
+ {
+ 	struct device_node *dn = NULL;
+ 	unsigned int i, cpu = 1;
+diff --git a/arch/arm64/kernel/smp_parking_protocol.c b/arch/arm64/kernel/smp_parking_protocol.c
+new file mode 100644
+index 0000000..e1153ce
+--- /dev/null
++++ b/arch/arm64/kernel/smp_parking_protocol.c
+@@ -0,0 +1,110 @@
++/*
++ * Parking Protocol SMP initialisation
++ *
++ * Based largely on spin-table method.
++ *
++ * Copyright (C) 2013 ARM Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/of.h>
++#include <linux/smp.h>
++#include <linux/types.h>
++#include <linux/acpi.h>
++
++#include <asm/cacheflush.h>
++#include <asm/cpu_ops.h>
++#include <asm/cputype.h>
++#include <asm/smp_plat.h>
++
++static phys_addr_t cpu_mailbox_addr[NR_CPUS];
++
++static void (*__smp_boot_wakeup)(int cpu);
++
++void set_smp_boot_wakeup_call(void (*fn)(int cpu))
++{
++	__smp_boot_wakeup = fn;
++}
++
++static int smp_parking_protocol_cpu_init(struct device_node *dn,
++					 unsigned int cpu)
++{
++	/*
++	 * Determine the mailbox address.
++	 */
++	if (!acpi_get_cpu_parked_address(cpu, &cpu_mailbox_addr[cpu])) {
++		pr_info("%s: ACPI parked addr=%llx\n",
++			__func__, cpu_mailbox_addr[cpu]);
++		return 0;
++	}
++
++	pr_err("CPU %d: missing or invalid parking protocol mailbox\n", cpu);
++
++	return -1;
++}
++
++static int smp_parking_protocol_cpu_prepare(unsigned int cpu)
++{
++	return 0;
++}
++
++struct parking_protocol_mailbox {
++	__le32 cpu_id;
++	__le32 reserved;
++	__le64 entry_point;
++};
++
++static int smp_parking_protocol_cpu_boot(unsigned int cpu)
++{
++	struct parking_protocol_mailbox __iomem *mailbox;
++
++	if (!cpu_mailbox_addr[cpu] || !__smp_boot_wakeup)
++		return -ENODEV;
++
++	/*
++	 * The mailbox may or may not be inside the linear mapping.
++	 * As ioremap_cache will either give us a new mapping or reuse the
++	 * existing linear mapping, we can use it to cover both cases. In
++	 * either case the memory will be MT_NORMAL.
++	 */
++	mailbox = ioremap_cache(cpu_mailbox_addr[cpu], sizeof(*mailbox));
++	if (!mailbox)
++		return -ENOMEM;
++
++	/*
++	 * We write the entry point and cpu id as LE regardless of the
++	 * native endianess of the kernel. Therefore, any boot-loaders
++	 * that read this address need to convert this address to the
++	 * Boot-Loader's endianess before jumping.
++	 */
++	writeq(__pa(secondary_entry), &mailbox->entry_point);
++	writel(cpu, &mailbox->cpu_id);
++	__flush_dcache_area(mailbox, sizeof(*mailbox));
++	__smp_boot_wakeup(cpu);
++
++	/* temp hack for broken firmware */
++	sev();
++
++	iounmap(mailbox);
++
++	return 0;
++}
++
++const struct cpu_operations smp_parking_protocol_ops = {
++	.name		= "parking-protocol",
++	.cpu_init	= smp_parking_protocol_cpu_init,
++	.cpu_prepare	= smp_parking_protocol_cpu_prepare,
++	.cpu_boot	= smp_parking_protocol_cpu_boot,
++};
+diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
+index 0347d38..4f93c67 100644
+--- a/arch/arm64/kernel/smp_spin_table.c
++++ b/arch/arm64/kernel/smp_spin_table.c
+@@ -20,6 +20,7 @@
+ #include <linux/init.h>
+ #include <linux/of.h>
+ #include <linux/smp.h>
++#include <linux/types.h>
+ 
+ #include <asm/cacheflush.h>
+ #include <asm/cpu_ops.h>
+@@ -65,12 +66,21 @@ static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
+ 
+ static int smp_spin_table_cpu_prepare(unsigned int cpu)
+ {
+-	void **release_addr;
++	__le64 __iomem *release_addr;
+ 
+ 	if (!cpu_release_addr[cpu])
+ 		return -ENODEV;
+ 
+-	release_addr = __va(cpu_release_addr[cpu]);
 +	/*
 +	 * The cpu-release-addr may or may not be inside the linear mapping.
 +	 * As ioremap_cache will either give us a new mapping or reuse the
@@ -713,7 +2307,7 @@ index 0347d38..70181c1 100644
  
  	/*
  	 * We write the release address as LE regardless of the native
-@@ -79,15 +89,16 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu)
+@@ -79,15 +89,17 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu)
  	 * boot-loader's endianess before jumping. This is mandated by
  	 * the boot protocol.
  	 */
@@ -721,7 +2315,8 @@ index 0347d38..70181c1 100644
 -
 -	__flush_dcache_area(release_addr, sizeof(release_addr[0]));
 +	writeq_relaxed(__pa(secondary_holding_pen), release_addr);
-+	__flush_dcache_area(release_addr, sizeof(*release_addr));
++	__flush_dcache_area((__force void *)release_addr,
++			    sizeof(*release_addr));
  
  	/*
  	 * Send an event to wake up the secondary CPU.
@@ -733,872 +2328,1878 @@ index 0347d38..70181c1 100644
  	return 0;
  }
  
-diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
-index bc28111..00e5a0c 100644
---- a/drivers/ata/ahci_xgene.c
-+++ b/drivers/ata/ahci_xgene.c
-@@ -134,7 +134,8 @@ static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
- 	struct xgene_ahci_context *ctx = hpriv->plat_data;
- 	int rc = 0;
+diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
+index 1a7125c..42f9195 100644
+--- a/arch/arm64/kernel/time.c
++++ b/arch/arm64/kernel/time.c
+@@ -35,6 +35,7 @@
+ #include <linux/delay.h>
+ #include <linux/clocksource.h>
+ #include <linux/clk-provider.h>
++#include <linux/acpi.h>
  
--	if (unlikely(ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA))
-+	if (unlikely(ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA ||
-+		     ctx->last_cmd[ap->port_no] == ATA_CMD_SMART))
- 		xgene_ahci_restart_engine(ap);
+ #include <clocksource/arm_arch_timer.h>
  
- 	rc = ahci_qc_issue(qc);
-diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
-index 4b959e6..c36c7ab55 100644
---- a/drivers/irqchip/irq-gic.c
-+++ b/drivers/irqchip/irq-gic.c
-@@ -381,6 +381,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
- 	void __iomem *dist_base = gic_data_dist_base(gic);
- 	void __iomem *base = gic_data_cpu_base(gic);
- 	unsigned int cpu_mask, cpu = smp_processor_id();
-+	unsigned int ctrl_mask;
- 	int i;
+@@ -72,6 +73,12 @@ void __init time_init(void)
+ 
+ 	tick_setup_hrtimer_broadcast();
  
++	/*
++	 * Since ACPI or FDT will only one be available in the system,
++	 * we can use acpi_generic_timer_init() here safely
++	 */
++	acpi_generic_timer_init();
++
+ 	arch_timer_rate = arch_timer_get_rate();
+ 	if (!arch_timer_rate)
+ 		panic("Unable to initialise architected timer.\n");
+diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
+index c319116..fa7e67e 100644
+--- a/arch/arm64/kvm/hyp-init.S
++++ b/arch/arm64/kvm/hyp-init.S
+@@ -63,17 +63,21 @@ __do_hyp_init:
+ 	mrs	x4, tcr_el1
+ 	ldr	x5, =TCR_EL2_MASK
+ 	and	x4, x4, x5
+-	ldr	x5, =TCR_EL2_FLAGS
+-	orr	x4, x4, x5
+-	msr	tcr_el2, x4
+-
+-	ldr	x4, =VTCR_EL2_FLAGS
  	/*
-@@ -401,13 +402,29 @@ static void gic_cpu_init(struct gic_chip_data *gic)
- 	gic_cpu_config(dist_base, NULL);
+ 	 * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in
+-	 * VTCR_EL2.
++	 * TCR_EL2 and both PS bits and T0SZ bits in VTCR_EL2.
+ 	 */
+ 	mrs	x5, ID_AA64MMFR0_EL1
+ 	bfi	x4, x5, #16, #3
++	msr	tcr_el2, x4
++
++	ldr	x4, =VTCR_EL2_FLAGS
++	bfi	x4, x5, #16, #3
++	and	x5, x5, #0xf
++	adr	x6, t0sz
++	add	x6, x6, x5, lsl #2
++	ldr	w5, [x6]
++	orr	x4, x4, x5
+ 	msr	vtcr_el2, x4
+ 
+ 	mrs	x4, mair_el1
+@@ -113,6 +117,10 @@ target: /* We're now in the trampoline code, switch page tables */
+ 
+ 	/* Hello, World! */
+ 	eret
++
++t0sz:
++	.word	VTCR_EL2_T0SZ(32), VTCR_EL2_T0SZ(36), VTCR_EL2_T0SZ(40)
++	.word	VTCR_EL2_T0SZ(42), VTCR_EL2_T0SZ(44), VTCR_EL2_T0SZ(48)
+ ENDPROC(__kvm_hyp_init)
+ 
+ 	.ltorg
+diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
+index 4164c5a..b864a24 100644
+--- a/arch/arm64/mm/dma-mapping.c
++++ b/arch/arm64/mm/dma-mapping.c
+@@ -23,10 +23,13 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/dma-contiguous.h>
+ #include <linux/of.h>
++#include <linux/of_address.h>
+ #include <linux/platform_device.h>
+ #include <linux/vmalloc.h>
+ #include <linux/swiotlb.h>
+ #include <linux/amba/bus.h>
++#include <linux/acpi.h>
++#include <linux/pci.h>
+ 
+ #include <asm/cacheflush.h>
+ 
+@@ -319,6 +322,63 @@ static int dma_bus_notifier(struct notifier_block *nb,
+ 	if (of_property_read_bool(dev->of_node, "dma-coherent"))
+ 		set_dma_ops(dev, &coherent_swiotlb_dma_ops);
  
- 	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
--	writel_relaxed(1, base + GIC_CPU_CTRL);
++#ifdef CONFIG_ACPI
++	else if (ACPI_HANDLE(dev)) {
++		acpi_status status;
++		int coherent;
 +
-+	ctrl_mask = readl(base + GIC_CPU_CTRL);
++		/*
++		 * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64
++		 * defaults to coherent. Set coherent ops if _CCA not found or _CCA
++		 * found and non-zero.
++		 */
++		status =  acpi_check_coherency(ACPI_HANDLE(dev), &coherent);
++		if (ACPI_FAILURE(status) || coherent)
++			set_dma_ops(dev, &coherent_swiotlb_dma_ops);
++	}
++#endif
++	return NOTIFY_OK;
++}
 +
-+	/* Mask out the gic v2 bypass bits */
-+	ctrl_mask &= 0x1e0;
++static int dma_bus_notifier_pci(struct notifier_block *nb,
++				unsigned long event, void *_dev)
++{
++	struct device *dev = _dev;
 +
-+	/* Enable group 0 */
-+	ctrl_mask |= 0x1;
-+	writel_relaxed(ctrl_mask, base + GIC_CPU_CTRL);
- }
- 
- void gic_cpu_if_down(void)
- {
-+	unsigned int ctrl_mask;
- 	void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]);
--	writel_relaxed(0, cpu_base + GIC_CPU_CTRL);
++	if (event != BUS_NOTIFY_ADD_DEVICE)
++		return NOTIFY_DONE;
 +
-+	ctrl_mask = readl(cpu_base + GIC_CPU_CTRL);
 +	/*
-+	 * Disable grp enable bit, leave the bypass bits alone as changing
-+	 * them could leave the system unstable
++	 * PCI devices won't have an of_node but the bridge will.
++	 * Search up the device chain until we find an of_node
++	 * to check.
 +	 */
-+	ctrl_mask &= 0x1e0;
-+	writel_relaxed(ctrl_mask, cpu_base + GIC_CPU_CTRL);
++	while (dev) {
++		if (dev->of_node) {
++			if (of_dma_is_coherent(dev->of_node))
++				set_dma_ops(_dev, &coherent_swiotlb_dma_ops);
++			break;
++		}
++#ifdef CONFIG_ACPI
++		if (ACPI_HANDLE(dev)) {
++			acpi_status status;
++			int coherent;
++
++			/*
++			 * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64
++			 * defaults to coherent. Set coherent ops if _CCA not found or _CCA
++			 * found and non-zero.
++			 */
++			status =  acpi_check_coherency(ACPI_HANDLE(dev), &coherent);
++			if (ACPI_FAILURE(status) || coherent) {
++				set_dma_ops(dev, &coherent_swiotlb_dma_ops);
++				break;
++			}
++		}
++#endif
++		dev = dev->parent;
++	}
++
+ 	return NOTIFY_OK;
  }
  
- #ifdef CONFIG_CPU_PM
-@@ -518,6 +535,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
- {
- 	int i;
- 	u32 *ptr;
-+	unsigned int ctrl_mask;
- 	void __iomem *dist_base;
- 	void __iomem *cpu_base;
+@@ -330,6 +390,10 @@ static struct notifier_block amba_bus_nb = {
+ 	.notifier_call = dma_bus_notifier,
+ };
+ 
++static struct notifier_block pci_bus_nb = {
++	.notifier_call = dma_bus_notifier_pci,
++};
++
+ extern int swiotlb_late_init_with_default_size(size_t default_size);
+ 
+ static int __init swiotlb_late_init(void)
+@@ -341,6 +405,7 @@ static int __init swiotlb_late_init(void)
+ 	 */
+ 	bus_register_notifier(&platform_bus_type, &platform_bus_nb);
+ 	bus_register_notifier(&amba_bustype, &amba_bus_nb);
++	bus_register_notifier(&pci_bus_type, &pci_bus_nb);
  
-@@ -542,7 +560,15 @@ static void gic_cpu_restore(unsigned int gic_nr)
- 		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+ 	dma_ops = &noncoherent_swiotlb_dma_ops;
  
- 	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
--	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+diff --git a/arch/arm64/pci/Makefile b/arch/arm64/pci/Makefile
+new file mode 100644
+index 0000000..b8d5dbd
+--- /dev/null
++++ b/arch/arm64/pci/Makefile
+@@ -0,0 +1 @@
++obj-y                 += pci.o
+diff --git a/arch/arm64/pci/pci.c b/arch/arm64/pci/pci.c
+new file mode 100644
+index 0000000..b03b0eb
+--- /dev/null
++++ b/arch/arm64/pci/pci.c
+@@ -0,0 +1,28 @@
++#include <linux/acpi.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
 +
-+	ctrl_mask = readl(cpu_base + GIC_CPU_CTRL);
++/**
++ * raw_pci_read - Platform-specific PCI config space access.
++ *
++ * Default empty implementation.  Replace with an architecture-specific setup
++ * routine, if necessary.
++ */
++int __weak raw_pci_read(unsigned int domain, unsigned int bus,
++			unsigned int devfn, int reg, int len, u32 *val)
++{
++	return -EINVAL;
++}
 +
-+	/* Mask out the gic v2 bypass bits */
-+	ctrl_mask &= 0x1e0;
++int __weak raw_pci_write(unsigned int domain, unsigned int bus,
++			unsigned int devfn, int reg, int len, u32 val)
++{
++	return -EINVAL;
++}
 +
-+	/* Enable group 0 */
-+	ctrl_mask |= 0x1;
-+	writel_relaxed(ctrl_mask, cpu_base + GIC_CPU_CTRL);
++/* Root bridge scanning */
++struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
++{
++	return NULL;
++}
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index d0f3265..3343080 100644
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -5,8 +5,7 @@
+ menuconfig ACPI
+ 	bool "ACPI (Advanced Configuration and Power Interface) Support"
+ 	depends on !IA64_HP_SIM
+-	depends on IA64 || X86
+-	depends on PCI
++	depends on ((IA64 || X86) && PCI) || ARM64
+ 	select PNP
+ 	default y
+ 	help
+@@ -163,6 +162,7 @@ config ACPI_PROCESSOR
+ 	tristate "Processor"
+ 	select THERMAL
+ 	select CPU_IDLE
++	depends on X86 || IA64
+ 	default y
+ 	help
+ 	  This driver installs ACPI as the idle handler for Linux and uses
+@@ -263,7 +263,7 @@ config ACPI_DEBUG
+ 
+ config ACPI_PCI_SLOT
+ 	bool "PCI slot detection driver"
+-	depends on SYSFS
++	depends on SYSFS && PCI
+ 	default n
+ 	help
+ 	  This driver creates entries in /sys/bus/pci/slots/ for all PCI
+diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
+index 505d4d7..6f3a74d 100644
+--- a/drivers/acpi/Makefile
++++ b/drivers/acpi/Makefile
+@@ -23,7 +23,11 @@ acpi-y				+= nvs.o
+ 
+ # Power management related files
+ acpi-y				+= wakeup.o
++ifeq ($(ARCH), arm64)
++acpi-y				+= sleep-arm.o
++else # X86, IA64
+ acpi-y				+= sleep.o
++endif
+ acpi-y				+= device_pm.o
+ acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
+ 
+@@ -39,7 +43,7 @@ acpi-y				+= processor_core.o
+ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
+ acpi-y				+= ec.o
+ acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
+-acpi-y				+= pci_root.o pci_link.o pci_irq.o
++acpi-$(CONFIG_PCI)		+= pci_root.o pci_link.o pci_irq.o
+ acpi-y				+= acpi_lpss.o
+ acpi-y				+= acpi_platform.o
+ acpi-y				+= acpi_pnp.o
+diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c
+index 14cb6c0..5cd017c 100644
+--- a/drivers/acpi/acpica/utresrc.c
++++ b/drivers/acpi/acpica/utresrc.c
+@@ -87,7 +87,9 @@ const char *acpi_gbl_io_decode[] = {
+ 
+ const char *acpi_gbl_ll_decode[] = {
+ 	"ActiveHigh",
+-	"ActiveLow"
++	"ActiveLow",
++	"ActiveBoth",
++	"Reserved"
+ };
+ 
+ const char *acpi_gbl_max_decode[] = {
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index 8b67bd0..c412fdb 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -448,6 +448,9 @@ static int __init acpi_bus_init_irq(void)
+ 	case ACPI_IRQ_MODEL_IOSAPIC:
+ 		message = "IOSAPIC";
+ 		break;
++	case ACPI_IRQ_MODEL_GIC:
++		message = "GIC";
++		break;
+ 	case ACPI_IRQ_MODEL_PLATFORM:
+ 		message = "platform specific model";
+ 		break;
+diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
+index 4c5cf77..e1e6487 100644
+--- a/drivers/acpi/internal.h
++++ b/drivers/acpi/internal.h
+@@ -26,8 +26,13 @@
+ acpi_status acpi_os_initialize1(void);
+ int init_acpi_device_notify(void);
+ int acpi_scan_init(void);
++#ifdef CONFIG_PCI
+ void acpi_pci_root_init(void);
+ void acpi_pci_link_init(void);
++#else
++static inline void acpi_pci_root_init(void) {}
++static inline void acpi_pci_link_init(void) {}
++#endif
+ void acpi_processor_init(void);
+ void acpi_platform_init(void);
+ void acpi_pnp_init(void);
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index 3abe9b2..c50757b 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -326,11 +326,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
+ 	return NULL;
  }
  
- static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
-diff --git a/drivers/of/address.c b/drivers/of/address.c
-index e371825..5eaadae 100644
---- a/drivers/of/address.c
-+++ b/drivers/of/address.c
-@@ -5,6 +5,7 @@
- #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/pci_regs.h>
-+#include <linux/slab.h>
- #include <linux/string.h>
+-#ifndef CONFIG_IA64
+-#define should_use_kmap(pfn)   page_is_ram(pfn)
+-#else
++#if defined(CONFIG_IA64) || defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ /* ioremap will take care of cache attributes */
+ #define should_use_kmap(pfn)   0
++#else
++#define should_use_kmap(pfn)   page_is_ram(pfn)
+ #endif
  
- /* Max address size we deal with */
-@@ -601,12 +602,72 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
+ static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
+diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
+index e32321c..4007313 100644
+--- a/drivers/acpi/processor_core.c
++++ b/drivers/acpi/processor_core.c
+@@ -64,6 +64,38 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
+ 	return 0;
  }
- EXPORT_SYMBOL(of_get_address);
  
-+struct io_range {
-+	struct list_head list;
-+	phys_addr_t start;
-+	resource_size_t size;
-+};
-+
-+static LIST_HEAD(io_range_list);
-+
 +/*
-+ * Record the PCI IO range (expressed as CPU physical address + size).
-+ * Return a negative value if an error has occured, zero otherwise
++ * On ARM platform, MPIDR value is the hardware ID as apic ID
++ * on Intel platforms
 + */
-+int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
++static int map_gicc_mpidr(struct acpi_subtable_header *entry,
++		int device_declaration, u32 acpi_id, int *mpidr)
 +{
-+#ifdef PCI_IOBASE
-+	struct io_range *res;
-+	resource_size_t allocated_size = 0;
-+
-+	/* check if the range hasn't been previously recorded */
-+	list_for_each_entry(res, &io_range_list, list) {
-+		if (addr >= res->start && addr + size <= res->start + size)
-+			return 0;
-+		allocated_size += res->size;
-+	}
-+
-+	/* range not registed yet, check for available space */
-+	if (allocated_size + size - 1 > IO_SPACE_LIMIT)
-+		return -E2BIG;
-+
-+	/* add the range to the list */
-+	res = kzalloc(sizeof(*res), GFP_KERNEL);
-+	if (!res)
-+		return -ENOMEM;
++	struct acpi_madt_generic_interrupt *gicc =
++	    container_of(entry, struct acpi_madt_generic_interrupt, header);
 +
-+	res->start = addr;
-+	res->size = size;
++	if (!(gicc->flags & ACPI_MADT_ENABLED))
++		return -ENODEV;
 +
-+	list_add_tail(&res->list, &io_range_list);
++	/* In the GIC interrupt model, logical processors are
++	 * required to have a Processor Device object in the DSDT,
++	 * so we should check device_declaration here
++	 */
++	if (device_declaration && (gicc->uid == acpi_id)) {
++		/*
++		 * Only bits [0:7] Aff0, bits [8:15] Aff1, bits [16:23] Aff2
++		 * and bits [32:39] Aff3 are meaningful, so pack the Affx
++		 * fields into a single 32 bit identifier to accommodate the
++		 * acpi processor drivers.
++		 */
++		*mpidr = ((gicc->arm_mpidr & 0xff00000000) >> 8)
++			 | gicc->arm_mpidr;
++		return 0;
++	}
 +
-+	return 0;
-+#else
 +	return -EINVAL;
-+#endif
 +}
 +
- unsigned long __weak pci_address_to_pio(phys_addr_t address)
+ static int map_madt_entry(int type, u32 acpi_id)
  {
-+#ifdef PCI_IOBASE
-+	struct io_range *res;
-+	resource_size_t offset = 0;
+ 	unsigned long madt_end, entry;
+@@ -99,6 +131,9 @@ static int map_madt_entry(int type, u32 acpi_id)
+ 		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
+ 			if (!map_lsapic_id(header, type, acpi_id, &apic_id))
+ 				break;
++		} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
++			if (!map_gicc_mpidr(header, type, acpi_id, &apic_id))
++				break;
+ 		}
+ 		entry += header->length;
+ 	}
+@@ -131,6 +166,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
+ 		map_lsapic_id(header, type, acpi_id, &apic_id);
+ 	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+ 		map_x2apic_id(header, type, acpi_id, &apic_id);
++	} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
++		map_gicc_mpidr(header, type, acpi_id, &apic_id);
+ 	}
+ 
+ exit:
+diff --git a/drivers/acpi/sleep-arm.c b/drivers/acpi/sleep-arm.c
+new file mode 100644
+index 0000000..54578ef
+--- /dev/null
++++ b/drivers/acpi/sleep-arm.c
+@@ -0,0 +1,28 @@
++/*
++ *  ARM64 Specific Sleep Functionality
++ *
++ *  Copyright (C) 2013-2014, Linaro Ltd.
++ *      Author: Graeme Gregory <graeme.gregory at linaro.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#include <linux/acpi.h>
++
++/*
++ * Currently the ACPI 5.1 standard does not define S states in a
++ * manner which is usable for ARM64. These two stubs are sufficient
++ * that system initialises and device PM works.
++ */
++u32 acpi_target_system_state(void)
++{
++	return ACPI_STATE_S0;
++}
++EXPORT_SYMBOL_GPL(acpi_target_system_state);
++
++int __init acpi_sleep_init(void)
++{
++	return -ENOSYS;
++}
+diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
+index 6d5a6cd..47f36d4 100644
+--- a/drivers/acpi/tables.c
++++ b/drivers/acpi/tables.c
+@@ -183,6 +183,49 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
+ 		}
+ 		break;
+ 
++	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
++		{
++			struct acpi_madt_generic_interrupt *p =
++				(struct acpi_madt_generic_interrupt *)header;
++			pr_info("GICC (acpi_id[0x%04x] address[%p] MPDIR[0x%llx] %s)\n",
++				p->uid, (void *)(unsigned long)p->base_address,
++				p->arm_mpidr,
++				(p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
 +
-+	list_for_each_entry(res, &io_range_list, list) {
-+		if (address >= res->start &&
-+			address < res->start + res->size) {
-+			return res->start - address + offset;
 +		}
-+		offset += res->size;
-+	}
++		break;
 +
-+	return (unsigned long)-1;
-+#else
- 	if (address > IO_SPACE_LIMIT)
- 		return (unsigned long)-1;
++	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
++		{
++			struct acpi_madt_generic_distributor *p =
++				(struct acpi_madt_generic_distributor *)header;
++			pr_info("GIC Distributor (gic_id[0x%04x] address[%p] gsi_base[%d])\n",
++				p->gic_id,
++				(void *)(unsigned long)p->base_address,
++				p->global_irq_base);
++		}
++		break;
++
++	case ACPI_MADT_TYPE_GENERIC_MSI_FRAME:
++		{
++			struct acpi_madt_generic_msi_frame *p =
++				(struct acpi_madt_generic_msi_frame *)header;
++			pr_info("GIC MSI Frame (msi_fame_id[%d] address[%p])\n",
++				p->msi_frame_id,
++				(void *)(unsigned long)p->base_address);
++		}
++		break;
++
++	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
++		{
++			struct acpi_madt_generic_redistributor *p =
++				(struct acpi_madt_generic_redistributor *)header;
++			pr_info("GIC Redistributor (address[%p] region_size[0x%x])\n",
++				(void *)(unsigned long)p->base_address,
++				p->length);
++		}
++		break;
++
+ 	default:
+ 		pr_warn("Found unsupported MADT entry (type = 0x%x)\n",
+ 			header->type);
+@@ -192,17 +235,14 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
  
- 	return (unsigned long) address;
-+#endif
+ 
+ int __init
+-acpi_table_parse_entries(char *id,
+-			     unsigned long table_size,
+-			     int entry_id,
+-			     acpi_tbl_entry_handler handler,
+-			     unsigned int max_entries)
++acpi_parse_entries(unsigned long table_size,
++		acpi_tbl_entry_handler handler,
++		struct acpi_table_header *table_header,
++		int entry_id, unsigned int max_entries)
+ {
+-	struct acpi_table_header *table_header = NULL;
+ 	struct acpi_subtable_header *entry;
+-	unsigned int count = 0;
++	int count = 0;
+ 	unsigned long table_end;
+-	acpi_size tbl_size;
+ 
+ 	if (acpi_disabled)
+ 		return -ENODEV;
+@@ -210,13 +250,11 @@ acpi_table_parse_entries(char *id,
+ 	if (!handler)
+ 		return -EINVAL;
+ 
+-	if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
+-		acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size);
+-	else
+-		acpi_get_table_with_size(id, 0, &table_header, &tbl_size);
++	if (!table_size)
++		return -EINVAL;
+ 
+ 	if (!table_header) {
+-		pr_warn("%4.4s not present\n", id);
++		pr_warn("Table header not present\n");
+ 		return -ENODEV;
+ 	}
+ 
+@@ -230,32 +268,67 @@ acpi_table_parse_entries(char *id,
+ 	while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
+ 	       table_end) {
+ 		if (entry->type == entry_id
+-		    && (!max_entries || count++ < max_entries))
++		    && (!max_entries || count < max_entries)) {
+ 			if (handler(entry, table_end))
+-				goto err;
++				return -EINVAL;
++
++			count++;
++		}
+ 
+ 		/*
+ 		 * If entry->length is 0, break from this loop to avoid
+ 		 * infinite loop.
+ 		 */
+ 		if (entry->length == 0) {
+-			pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
+-			goto err;
++			pr_err("[0x%02x] Invalid zero length\n", entry_id);
++			return -EINVAL;
+ 		}
+ 
+ 		entry = (struct acpi_subtable_header *)
+ 		    ((unsigned long)entry + entry->length);
+ 	}
++
+ 	if (max_entries && count > max_entries) {
+ 		pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n",
+-			id, entry_id, count - max_entries, count);
++			table_header->signature, entry_id, count - max_entries,
++			count);
+ 	}
+ 
+-	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
+ 	return count;
+-err:
++}
++
++int __init
++acpi_table_parse_entries(char *id,
++			 unsigned long table_size,
++			 int entry_id,
++			 acpi_tbl_entry_handler handler,
++			 unsigned int max_entries)
++{
++	struct acpi_table_header *table_header = NULL;
++	acpi_size tbl_size;
++	int count;
++
++	if (acpi_disabled)
++		return -ENODEV;
++
++	if (!handler)
++		return -EINVAL;
++
++	if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
++		acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size);
++	else
++		acpi_get_table_with_size(id, 0, &table_header, &tbl_size);
++
++	if (!table_header) {
++		pr_warn("%4.4s not present\n", id);
++		return -ENODEV;
++	}
++
++	count = acpi_parse_entries(table_size, handler, table_header,
++			entry_id, max_entries);
++
+ 	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
+-	return -EINVAL;
++	return count;
  }
  
- static int __of_address_to_resource(struct device_node *dev,
-@@ -847,3 +908,50 @@ bool of_dma_is_coherent(struct device_node *np)
+ int __init
+diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
+index 07c8c5a..aec9656 100644
+--- a/drivers/acpi/utils.c
++++ b/drivers/acpi/utils.c
+@@ -698,3 +698,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
  	return false;
  }
- EXPORT_SYMBOL_GPL(of_dma_is_coherent);
+ EXPORT_SYMBOL(acpi_check_dsm);
 +
-+/*
-+ * of_pci_range_to_resource - Create a resource from an of_pci_range
-+ * @range:	the PCI range that describes the resource
-+ * @np:		device node where the range belongs to
-+ * @res:	pointer to a valid resource that will be updated to
-+ *              reflect the values contained in the range.
-+ *
-+ * Returns EINVAL if the range cannot be converted to resource.
++/**
++ * acpi_check_coherency - check for memory coherency of a device
++ * @handle: ACPI device handle
++ * @val:    Pointer to returned value
 + *
-+ * Note that if the range is an IO range, the resource will be converted
-+ * using pci_address_to_pio() which can fail if it is called too early or
-+ * if the range cannot be matched to any host bridge IO space (our case here).
-+ * To guard against that we try to register the IO range first.
-+ * If that fails we know that pci_address_to_pio() will do too.
++ * Search a device and its parents for a _CCA method and return
++ * its value.
 + */
-+int of_pci_range_to_resource(struct of_pci_range *range,
-+	struct device_node *np, struct resource *res)
++acpi_status acpi_check_coherency(acpi_handle handle, int *val)
 +{
-+	int err;
-+	res->flags = range->flags;
-+	res->parent = res->child = res->sibling = NULL;
-+	res->name = np->full_name;
++	unsigned long long data;
++	acpi_status status;
 +
-+	if (res->flags & IORESOURCE_IO) {
-+		unsigned long port = -1;
-+		err = pci_register_io_range(range->cpu_addr, range->size);
-+		if (err)
-+			goto invalid_range;
-+		port = pci_address_to_pio(range->cpu_addr);
-+		if (port == (unsigned long)-1) {
-+			err = -EINVAL;
-+			goto invalid_range;
++	do {
++		status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
++		if (!ACPI_FAILURE(status)) {
++			*val = data;
++			break;
 +		}
-+		res->start = port;
-+	} else {
-+		res->start = range->cpu_addr;
-+	}
-+	res->end = res->start + range->size - 1;
-+	return 0;
++		status = acpi_get_parent(handle, &handle);
++	} while (!ACPI_FAILURE(status));
 +
-+invalid_range:
-+	res->start = (resource_size_t)OF_BAD_ADDR;
-+	res->end = (resource_size_t)OF_BAD_ADDR;
-+	return err;
++	return status;
 +}
++EXPORT_SYMBOL(acpi_check_coherency);
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index e1b9278..f2e6c9e 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -48,7 +48,7 @@ config ATA_VERBOSE_ERROR
+ 
+ config ATA_ACPI
+ 	bool "ATA ACPI Support"
+-	depends on ACPI && PCI
++	depends on ACPI
+ 	default y
+ 	help
+ 	  This option adds support for ATA-related ACPI objects.
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index f61ddb9..3499bab 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -20,6 +20,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/libata.h>
+ #include <linux/ahci_platform.h>
++#ifdef CONFIG_ATA_ACPI
++#include <linux/acpi.h>
++#endif
+ #include "ahci.h"
+ 
+ static const struct ata_port_info ahci_port_info = {
+@@ -87,6 +90,13 @@ static const struct of_device_id ahci_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, ahci_of_match);
+ 
++#ifdef CONFIG_ATA_ACPI
++static const struct acpi_device_id ahci_acpi_match[] = {
++	{ "AMDI0600", 0 }, /* AMD Seattle AHCI */
++	{ },
++};
++#endif
 +
-diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
-index 8481996..e81402a 100644
---- a/drivers/of/of_pci.c
-+++ b/drivers/of/of_pci.c
-@@ -1,6 +1,7 @@
- #include <linux/kernel.h>
- #include <linux/export.h>
- #include <linux/of.h>
-+#include <linux/of_address.h>
- #include <linux/of_pci.h>
+ static struct platform_driver ahci_driver = {
+ 	.probe = ahci_probe,
+ 	.remove = ata_platform_remove_one,
+@@ -94,6 +104,9 @@ static struct platform_driver ahci_driver = {
+ 		.name = "ahci",
+ 		.owner = THIS_MODULE,
+ 		.of_match_table = ahci_of_match,
++#ifdef CONFIG_ATA_ACPI
++		.acpi_match_table = ACPI_PTR(ahci_acpi_match),
++#endif
+ 		.pm = &ahci_pm_ops,
+ 	},
+ };
+diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
+index f03aab1..b02ba9d 100644
+--- a/drivers/ata/ahci_xgene.c
++++ b/drivers/ata/ahci_xgene.c
+@@ -28,6 +28,7 @@
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/phy/phy.h>
++#include <linux/acpi.h>
+ #include "ahci.h"
  
- static inline int __of_pci_pci_compare(struct device_node *node,
-@@ -89,6 +90,141 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
+ /* Max # of disk per a controller */
+@@ -137,7 +138,8 @@ static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
+ 	struct xgene_ahci_context *ctx = hpriv->plat_data;
+ 	int rc = 0;
+ 
+-	if (unlikely(ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA))
++	if (unlikely(ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA ||
++		     ctx->last_cmd[ap->port_no] == ATA_CMD_SMART))
+ 		xgene_ahci_restart_engine(ap);
+ 
+ 	rc = ahci_qc_issue(qc);
+@@ -148,14 +150,6 @@ static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
+ 	return rc;
  }
- EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
  
-+/**
-+ * pci_host_bridge_of_get_ranges - Parse PCI host bridge resources from DT
-+ * @dev: device node of the host bridge having the range property
-+ * @resources: list where the range of resources will be added after DT parsing
-+ * @io_base: pointer to a variable that will contain the physical address for
-+ * the start of the I/O range.
-+ *
-+ * It is the callers job to free the @resources list if an error is returned.
-+ *
-+ * This function will parse the "ranges" property of a PCI host bridge device
-+ * node and setup the resource mapping based on its content. It is expected
-+ * that the property conforms with the Power ePAPR document.
-+ *
-+ * Each architecture is then offered the chance of applying their own
-+ * filtering of pci_host_bridge_windows based on their own restrictions by
-+ * calling pcibios_fixup_bridge_ranges(). The filtered list of windows
-+ * can then be used when creating a pci_host_bridge structure.
-+ */
-+static int pci_host_bridge_of_get_ranges(struct device_node *dev,
-+		struct list_head *resources, resource_size_t *io_base)
+-static bool xgene_ahci_is_memram_inited(struct xgene_ahci_context *ctx)
+-{
+-	void __iomem *diagcsr = ctx->csr_diag;
+-
+-	return (readl(diagcsr + CFG_MEM_RAM_SHUTDOWN) == 0 &&
+-	        readl(diagcsr + BLOCK_MEM_RDY) == 0xFFFFFFFF);
+-}
+-
+ /**
+  * xgene_ahci_read_id - Read ID data from the specified device
+  * @dev: device
+@@ -495,11 +489,6 @@ static int xgene_ahci_probe(struct platform_device *pdev)
+ 		return -ENODEV;
+ 	}
+ 
+-	if (xgene_ahci_is_memram_inited(ctx)) {
+-		dev_info(dev, "skip clock and PHY initialization\n");
+-		goto skip_clk_phy;
+-	}
+-
+ 	/* Due to errata, HW requires full toggle transition */
+ 	rc = ahci_platform_enable_clks(hpriv);
+ 	if (rc)
+@@ -512,7 +501,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
+ 
+ 	/* Configure the host controller */
+ 	xgene_ahci_hw_init(hpriv);
+-skip_clk_phy:
++
+ 	hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ;
+ 
+ 	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info);
+@@ -527,6 +516,16 @@ disable_resources:
+ 	return rc;
+ }
+ 
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id xgene_ahci_acpi_match[] = {
++	{ "APMC0D00", },
++	{ "APMC0D0D", },
++	{ "APMC0D09", },
++	{ }
++};
++MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
++#endif
++
+ static const struct of_device_id xgene_ahci_of_match[] = {
+ 	{.compatible = "apm,xgene-ahci"},
+ 	{},
+@@ -540,6 +539,7 @@ static struct platform_driver xgene_ahci_driver = {
+ 		.name = "xgene-ahci",
+ 		.owner = THIS_MODULE,
+ 		.of_match_table = xgene_ahci_of_match,
++		.acpi_match_table = ACPI_PTR(xgene_ahci_acpi_match),
+ 	},
+ };
+ 
+diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
+index 5163ec1..1bec05b 100644
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -21,6 +21,7 @@
+ #include <linux/io.h>
+ #include <linux/slab.h>
+ #include <linux/sched_clock.h>
++#include <linux/acpi.h>
+ 
+ #include <asm/arch_timer.h>
+ #include <asm/virt.h>
+@@ -61,7 +62,8 @@ enum ppi_nr {
+ 	MAX_TIMER_PPI
+ };
+ 
+-static int arch_timer_ppi[MAX_TIMER_PPI];
++int arch_timer_ppi[MAX_TIMER_PPI];
++EXPORT_SYMBOL(arch_timer_ppi);
+ 
+ static struct clock_event_device __percpu *arch_timer_evt;
+ 
+@@ -338,8 +340,12 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
+ 	if (arch_timer_rate)
+ 		return;
+ 
+-	/* Try to determine the frequency from the device tree or CNTFRQ */
+-	if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) {
++	/*
++	 * Try to determine the frequency from the device tree or CNTFRQ,
++	 * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
++	 */
++	if (!acpi_disabled ||
++	    of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) {
+ 		if (cntbase)
+ 			arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
+ 		else
+@@ -635,20 +641,8 @@ static void __init arch_timer_common_init(void)
+ 	arch_timer_arch_init();
+ }
+ 
+-static void __init arch_timer_init(struct device_node *np)
++static void __init arch_timer_init(void)
+ {
+-	int i;
+-
+-	if (arch_timers_present & ARCH_CP15_TIMER) {
+-		pr_warn("arch_timer: multiple nodes in dt, skipping\n");
+-		return;
+-	}
+-
+-	arch_timers_present |= ARCH_CP15_TIMER;
+-	for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
+-		arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
+-	arch_timer_detect_rate(NULL, np);
+-
+ 	/*
+ 	 * If HYP mode is available, we know that the physical timer
+ 	 * has been configured to be accessible from PL1. Use it, so
+@@ -667,13 +661,31 @@ static void __init arch_timer_init(struct device_node *np)
+ 		}
+ 	}
+ 
+-	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
+-
+ 	arch_timer_register();
+ 	arch_timer_common_init();
+ }
+-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init);
+-CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init);
++
++static void __init arch_timer_of_init(struct device_node *np)
 +{
-+	struct resource *res;
-+	struct of_pci_range range;
-+	struct of_pci_range_parser parser;
-+	int err;
++	int i;
 +
-+	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
++	if (arch_timers_present & ARCH_CP15_TIMER) {
++		pr_warn("arch_timer: multiple nodes in dt, skipping\n");
++		return;
++	}
 +
-+	/* Check for ranges property */
-+	err = of_pci_range_parser_init(&parser, dev);
-+	if (err)
-+		return err;
++	arch_timers_present |= ARCH_CP15_TIMER;
++	for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
++		arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 +
-+	pr_debug("Parsing ranges property...\n");
-+	for_each_of_pci_range(&parser, &range) {
-+		/* Read next ranges element */
-+		pr_debug("pci_space: 0x%08x pci_addr:0x%016llx cpu_addr:0x%016llx size:0x%016llx\n",
-+			range.pci_space, range.pci_addr, range.cpu_addr, range.size);
++	arch_timer_detect_rate(NULL, np);
 +
-+		/*
-+		 * If we failed translation or got a zero-sized region
-+		 * then skip this range
-+		 */
-+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
-+			continue;
++	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 +
-+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
-+		if (!res)
-+			return -ENOMEM;
++	arch_timer_init();
++}
++CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
++CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
+ 
+ static void __init arch_timer_mem_init(struct device_node *np)
+ {
+@@ -740,3 +752,71 @@ static void __init arch_timer_mem_init(struct device_node *np)
+ }
+ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
+ 		       arch_timer_mem_init);
 +
-+		err = of_pci_range_to_resource(&range, dev, res);
-+		if (err)
-+			return err;
++#ifdef CONFIG_ACPI
++static int __init
++map_generic_timer_interrupt(u32 interrupt, u32 flags)
++{
++	int trigger, polarity;
 +
-+		if (resource_type(res) == IORESOURCE_IO)
-+			*io_base = range.cpu_addr;
++	if (!interrupt)
++		return 0;
 +
-+		pci_add_resource_offset(resources, res,
-+				res->start - range.pci_addr);
-+	}
++	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
++			: ACPI_LEVEL_SENSITIVE;
 +
-+	/* Apply architecture specific fixups for the ranges */
-+	return pcibios_fixup_bridge_ranges(resources);
-+}
++	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
++			: ACPI_ACTIVE_HIGH;
 +
-+static atomic_t domain_nr = ATOMIC_INIT(-1);
++	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
++}
 +
-+/**
-+ * of_create_pci_host_bridge - Create a PCI host bridge structure using
-+ * information passed in the DT.
-+ * @parent: device owning this host bridge
-+ * @ops: pci_ops associated with the host controller
-+ * @host_data: opaque data structure used by the host controller.
-+ *
-+ * returns a pointer to the newly created pci_host_bridge structure, or
-+ * NULL if the call failed.
-+ *
-+ * This function will try to obtain the host bridge domain number by
-+ * using of_alias_get_id() call with "pci-domain" as a stem. If that
-+ * fails, a local allocator will be used that will put each host bridge
-+ * in a new domain.
-+ */
-+struct pci_host_bridge *
-+of_create_pci_host_bridge(struct device *parent, struct pci_ops *ops, void *host_data)
++/* Initialize per-processor generic timer */
++static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 +{
-+	int err, domain, busno;
-+	struct resource *bus_range;
-+	struct pci_bus *root_bus;
-+	struct pci_host_bridge *bridge;
-+	resource_size_t io_base = 0;
-+	LIST_HEAD(res);
++	struct acpi_table_gtdt *gtdt;
 +
-+	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
-+	if (!bus_range)
-+		return ERR_PTR(-ENOMEM);
++	if (arch_timers_present & ARCH_CP15_TIMER) {
++		pr_warn("arch_timer: already initialized, skipping\n");
++		return -EINVAL;
++	}
 +
-+	domain = of_alias_get_id(parent->of_node, "pci-domain");
-+	if (domain == -ENODEV)
-+		domain = atomic_inc_return(&domain_nr);
++	gtdt = container_of(table, struct acpi_table_gtdt, header);
 +
-+	err = of_pci_parse_bus_range(parent->of_node, bus_range);
-+	if (err) {
-+		dev_info(parent, "No bus range for %s, using default [0-255]\n",
-+			parent->of_node->full_name);
-+		bus_range->start = 0;
-+		bus_range->end = 255;
-+		bus_range->flags = IORESOURCE_BUS;
-+	}
-+	busno = bus_range->start;
-+	pci_add_resource(&res, bus_range);
++	arch_timers_present |= ARCH_CP15_TIMER;
 +
-+	/* now parse the rest of host bridge bus ranges */
-+	err = pci_host_bridge_of_get_ranges(parent->of_node, &res, &io_base);
-+	if (err)
-+		goto err_create;
++	arch_timer_ppi[PHYS_SECURE_PPI] =
++		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
++		gtdt->secure_el1_flags);
 +
-+	/* then create the root bus */
-+	root_bus = pci_create_root_bus_in_domain(parent, domain, busno,
-+						ops, host_data, &res);
-+	if (IS_ERR(root_bus)) {
-+		err = PTR_ERR(root_bus);
-+		goto err_create;
-+	}
++	arch_timer_ppi[PHYS_NONSECURE_PPI] =
++		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
++		gtdt->non_secure_el1_flags);
 +
-+	bridge = to_pci_host_bridge(root_bus->bridge);
-+	bridge->io_base = io_base;
++	arch_timer_ppi[VIRT_PPI] =
++		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
++		gtdt->virtual_timer_flags);
 +
-+	return bridge;
++	arch_timer_ppi[HYP_PPI] =
++		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
++		gtdt->non_secure_el2_flags);
 +
-+err_create:
-+	pci_free_resource_list(&res);
-+	return ERR_PTR(err);
++	/* Get the frequency from CNTFRQ */
++	arch_timer_detect_rate(NULL, NULL);
++
++	/* Always-on capability */
++	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
++
++	arch_timer_init();
++	return 0;
 +}
-+EXPORT_SYMBOL_GPL(of_create_pci_host_bridge);
 +
- #ifdef CONFIG_PCI_MSI
- 
- static LIST_HEAD(of_pci_msi_chip_list);
-diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
-index 0e5f3c9..54ceafd 100644
---- a/drivers/pci/host-bridge.c
-+++ b/drivers/pci/host-bridge.c
-@@ -16,12 +16,13 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
- 	return bus;
++/* Initialize all the generic timers presented in GTDT */
++void __init acpi_generic_timer_init(void)
++{
++	if (acpi_disabled)
++		return;
++
++	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
++}
++#endif
+diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
+index a0698b4..d2da911 100644
+--- a/drivers/irqchip/irq-gic-v3.c
++++ b/drivers/irqchip/irq-gic-v3.c
+@@ -490,9 +490,19 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+ 	isb();
  }
  
--static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
-+struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++static void gic_wakeup_parked_cpu(int cpu)
++{
++	gic_raise_softirq(cpumask_of(cpu), 0);
++}
++#endif
++
+ static void gic_smp_init(void)
  {
- 	struct pci_bus *root_bus = find_pci_root_bus(bus);
- 
- 	return to_pci_host_bridge(root_bus->bridge);
+ 	set_smp_cross_call(gic_raise_softirq);
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++	set_smp_boot_wakeup_call(gic_wakeup_parked_cpu);
++#endif
+ 	register_cpu_notifier(&gic_cpu_notifier);
  }
-+EXPORT_SYMBOL_GPL(find_pci_host_bridge);
  
- void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
- 				 void (*release_fn)(struct pci_host_bridge *),
-@@ -82,3 +83,18 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
- 	res->end = region->end + offset;
+diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
+index dda6dbc..5d9bdd3 100644
+--- a/drivers/irqchip/irq-gic.c
++++ b/drivers/irqchip/irq-gic.c
+@@ -33,12 +33,14 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
++#include <linux/acpi.h>
+ #include <linux/irqdomain.h>
+ #include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/slab.h>
+ #include <linux/irqchip/chained_irq.h>
+ #include <linux/irqchip/arm-gic.h>
++#include <linux/irqchip/arm-gic-acpi.h>
+ 
+ #include <asm/cputype.h>
+ #include <asm/irq.h>
+@@ -622,6 +624,13 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+ 
+ 	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
  }
- EXPORT_SYMBOL(pcibios_bus_to_resource);
 +
-+/**
-+ * Simple version of the platform specific code for filtering the list
-+ * of resources obtained from the ranges declaration in DT.
-+ *
-+ * Platforms can override this function in order to impose stronger
-+ * constraints onto the list of resources that a host bridge can use.
-+ * The filtered list will then be used to create a root bus and associate
-+ * it with the host bridge.
-+ *
-+ */
-+int __weak pcibios_fixup_bridge_ranges(struct list_head *resources)
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++static void gic_wakeup_parked_cpu(int cpu)
 +{
-+	return 0;
++	gic_raise_softirq(cpumask_of(cpu), GIC_DIST_SOFTINT_NSATT);
 +}
-diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
-index 2d8a4d0..e17a28e 100644
---- a/drivers/pci/host/Kconfig
-+++ b/drivers/pci/host/Kconfig
-@@ -54,4 +54,14 @@ config PCIE_SPEAR13XX
- 	help
- 	  Say Y here if you want PCIe support on SPEAr13XX SoCs.
++#endif
+ #endif
  
-+config PCI_XGENE
-+	bool "X-Gene PCIe controller"
-+	depends on ARCH_XGENE
-+	depends on OF
-+	select PCIEPORTBUS
-+	help
-+	  Say Y here if you want internal PCI support on APM X-Gene SoC.
-+	  There are 5 internal PCIe ports available. Each port is GEN3 capable
-+	  and have varied lanes from x1 to x8.
+ #ifdef CONFIG_BL_SWITCHER
+@@ -977,6 +986,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
+ #ifdef CONFIG_SMP
+ 		set_smp_cross_call(gic_raise_softirq);
+ 		register_cpu_notifier(&gic_cpu_notifier);
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++		set_smp_boot_wakeup_call(gic_wakeup_parked_cpu);
++#endif
+ #endif
+ 		set_handle_irq(gic_handle_irq);
+ 	}
+@@ -1029,3 +1041,107 @@ IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
+ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
+ 
+ #endif
 +
- endmenu
-diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
-index 0daec79..7600482 100644
---- a/drivers/pci/host/Makefile
-+++ b/drivers/pci/host/Makefile
-@@ -7,3 +7,4 @@ obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
- obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
- obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
- obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
-+obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
-diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
-new file mode 100644
-index 0000000..7bf4ac7
---- /dev/null
-+++ b/drivers/pci/host/pci-xgene.c
-@@ -0,0 +1,725 @@
-+/**
-+ * APM X-Gene PCIe Driver
-+ *
-+ * Copyright (c) 2013 Applied Micro Circuits Corporation.
-+ *
-+ * Author: Tanmay Inamdar <tinamdar at apm.com>.
-+ *
-+ * 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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ */
-+#include <linux/clk-private.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/jiffies.h>
-+#include <linux/memblock.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+#include <linux/pci.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
++#ifdef CONFIG_ACPI
++static phys_addr_t dist_phy_base, cpu_phy_base;
++static int cpu_base_assigned;
 +
-+#define PCIECORE_LTSSM			0x4c
-+#define PCIECORE_CTLANDSTATUS		0x50
-+#define INTXSTATUSMASK			0x6c
-+#define PIM1_1L				0x80
-+#define IBAR2				0x98
-+#define IR2MSK				0x9c
-+#define PIM2_1L				0xa0
-+#define IBAR3L				0xb4
-+#define IR3MSKL				0xbc
-+#define PIM3_1L				0xc4
-+#define OMR1BARL			0x100
-+#define OMR2BARL			0x118
-+#define OMR3BARL			0x130
-+#define CFGBARL				0x154
-+#define CFGBARH				0x158
-+#define CFGCTL				0x15c
-+#define RTDID				0x160
-+#define BRIDGE_CFG_0			0x2000
-+#define BRIDGE_CFG_1			0x2004
-+#define BRIDGE_CFG_4			0x2010
-+#define BRIDGE_CFG_32			0x2030
-+#define BRIDGE_CFG_14			0x2038
-+#define BRIDGE_CTRL_1			0x2204
-+#define BRIDGE_CTRL_2			0x2208
-+#define BRIDGE_CTRL_5			0x2214
-+#define BRIDGE_STATUS_0			0x2600
-+#define MEM_RAM_SHUTDOWN                0xd070
-+#define BLOCK_MEM_RDY                   0xd074
++static int __init
++gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
++			const unsigned long end)
++{
++	struct acpi_madt_generic_interrupt *processor;
++	phys_addr_t gic_cpu_base;
 +
-+#define DEVICE_PORT_TYPE_MASK		0x03c00000
-+#define PM_FORCE_RP_MODE_MASK		0x00000400
-+#define SWITCH_PORT_MODE_MASK		0x00000800
-+#define CLASS_CODE_MASK			0xffffff00
-+#define LINK_UP_MASK			0x00000100
-+#define AER_OPTIONAL_ERROR_EN		0xffc00000
-+#define XGENE_PCIE_DEV_CTRL		0x2f0f
-+#define AXI_EP_CFG_ACCESS		0x10000
-+#define ENABLE_ASPM			0x08000000
-+#define XGENE_PORT_TYPE_RC		0x05000000
-+#define BLOCK_MEM_RDY_VAL               0xFFFFFFFF
-+#define EN_COHERENCY			0xF0000000
-+#define EN_REG				0x00000001
-+#define OB_LO_IO			0x00000002
-+#define XGENE_PCIE_VENDORID		0xE008
-+#define XGENE_PCIE_DEVICEID		0xE004
-+#define XGENE_PCIE_ECC_TIMEOUT		10 /* ms */
-+#define XGENE_LTSSM_DETECT_WAIT		20 /* ms */
-+#define XGENE_LTSSM_L0_WAIT		4  /* ms */
-+#define SZ_1T				(SZ_1G*1024ULL)
-+#define PIPE_PHY_RATE_RD(src)		((0xc000 & (u32)(src)) >> 0xe)
++	processor = (struct acpi_madt_generic_interrupt *)header;
 +
-+struct xgene_pcie_port {
-+	struct device_node	*node;
-+	struct device		*dev;
-+	struct clk		*clk;
-+	void __iomem		*csr_base;
-+	void __iomem		*cfg_base;
-+	u8			link_up;
-+};
++	if (BAD_MADT_ENTRY(processor, end))
++		return -EINVAL;
 +
-+static inline u32 pcie_bar_low_val(u32 addr, u32 flags)
-+{
-+	return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags;
-+}
++	/*
++	 * There is no support for non-banked GICv1/2 register in ACPI spec.
++	 * All CPU interface addresses have to be the same.
++	 */
++	gic_cpu_base = processor->base_address;
++	if (cpu_base_assigned && gic_cpu_base != cpu_phy_base)
++		return -EFAULT;
 +
-+/* PCIE Configuration Out/In */
-+static inline void xgene_pcie_cfg_out32(void __iomem *addr, int offset, u32 val)
-+{
-+	writel(val, addr + offset);
++	cpu_phy_base = gic_cpu_base;
++	cpu_base_assigned = 1;
++	return 0;
 +}
 +
-+static inline void xgene_pcie_cfg_out16(void __iomem *addr, int offset, u16 val)
++static int __init
++gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
++				const unsigned long end)
 +{
-+	u32 val32 = readl(addr + (offset & ~0x3));
-+
-+	switch (offset & 0x3) {
-+	case 2:
-+		val32 &= ~0xFFFF0000;
-+		val32 |= (u32)val << 16;
-+		break;
-+	case 0:
-+	default:
-+		val32 &= ~0xFFFF;
-+		val32 |= val;
-+		break;
-+	}
-+	writel(val32, addr + (offset & ~0x3));
-+}
++	struct acpi_madt_generic_distributor *dist;
 +
-+static inline void xgene_pcie_cfg_out8(void __iomem *addr, int offset, u8 val)
-+{
-+	u32 val32 = readl(addr + (offset & ~0x3));
++	dist = (struct acpi_madt_generic_distributor *)header;
 +
-+	switch (offset & 0x3) {
-+	case 0:
-+		val32 &= ~0xFF;
-+		val32 |= val;
-+		break;
-+	case 1:
-+		val32 &= ~0xFF00;
-+		val32 |= (u32)val << 8;
-+		break;
-+	case 2:
-+		val32 &= ~0xFF0000;
-+		val32 |= (u32)val << 16;
-+		break;
-+	case 3:
-+	default:
-+		val32 &= ~0xFF000000;
-+		val32 |= (u32)val << 24;
-+		break;
-+	}
-+	writel(val32, addr + (offset & ~0x3));
-+}
++	if (BAD_MADT_ENTRY(dist, end))
++		return -EINVAL;
 +
-+static inline void xgene_pcie_cfg_in32(void __iomem *addr, int offset, u32 *val)
-+{
-+	*val = readl(addr + offset);
++	dist_phy_base = dist->base_address;
++	return 0;
 +}
 +
-+static inline void
-+xgene_pcie_cfg_in16(void __iomem *addr, int offset, u32 *val)
++int __init
++gic_v2_acpi_init(struct acpi_table_header *table)
 +{
-+	*val = readl(addr + (offset & ~0x3));
-+
-+	switch (offset & 0x3) {
-+	case 2:
-+		*val >>= 16;
-+		break;
++	void __iomem *cpu_base, *dist_base;
++	int count;
++
++	/* Collect CPU base addresses */
++	count = acpi_parse_entries(sizeof(struct acpi_table_madt),
++				   gic_acpi_parse_madt_cpu, table,
++				   ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
++	if (count < 0) {
++		pr_err("Error during GICC entries parsing\n");
++		return -EFAULT;
++	} else if (!count) {
++		pr_err("No valid GICC entries exist\n");
++		return -EINVAL;
 +	}
 +
-+	*val &= 0xFFFF;
-+}
++	/*
++	 * Find distributor base address. We expect one distributor entry since
++	 * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
++	 */
++	count = acpi_parse_entries(sizeof(struct acpi_table_madt),
++				   gic_acpi_parse_madt_distributor, table,
++				   ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
++	if (count <= 0) {
++		pr_err("Error during GICD entries parsing\n");
++		return -EFAULT;
++	} else if (!count) {
++		pr_err("No valid GICD entries exist\n");
++		return -EINVAL;
++	} else if (count > 1) {
++		pr_err("More than one GICD entry detected\n");
++		return -EINVAL;
++	}
 +
-+static inline void
-+xgene_pcie_cfg_in8(void __iomem *addr, int offset, u32 *val)
-+{
-+	*val = readl(addr + (offset & ~0x3));
++	cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
++	if (!cpu_base) {
++		pr_err("Unable to map GICC registers\n");
++		return -ENOMEM;
++	}
 +
-+	switch (offset & 0x3) {
-+	case 3:
-+		*val = *val >> 24;
-+		break;
-+	case 2:
-+		*val = *val >> 16;
-+		break;
-+	case 1:
-+		*val = *val >> 8;
-+		break;
++	dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE);
++	if (!dist_base) {
++		pr_err("Unable to map GICD registers\n");
++		iounmap(cpu_base);
++		return -ENOMEM;
 +	}
-+	*val &= 0xFF;
++
++	/*
++	 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
++	 * as default IRQ domain to allow for GSI registration and GSI to IRQ
++	 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
++	 */
++	gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
++	irq_set_default_host(gic_data[0].domain);
++	return 0;
 +}
++#endif
+diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
+index 0fe2f71..9106c6d 100644
+--- a/drivers/irqchip/irqchip.c
++++ b/drivers/irqchip/irqchip.c
+@@ -11,6 +11,7 @@
+ #include <linux/init.h>
+ #include <linux/of_irq.h>
+ #include <linux/irqchip.h>
++#include <linux/irqchip/arm-gic-acpi.h>
+ 
+ /*
+  * This special of_device_id is the sentinel at the end of the
+@@ -26,4 +27,6 @@ extern struct of_device_id __irqchip_of_table[];
+ void __init irqchip_init(void)
+ {
+ 	of_irq_init(__irqchip_of_table);
 +
-+/* When the address bit [17:16] is 2'b01, the Configuration access will be
-+ * treated as Type 1 and it will be forwarded to external PCIe device.
++	acpi_gic_init();
+ }
+diff --git a/drivers/of/address.c b/drivers/of/address.c
+index e371825..afdb782 100644
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -5,6 +5,8 @@
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/pci_regs.h>
++#include <linux/sizes.h>
++#include <linux/slab.h>
+ #include <linux/string.h>
+ 
+ /* Max address size we deal with */
+@@ -293,6 +295,51 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
+ }
+ EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
+ 
++/*
++ * of_pci_range_to_resource - Create a resource from an of_pci_range
++ * @range:	the PCI range that describes the resource
++ * @np:		device node where the range belongs to
++ * @res:	pointer to a valid resource that will be updated to
++ *              reflect the values contained in the range.
++ *
++ * Returns EINVAL if the range cannot be converted to resource.
++ *
++ * Note that if the range is an IO range, the resource will be converted
++ * using pci_address_to_pio() which can fail if it is called too early or
++ * if the range cannot be matched to any host bridge IO space (our case here).
++ * To guard against that we try to register the IO range first.
++ * If that fails we know that pci_address_to_pio() will do too.
 + */
-+static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus)
++int of_pci_range_to_resource(struct of_pci_range *range,
++			     struct device_node *np, struct resource *res)
 +{
-+	struct xgene_pcie_port *port = bus->sysdata;
-+
-+	if (bus->number >= (bus->primary + 1))
-+		return port->cfg_base + AXI_EP_CFG_ACCESS;
-+
-+	return port->cfg_base;
-+}
-+
-+/* For Configuration request, RTDID register is used as Bus Number,
-+ * Device Number and Function number of the header fields.
-+ */
-+static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
-+{
-+	struct xgene_pcie_port *port = bus->sysdata;
-+	unsigned int b, d, f;
-+	u32 rtdid_val = 0;
-+
-+	b = bus->number;
-+	d = PCI_SLOT(devfn);
-+	f = PCI_FUNC(devfn);
++	int err;
++	res->flags = range->flags;
++	res->parent = res->child = res->sibling = NULL;
++	res->name = np->full_name;
 +
-+	if (!pci_is_root_bus(bus))
-+		rtdid_val = (b << 8) | (d << 3) | f;
++	if (res->flags & IORESOURCE_IO) {
++		unsigned long port;
++		err = pci_register_io_range(range->cpu_addr, range->size);
++		if (err)
++			goto invalid_range;
++		port = pci_address_to_pio(range->cpu_addr);
++		if (port == (unsigned long)-1) {
++			err = -EINVAL;
++			goto invalid_range;
++		}
++		res->start = port;
++	} else {
++		res->start = range->cpu_addr;
++	}
++	res->end = res->start + range->size - 1;
++	return 0;
 +
-+	writel(rtdid_val, port->csr_base + RTDID);
-+	/* read the register back to ensure flush */
-+	readl(port->csr_base + RTDID);
++invalid_range:
++	res->start = (resource_size_t)OF_BAD_ADDR;
++	res->end = (resource_size_t)OF_BAD_ADDR;
++	return err;
 +}
+ #endif /* CONFIG_PCI */
+ 
+ /*
+@@ -601,12 +648,119 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
+ }
+ EXPORT_SYMBOL(of_get_address);
+ 
++#ifdef PCI_IOBASE
++struct io_range {
++	struct list_head list;
++	phys_addr_t start;
++	resource_size_t size;
++};
 +
-+static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
-+				  int offset, int len, u32 *val)
++static LIST_HEAD(io_range_list);
++static DEFINE_SPINLOCK(io_range_lock);
++#endif
++
++/*
++ * Record the PCI IO range (expressed as CPU physical address + size).
++ * Return a negative value if an error has occured, zero otherwise
++ */
++int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 +{
-+	struct xgene_pcie_port *port = bus->sysdata;
-+	void __iomem *addr;
++	int err = 0;
 +
-+	if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
-+		return PCIBIOS_DEVICE_NOT_FOUND;
++#ifdef PCI_IOBASE
++	struct io_range *range;
++	resource_size_t allocated_size = 0;
 +
-+	xgene_pcie_set_rtdid_reg(bus, devfn);
-+	addr = xgene_pcie_get_cfg_base(bus);
-+	switch (len) {
-+	case 1:
-+		xgene_pcie_cfg_in8(addr, offset, val);
-+		break;
-+	case 2:
-+		xgene_pcie_cfg_in16(addr, offset, val);
-+		break;
-+	default:
-+		xgene_pcie_cfg_in32(addr, offset, val);
-+		break;
++	/* check if the range hasn't been previously recorded */
++	spin_lock(&io_range_lock);
++	list_for_each_entry(range, &io_range_list, list) {
++		if (addr >= range->start && addr + size <= range->start + size) {
++			/* range already registered, bail out */
++			goto end_register;
++		}
++		allocated_size += range->size;
 +	}
-+	return PCIBIOS_SUCCESSFUL;
-+}
 +
-+static int xgene_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
-+				   int offset, int len, u32 val)
-+{
-+	struct xgene_pcie_port *port = bus->sysdata;
-+	void __iomem *addr;
++	/* range not registed yet, check for available space */
++	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
++		/* if it's too big check if 64K space can be reserved */
++		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
++			err = -E2BIG;
++			goto end_register;
++		}
 +
-+	if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
-+		return PCIBIOS_DEVICE_NOT_FOUND;
++		size = SZ_64K;
++		pr_warn("Requested IO range too big, new size set to 64K\n");
++	}
 +
-+	xgene_pcie_set_rtdid_reg(bus, devfn);
-+	addr = xgene_pcie_get_cfg_base(bus);
-+	switch (len) {
-+	case 1:
-+		xgene_pcie_cfg_out8(addr, offset, (u8)val);
-+		break;
-+	case 2:
-+		xgene_pcie_cfg_out16(addr, offset, (u16)val);
-+		break;
-+	default:
-+		xgene_pcie_cfg_out32(addr, offset, val);
-+		break;
++	/* add the range to the list */
++	range = kzalloc(sizeof(*range), GFP_KERNEL);
++	if (!range) {
++		err = -ENOMEM;
++		goto end_register;
 +	}
-+	return PCIBIOS_SUCCESSFUL;
-+}
 +
-+static struct pci_ops xgene_pcie_ops = {
-+	.read = xgene_pcie_read_config,
-+	.write = xgene_pcie_write_config
-+};
++	range->start = addr;
++	range->size = size;
 +
-+static void xgene_pcie_program_core(void __iomem *csr_base)
-+{
-+	u32 val;
++	list_add_tail(&range->list, &io_range_list);
++
++end_register:
++	spin_unlock(&io_range_lock);
++#endif
 +
-+	val = readl(csr_base + BRIDGE_CFG_0);
-+	val |= AER_OPTIONAL_ERROR_EN;
-+	writel(val, csr_base + BRIDGE_CFG_0);
-+	writel(0x0, csr_base + INTXSTATUSMASK);
-+	val = readl(csr_base + BRIDGE_CTRL_1);
-+	val = (val & ~0xffff) | XGENE_PCIE_DEV_CTRL;
-+	writel(val, csr_base + BRIDGE_CTRL_1);
++	return err;
 +}
 +
-+static u64 xgene_pcie_set_ib_mask(void __iomem *csr_base, u32 addr,
-+				  u32 flags, u64 size)
++phys_addr_t pci_pio_to_address(unsigned long pio)
 +{
-+	u64 mask = (~(size - 1) & PCI_BASE_ADDRESS_MEM_MASK) | flags;
-+	u32 val32 = 0;
-+	u32 val;
-+
-+	val32 = readl(csr_base + addr);
-+	val = (val32 & 0x0000ffff) | (lower_32_bits(mask) << 16);
-+	writel(val, csr_base + addr);
++	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
 +
-+	val32 = readl(csr_base + addr + 0x04);
-+	val = (val32 & 0xffff0000) | (lower_32_bits(mask) >> 16);
-+	writel(val, csr_base + addr + 0x04);
++#ifdef PCI_IOBASE
++	struct io_range *range;
++	resource_size_t allocated_size = 0;
 +
-+	val32 = readl(csr_base + addr + 0x04);
-+	val = (val32 & 0x0000ffff) | (upper_32_bits(mask) << 16);
-+	writel(val, csr_base + addr + 0x04);
++	if (pio > IO_SPACE_LIMIT)
++		return address;
 +
-+	val32 = readl(csr_base + addr + 0x08);
-+	val = (val32 & 0xffff0000) | (upper_32_bits(mask) >> 16);
-+	writel(val, csr_base + addr + 0x08);
++	spin_lock(&io_range_lock);
++	list_for_each_entry(range, &io_range_list, list) {
++		if (pio >= allocated_size && pio < allocated_size + range->size) {
++			address = range->start + pio - allocated_size;
++			break;
++		}
++		allocated_size += range->size;
++	}
++	spin_unlock(&io_range_lock);
++#endif
 +
-+	return mask;
++	return address;
 +}
 +
-+static void xgene_pcie_poll_linkup(struct xgene_pcie_port *port,
-+				   u32 *lanes, u32 *speed)
-+{
-+	void __iomem *csr_base = port->csr_base;
-+	ulong timeout;
-+	u32 val32;
+ unsigned long __weak pci_address_to_pio(phys_addr_t address)
+ {
++#ifdef PCI_IOBASE
++	struct io_range *res;
++	resource_size_t offset = 0;
++	unsigned long addr = -1;
 +
-+	/*
-+	 * A component enters the LTSSM Detect state within
-+	 * 20ms of the end of fundamental core reset.
-+	 */
-+	msleep(XGENE_LTSSM_DETECT_WAIT);
-+	port->link_up = 0;
-+	timeout = jiffies + msecs_to_jiffies(XGENE_LTSSM_L0_WAIT);
-+	while (time_before(jiffies, timeout)) {
-+		val32 = readl(csr_base + PCIECORE_CTLANDSTATUS);
-+		if (val32 & LINK_UP_MASK) {
-+			port->link_up = 1;
-+			*speed = PIPE_PHY_RATE_RD(val32);
-+			val32 = readl(csr_base + BRIDGE_STATUS_0);
-+			*lanes = val32 >> 26;
++	spin_lock(&io_range_lock);
++	list_for_each_entry(res, &io_range_list, list) {
++		if (address >= res->start && address < res->start + res->size) {
++			addr = res->start - address + offset;
 +			break;
 +		}
-+		msleep(1);
++		offset += res->size;
 +	}
-+}
++	spin_unlock(&io_range_lock);
 +
-+static void xgene_pcie_setup_root_complex(struct xgene_pcie_port *port)
++	return addr;
++#else
+ 	if (address > IO_SPACE_LIMIT)
+ 		return (unsigned long)-1;
+ 
+ 	return (unsigned long) address;
++#endif
+ }
+ 
+ static int __of_address_to_resource(struct device_node *dev,
+diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
+index 8481996..8882b46 100644
+--- a/drivers/of/of_pci.c
++++ b/drivers/of/of_pci.c
+@@ -1,7 +1,9 @@
+ #include <linux/kernel.h>
+ #include <linux/export.h>
+ #include <linux/of.h>
++#include <linux/of_address.h>
+ #include <linux/of_pci.h>
++#include <linux/slab.h>
+ 
+ static inline int __of_pci_pci_compare(struct device_node *node,
+ 				       unsigned int data)
+@@ -89,6 +91,146 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
+ }
+ EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+ 
++/**
++ * This function will try to obtain the host bridge domain number by
++ * finding a property called "linux,pci-domain" of the given device node.
++ *
++ * @node: device tree node with the domain information
++ *
++ * Returns the associated domain number from DT in the range [0-0xffff], or
++ * a negative value if the required property is not found.
++ */
++int of_get_pci_domain_nr(struct device_node *node)
 +{
-+	void __iomem *csr_base = port->csr_base;
-+	u32 val;
-+
-+	val = (XGENE_PCIE_DEVICEID << 16) | XGENE_PCIE_VENDORID;
-+	writel(val, csr_base + BRIDGE_CFG_0);
++	const __be32 *value;
++	int len;
++	u16 domain;
 +
-+	val = readl(csr_base + BRIDGE_CFG_1);
-+	val &= ~CLASS_CODE_MASK;
-+	val |= PCI_CLASS_BRIDGE_PCI << 16;
-+	writel(val, csr_base + BRIDGE_CFG_1);
-+
-+	val = readl(csr_base + BRIDGE_CFG_14);
-+	val |= SWITCH_PORT_MODE_MASK;
-+	val &= ~PM_FORCE_RP_MODE_MASK;
-+	writel(val, csr_base + BRIDGE_CFG_14);
-+
-+	val = readl(csr_base + BRIDGE_CTRL_5);
-+	val &= ~DEVICE_PORT_TYPE_MASK;
-+	val |= XGENE_PORT_TYPE_RC;
-+	writel(val, csr_base + BRIDGE_CTRL_5);
++	value = of_get_property(node, "linux,pci-domain", &len);
++	if (!value || len < sizeof(*value))
++		return -EINVAL;
 +
-+	val = readl(csr_base + BRIDGE_CTRL_2);
-+	val |= ENABLE_ASPM;
-+	writel(val, csr_base + BRIDGE_CTRL_2);
++	domain = (u16)be32_to_cpup(value);
 +
-+	val = readl(csr_base + BRIDGE_CFG_32);
-+	writel(val | (1 << 19), csr_base + BRIDGE_CFG_32);
++	return domain;
 +}
++EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
 +
-+/* Return 0 on success */
-+static int xgene_pcie_init_ecc(struct xgene_pcie_port *port)
++#if defined(CONFIG_OF_ADDRESS)
++/**
++ * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
++ * @dev: device node of the host bridge having the range property
++ * @busno: bus number associated with the bridge root bus
++ * @bus_max: maximum number of buses for this bridge
++ * @resources: list where the range of resources will be added after DT parsing
++ * @io_base: pointer to a variable that will contain on return the physical
++ * address for the start of the I/O range. Can be NULL if the caller doesn't
++ * expect IO ranges to be present in the device tree.
++ *
++ * It is the caller's job to free the @resources list.
++ *
++ * This function will parse the "ranges" property of a PCI host bridge device
++ * node and setup the resource mapping based on its content. It is expected
++ * that the property conforms with the Power ePAPR document.
++ *
++ * It returns zero if the range parsing has been successful or a standard error
++ * value if it failed.
++ */
++int of_pci_get_host_bridge_resources(struct device_node *dev,
++			unsigned char busno, unsigned char bus_max,
++			struct list_head *resources, resource_size_t *io_base)
 +{
-+	void __iomem *csr_base = port->csr_base;
-+	ulong timeout;
-+	u32 val;
-+
-+	val = readl(csr_base + MEM_RAM_SHUTDOWN);
-+	if (!val)
-+		return 0;
-+	writel(0x0, csr_base + MEM_RAM_SHUTDOWN);
-+	timeout = jiffies + msecs_to_jiffies(XGENE_PCIE_ECC_TIMEOUT);
-+	while (time_before(jiffies, timeout)) {
-+		val = readl(csr_base + BLOCK_MEM_RDY);
-+		if (val == BLOCK_MEM_RDY_VAL)
-+			return 0;
-+		msleep(1);
-+	}
++	struct resource *res;
++	struct resource *bus_range;
++	struct of_pci_range range;
++	struct of_pci_range_parser parser;
++	char range_type[4];
++	int err;
 +
-+	return 1;
-+}
++	if (io_base)
++		*io_base = (resource_size_t)OF_BAD_ADDR;
 +
-+static int xgene_pcie_init_port(struct xgene_pcie_port *port)
-+{
-+	int rc;
++	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
++	if (!bus_range)
++		return -ENOMEM;
 +
-+	port->clk = clk_get(port->dev, NULL);
-+	if (IS_ERR(port->clk)) {
-+		dev_err(port->dev, "clock not available\n");
-+		return -ENODEV;
-+	}
++	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
 +
-+	rc = clk_prepare_enable(port->clk);
-+	if (rc) {
-+		dev_err(port->dev, "clock enable failed\n");
-+		return rc;
++	err = of_pci_parse_bus_range(dev, bus_range);
++	if (err) {
++		bus_range->start = busno;
++		bus_range->end = bus_max;
++		bus_range->flags = IORESOURCE_BUS;
++		pr_info("  No bus range found for %s, using %pR\n",
++			dev->full_name, bus_range);
++	} else {
++		if (bus_range->end > bus_range->start + bus_max)
++			bus_range->end = bus_range->start + bus_max;
 +	}
++	pci_add_resource(resources, bus_range);
 +
-+	rc = xgene_pcie_init_ecc(port);
-+	if (rc) {
-+		dev_err(port->dev, "memory init failed\n");
-+		return rc;
-+	}
++	/* Check for ranges property */
++	err = of_pci_range_parser_init(&parser, dev);
++	if (err)
++		goto parse_failed;
 +
-+	return 0;
-+}
++	pr_debug("Parsing ranges property...\n");
++	for_each_of_pci_range(&parser, &range) {
++		/* Read next ranges element */
++		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
++			snprintf(range_type, 4, " IO");
++		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
++			snprintf(range_type, 4, "MEM");
++		else
++			snprintf(range_type, 4, "err");
++		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
++			range.cpu_addr, range.cpu_addr + range.size - 1,
++			range.pci_addr);
 +
-+static void xgene_pcie_fixup_bridge(struct pci_dev *dev)
-+{
-+	int i;
++		/*
++		 * If we failed translation or got a zero-sized region
++		 * then skip this range
++		 */
++		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
++			continue;
++
++		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
++		if (!res) {
++			err = -ENOMEM;
++			goto parse_failed;
++		}
++
++		err = of_pci_range_to_resource(&range, dev, res);
++		if (err)
++			goto conversion_failed;
++
++		if (resource_type(res) == IORESOURCE_IO) {
++			if (!io_base) {
++				pr_err("I/O range found for %s. Please provide an io_base pointer to save CPU base address\n",
++					dev->full_name);
++				err = -EINVAL;
++				goto conversion_failed;
++			}
++			if (*io_base != (resource_size_t)OF_BAD_ADDR)
++				pr_warn("More than one I/O resource converted for %s. CPU base address for old range lost!\n",
++					dev->full_name);
++			*io_base = range.cpu_addr;
++		}
++
++		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
++	}
++
++	return 0;
++
++conversion_failed:
++	kfree(res);
++parse_failed:
++	pci_free_resource_list(resources);
++	return err;
++}
++EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
++#endif /* CONFIG_OF_ADDRESS */
++
+ #ifdef CONFIG_PCI_MSI
+ 
+ static LIST_HEAD(of_pci_msi_chip_list);
+diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
+index 90f5cca..382fd3d 100644
+--- a/drivers/pci/host/Kconfig
++++ b/drivers/pci/host/Kconfig
+@@ -63,4 +63,14 @@ config PCIE_SPEAR13XX
+ 	help
+ 	  Say Y here if you want PCIe support on SPEAr13XX SoCs.
+ 
++config PCI_XGENE
++	bool "X-Gene PCIe controller"
++	depends on ARCH_XGENE
++	depends on OF
++	select PCIEPORTBUS
++	help
++	  Say Y here if you want internal PCI support on APM X-Gene SoC.
++	  There are 5 internal PCIe ports available. Each port is GEN3 capable
++	  and have varied lanes from x1 to x8.
++
+ endmenu
+diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
+index d0e88f1..845611f 100644
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -8,3 +8,4 @@ obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
+ obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
+ obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
+ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
++obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
+diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
+index 0fb0fdb..946935d 100644
+--- a/drivers/pci/host/pci-tegra.c
++++ b/drivers/pci/host/pci-tegra.c
+@@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
+ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
+ {
+ 	struct tegra_pcie *pcie = sys_to_pcie(sys);
++	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
+ 
+ 	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
+ 	pci_add_resource_offset(&sys->resources, &pcie->prefetch,
+ 				sys->mem_offset);
+ 	pci_add_resource(&sys->resources, &pcie->busn);
+ 
+-	pci_ioremap_io(nr * SZ_64K, pcie->io.start);
++	pci_ioremap_io(nr * SZ_64K, io_start);
+ 
+ 	return 1;
+ }
+@@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
+ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
+ {
+ 	u32 fpci_bar, size, axi_address;
++	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
+ 
+ 	/* Bar 0: type 1 extended configuration space */
+ 	fpci_bar = 0xfe100000;
+@@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
+ 	/* Bar 1: downstream IO bar */
+ 	fpci_bar = 0xfdfc0000;
+ 	size = resource_size(&pcie->io);
+-	axi_address = pcie->io.start;
++	axi_address = io_start;
+ 	afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
+ 	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
+ 	afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
+@@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+ 	}
+ 
+ 	for_each_of_pci_range(&parser, &range) {
+-		of_pci_range_to_resource(&range, np, &res);
++		err = of_pci_range_to_resource(&range, np, &res);
++		if (err < 0)
++			return err;
+ 
+ 		switch (res.flags & IORESOURCE_TYPE_BITS) {
+ 		case IORESOURCE_IO:
+diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
+new file mode 100644
+index 0000000..dae61a6
+--- /dev/null
++++ b/drivers/pci/host/pci-xgene.c
+@@ -0,0 +1,646 @@
++/**
++ * APM X-Gene PCIe Driver
++ *
++ * Copyright (c) 2014 Applied Micro Circuits Corporation.
++ *
++ * Author: Tanmay Inamdar <tinamdar at apm.com>.
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ */
++#include <linux/clk-private.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
++#include <linux/memblock.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#define PCIECORE_CTLANDSTATUS		0x50
++#define PIM1_1L				0x80
++#define IBAR2				0x98
++#define IR2MSK				0x9c
++#define PIM2_1L				0xa0
++#define IBAR3L				0xb4
++#define IR3MSKL				0xbc
++#define PIM3_1L				0xc4
++#define OMR1BARL			0x100
++#define OMR2BARL			0x118
++#define OMR3BARL			0x130
++#define CFGBARL				0x154
++#define CFGBARH				0x158
++#define CFGCTL				0x15c
++#define RTDID				0x160
++#define BRIDGE_CFG_4			0x2010
++#define BRIDGE_STATUS_0			0x2600
++
++#define LINK_UP_MASK			0x00000100
++#define AXI_EP_CFG_ACCESS		0x10000
++#define EN_COHERENCY			0xF0000000
++#define EN_REG				0x00000001
++#define OB_LO_IO			0x00000002
++#define XGENE_PCIE_VENDORID		0x10E8
++#define XGENE_PCIE_DEVICEID		0xE004
++#define SZ_1T				(SZ_1G*1024ULL)
++#define PIPE_PHY_RATE_RD(src)		((0xc000 & (u32)(src)) >> 0xe)
++
++struct xgene_pcie_port {
++	struct device_node	*node;
++	struct device		*dev;
++	struct clk		*clk;
++	void __iomem		*csr_base;
++	void __iomem		*cfg_base;
++	unsigned long		cfg_addr;
++	bool			link_up;
++};
++
++static inline u32 pcie_bar_low_val(u32 addr, u32 flags)
++{
++	return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags;
++}
++
++/* PCIE Configuration Out/In */
++static inline void xgene_pcie_cfg_out32(void __iomem *addr, int offset, u32 val)
++{
++	writel(val, addr + offset);
++}
++
++static inline void xgene_pcie_cfg_out16(void __iomem *addr, int offset, u16 val)
++{
++	u32 val32 = readl(addr + (offset & ~0x3));
++
++	switch (offset & 0x3) {
++	case 2:
++		val32 &= ~0xFFFF0000;
++		val32 |= (u32)val << 16;
++		break;
++	case 0:
++	default:
++		val32 &= ~0xFFFF;
++		val32 |= val;
++		break;
++	}
++	writel(val32, addr + (offset & ~0x3));
++}
++
++static inline void xgene_pcie_cfg_out8(void __iomem *addr, int offset, u8 val)
++{
++	u32 val32 = readl(addr + (offset & ~0x3));
++
++	switch (offset & 0x3) {
++	case 0:
++		val32 &= ~0xFF;
++		val32 |= val;
++		break;
++	case 1:
++		val32 &= ~0xFF00;
++		val32 |= (u32)val << 8;
++		break;
++	case 2:
++		val32 &= ~0xFF0000;
++		val32 |= (u32)val << 16;
++		break;
++	case 3:
++	default:
++		val32 &= ~0xFF000000;
++		val32 |= (u32)val << 24;
++		break;
++	}
++	writel(val32, addr + (offset & ~0x3));
++}
++
++static inline void xgene_pcie_cfg_in32(void __iomem *addr, int offset, u32 *val)
++{
++	*val = readl(addr + offset);
++}
++
++static inline void
++xgene_pcie_cfg_in16(void __iomem *addr, int offset, u32 *val)
++{
++	*val = readl(addr + (offset & ~0x3));
++
++	switch (offset & 0x3) {
++	case 2:
++		*val >>= 16;
++		break;
++	}
++
++	*val &= 0xFFFF;
++}
++
++static inline void
++xgene_pcie_cfg_in8(void __iomem *addr, int offset, u32 *val)
++{
++	*val = readl(addr + (offset & ~0x3));
++
++	switch (offset & 0x3) {
++	case 3:
++		*val = *val >> 24;
++		break;
++	case 2:
++		*val = *val >> 16;
++		break;
++	case 1:
++		*val = *val >> 8;
++		break;
++	}
++	*val &= 0xFF;
++}
++
++/* When the address bit [17:16] is 2'b01, the Configuration access will be
++ * treated as Type 1 and it will be forwarded to external PCIe device.
++ */
++static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus)
++{
++	struct xgene_pcie_port *port = bus->sysdata;
++
++	if (bus->number >= (bus->primary + 1))
++		return port->cfg_base + AXI_EP_CFG_ACCESS;
++
++	return port->cfg_base;
++}
++
++/* For Configuration request, RTDID register is used as Bus Number,
++ * Device Number and Function number of the header fields.
++ */
++static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
++{
++	struct xgene_pcie_port *port = bus->sysdata;
++	unsigned int b, d, f;
++	u32 rtdid_val = 0;
++
++	b = bus->number;
++	d = PCI_SLOT(devfn);
++	f = PCI_FUNC(devfn);
++
++	if (!pci_is_root_bus(bus))
++		rtdid_val = (b << 8) | (d << 3) | f;
++
++	writel(rtdid_val, port->csr_base + RTDID);
++	/* read the register back to ensure flush */
++	readl(port->csr_base + RTDID);
++}
++
++static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
++				  int offset, int len, u32 *val)
++{
++	struct xgene_pcie_port *port = bus->sysdata;
++	void __iomem *addr;
++
++	if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	xgene_pcie_set_rtdid_reg(bus, devfn);
++	addr = xgene_pcie_get_cfg_base(bus);
++	switch (len) {
++	case 1:
++		xgene_pcie_cfg_in8(addr, offset, val);
++		break;
++	case 2:
++		xgene_pcie_cfg_in16(addr, offset, val);
++		break;
++	default:
++		xgene_pcie_cfg_in32(addr, offset, val);
++		break;
++	}
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int xgene_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
++				   int offset, int len, u32 val)
++{
++	struct xgene_pcie_port *port = bus->sysdata;
++	void __iomem *addr;
++
++	if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	xgene_pcie_set_rtdid_reg(bus, devfn);
++	addr = xgene_pcie_get_cfg_base(bus);
++	switch (len) {
++	case 1:
++		xgene_pcie_cfg_out8(addr, offset, (u8)val);
++		break;
++	case 2:
++		xgene_pcie_cfg_out16(addr, offset, (u16)val);
++		break;
++	default:
++		xgene_pcie_cfg_out32(addr, offset, val);
++		break;
++	}
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops xgene_pcie_ops = {
++	.read = xgene_pcie_read_config,
++	.write = xgene_pcie_write_config
++};
++
++static u64 xgene_pcie_set_ib_mask(void __iomem *csr_base, u32 addr,
++				  u32 flags, u64 size)
++{
++	u64 mask = (~(size - 1) & PCI_BASE_ADDRESS_MEM_MASK) | flags;
++	u32 val32 = 0;
++	u32 val;
++
++	val32 = readl(csr_base + addr);
++	val = (val32 & 0x0000ffff) | (lower_32_bits(mask) << 16);
++	writel(val, csr_base + addr);
++
++	val32 = readl(csr_base + addr + 0x04);
++	val = (val32 & 0xffff0000) | (lower_32_bits(mask) >> 16);
++	writel(val, csr_base + addr + 0x04);
++
++	val32 = readl(csr_base + addr + 0x04);
++	val = (val32 & 0x0000ffff) | (upper_32_bits(mask) << 16);
++	writel(val, csr_base + addr + 0x04);
++
++	val32 = readl(csr_base + addr + 0x08);
++	val = (val32 & 0xffff0000) | (upper_32_bits(mask) >> 16);
++	writel(val, csr_base + addr + 0x08);
++
++	return mask;
++}
++
++static void xgene_pcie_linkup(struct xgene_pcie_port *port,
++				   u32 *lanes, u32 *speed)
++{
++	void __iomem *csr_base = port->csr_base;
++	u32 val32;
++
++	port->link_up = false;
++	val32 = readl(csr_base + PCIECORE_CTLANDSTATUS);
++	if (val32 & LINK_UP_MASK) {
++		port->link_up = true;
++		*speed = PIPE_PHY_RATE_RD(val32);
++		val32 = readl(csr_base + BRIDGE_STATUS_0);
++		*lanes = val32 >> 26;
++	}
++}
++
++static int xgene_pcie_init_port(struct xgene_pcie_port *port)
++{
++	int rc;
++
++	port->clk = clk_get(port->dev, NULL);
++	if (IS_ERR(port->clk)) {
++		dev_err(port->dev, "clock not available\n");
++		return -ENODEV;
++	}
++
++	rc = clk_prepare_enable(port->clk);
++	if (rc) {
++		dev_err(port->dev, "clock enable failed\n");
++		return rc;
++	}
++
++	return 0;
++}
++
++static void xgene_pcie_fixup_bridge(struct pci_dev *dev)
++{
++	int i;
 +
 +	/* Hide the PCI host BARs from the kernel as their content doesn't
 +	 * fit well in the resource management
@@ -1610,493 +4211,1128 @@ index 0000000..7bf4ac7
 +	dev_info(&dev->dev, "Hiding X-Gene pci host bridge resources %s\n",
 +		 pci_name(dev));
 +}
-+DECLARE_PCI_FIXUP_HEADER(XGENE_PCIE_VENDORID, XGENE_PCIE_DEVICEID,
-+			 xgene_pcie_fixup_bridge);
++DECLARE_PCI_FIXUP_HEADER(XGENE_PCIE_VENDORID, XGENE_PCIE_DEVICEID,
++			 xgene_pcie_fixup_bridge);
++
++static int xgene_pcie_map_reg(struct xgene_pcie_port *port,
++			      struct platform_device *pdev)
++{
++	struct resource *res;
++
++	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr");
++	port->csr_base = devm_ioremap_resource(port->dev, res);
++	if (IS_ERR(port->csr_base))
++		return PTR_ERR(port->csr_base);
++
++	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
++	port->cfg_base = devm_ioremap_resource(port->dev, res);
++	if (IS_ERR(port->cfg_base))
++		return PTR_ERR(port->cfg_base);
++	port->cfg_addr = res->start;
++
++	return 0;
++}
++
++static void xgene_pcie_setup_ob_reg(struct xgene_pcie_port *port,
++				    struct resource *res, u32 offset,
++				    u64 cpu_addr, u64 pci_addr)
++{
++	void __iomem *base = port->csr_base + offset;
++	resource_size_t size = resource_size(res);
++	u64 restype = resource_type(res);
++	u64 mask = 0;
++	u32 min_size;
++	u32 flag = EN_REG;
++
++	if (restype == IORESOURCE_MEM) {
++		min_size = SZ_128M;
++	} else {
++		min_size = 128;
++		flag |= OB_LO_IO;
++	}
++
++	if (size >= min_size)
++		mask = ~(size - 1) | flag;
++	else
++		dev_warn(port->dev, "res size 0x%llx less than minimum 0x%x\n",
++			 (u64)size, min_size);
++
++	writel(lower_32_bits(cpu_addr), base);
++	writel(upper_32_bits(cpu_addr), base + 0x04);
++	writel(lower_32_bits(mask), base + 0x08);
++	writel(upper_32_bits(mask), base + 0x0c);
++	writel(lower_32_bits(pci_addr), base + 0x10);
++	writel(upper_32_bits(pci_addr), base + 0x14);
++}
++
++static void xgene_pcie_setup_cfg_reg(void __iomem *csr_base, u64 addr)
++{
++	writel(lower_32_bits(addr), csr_base + CFGBARL);
++	writel(upper_32_bits(addr), csr_base + CFGBARH);
++	writel(EN_REG, csr_base + CFGCTL);
++}
++
++static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
++				 struct list_head *res,
++				 resource_size_t io_base)
++{
++	struct pci_host_bridge_window *window;
++	struct device *dev = port->dev;
++	int ret;
++
++	list_for_each_entry(window, res, list) {
++		struct resource *res = window->res;
++		u64 restype = resource_type(res);
++
++		dev_dbg(port->dev, "0x%08lx 0x%016llx...0x%016llx\n",
++			res->flags, res->start, res->end);
++
++		switch (restype) {
++		case IORESOURCE_IO:
++			xgene_pcie_setup_ob_reg(port, res, OMR3BARL, io_base,
++						res->start - window->offset);
++			ret = pci_remap_iospace(res, io_base);
++			if (ret < 0)
++				return ret;
++			break;
++		case IORESOURCE_MEM:
++			xgene_pcie_setup_ob_reg(port, res, OMR1BARL, res->start,
++						res->start - window->offset);
++			break;
++		case IORESOURCE_BUS:
++			break;
++		default:
++			dev_err(dev, "invalid io resource!");
++			return -EINVAL;
++		}
++	}
++	xgene_pcie_setup_cfg_reg(port->csr_base, port->cfg_addr);
++
++	return 0;
++}
++
++static void xgene_pcie_setup_pims(void *addr, u64 pim, u64 size)
++{
++	writel(lower_32_bits(pim), addr);
++	writel(upper_32_bits(pim) | EN_COHERENCY, addr + 0x04);
++	writel(lower_32_bits(size), addr + 0x10);
++	writel(upper_32_bits(size), addr + 0x14);
++}
++
++/*
++ * X-Gene PCIe support maximum 3 inbound memory regions
++ * This function helps to select a region based on size of region
++ */
++static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size)
++{
++	if ((size > 4) && (size < SZ_16M) && !(*ib_reg_mask & (1 << 1))) {
++		*ib_reg_mask |= (1 << 1);
++		return 1;
++	}
++
++	if ((size > SZ_1K) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 0))) {
++		*ib_reg_mask |= (1 << 0);
++		return 0;
++	}
++
++	if ((size > SZ_1M) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 2))) {
++		*ib_reg_mask |= (1 << 2);
++		return 2;
++	}
++
++	return -EINVAL;
++}
++
++static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port,
++				    struct of_pci_range *range, u8 *ib_reg_mask)
++{
++	void __iomem *csr_base = port->csr_base;
++	void __iomem *cfg_base = port->cfg_base;
++	void *bar_addr;
++	void *pim_addr;
++	u64 cpu_addr = range->cpu_addr;
++	u64 pci_addr = range->pci_addr;
++	u64 size = range->size;
++	u64 mask = ~(size - 1) | EN_REG;
++	u32 flags = PCI_BASE_ADDRESS_MEM_TYPE_64;
++	u32 bar_low;
++	int region;
++
++	region = xgene_pcie_select_ib_reg(ib_reg_mask, range->size);
++	if (region < 0) {
++		dev_warn(port->dev, "invalid pcie dma-range config\n");
++		return;
++	}
++
++	if (range->flags & IORESOURCE_PREFETCH)
++		flags |= PCI_BASE_ADDRESS_MEM_PREFETCH;
++
++	bar_low = pcie_bar_low_val((u32)cpu_addr, flags);
++	switch (region) {
++	case 0:
++		xgene_pcie_set_ib_mask(csr_base, BRIDGE_CFG_4, flags, size);
++		bar_addr = cfg_base + PCI_BASE_ADDRESS_0;
++		writel(bar_low, bar_addr);
++		writel(upper_32_bits(cpu_addr), bar_addr + 0x4);
++		pim_addr = csr_base + PIM1_1L;
++		break;
++	case 1:
++		bar_addr = csr_base + IBAR2;
++		writel(bar_low, bar_addr);
++		writel(lower_32_bits(mask), csr_base + IR2MSK);
++		pim_addr = csr_base + PIM2_1L;
++		break;
++	case 2:
++		bar_addr = csr_base + IBAR3L;
++		writel(bar_low, bar_addr);
++		writel(upper_32_bits(cpu_addr), bar_addr + 0x4);
++		writel(lower_32_bits(mask), csr_base + IR3MSKL);
++		writel(upper_32_bits(mask), csr_base + IR3MSKL + 0x4);
++		pim_addr = csr_base + PIM3_1L;
++		break;
++	}
++
++	xgene_pcie_setup_pims(pim_addr, pci_addr, ~(size - 1));
++}
++
++static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
++				     struct device_node *node)
++{
++	const int na = 3, ns = 2;
++	int rlen;
++
++	parser->node = node;
++	parser->pna = of_n_addr_cells(node);
++	parser->np = parser->pna + na + ns;
++
++	parser->range = of_get_property(node, "dma-ranges", &rlen);
++	if (!parser->range)
++		return -ENOENT;
++	parser->end = parser->range + rlen / sizeof(__be32);
++
++	return 0;
++}
++
++static int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port)
++{
++	struct device_node *np = port->node;
++	struct of_pci_range range;
++	struct of_pci_range_parser parser;
++	struct device *dev = port->dev;
++	u8 ib_reg_mask = 0;
++
++	if (pci_dma_range_parser_init(&parser, np)) {
++		dev_err(dev, "missing dma-ranges property\n");
++		return -EINVAL;
++	}
++
++	/* Get the dma-ranges from DT */
++	for_each_of_pci_range(&parser, &range) {
++		u64 end = range.cpu_addr + range.size - 1;
++
++		dev_dbg(port->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
++			range.flags, range.cpu_addr, end, range.pci_addr);
++		xgene_pcie_setup_ib_reg(port, &range, &ib_reg_mask);
++	}
++	return 0;
++}
++
++/* clear bar configuration which was done by firmware */
++static void xgene_pcie_clear_config(struct xgene_pcie_port *port)
++{
++	int i;
++
++	for (i = PIM1_1L; i <= CFGCTL; i += 4)
++		writel(0x0, port->csr_base + i);
++}
 +
-+static int xgene_pcie_map_reg(struct xgene_pcie_port *port,
-+			      struct platform_device *pdev, u64 *cfg_addr)
++static int xgene_pcie_setup(struct xgene_pcie_port *port,
++			    struct list_head *res,
++			    resource_size_t io_base)
 +{
-+	struct resource *res;
++	u32 lanes = 0, speed = 0;
++	int ret;
 +
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr");
-+	port->csr_base = devm_ioremap_resource(port->dev, res);
-+	if (IS_ERR(port->csr_base))
-+		return PTR_ERR(port->csr_base);
++	xgene_pcie_clear_config(port);
 +
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
-+	port->cfg_base = devm_ioremap_resource(port->dev, res);
-+	if (IS_ERR(port->cfg_base))
-+		return PTR_ERR(port->cfg_base);
-+	*cfg_addr = res->start;
++	ret = xgene_pcie_map_ranges(port, res, io_base);
++	if (ret)
++		return ret;
++
++	ret = xgene_pcie_parse_map_dma_ranges(port);
++	if (ret)
++		return ret;
 +
++	xgene_pcie_linkup(port, &lanes, &speed);
++	if (!port->link_up)
++		dev_info(port->dev, "(rc) link down\n");
++	else
++		dev_info(port->dev, "(rc) x%d gen-%d link up\n",
++				lanes, speed + 1);
 +	return 0;
 +}
 +
-+static void xgene_pcie_setup_ob_reg(struct xgene_pcie_port *port,
-+				    struct resource *res, u32 offset, u64 addr)
++static int xgene_pcie_probe_bridge(struct platform_device *pdev)
 +{
-+	void __iomem *base = port->csr_base + offset;
-+	resource_size_t size = resource_size(res);
-+	u64 restype = resource_type(res);
-+	u64 cpu_addr, pci_addr;
-+	u64 mask = 0;
-+	u32 min_size;
-+	u32 flag = EN_REG;
++	struct device_node *dn = pdev->dev.of_node;
++	struct xgene_pcie_port *port;
++	resource_size_t iobase = 0;
++	struct pci_bus *bus;
++	int ret;
++	LIST_HEAD(res);
 +
-+	if (restype == IORESOURCE_MEM) {
-+		cpu_addr = res->start;
-+		pci_addr = addr;
-+		min_size = SZ_128M;
-+	} else {
-+		cpu_addr = addr;
-+		pci_addr = res->start;
-+		min_size = 128;
-+		flag |= OB_LO_IO;
-+	}
-+	if (size >= min_size)
-+		mask = ~(size - 1) | flag;
++	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
++	if (!port)
++		return -ENOMEM;
++	port->node = of_node_get(pdev->dev.of_node);
++	port->dev = &pdev->dev;
++
++	ret = xgene_pcie_map_reg(port, pdev);
++	if (ret)
++		return ret;
++
++	ret = xgene_pcie_init_port(port);
++	if (ret)
++		return ret;
++
++	ret = of_pci_get_host_bridge_resources(dn, 0, 0xff, &res, &iobase);
++	if (ret)
++		return ret;
++
++	ret = xgene_pcie_setup(port, &res, iobase);
++	if (ret)
++		return ret;
++
++	bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res);
++	if (!bus)
++		return -ENOMEM;
++
++	platform_set_drvdata(pdev, port);
++	return 0;
++}
++
++static const struct of_device_id xgene_pcie_match_table[] = {
++	{.compatible = "apm,xgene-pcie",},
++	{},
++};
++
++static struct platform_driver xgene_pcie_driver = {
++	.driver = {
++		   .name = "xgene-pcie",
++		   .owner = THIS_MODULE,
++		   .of_match_table = of_match_ptr(xgene_pcie_match_table),
++	},
++	.probe = xgene_pcie_probe_bridge,
++};
++module_platform_driver(xgene_pcie_driver);
++
++MODULE_AUTHOR("Tanmay Inamdar <tinamdar at apm.com>");
++MODULE_DESCRIPTION("APM X-Gene PCIe driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
+index 4884ee5..61158e0 100644
+--- a/drivers/pci/host/pcie-rcar.c
++++ b/drivers/pci/host/pcie-rcar.c
+@@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
+ 
+ 	/* Setup PCIe address space mappings for each resource */
+ 	resource_size_t size;
++	resource_size_t res_start;
+ 	u32 mask;
+ 
+ 	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
+@@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
+ 	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+ 	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
+ 
+-	rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
+-	rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
++	if (res->flags & IORESOURCE_IO)
++		res_start = pci_pio_to_address(res->start);
 +	else
-+		dev_warn(port->dev, "res size 0x%llx less than minimum 0x%x\n",
-+			 (u64)size, min_size);
-+	writel(lower_32_bits(cpu_addr), base);
-+	writel(upper_32_bits(cpu_addr), base + 0x04);
-+	writel(lower_32_bits(mask), base + 0x08);
-+	writel(upper_32_bits(mask), base + 0x0c);
-+	writel(lower_32_bits(pci_addr), base + 0x10);
-+	writel(upper_32_bits(pci_addr), base + 0x14);
++		res_start = res->start;
++
++	rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
++	rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
+ 
+ 	/* First resource is for IO */
+ 	mask = PAR_ENABLE;
+@@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
+ 
+ 		rcar_pcie_setup_window(i, pcie);
+ 
+-		if (res->flags & IORESOURCE_IO)
+-			pci_ioremap_io(nr * SZ_64K, res->start);
+-		else
++		if (res->flags & IORESOURCE_IO) {
++			phys_addr_t io_start = pci_pio_to_address(res->start);
++			pci_ioremap_io(nr * SZ_64K, io_start);
++		} else
+ 			pci_add_resource(&sys->resources, res);
+ 	}
+ 	pci_add_resource(&sys->resources, &pcie->busn);
+@@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	for_each_of_pci_range(&parser, &range) {
+-		of_pci_range_to_resource(&range, pdev->dev.of_node,
++		err = of_pci_range_to_resource(&range, pdev->dev.of_node,
+ 						&pcie->res[win++]);
++		if (err < 0)
++			return err;
+ 
+ 		if (win > RCAR_PCI_MAX_RESOURCES)
+ 			break;
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 2c9ac70..6e994fc 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -2704,6 +2704,37 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
+ }
+ EXPORT_SYMBOL(pci_request_regions_exclusive);
+ 
++/**
++ *	pci_remap_iospace - Remap the memory mapped I/O space
++ *	@res: Resource describing the I/O space
++ *	@phys_addr: physical address of range to be mapped
++ *
++ *	Remap the memory mapped I/O space described by the @res
++ *	and the CPU physical address @phys_addr into virtual address space.
++ *	Only architectures that have memory mapped IO functions defined
++ *	(and the PCI_IOBASE value defined) should call this function.
++ */
++int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
++{
++#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
++	unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
++
++	if (!(res->flags & IORESOURCE_IO))
++		return -EINVAL;
++
++	if (res->end > IO_SPACE_LIMIT)
++		return -EINVAL;
++
++	return ioremap_page_range(vaddr, vaddr + resource_size(res), phys_addr,
++				  pgprot_device(PAGE_KERNEL));
++#else
++	/* this architecture does not have memory mapped I/O space,
++	   so this function should never be called */
++	WARN_ONCE(1, "This architecture does not support memory mapped I/O\n");
++	return -ENODEV;
++#endif
++}
++
+ static void __pci_set_master(struct pci_dev *dev, bool enable)
+ {
+ 	u16 old_cmd, cmd;
+@@ -4406,6 +4437,15 @@ static void pci_no_domains(void)
+ #endif
+ }
+ 
++#ifdef CONFIG_PCI_DOMAINS
++static atomic_t __domain_nr = ATOMIC_INIT(-1);
++
++int pci_get_new_domain_nr(void)
++{
++	return atomic_inc_return(&__domain_nr);
 +}
++#endif
++
+ /**
+  * pci_ext_cfg_avail - can we access extended PCI config space?
+  *
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 4170113..c3cec34 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -485,7 +485,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
+ 	}
+ }
+ 
+-static struct pci_bus *pci_alloc_bus(void)
++static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
+ {
+ 	struct pci_bus *b;
+ 
+@@ -500,6 +500,10 @@ static struct pci_bus *pci_alloc_bus(void)
+ 	INIT_LIST_HEAD(&b->resources);
+ 	b->max_bus_speed = PCI_SPEED_UNKNOWN;
+ 	b->cur_bus_speed = PCI_SPEED_UNKNOWN;
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++	if (parent)
++		b->domain_nr = parent->domain_nr;
++#endif
+ 	return b;
+ }
+ 
+@@ -515,7 +519,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
+ 	kfree(bridge);
+ }
+ 
+-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
++static struct pci_host_bridge *pci_alloc_host_bridge(void)
+ {
+ 	struct pci_host_bridge *bridge;
+ 
+@@ -524,7 +528,8 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+ 		return NULL;
+ 
+ 	INIT_LIST_HEAD(&bridge->windows);
+-	bridge->bus = b;
++	bridge->dev.release = pci_release_host_bridge_dev;
++
+ 	return bridge;
+ }
+ 
+@@ -671,7 +676,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
+ 	/*
+ 	 * Allocate a new bus, and inherit stuff from the parent..
+ 	 */
+-	child = pci_alloc_bus();
++	child = pci_alloc_bus(parent);
+ 	if (!child)
+ 		return NULL;
+ 
+@@ -1751,37 +1756,37 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ 	char bus_addr[64];
+ 	char *fmt;
+ 
+-	b = pci_alloc_bus();
+-	if (!b)
++	bridge = pci_alloc_host_bridge();
++	if (!bridge)
+ 		return NULL;
+ 
++	bridge->dev.parent = parent;
++
++	b = pci_alloc_bus(NULL);
++	if (!b)
++		goto err_out;
++
+ 	b->sysdata = sysdata;
+ 	b->ops = ops;
+ 	b->number = b->busn_res.start = bus;
++	pci_bus_assign_domain_nr(b, parent);
+ 	b2 = pci_find_bus(pci_domain_nr(b), bus);
+ 	if (b2) {
+ 		/* If we already got to this bus through a different bridge, ignore it */
+ 		dev_dbg(&b2->dev, "bus already known\n");
+-		goto err_out;
++		goto err_bus_out;
+ 	}
+ 
+-	bridge = pci_alloc_host_bridge(b);
+-	if (!bridge)
+-		goto err_out;
+-
+-	bridge->dev.parent = parent;
+-	bridge->dev.release = pci_release_host_bridge_dev;
++	bridge->bus = b;
+ 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ 	error = pcibios_root_bridge_prepare(bridge);
+-	if (error) {
+-		kfree(bridge);
++	if (error)
+ 		goto err_out;
+-	}
+ 
+ 	error = device_register(&bridge->dev);
+ 	if (error) {
+ 		put_device(&bridge->dev);
+-		goto err_out;
++		goto err_bus_out;
+ 	}
+ 	b->bridge = get_device(&bridge->dev);
+ 	device_enable_async_suspend(b->bridge);
+@@ -1838,8 +1843,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ class_dev_reg_err:
+ 	put_device(&bridge->dev);
+ 	device_unregister(&bridge->dev);
+-err_out:
++err_bus_out:
+ 	kfree(b);
++err_out:
++	kfree(bridge);
+ 	return NULL;
+ }
+ 
+@@ -1936,6 +1943,9 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+ 	if (!found)
+ 		pci_bus_update_busn_res_end(b, max);
+ 
++	if (!pci_has_flag(PCI_PROBE_ONLY))
++		pci_assign_unassigned_bus_resources(b);
++
+ 	pci_bus_add_devices(b);
+ 	return b;
+ }
+diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
+index 782e822..d952462 100644
+--- a/drivers/pnp/resource.c
++++ b/drivers/pnp/resource.c
+@@ -313,6 +313,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
+ 	progif = class & 0xff;
+ 	class >>= 8;
+ 
++#ifdef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
+ 	if (class == PCI_CLASS_STORAGE_IDE) {
+ 		/*
+ 		 * Unless both channels are native-PCI mode only,
+@@ -326,6 +327,7 @@ static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
+ 				return 1;
+ 			}
+ 	}
++#endif /* HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ */
+ 
+ 	return 0;
+ }
+diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
+index b24aa01..50fe279 100644
+--- a/drivers/tty/Kconfig
++++ b/drivers/tty/Kconfig
+@@ -419,4 +419,10 @@ config DA_CONSOLE
+ 	help
+ 	  This enables a console on a Dash channel.
+ 
++config SBSAUART_TTY
++	tristate "SBSA UART TTY Driver"
++	help
++	  Console and system TTY driver for the SBSA UART which is defined
++	  in the Server Base System Architecure document for ARM64 servers.
++
+ endif # TTY
+diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
+index 58ad1c0..c3211c0 100644
+--- a/drivers/tty/Makefile
++++ b/drivers/tty/Makefile
+@@ -29,5 +29,6 @@ obj-$(CONFIG_SYNCLINK)		+= synclink.o
+ obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o
+ obj-$(CONFIG_GOLDFISH_TTY)	+= goldfish.o
+ obj-$(CONFIG_DA_TTY)		+= metag_da.o
++obj-$(CONFIG_SBSAUART_TTY)	+= sbsauart.o
+ 
+ obj-y += ipwireless/
+diff --git a/drivers/tty/sbsauart.c b/drivers/tty/sbsauart.c
+new file mode 100644
+index 0000000..402f168
+--- /dev/null
++++ b/drivers/tty/sbsauart.c
+@@ -0,0 +1,355 @@
++/*
++ * SBSA (Server Base System Architecture) Compatible UART driver
++ *
++ * Copyright (C) 2014 Linaro Ltd
++ *
++ * Author: Graeme Gregory <graeme.gregory at linaro.org>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ */
 +
-+static void xgene_pcie_setup_cfg_reg(void __iomem *csr_base, u64 addr)
++#include <linux/acpi.h>
++#include <linux/amba/serial.h>
++#include <linux/console.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/serial_core.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++
++struct sbsa_tty {
++	struct tty_port port;
++	spinlock_t lock;
++	void __iomem *base;
++	u32 irq;
++	int opencount;
++	struct console console;
++};
++
++static struct tty_driver *sbsa_tty_driver;
++static struct sbsa_tty *sbsa_tty;
++
++#define SBSAUART_CHAR_MASK	0xFF
++
++static void sbsa_raw_putc(struct uart_port *port, int c)
 +{
-+	writel(lower_32_bits(addr), csr_base + CFGBARL);
-+	writel(upper_32_bits(addr), csr_base + CFGBARH);
-+	writel(EN_REG, csr_base + CFGCTL);
++	while (readw(port->membase + UART01x_FR) & UART01x_FR_TXFF)
++		;
++	writew(c & 0xFF, port->membase + UART01x_DR);
 +}
 +
-+static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
-+				 struct pci_host_bridge *bridge,
-+				 u64 cfg_addr)
++static void sbsa_uart_early_write(struct console *con, const char *buf,
++				  unsigned count)
 +{
-+	struct device *dev = port->dev;
-+	struct pci_host_bridge_window *window;
-+	int ret;
++	struct earlycon_device *dev = con->data;
 +
-+	list_for_each_entry(window, &bridge->windows, list) {
-+		struct resource *res = window->res;
-+		u64 restype = resource_type(res);
-+		dev_dbg(port->dev, "0x%08lx 0x%016llx...0x%016llx\n",
-+			res->flags, res->start, res->end);
++	uart_console_write(&dev->port, buf, count, sbsa_raw_putc);
++}
 +
-+		switch (restype) {
-+		case IORESOURCE_IO:
-+			xgene_pcie_setup_ob_reg(port, res, OMR2BARL,
-+						bridge->io_base);
-+			ret = pci_remap_iospace(res, bridge->io_base);
-+			if (ret < 0)
-+				return ret;
-+			break;
-+		case IORESOURCE_MEM:
-+			xgene_pcie_setup_ob_reg(port, res, OMR3BARL,
-+						res->start - window->offset);
-+			break;
-+		case IORESOURCE_BUS:
-+			break;
-+		default:
-+			dev_err(dev, "invalid io resource!");
-+			return -EINVAL;
-+		}
-+	}
-+	xgene_pcie_setup_cfg_reg(port->csr_base, cfg_addr);
++static int __init sbsa_uart_early_console_setup(struct earlycon_device *device,
++						const char *opt)
++{
++	if (!device->port.membase)
++		return -ENODEV;
++
++	device->con->write = sbsa_uart_early_write;
 +	return 0;
 +}
++EARLYCON_DECLARE(sbsauart, sbsa_uart_early_console_setup);
 +
-+static void xgene_pcie_setup_pims(void *addr, u64 pim, u64 size)
++static void sbsa_tty_do_write(const char *buf, unsigned count)
 +{
-+	writel(lower_32_bits(pim), addr);
-+	writel(upper_32_bits(pim) | EN_COHERENCY, addr + 0x04);
-+	writel(lower_32_bits(size), addr + 0x10);
-+	writel(upper_32_bits(size), addr + 0x14);
++	unsigned long irq_flags;
++	struct sbsa_tty *qtty = sbsa_tty;
++	void __iomem *base = qtty->base;
++	unsigned n;
++
++	spin_lock_irqsave(&qtty->lock, irq_flags);
++	for (n = 0; n < count; n++) {
++		while (readw(base + UART01x_FR) & UART01x_FR_TXFF)
++			;
++		writew(buf[n], base + UART01x_DR);
++	}
++	spin_unlock_irqrestore(&qtty->lock, irq_flags);
 +}
 +
-+/*
-+ * X-Gene PCIe support maximum 3 inbound memory regions
-+ * This function helps to select a region based on size of region
-+ */
-+static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size)
++static void sbsauart_fifo_to_tty(struct sbsa_tty *qtty)
 +{
-+	if ((size > 4) && (size < SZ_16M) && !(*ib_reg_mask & (1 << 1))) {
-+		*ib_reg_mask |= (1 << 1);
-+		return 1;
-+	}
++	void __iomem *base = qtty->base;
++	unsigned int flag, max_count = 32;
++	u16 status, ch;
 +
-+	if ((size > SZ_1K) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 0))) {
-+		*ib_reg_mask |= (1 << 0);
-+		return 0;
-+	}
++	while (max_count--) {
++		status = readw(base + UART01x_FR);
++		if (status & UART01x_FR_RXFE)
++			break;
 +
-+	if ((size > SZ_1M) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 2))) {
-+		*ib_reg_mask |= (1 << 2);
-+		return 2;
++		/* Take chars from the FIFO and update status */
++		ch = readw(base + UART01x_DR);
++		flag = TTY_NORMAL;
++
++		if (ch & UART011_DR_BE)
++			flag = TTY_BREAK;
++		else if (ch & UART011_DR_PE)
++			flag = TTY_PARITY;
++		else if (ch & UART011_DR_FE)
++			flag = TTY_FRAME;
++		else if (ch & UART011_DR_OE)
++			flag = TTY_OVERRUN;
++
++		ch &= SBSAUART_CHAR_MASK;
++
++		tty_insert_flip_char(&qtty->port, ch, flag);
 +	}
-+	return -EINVAL;
++
++	tty_schedule_flip(&qtty->port);
++
++	/* Clear the RX IRQ */
++	writew(UART011_RXIC | UART011_RXIC, base + UART011_ICR);
 +}
 +
-+static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port,
-+				    struct of_pci_range *range, u8 *ib_reg_mask)
++static irqreturn_t sbsa_tty_interrupt(int irq, void *dev_id)
 +{
-+	void __iomem *csr_base = port->csr_base;
-+	void __iomem *cfg_base = port->cfg_base;
-+	void *bar_addr;
-+	void *pim_addr;
-+	u64 restype = range->flags & IORESOURCE_TYPE_BITS;
-+	u64 cpu_addr = range->cpu_addr;
-+	u64 pci_addr = range->pci_addr;
-+	u64 size = range->size;
-+	u64 mask = ~(size - 1) | EN_REG;
-+	u32 flags = PCI_BASE_ADDRESS_MEM_TYPE_64;
-+	u32 bar_low;
-+	int region;
++	struct sbsa_tty *qtty = sbsa_tty;
++	unsigned long irq_flags;
 +
-+	region = xgene_pcie_select_ib_reg(ib_reg_mask, range->size);
-+	if (region < 0) {
-+		dev_warn(port->dev, "invalid pcie dma-range config\n");
-+		return;
-+	}
++	spin_lock_irqsave(&qtty->lock, irq_flags);
++	sbsauart_fifo_to_tty(qtty);
++	spin_unlock_irqrestore(&qtty->lock, irq_flags);
 +
-+	if (restype == PCI_BASE_ADDRESS_MEM_PREFETCH)
-+		flags |= PCI_BASE_ADDRESS_MEM_PREFETCH;
++	return IRQ_HANDLED;
++}
 +
-+	bar_low = pcie_bar_low_val((u32)cpu_addr, flags);
-+	switch (region) {
-+	case 0:
-+		xgene_pcie_set_ib_mask(csr_base, BRIDGE_CFG_4, flags, size);
-+		bar_addr = cfg_base + PCI_BASE_ADDRESS_0;
-+		writel(bar_low, bar_addr);
-+		writel(upper_32_bits(cpu_addr), bar_addr + 0x4);
-+		pim_addr = csr_base + PIM1_1L;
-+		break;
-+	case 1:
-+		bar_addr = csr_base + IBAR2;
-+		writel(bar_low, bar_addr);
-+		writel(lower_32_bits(mask), csr_base + IR2MSK);
-+		pim_addr = csr_base + PIM2_1L;
-+		break;
-+	case 2:
-+		bar_addr = csr_base + IBAR3L;
-+		writel(bar_low, bar_addr);
-+		writel(upper_32_bits(cpu_addr), bar_addr + 0x4);
-+		writel(lower_32_bits(mask), csr_base + IR3MSKL);
-+		writel(upper_32_bits(mask), csr_base + IR3MSKL + 0x4);
-+		pim_addr = csr_base + PIM3_1L;
-+		break;
-+	}
++static int sbsa_tty_open(struct tty_struct *tty, struct file *filp)
++{
++	struct sbsa_tty *qtty = sbsa_tty;
 +
-+	xgene_pcie_setup_pims(pim_addr, pci_addr, size);
++	return tty_port_open(&qtty->port, tty, filp);
 +}
 +
-+static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
-+				     struct device_node *node)
++static void sbsa_tty_close(struct tty_struct *tty, struct file *filp)
 +{
-+	const int na = 3, ns = 2;
-+	int rlen;
++	tty_port_close(tty->port, tty, filp);
++}
 +
-+	parser->node = node;
-+	parser->pna = of_n_addr_cells(node);
-+	parser->np = parser->pna + na + ns;
++static void sbsa_tty_hangup(struct tty_struct *tty)
++{
++	tty_port_hangup(tty->port);
++}
 +
-+	parser->range = of_get_property(node, "dma-ranges", &rlen);
-+	if (!parser->range)
-+		return -ENOENT;
++static int sbsa_tty_write(struct tty_struct *tty, const unsigned char *buf,
++								int count)
++{
++	sbsa_tty_do_write(buf, count);
++	return count;
++}
 +
-+	parser->end = parser->range + rlen / sizeof(__be32);
++static int sbsa_tty_write_room(struct tty_struct *tty)
++{
++	return 32;
++}
++
++static void sbsa_tty_console_write(struct console *co, const char *b,
++								unsigned count)
++{
++	sbsa_tty_do_write(b, count);
++
++	if (b[count - 1] == '\n')
++		sbsa_tty_do_write("\r", 1);
++}
++
++static struct tty_driver *sbsa_tty_console_device(struct console *c,
++								int *index)
++{
++	*index = c->index;
++	return sbsa_tty_driver;
++}
++
++static int sbsa_tty_console_setup(struct console *co, char *options)
++{
++	if ((unsigned)co->index > 0)
++		return -ENODEV;
++	if (sbsa_tty->base == NULL)
++		return -ENODEV;
 +	return 0;
 +}
 +
-+static int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port)
++static struct tty_port_operations sbsa_port_ops = {
++};
++
++static const struct tty_operations sbsa_tty_ops = {
++	.open = sbsa_tty_open,
++	.close = sbsa_tty_close,
++	.hangup = sbsa_tty_hangup,
++	.write = sbsa_tty_write,
++	.write_room = sbsa_tty_write_room,
++};
++
++static int sbsa_tty_create_driver(void)
 +{
-+	struct device_node *np = port->node;
-+	struct of_pci_range range;
-+	struct of_pci_range_parser parser;
-+	struct device *dev = port->dev;
-+	u8 ib_reg_mask = 0;
++	int ret;
++	struct tty_driver *tty;
 +
-+	if (pci_dma_range_parser_init(&parser, np)) {
-+		dev_err(dev, "missing dma-ranges property\n");
-+		return -EINVAL;
++	sbsa_tty = kzalloc(sizeof(*sbsa_tty), GFP_KERNEL);
++	if (sbsa_tty == NULL) {
++		ret = -ENOMEM;
++		goto err_alloc_sbsa_tty_failed;
 +	}
-+
-+	/* Get the dma-ranges from DT */
-+	for_each_of_pci_range(&parser, &range) {
-+		u64 end = range.cpu_addr + range.size - 1;
-+		dev_dbg(port->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n",
-+			range.flags, range.cpu_addr, end, range.pci_addr);
-+		xgene_pcie_setup_ib_reg(port, &range, &ib_reg_mask);
++	tty = alloc_tty_driver(1);
++	if (tty == NULL) {
++		ret = -ENOMEM;
++		goto err_alloc_tty_driver_failed;
 +	}
++	tty->driver_name = "sbsauart";
++	tty->name = "ttySBSA";
++	tty->type = TTY_DRIVER_TYPE_SERIAL;
++	tty->subtype = SERIAL_TYPE_NORMAL;
++	tty->init_termios = tty_std_termios;
++	tty->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
++						TTY_DRIVER_DYNAMIC_DEV;
++	tty_set_operations(tty, &sbsa_tty_ops);
++	ret = tty_register_driver(tty);
++	if (ret)
++		goto err_tty_register_driver_failed;
++
++	sbsa_tty_driver = tty;
 +	return 0;
++
++err_tty_register_driver_failed:
++	put_tty_driver(tty);
++err_alloc_tty_driver_failed:
++	kfree(sbsa_tty);
++	sbsa_tty = NULL;
++err_alloc_sbsa_tty_failed:
++	return ret;
 +}
 +
-+static int xgene_pcie_probe_bridge(struct platform_device *pdev)
++static void sbsa_tty_delete_driver(void)
 +{
-+	struct device_node *np = of_node_get(pdev->dev.of_node);
-+	struct xgene_pcie_port *port;
-+	struct pci_host_bridge *bridge;
-+	resource_size_t lastbus;
-+	u32 lanes = 0, speed = 0;
-+	u64 cfg_addr = 0;
-+	int ret;
++	tty_unregister_driver(sbsa_tty_driver);
++	put_tty_driver(sbsa_tty_driver);
++	sbsa_tty_driver = NULL;
++	kfree(sbsa_tty);
++	sbsa_tty = NULL;
++}
 +
-+	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
-+	if (!port)
-+		return -ENOMEM;
-+	port->node = np;
-+	port->dev = &pdev->dev;
++static int sbsa_tty_probe(struct platform_device *pdev)
++{
++	struct sbsa_tty *qtty;
++	int ret = -EINVAL;
++	int i;
++	struct resource *r;
++	struct device *ttydev;
++	void __iomem *base;
++	u32 irq;
 +
-+	ret = xgene_pcie_map_reg(port, pdev, &cfg_addr);
-+	if (ret)
-+		return ret;
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (r == NULL)
++		return -EINVAL;
 +
-+	ret = xgene_pcie_init_port(port);
-+	if (ret)
-+		return ret;
-+	xgene_pcie_program_core(port->csr_base);
-+	xgene_pcie_setup_root_complex(port);
++	base = ioremap(r->start, r->end - r->start);
++	if (base == NULL)
++		pr_err("sbsa_tty: unable to remap base\n");
 +
-+	bridge = of_create_pci_host_bridge(&pdev->dev, &xgene_pcie_ops, port);
-+	if (IS_ERR_OR_NULL(bridge))
-+		return PTR_ERR(bridge);
++	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++	if (r == NULL)
++		goto err_unmap;
 +
-+	ret = xgene_pcie_map_ranges(port, bridge, cfg_addr);
++	irq = r->start;
++
++	if (pdev->id > 0)
++		goto err_unmap;
++
++	ret = sbsa_tty_create_driver();
 +	if (ret)
-+		return ret;
++		goto err_unmap;
 +
-+	ret = xgene_pcie_parse_map_dma_ranges(port);
++	qtty = sbsa_tty;
++	spin_lock_init(&qtty->lock);
++	tty_port_init(&qtty->port);
++	qtty->port.ops = &sbsa_port_ops;
++	qtty->base = base;
++	qtty->irq = irq;
++
++	/* Clear and Mask all IRQs */
++	writew(0, base + UART011_IMSC);
++	writew(0xFFFF, base + UART011_ICR);
++
++	ret = request_irq(irq, sbsa_tty_interrupt, IRQF_SHARED,
++						"sbsa_tty", pdev);
 +	if (ret)
-+		return ret;
++		goto err_request_irq_failed;
 +
-+	xgene_pcie_poll_linkup(port, &lanes, &speed);
-+	if (!port->link_up)
-+		dev_info(port->dev, "(rc) link down\n");
-+	else
-+		dev_info(port->dev, "(rc) x%d gen-%d link up\n",
-+				lanes, speed + 1);
-+	platform_set_drvdata(pdev, port);
-+	lastbus = pci_rescan_bus(bridge->bus);
-+	pci_bus_update_busn_res_end(bridge->bus, lastbus);
-+	return 0;
-+}
++	/* Unmask the RX IRQ */
++	writew(UART011_RXIM | UART011_RTIM, base + UART011_IMSC);
 +
-+static const struct of_device_id xgene_pcie_match_table[] = {
-+	{.compatible = "apm,xgene-pcie",},
-+	{},
-+};
++	ttydev = tty_port_register_device(&qtty->port, sbsa_tty_driver,
++							0, &pdev->dev);
++	if (IS_ERR(ttydev)) {
++		ret = PTR_ERR(ttydev);
++		goto err_tty_register_device_failed;
++	}
 +
-+static struct platform_driver xgene_pcie_driver = {
-+	.driver = {
-+		   .name = "xgene-pcie",
-+		   .owner = THIS_MODULE,
-+		   .of_match_table = of_match_ptr(xgene_pcie_match_table),
-+	},
-+	.probe = xgene_pcie_probe_bridge,
-+};
-+module_platform_driver(xgene_pcie_driver);
++	strcpy(qtty->console.name, "ttySBSA");
++	qtty->console.write = sbsa_tty_console_write;
++	qtty->console.device = sbsa_tty_console_device;
++	qtty->console.setup = sbsa_tty_console_setup;
++	qtty->console.flags = CON_PRINTBUFFER;
++	qtty->console.index = pdev->id;
++	register_console(&qtty->console);
 +
-+MODULE_AUTHOR("Tanmay Inamdar <tinamdar at apm.com>");
-+MODULE_DESCRIPTION("APM X-Gene PCIe driver");
-+MODULE_LICENSE("GPL v2");
-diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index 2c9ac70..7bae0f9 100644
---- a/drivers/pci/pci.c
-+++ b/drivers/pci/pci.c
-@@ -17,6 +17,7 @@
- #include <linux/spinlock.h>
- #include <linux/string.h>
- #include <linux/log2.h>
-+#include <linux/of_pci.h>
- #include <linux/pci-aspm.h>
- #include <linux/pm_wakeup.h>
- #include <linux/interrupt.h>
-@@ -1453,6 +1454,9 @@ EXPORT_SYMBOL(pcim_pin_device);
-  */
- int __weak pcibios_add_device(struct pci_dev *dev)
- {
-+#ifdef CONFIG_OF
-+	dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-+#endif
- 	return 0;
- }
- 
-@@ -2704,6 +2708,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
- }
- EXPORT_SYMBOL(pci_request_regions_exclusive);
- 
-+/**
-+ *	pci_remap_iospace - Remap the memory mapped I/O space
-+ *	@res: Resource describing the I/O space
-+ *	@phys_addr: physical address where the range will be mapped.
-+ *
-+ *	Remap the memory mapped I/O space described by the @res
-+ *	into the CPU physical address space. Only architectures
-+ *	that have memory mapped IO defined (and hence PCI_IOBASE)
-+ *	should call this function.
-+ */
-+int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
-+{
-+	int err = -ENODEV;
++	return 0;
 +
-+#ifdef PCI_IOBASE
-+	if (!(res->flags & IORESOURCE_IO))
-+		return -EINVAL;
++	tty_unregister_device(sbsa_tty_driver, i);
++err_tty_register_device_failed:
++	free_irq(irq, pdev);
++err_request_irq_failed:
++	sbsa_tty_delete_driver();
++err_unmap:
++	iounmap(base);
++	return ret;
++}
 +
-+	if (res->end > IO_SPACE_LIMIT)
-+		return -EINVAL;
++static int sbsa_tty_remove(struct platform_device *pdev)
++{
++	struct sbsa_tty *qtty;
++
++	qtty = sbsa_tty;
++	unregister_console(&qtty->console);
++	tty_unregister_device(sbsa_tty_driver, pdev->id);
++	iounmap(qtty->base);
++	qtty->base = 0;
++	free_irq(qtty->irq, pdev);
++	sbsa_tty_delete_driver();
++	return 0;
++}
 +
-+	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
-+				res->end + 1 + (unsigned long)PCI_IOBASE,
-+				phys_addr, __pgprot(PROT_DEVICE_nGnRE));
-+#else
-+	/* this architecture does not have memory mapped I/O space,
-+	   so this function should never be called */
-+	WARN_ON(1);
-+#endif
++static const struct acpi_device_id sbsa_acpi_match[] = {
++	{ "ARMH0011", 0 },
++	{ }
++};
++
++static struct platform_driver sbsa_tty_platform_driver = {
++	.probe = sbsa_tty_probe,
++	.remove = sbsa_tty_remove,
++	.driver = {
++		.name = "sbsa_tty",
++		.acpi_match_table = ACPI_PTR(sbsa_acpi_match),
++	}
++};
 +
-+	return err;
-+}
++module_platform_driver(sbsa_tty_platform_driver);
 +
- static void __pci_set_master(struct pci_dev *dev, bool enable)
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index 57d9df8..e075437 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -313,10 +313,18 @@ static int dw8250_probe_of(struct uart_port *p,
+ static int dw8250_probe_acpi(struct uart_8250_port *up,
+ 			     struct dw8250_data *data)
  {
- 	u16 old_cmd, cmd;
-diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
-index e3cf8a2..abf5e82 100644
---- a/drivers/pci/probe.c
-+++ b/drivers/pci/probe.c
-@@ -515,7 +515,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
- 	kfree(bridge);
- }
++	const struct acpi_device_id *id;
+ 	struct uart_port *p = &up->port;
  
--static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
-+static struct pci_host_bridge *pci_alloc_host_bridge(void)
- {
- 	struct pci_host_bridge *bridge;
+ 	dw8250_setup_port(up);
  
-@@ -524,7 +524,6 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
- 		return NULL;
++	id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
++	if (!id)
++		return -ENODEV;
++
++	if (!p->uartclk)
++		p->uartclk = (unsigned int)id->driver_data;
++
+ 	p->iotype = UPIO_MEM32;
+ 	p->serial_in = dw8250_serial_in32;
+ 	p->serial_out = dw8250_serial_out32;
+@@ -541,6 +549,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = {
+ 	{ "INT3435", 0 },
+ 	{ "80860F0A", 0 },
+ 	{ "8086228A", 0 },
++	{ "APMC0D08", 50000000},
+ 	{ },
+ };
+ MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
+diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
+index c728113..f97804b 100644
+--- a/include/acpi/acnames.h
++++ b/include/acpi/acnames.h
+@@ -59,6 +59,10 @@
+ #define METHOD_NAME__PRS        "_PRS"
+ #define METHOD_NAME__PRT        "_PRT"
+ #define METHOD_NAME__PRW        "_PRW"
++#define METHOD_NAME__PS0        "_PS0"
++#define METHOD_NAME__PS1        "_PS1"
++#define METHOD_NAME__PS2        "_PS2"
++#define METHOD_NAME__PS3        "_PS3"
+ #define METHOD_NAME__REG        "_REG"
+ #define METHOD_NAME__SB_        "_SB_"
+ #define METHOD_NAME__SEG        "_SEG"
+diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
+index d91e59b..68d5ade 100644
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -68,6 +68,8 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs);
+ union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
+ 			int rev, int func, union acpi_object *argv4);
  
- 	INIT_LIST_HEAD(&bridge->windows);
--	bridge->bus = b;
- 	return bridge;
- }
++acpi_status acpi_check_coherency(acpi_handle handle, int *val);
++
+ static inline union acpi_object *
+ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
+ 			union acpi_object *argv4, acpi_object_type type)
+diff --git a/include/acpi/acpi_io.h b/include/acpi/acpi_io.h
+index 444671e..9d573db 100644
+--- a/include/acpi/acpi_io.h
++++ b/include/acpi/acpi_io.h
+@@ -1,11 +1,17 @@
+ #ifndef _ACPI_IO_H_
+ #define _ACPI_IO_H_
+ 
++#include <linux/mm.h>
+ #include <linux/io.h>
  
-@@ -1749,8 +1748,9 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
+ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
+ 					    acpi_size size)
  {
++#ifdef CONFIG_ARM64
++	if (!page_is_ram(phys >> PAGE_SHIFT))
++		return ioremap(phys, size);
++#endif
++
+        return ioremap_cache(phys, size);
  }
  
--struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
--		struct pci_ops *ops, void *sysdata, struct list_head *resources)
-+struct pci_bus *pci_create_root_bus_in_domain(struct device *parent,
-+		int domain, int bus, struct pci_ops *ops, void *sysdata,
-+		struct list_head *resources)
- {
- 	int error;
- 	struct pci_host_bridge *bridge;
-@@ -1761,37 +1761,41 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- 	char bus_addr[64];
- 	char *fmt;
+diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
+index b7c89d4..dc9d037 100644
+--- a/include/acpi/acpixf.h
++++ b/include/acpi/acpixf.h
+@@ -46,7 +46,7 @@
  
-+	bridge = pci_alloc_host_bridge();
-+	if (!bridge)
-+		return ERR_PTR(-ENOMEM);
-+
-+	bridge->dev.parent = parent;
-+	bridge->dev.release = pci_release_host_bridge_dev;
-+	bridge->domain_nr = domain;
-+
- 	b = pci_alloc_bus();
--	if (!b)
--		return NULL;
-+	if (!b) {
-+		error = -ENOMEM;
-+		goto err_out;
-+	}
+ /* Current ACPICA subsystem version in YYYYMMDD format */
  
- 	b->sysdata = sysdata;
- 	b->ops = ops;
- 	b->number = b->busn_res.start = bus;
--	b2 = pci_find_bus(pci_domain_nr(b), bus);
-+	b2 = pci_find_bus(bridge->domain_nr, bus);
- 	if (b2) {
- 		/* If we already got to this bus through a different bridge, ignore it */
- 		dev_dbg(&b2->dev, "bus already known\n");
--		goto err_out;
-+		error = -EEXIST;
-+		goto err_bus_out;
- 	}
+-#define ACPI_CA_VERSION                 0x20140724
++#define ACPI_CA_VERSION                 0x20140828
  
--	bridge = pci_alloc_host_bridge(b);
--	if (!bridge)
--		goto err_out;
--
--	bridge->dev.parent = parent;
--	bridge->dev.release = pci_release_host_bridge_dev;
--	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-+	bridge->bus = b;
-+	dev_set_name(&bridge->dev, "pci%04x:%02x", bridge->domain_nr, bus);
- 	error = pcibios_root_bridge_prepare(bridge);
--	if (error) {
--		kfree(bridge);
-+	if (error)
- 		goto err_out;
--	}
+ #include <acpi/acconfig.h>
+ #include <acpi/actypes.h>
+diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
+index 7626bfe..29e7937 100644
+--- a/include/acpi/actbl1.h
++++ b/include/acpi/actbl1.h
+@@ -952,7 +952,8 @@ enum acpi_srat_type {
+ 	ACPI_SRAT_TYPE_CPU_AFFINITY = 0,
+ 	ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1,
+ 	ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
+-	ACPI_SRAT_TYPE_RESERVED = 3	/* 3 and greater are reserved */
++	ACPI_SRAT_TYPE_GICC_AFFINITY = 3,
++	ACPI_SRAT_TYPE_RESERVED = 4	/* 4 and greater are reserved */
+ };
  
- 	error = device_register(&bridge->dev);
- 	if (error) {
- 		put_device(&bridge->dev);
--		goto err_out;
-+		goto err_bus_out;
- 	}
- 	b->bridge = get_device(&bridge->dev);
- 	device_enable_async_suspend(b->bridge);
-@@ -1802,7 +1806,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- 
- 	b->dev.class = &pcibus_class;
- 	b->dev.parent = b->bridge;
--	dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
-+	dev_set_name(&b->dev, "%04x:%02x", bridge->domain_nr, bus);
- 	error = device_register(&b->dev);
- 	if (error)
- 		goto class_dev_reg_err;
-@@ -1848,9 +1852,31 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- class_dev_reg_err:
- 	put_device(&bridge->dev);
- 	device_unregister(&bridge->dev);
-+err_bus_out:
-+	kfree(b);
- err_out:
-+	kfree(bridge);
-+	return ERR_PTR(error);
-+}
+ /*
+@@ -968,7 +969,7 @@ struct acpi_srat_cpu_affinity {
+ 	u32 flags;
+ 	u8 local_sapic_eid;
+ 	u8 proximity_domain_hi[3];
+-	u32 reserved;		/* Reserved, must be zero */
++	u32 clock_domain;
+ };
+ 
+ /* Flags */
+@@ -1010,6 +1011,20 @@ struct acpi_srat_x2apic_cpu_affinity {
+ 
+ #define ACPI_SRAT_CPU_ENABLED       (1)	/* 00: Use affinity structure */
+ 
++/* 3: GICC Affinity (ACPI 5.1) */
++
++struct acpi_srat_gicc_affinity {
++	struct acpi_subtable_header header;
++	u32 proximity_domain;
++	u32 acpi_processor_uid;
++	u32 flags;
++	u32 clock_domain;
++};
 +
-+struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
-+		struct pci_ops *ops, void *sysdata, struct list_head *resources)
-+{
-+	int domain_nr;
-+	struct pci_bus *b = pci_alloc_bus();
-+	if (!b)
-+		return NULL;
++/* Flags for struct acpi_srat_gicc_affinity */
 +
-+	b->sysdata = sysdata;
-+	domain_nr = pci_domain_nr(b);
- 	kfree(b);
--	return NULL;
++#define ACPI_SRAT_GICC_ENABLED     (1)	/* 00: Use affinity structure */
 +
-+	b = pci_create_root_bus_in_domain(parent, domain_nr, bus,
-+				ops, sysdata, resources);
-+	if (IS_ERR(b))
-+		return NULL;
+ /* Reset to default packing */
+ 
+ #pragma pack()
+diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
+index 787bcc8..5480cb2 100644
+--- a/include/acpi/actbl3.h
++++ b/include/acpi/actbl3.h
+@@ -310,10 +310,15 @@ struct acpi_gtdt_timer_entry {
+ 	u32 common_flags;
+ };
+ 
++/* Flag Definitions: timer_flags and virtual_timer_flags above */
 +
-+	return b;
- }
++#define ACPI_GTDT_GT_IRQ_MODE               (1)
++#define ACPI_GTDT_GT_IRQ_POLARITY           (1<<1)
++
+ /* Flag Definitions: common_flags above */
+ 
+-#define ACPI_GTDT_GT_IS_SECURE_TIMER    (1)
+-#define ACPI_GTDT_GT_ALWAYS_ON          (1<<1)
++#define ACPI_GTDT_GT_IS_SECURE_TIMER        (1)
++#define ACPI_GTDT_GT_ALWAYS_ON              (1<<1)
+ 
+ /* 1: SBSA Generic Watchdog Structure */
  
- int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
 index 975e1cc..2e2161b 100644
 --- a/include/asm-generic/io.h
@@ -2110,11 +5346,147 @@ index 975e1cc..2e2161b 100644
  }
  
  static inline void ioport_unmap(void __iomem *p)
+diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
+index 53b2acc..977e545 100644
+--- a/include/asm-generic/pgtable.h
++++ b/include/asm-generic/pgtable.h
+@@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
+ #define pgprot_writecombine pgprot_noncached
+ #endif
+ 
++#ifndef pgprot_device
++#define pgprot_device pgprot_noncached
++#endif
++
+ /*
+  * When walking page tables, get the address of the next boundary,
+  * or the end address of the range if that comes earlier.  Although no
+diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
+index 35b0c12..d98e96b 100644
+--- a/include/kvm/arm_vgic.h
++++ b/include/kvm/arm_vgic.h
+@@ -237,17 +237,19 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+ #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+ #define vgic_initialized(k)	((k)->arch.vgic.ready)
+ 
+-int vgic_v2_probe(struct device_node *vgic_node,
+-		  const struct vgic_ops **ops,
+-		  const struct vgic_params **params);
++int vgic_v2_dt_probe(struct device_node *vgic_node,
++		     const struct vgic_ops **ops,
++		     const struct vgic_params **params);
++int vgic_v2_acpi_probe(const struct vgic_ops **ops,
++		       const struct vgic_params **params);
+ #ifdef CONFIG_ARM_GIC_V3
+-int vgic_v3_probe(struct device_node *vgic_node,
+-		  const struct vgic_ops **ops,
+-		  const struct vgic_params **params);
++int vgic_v3_dt_probe(struct device_node *vgic_node,
++		     const struct vgic_ops **ops,
++		     const struct vgic_params **params);
+ #else
+-static inline int vgic_v3_probe(struct device_node *vgic_node,
+-				const struct vgic_ops **ops,
+-				const struct vgic_params **params)
++static inline int vgic_v3_dt_probe(struct device_node *vgic_node,
++				   const struct vgic_ops **ops,
++				   const struct vgic_params **params)
+ {
+ 	return -ENODEV;
+ }
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 807cbc4..4615eb1 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -71,6 +71,7 @@ enum acpi_irq_model_id {
+ 	ACPI_IRQ_MODEL_IOAPIC,
+ 	ACPI_IRQ_MODEL_IOSAPIC,
+ 	ACPI_IRQ_MODEL_PLATFORM,
++	ACPI_IRQ_MODEL_GIC,
+ 	ACPI_IRQ_MODEL_COUNT
+ };
+ 
+@@ -123,6 +124,10 @@ int acpi_numa_init (void);
+ 
+ int acpi_table_init (void);
+ int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
++int __init acpi_parse_entries(unsigned long table_size,
++			      acpi_tbl_entry_handler handler,
++			      struct acpi_table_header *table_header,
++			      int entry_id, unsigned int max_entries);
+ int __init acpi_table_parse_entries(char *id, unsigned long table_size,
+ 				    int entry_id,
+ 				    acpi_tbl_entry_handler handler,
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index 653f0e2..5839f98 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -346,4 +346,10 @@ extern void clocksource_of_init(void);
+ static inline void clocksource_of_init(void) {}
+ #endif
+ 
++#ifdef CONFIG_ACPI
++void acpi_generic_timer_init(void);
++#else
++static inline void acpi_generic_timer_init(void) {}
++#endif
++
+ #endif /* _LINUX_CLOCKSOURCE_H */
+diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
+new file mode 100644
+index 0000000..ad5b577
+--- /dev/null
++++ b/include/linux/irqchip/arm-gic-acpi.h
+@@ -0,0 +1,31 @@
++/*
++ * Copyright (C) 2014, Linaro Ltd.
++ *	Author: Tomasz Nowicki <tomasz.nowicki at linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef ARM_GIC_ACPI_H_
++#define ARM_GIC_ACPI_H_
++
++#ifdef CONFIG_ACPI
++
++/*
++ * Hard code here, we can not get memory size from MADT (but FDT does),
++ * Actually no need to do that, because this size can be inferred
++ * from GIC spec.
++ */
++#define ACPI_GICV2_DIST_MEM_SIZE	(SZ_4K)
++#define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
++
++struct acpi_table_header;
++
++void acpi_gic_init(void);
++int gic_v2_acpi_init(struct acpi_table_header *table);
++#else
++static inline void acpi_gic_init(void) { }
++#endif
++
++#endif /* ARM_GIC_ACPI_H_ */
+diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
+index 45e2d8c..2b0f246 100644
+--- a/include/linux/irqchip/arm-gic.h
++++ b/include/linux/irqchip/arm-gic.h
+@@ -39,6 +39,8 @@
+ #define GIC_DIST_SGI_PENDING_CLEAR	0xf10
+ #define GIC_DIST_SGI_PENDING_SET	0xf20
+ 
++#define GIC_DIST_SOFTINT_NSATT		0x8000
++
+ #define GICH_HCR			0x0
+ #define GICH_VTR			0x4
+ #define GICH_VMCR			0x8
 diff --git a/include/linux/of_address.h b/include/linux/of_address.h
-index fb7b722..cb9479e4 100644
+index fb7b722..7ebb877 100644
 --- a/include/linux/of_address.h
 +++ b/include/linux/of_address.h
-@@ -23,17 +23,8 @@ struct of_pci_range {
+@@ -23,17 +23,6 @@ struct of_pci_range {
  #define for_each_of_pci_range(parser, range) \
  	for (; of_pci_range_parser_one(parser, range);)
  
@@ -2129,71 +5501,96 @@ index fb7b722..cb9479e4 100644
 -	res->name = np->full_name;
 -}
 -
-+extern int of_pci_range_to_resource(struct of_pci_range *range,
-+		struct device_node *np, struct resource *res);
  /* Translate a DMA address from device space to CPU space */
  extern u64 of_translate_dma_address(struct device_node *dev,
  				    const __be32 *in_addr);
-@@ -55,6 +46,7 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
+@@ -55,7 +44,9 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
  extern const __be32 *of_get_address(struct device_node *dev, int index,
  			   u64 *size, unsigned int *flags);
  
 +extern int pci_register_io_range(phys_addr_t addr, resource_size_t size);
  extern unsigned long pci_address_to_pio(phys_addr_t addr);
++extern phys_addr_t pci_pio_to_address(unsigned long pio);
  
  extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
+ 			struct device_node *node);
+@@ -138,6 +129,9 @@ extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,
+ 			       u64 *size, unsigned int *flags);
+ extern int of_pci_address_to_resource(struct device_node *dev, int bar,
+ 				      struct resource *r);
++extern int of_pci_range_to_resource(struct of_pci_range *range,
++				    struct device_node *np,
++				    struct resource *res);
+ #else /* CONFIG_OF_ADDRESS && CONFIG_PCI */
+ static inline int of_pci_address_to_resource(struct device_node *dev, int bar,
+ 				             struct resource *r)
+@@ -153,4 +147,3 @@ static inline const __be32 *of_get_pci_address(struct device_node *dev,
+ #endif /* CONFIG_OF_ADDRESS && CONFIG_PCI */
+ 
+ #endif /* __OF_ADDRESS_H */
+-
 diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
-index dde3a4a..71e36d0 100644
+index dde3a4a..1fd207e 100644
 --- a/include/linux/of_pci.h
 +++ b/include/linux/of_pci.h
-@@ -15,6 +15,9 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
+@@ -15,6 +15,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
  int of_pci_get_devfn(struct device_node *np);
  int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
  int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
-+struct pci_host_bridge *of_create_pci_host_bridge(struct device *parent,
-+					struct pci_ops *ops, void *host_data);
-+
++int of_get_pci_domain_nr(struct device_node *node);
  #else
  static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
  {
-@@ -43,6 +46,13 @@ of_pci_parse_bus_range(struct device_node *node, struct resource *res)
+@@ -43,6 +44,18 @@ of_pci_parse_bus_range(struct device_node *node, struct resource *res)
  {
  	return -EINVAL;
  }
 +
-+static inline struct pci_host_bridge *
-+of_create_pci_host_bridge(struct device *parent, struct pci_ops *ops,
-+			void *host_data)
++static inline int
++of_get_pci_domain_nr(struct device_node *node)
 +{
-+	return NULL;
++	return -1;
 +}
++#endif
++
++#if defined(CONFIG_OF_ADDRESS)
++int of_pci_get_host_bridge_resources(struct device_node *dev,
++			unsigned char busno, unsigned char bus_max,
++			struct list_head *resources, resource_size_t *io_base);
  #endif
  
  #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
 diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 61978a4..f582746 100644
+index 96453f9..6d540b9 100644
 --- a/include/linux/pci.h
 +++ b/include/linux/pci.h
-@@ -401,6 +401,8 @@ struct pci_host_bridge_window {
- struct pci_host_bridge {
- 	struct device dev;
- 	struct pci_bus *bus;		/* root bus */
-+	int domain_nr;
-+	resource_size_t io_base;	/* physical address for the start of I/O area */
- 	struct list_head windows;	/* pci_host_bridge_windows */
- 	void (*release_fn)(struct pci_host_bridge *);
- 	void *release_data;
-@@ -769,6 +771,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
- struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
- 				    struct pci_ops *ops, void *sysdata,
- 				    struct list_head *resources);
-+struct pci_bus *pci_create_root_bus_in_domain(struct device *parent,
-+			int domain, int bus, struct pci_ops *ops,
-+			void *sysdata, struct list_head *resources);
- int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
- int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
- void pci_bus_release_busn_res(struct pci_bus *b);
-@@ -1097,6 +1102,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
+@@ -457,6 +457,9 @@ struct pci_bus {
+ 	unsigned char	primary;	/* number of primary bridge */
+ 	unsigned char	max_bus_speed;	/* enum pci_bus_speed */
+ 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++	int		domain_nr;
++#endif
+ 
+ 	char		name[48];
+ 
+@@ -559,15 +562,6 @@ struct pci_ops {
+ 	int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
+ };
+ 
+-/*
+- * ACPI needs to be able to access PCI config space before we've done a
+- * PCI bus scan and created pci_bus structures.
+- */
+-int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+-		 int reg, int len, u32 *val);
+-int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
+-		  int reg, int len, u32 val);
+-
+ struct pci_bus_region {
+ 	dma_addr_t start;
+ 	dma_addr_t end;
+@@ -1103,6 +1097,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
  						  resource_size_t),
  			void *alignf_data);
  
@@ -2203,22 +5600,89 @@ index 61978a4..f582746 100644
  static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
  {
  	struct pci_bus_region region;
-@@ -1815,8 +1823,15 @@ static inline void pci_set_of_node(struct pci_dev *dev) { }
- static inline void pci_release_of_node(struct pci_dev *dev) { }
- static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
- static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
+@@ -1288,17 +1285,47 @@ void pci_cfg_access_unlock(struct pci_dev *dev);
+  */
+ #ifdef CONFIG_PCI_DOMAINS
+ extern int pci_domains_supported;
++int pci_get_new_domain_nr(void);
+ #else
+ enum { pci_domains_supported = 0 };
+ static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
+ static inline int pci_proc_domain(struct pci_bus *bus) { return 0; }
++static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
+ #endif /* CONFIG_PCI_DOMAINS */
+ 
++/*
++ * Generic implementation for PCI domain support. If your
++ * architecture does not need custom management of PCI
++ * domains then this implementation will be used
++ */
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++static inline int pci_domain_nr(struct pci_bus *bus)
++{
++	return bus->domain_nr;
++}
++void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
++#else
++static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
++					struct device *parent)
++{
++}
++#endif
 +
- #endif  /* CONFIG_OF */
+ /* some architectures require additional setup to direct VGA traffic */
+ typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
+ 		      unsigned int command_bits, u32 flags);
+ void pci_register_set_vga_state(arch_set_vga_state_t func);
  
-+/* Used by architecture code to apply any quirks to the list of
-+ * pci_host_bridge resource ranges before they are being used
-+ * by of_create_pci_host_bridge()
++/*
++ * ACPI needs to be able to access PCI config space before we've done a
++ * PCI bus scan and created pci_bus structures.
 + */
-+extern int pcibios_fixup_bridge_ranges(struct list_head *resources);
++int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
++		 int reg, int len, u32 *val);
++int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
++		  int reg, int len, u32 val);
++void pcibios_penalize_isa_irq(int irq, int active);
 +
- #ifdef CONFIG_EEH
- static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev)
- {
+ #else /* CONFIG_PCI is not enabled */
+ 
+ /*
+@@ -1400,8 +1427,26 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
+ 						unsigned int devfn)
+ { return NULL; }
+ 
++static inline struct pci_bus *pci_find_bus(int domain, int busnr)
++{ return NULL; }
++
++static inline int pci_bus_write_config_byte(struct pci_bus *bus,
++				unsigned int devfn, int where, u8 val)
++{ return -ENOSYS; }
++
++static inline int raw_pci_read(unsigned int domain, unsigned int bus,
++			unsigned int devfn, int reg, int len, u32 *val)
++{ return -ENOSYS; }
++
++static inline int raw_pci_write(unsigned int domain, unsigned int bus,
++			unsigned int devfn, int reg, int len, u32 val)
++{ return -ENOSYS; }
++
++static inline void pcibios_penalize_isa_irq(int irq, int active) { }
++
+ static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
+ static inline struct pci_dev *pci_dev_get(struct pci_dev *dev) { return NULL; }
++static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
+ 
+ #define dev_is_pci(d) (false)
+ #define dev_is_pf(d) (false)
+@@ -1613,7 +1658,6 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
+ 				 enum pcie_reset_state state);
+ int pcibios_add_device(struct pci_dev *dev);
+ void pcibios_release_device(struct pci_dev *dev);
+-void pcibios_penalize_isa_irq(int irq, int active);
+ 
+ #ifdef CONFIG_HIBERNATE_CALLBACKS
+ extern struct dev_pm_ops pcibios_pm_ops;
 diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
 index e9441b9..1d3f39c 100644
 --- a/tools/perf/arch/arm64/include/perf_regs.h
@@ -2232,3 +5696,353 @@ index e9441b9..1d3f39c 100644
  #define PERF_REG_IP	PERF_REG_ARM64_PC
  #define PERF_REG_SP	PERF_REG_ARM64_SP
  
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 22fa819..9cd5dbd 100644
+--- a/virt/kvm/arm/arch_timer.c
++++ b/virt/kvm/arm/arch_timer.c
+@@ -21,9 +21,11 @@
+ #include <linux/kvm.h>
+ #include <linux/kvm_host.h>
+ #include <linux/interrupt.h>
++#include <linux/acpi.h>
+ 
+ #include <clocksource/arm_arch_timer.h>
+ #include <asm/arch_timer.h>
++#include <asm/acpi.h>
+ 
+ #include <kvm/arm_vgic.h>
+ #include <kvm/arm_arch_timer.h>
+@@ -244,60 +246,92 @@ static const struct of_device_id arch_timer_of_match[] = {
+ 	{},
+ };
+ 
+-int kvm_timer_hyp_init(void)
++static int kvm_timer_ppi_parse_dt(unsigned int *ppi)
+ {
+ 	struct device_node *np;
+-	unsigned int ppi;
+-	int err;
+-
+-	timecounter = arch_timer_get_timecounter();
+-	if (!timecounter)
+-		return -ENODEV;
+ 
+ 	np = of_find_matching_node(NULL, arch_timer_of_match);
+ 	if (!np) {
+-		kvm_err("kvm_arch_timer: can't find DT node\n");
+ 		return -ENODEV;
+ 	}
+ 
+-	ppi = irq_of_parse_and_map(np, 2);
+-	if (!ppi) {
+-		kvm_err("kvm_arch_timer: no virtual timer interrupt\n");
+-		err = -EINVAL;
+-		goto out;
++	*ppi = irq_of_parse_and_map(np, 2);
++	if (*ppi == 0) {
++		of_node_put(np);
++		return -EINVAL;
+ 	}
+ 
+-	err = request_percpu_irq(ppi, kvm_arch_timer_handler,
+-				 "kvm guest timer", kvm_get_running_vcpus());
+-	if (err) {
+-		kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
+-			ppi, err);
+-		goto out;
+-	}
++	return 0;
++}
+ 
+-	host_vtimer_irq = ppi;
++extern int acadia_kvm_acpi;
++extern int arch_timer_ppi[];
+ 
+-	err = __register_cpu_notifier(&kvm_timer_cpu_nb);
+-	if (err) {
+-		kvm_err("Cannot register timer CPU notifier\n");
+-		goto out_free;
+-	}
++static int kvm_timer_ppi_parse_acpi(unsigned int *ppi)
+ 
+-	wqueue = create_singlethread_workqueue("kvm_arch_timer");
+-	if (!wqueue) {
+-		err = -ENOMEM;
+-		goto out_free;
+-	}
++{
++	/* retrieve VIRT_PPI info */
++	*ppi = arch_timer_ppi[2];
+ 
+-	kvm_info("%s IRQ%d\n", np->name, ppi);
+-	on_each_cpu(kvm_timer_init_interrupt, NULL, 1);
++	if (*ppi == 0)
++		return -EINVAL;
++	else
++		return 0;
++}
++
++int kvm_timer_hyp_init(void)
++{
++	unsigned int ppi;
++	int err;
++
++        timecounter = arch_timer_get_timecounter();
++        if (!timecounter)
++		return -ENODEV;
++
++	/* PPI DT parsing */
++	err = kvm_timer_ppi_parse_dt(&ppi);
+ 
+-	goto out;
++	/* if DT parsing fails, try ACPI next */
++	if (err && !acpi_disabled && acadia_kvm_acpi )
++		err = kvm_timer_ppi_parse_acpi(&ppi);
++
++	if (err) {
++		kvm_err("kvm_timer_hyp_init: can't find virtual timer info or "
++			"config virtual timer interrupt\n");
++		return err;
++	}
++
++	/* configure IRQ handler */
++	err = request_percpu_irq(ppi, kvm_arch_timer_handler,
++                                 "kvm guest timer", kvm_get_running_vcpus());
++        if (err) {
++                kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
++                        ppi, err);
++                goto out;
++        }
++
++        host_vtimer_irq = ppi;
++
++        err = __register_cpu_notifier(&kvm_timer_cpu_nb);
++        if (err) {
++                kvm_err("Cannot register timer CPU notifier\n");
++                goto out_free;
++        }
++
++        wqueue = create_singlethread_workqueue("kvm_arch_timer");
++        if (!wqueue) {
++                err = -ENOMEM;
++                goto out_free;
++        }
++
++        kvm_info("timer IRQ%d\n", ppi);
++        on_each_cpu(kvm_timer_init_interrupt, NULL, 1);
++
++        goto out;
+ out_free:
+-	free_percpu_irq(ppi, kvm_get_running_vcpus());
++        free_percpu_irq(ppi, kvm_get_running_vcpus());
+ out:
+-	of_node_put(np);
+-	return err;
++        return err;
+ }
+ 
+ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
+diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
+index 416baed..53bdd33 100644
+--- a/virt/kvm/arm/vgic-v2.c
++++ b/virt/kvm/arm/vgic-v2.c
+@@ -19,6 +19,7 @@
+ #include <linux/kvm.h>
+ #include <linux/kvm_host.h>
+ #include <linux/interrupt.h>
++#include <linux/acpi.h>
+ #include <linux/io.h>
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+@@ -26,6 +27,7 @@
+ 
+ #include <linux/irqchip/arm-gic.h>
+ 
++#include <asm/acpi.h>
+ #include <asm/kvm_emulate.h>
+ #include <asm/kvm_arm.h>
+ #include <asm/kvm_mmu.h>
+@@ -177,7 +179,7 @@ static const struct vgic_ops vgic_v2_ops = {
+ static struct vgic_params vgic_v2_params;
+ 
+ /**
+- * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
++ * vgic_v2_dt_probe - probe for a GICv2 compatible interrupt controller in DT
+  * @node:	pointer to the DT node
+  * @ops: 	address of a pointer to the GICv2 operations
+  * @params:	address of a pointer to HW-specific parameters
+@@ -186,7 +188,7 @@ static struct vgic_params vgic_v2_params;
+  * in *ops and the HW parameters in *params. Returns an error code
+  * otherwise.
+  */
+-int vgic_v2_probe(struct device_node *vgic_node,
++int vgic_v2_dt_probe(struct device_node *vgic_node,
+ 		  const struct vgic_ops **ops,
+ 		  const struct vgic_params **params)
+ {
+@@ -263,3 +265,72 @@ out:
+ 	of_node_put(vgic_node);
+ 	return ret;
+ }
++
++struct acpi_madt_generic_interrupt *vgic_acpi;
++static void gic_get_acpi_header(struct acpi_subtable_header *header)
++{
++	vgic_acpi = (struct acpi_madt_generic_interrupt *)header;
++}
++
++int vgic_v2_acpi_probe(const struct vgic_ops **ops,
++		       const struct vgic_params **params)
++{
++	struct vgic_params *vgic = &vgic_v2_params;
++	int irq_mode, ret;
++
++	/* MADT table */
++	ret = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
++			(acpi_tbl_entry_handler)gic_get_acpi_header, 0);
++	if (!ret) {
++		pr_err("Failed to get MADT VGIC CPU entry\n");
++		ret = -ENODEV;
++		goto out;
++	}
++
++	/* IRQ trigger mode */
++	irq_mode = (vgic_acpi->flags & ACPI_MADT_VGIC_IRQ_MODE) ?
++		ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
++	/* According to GIC-400 manual, all PPIs are active-LOW, level
++	 *  sensative. We register IRQ as active-low.
++	 */
++	vgic->maint_irq = acpi_register_gsi(NULL, vgic_acpi->vgic_interrupt,
++					    irq_mode, ACPI_ACTIVE_LOW);
++	if (!vgic->maint_irq) {
++		pr_err("Cannot register VGIC ACPI maintenance irq\n");
++		ret = -ENXIO;
++		goto out;
++	}
++
++	/* GICH resource */
++	vgic->vctrl_base = ioremap(vgic_acpi->gich_base_address, SZ_8K);
++	if (!vgic->vctrl_base) {
++		pr_err("cannot ioremap GICH memory\n");
++		ret = -ENOMEM;
++		goto out;
++	}
++
++        vgic->nr_lr = readl_relaxed(vgic->vctrl_base + GICH_VTR);
++        vgic->nr_lr = (vgic->nr_lr & 0x3f) + 1;
++
++        ret = create_hyp_io_mappings(vgic->vctrl_base,
++                                     vgic->vctrl_base + SZ_8K,
++                                     vgic_acpi->gich_base_address);
++        if (ret) {
++                kvm_err("Cannot map GICH into hyp\n");
++		goto out;
++        }
++
++	vgic->vcpu_base = vgic_acpi->gicv_base_address;
++
++	kvm_info("GICH base=0x%llx, GICV base=0x%llx, IRQ=%d\n",
++		 (unsigned long long)vgic_acpi->gich_base_address,
++		 (unsigned long long)vgic_acpi->gicv_base_address,
++		 vgic->maint_irq);
++
++	vgic->type = VGIC_V2;
++	*ops = &vgic_v2_ops;
++	*params = vgic;
++
++out:
++	return ret;
++}
+diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
+index 1c2c8ee..8b56920 100644
+--- a/virt/kvm/arm/vgic-v3.c
++++ b/virt/kvm/arm/vgic-v3.c
+@@ -173,7 +173,7 @@ static const struct vgic_ops vgic_v3_ops = {
+ static struct vgic_params vgic_v3_params;
+ 
+ /**
+- * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
++ * vgic_v3_dt_probe - probe for a GICv3 compatible interrupt controller in DT
+  * @node:	pointer to the DT node
+  * @ops: 	address of a pointer to the GICv3 operations
+  * @params:	address of a pointer to HW-specific parameters
+@@ -182,9 +182,9 @@ static struct vgic_params vgic_v3_params;
+  * in *ops and the HW parameters in *params. Returns an error code
+  * otherwise.
+  */
+-int vgic_v3_probe(struct device_node *vgic_node,
+-		  const struct vgic_ops **ops,
+-		  const struct vgic_params **params)
++int vgic_v3_dt_probe(struct device_node *vgic_node,
++		     const struct vgic_ops **ops,
++		     const struct vgic_params **params)
+ {
+ 	int ret = 0;
+ 	u32 gicv_idx;
+diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
+index 73eba79..ca98a3b 100644
+--- a/virt/kvm/arm/vgic.c
++++ b/virt/kvm/arm/vgic.c
+@@ -25,9 +25,11 @@
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/uaccess.h>
++#include <linux/acpi.h>
+ 
+ #include <linux/irqchip/arm-gic.h>
+ 
++#include <asm/acpi.h>
+ #include <asm/kvm_emulate.h>
+ #include <asm/kvm_arm.h>
+ #include <asm/kvm_mmu.h>
+@@ -1549,31 +1551,39 @@ static struct notifier_block vgic_cpu_nb = {
+ };
+ 
+ static const struct of_device_id vgic_ids[] = {
+-	{ .compatible = "arm,cortex-a15-gic", .data = vgic_v2_probe, },
+-	{ .compatible = "arm,gic-v3", .data = vgic_v3_probe, },
++	{ .compatible = "arm,cortex-a15-gic", .data = vgic_v2_dt_probe, },
++	{ .compatible = "arm,gic-v3", .data = vgic_v3_dt_probe, },
+ 	{},
+ };
+ 
++extern int acadia_kvm_acpi;
++
+ int kvm_vgic_hyp_init(void)
+ {
+ 	const struct of_device_id *matched_id;
+ 	int (*vgic_probe)(struct device_node *,const struct vgic_ops **,
+ 			  const struct vgic_params **);
+ 	struct device_node *vgic_node;
+-	int ret;
++	int ret = -ENODEV;
+ 
+-	vgic_node = of_find_matching_node_and_match(NULL,
+-						    vgic_ids, &matched_id);
+-	if (!vgic_node) {
+-		kvm_err("error: no compatible GIC node found\n");
+-		return -ENODEV;
++	/* probe VGIC */
++	if (vgic_node = of_find_matching_node_and_match(NULL,
++				vgic_ids, &matched_id)) {
++		/* probe VGIC in DT */
++		vgic_probe = matched_id->data;
++		ret = vgic_probe(vgic_node, &vgic_ops, &vgic);
++	}
++	else if (!acpi_disabled && acadia_kvm_acpi) {
++		/* probe VGIC in ACPI */
++		ret = vgic_v2_acpi_probe(&vgic_ops, &vgic);
+ 	}
+ 
+-	vgic_probe = matched_id->data;
+-	ret = vgic_probe(vgic_node, &vgic_ops, &vgic);
+-	if (ret)
++	if (ret) {
++		kvm_err("error: no compatible GIC info found\n");
+ 		return ret;
++	}
+ 
++	/* configuration */
+ 	ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
+ 				 "vgic", kvm_get_running_vcpus());
+ 	if (ret) {
diff --git a/kernel.spec b/kernel.spec
index 47787cf..7196ab8 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -2223,6 +2223,9 @@ fi
 #                                    ||----w |
 #                                    ||     ||
 %changelog
+* Mon Sep 29 2014 Kyle McMartin <kyle at fedoraproject.org>
+- Update kernel-arm64.patch from git.
+
 * Mon Sep 29 2014 Josh Boyer <jwboyer at fedoraproject.org> - 3.17.0-0.rc7.git0.1
 - Linux v3.17-rc7
 


More information about the scm-commits mailing list