[kernel/f20] Linux v3.18.7

Justin M. Forbes jforbes at fedoraproject.org
Wed Feb 11 18:18:01 UTC 2015


commit 8b0e0fee0e78e8f3c284389f9f494b6575e9f296
Author: Justin M. Forbes <jforbes at redhat.com>
Date:   Wed Feb 11 12:17:48 2015 -0600

    Linux v3.18.7

 kernel-arm64.patch |20606 ++++++++++++++++++++++++++++++----------------------
 kernel.spec        |    5 +-
 sources            |    2 +-
 3 files changed, 11901 insertions(+), 8712 deletions(-)
---
diff --git a/kernel-arm64.patch b/kernel-arm64.patch
index 25f0479..e98d10a 100644
--- a/kernel-arm64.patch
+++ b/kernel-arm64.patch
@@ -1,767 +1,1348 @@
-commit db044807ca763c21bae298388239be6177c6ccec
-Merge: 649c9e3 26bcd8b
-Author: Kyle McMartin <kmcmarti at redhat.com>
-Date:   Wed Jul 30 14:31:24 2014 -0400
+commit 0335b5034b998e978bf9343da77246bcbad33981
+Author: Mark Salter <msalter at redhat.com>
+Date:   Wed Nov 19 10:32:11 2014 -0500
 
-    Merge branch 'master' into devel
+    arm64: explicitly set noncoherent ops for _CCA handling
     
-    Conflicts:
-    	virt/kvm/arm/vgic.c
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 649c9e3a45e81852daf80c126a332297b75cb109
-Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
-Date:   Tue Jul 29 12:49:10 2014 +0200
+commit 4a2d43442e20a24b78594d12914706deddc119de
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Nov 10 17:09:29 2014 -0500
 
-    arm64/efi: efistub: don't abort if base of DRAM is occupied
+    DO NOT UPSTREAM - pci/xgene: Provide fixup for ACPI MCFG support
     
-    If we cannot relocate the kernel Image to its preferred offset of base of DRAM
-    plus TEXT_OFFSET, instead relocate it to the lowest available 2 MB boundary plus
-    TEXT_OFFSET. We may lose a bit of memory at the low end, but we can still
-    proceed normally otherwise.
+    Xgene doesn't decode bus bits of mmconfig region and only
+    supports devfn 0 of bus 0. For other buses/devices, some
+    internal registers need to be poked. This patch provides
+    a fixup to support ACPI MCFG tables. This is a horrible
+    hack allowing the hardware to be used for PCI testing, but
+    it is not intended to be a long term patch.
     
-    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 5102fd06b12467a0518537061805483a759bc856
-Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
-Date:   Tue Jul 29 12:49:09 2014 +0200
+commit b93f804830d9ef6d572dd6be9734108199141b87
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Nov 10 17:33:18 2014 -0500
 
-    arm64/efi: efistub: cover entire static mem footprint in PE/COFF .text
-    
-    The static memory footprint of a kernel Image at boot is larger than the
-    Image file itself. Things like .bss data and initial page tables are allocated
-    statically but populated dynamically so their content is not contained in the
-    Image file.
+    DO NOT UPSTREAM - provide hook for MCFG fixups
     
-    However, if EFI (or GRUB) has loaded the Image at precisely the desired offset
-    of base of DRAM + TEXT_OFFSET, the Image will be booted in place, and we have
-    to make sure that the allocation done by the PE/COFF loader is large enough.
+    This is a temprary mechanism needed by at least one early
+    arm64 hardware platform with broken MCFG support. This is
+    not intended for upstream and will go away as soon as newer
+    hardware with fully compliant ECAM becomes available.
     
-    Fix this by growing the PE/COFF .text section to cover the entire static
-    memory footprint. The part of the section that is not covered by the payload
-    will be zero initialised by the PE/COFF loader.
-    
-    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 3b4dfb00a401b7fecf01d3c89b154907167dff52
-Author: Mark Rutland <mark.rutland at arm.com>
-Date:   Tue Jul 29 12:49:08 2014 +0200
+commit 2d76cb937a6c0010d1de181d0142f0822df5071d
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Nov 10 17:30:25 2014 -0500
 
-    arm64: spin-table: handle unmapped cpu-release-addrs
+    arm64/pci/acpi: initial support for ACPI probing of PCI
     
-    In certain cases the cpu-release-addr of a CPU may not fall in the
-    linear mapping (e.g. when the kernel is loaded above this address due to
-    the presence of other images in memory). This is problematic for the
-    spin-table code as it assumes that it can trivially convert a
-    cpu-release-addr to a valid VA in the linear map.
+    Signed-off-by: Mark Salter <msalter at redhat.com>
+
+commit a438ff7be0140738b1224d5ade6345a9febad279
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Nov 10 17:23:57 2014 -0500
+
+    arm64/acpi/pci: add support for parsing MCFG table
     
-    This patch modifies the spin-table code to use a temporary cached
-    mapping to write to a given cpu-release-addr, enabling us to support
-    addresses regardless of whether they are covered by the linear mapping.
+    Add support for parsing MCFG table and provide functions to read/write
+    PCI configuration space based on the parsed info. This provides the
+    low-level raw_pci_read/raw_pci_write functionality.
     
-    Signed-off-by: Mark Rutland <mark.rutland at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit a49ad891b2e91338587dc5576c9da73b249a9d13
+commit 814b22167d35b18fc3de745277a2190ff0841585
 Author: Mark Salter <msalter at redhat.com>
-Date:   Mon Jul 14 15:52:06 2014 -0400
+Date:   Mon Nov 10 16:42:14 2014 -0500
 
-    pci/xgene: use pci_remap_iospace() instead of pci_ioremap_io()
+    DO NOT UPSTREAM - pci/xgene: workaround CRS issue
+    
+    CRS is not behaving properly for some reason. Until this
+    gets diagnosed properly, pretend not to support it in order
+    to prevent hangs in 3.18 kernel.
     
     Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 1a958ec71db226d35ed51756b7164142bb0a60a3
-Author: Tanmay Inamdar <tinamdar at apm.com>
-Date:   Wed Mar 19 16:12:42 2014 -0700
+commit b90d000000801b473ed4c69757d3be9e433b6c5e
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Nov 10 16:31:05 2014 -0500
 
-    MAINTAINERS: entry for APM X-Gene PCIe host driver
+    iommu/arm-smmu: fix NULL dereference with ACPI PCI devices
     
-    Add entry for AppliedMicro X-Gene PCIe host driver.
+    Fix a NULL dereference in find_mmu_master which occurs when
+    booting with ACPI. In that case, PCI bridges with not have
+    an of_node. Add a check for NULL of_node and bail out if that
+    is the case.
     
-    Signed-off-by: Tanmay Inamdar <tinamdar at apm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 03dc92f35b8f8be898ca12e3dc7c15961f414907
-Author: Tanmay Inamdar <tinamdar at apm.com>
-Date:   Wed Mar 19 16:12:41 2014 -0700
+commit 243e5c1dc198958ce862e39d33efc798a47b339a
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Nov 10 21:35:11 2014 -0500
 
-    dt-bindings: pci: xgene pcie device tree bindings
+    DO NOT UPSTREAM - arm64: fix dma_ops for ACPI and PCI devices
+    
+    Commit 2189064795dc3fb4101e5:
     
-    This patch adds the bindings for X-Gene PCIe driver. The driver resides
-    under 'drivers/pci/host/pci-xgene.c' file.
+      arm64: Implement set_arch_dma_coherent_ops() to replace bus notifiers
     
-    Signed-off-by: Tanmay Inamdar <tinamdar at apm.com>
+    removed the bus notifiers from dma-mapping.c. This patch
+    adds the notifier back for ACPI and PCI devices until a
+    better permanent solution is worked out.
+    
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 1f8d894f2066d9db2b251d512f6f6f772ae7147f
-Author: Tanmay Inamdar <tinamdar at apm.com>
-Date:   Wed Mar 19 16:12:40 2014 -0700
+commit 612eea3ae291b28f7ed50ccf50bd1685a2a7f753
+Author: Mark Salter <msalter at redhat.com>
+Date:   Thu Aug 14 12:32:13 2014 -0400
 
-    arm64: dts: APM X-Gene PCIe device tree nodes
+    acpi: add utility to test for device dma coherency
+    
+    ACPI 5.1 adds a _CCA object to indicate memory coherency
+    of a bus master device. It is an integer with zero meaning
+    non-coherent and one meaning coherent. This attribute may
+    be inherited from a parent device. It may also be missing
+    entirely, in which case, an architecture-specific default
+    is assumed.
     
-    This patch adds the device tree nodes for APM X-Gene PCIe controller and
-    PCIe clock interface. Since X-Gene SOC supports maximum 5 ports, 5 dts
-    nodes are added.
+    This patch adds a utility function to parse a device handle
+    (and its parents) for a _CCA object and return the coherency
+    attribute if found.
     
-    Signed-off-by: Tanmay Inamdar <tinamdar at apm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit c0855fcf0cc9adcb1ba5e6b1318536c56244796d
-Author: Tanmay Inamdar <tinamdar at apm.com>
-Date:   Wed Mar 19 16:12:39 2014 -0700
+commit 3d509a508c6fd70eb0fb2f0e82d08d92cc96568c
+Author: Mark Salter <msalter at redhat.com>
+Date:   Sat Nov 22 12:08:53 2014 -0500
 
-    pci: APM X-Gene PCIe controller driver
+    DO NOT UPSTREAM - arm64: kvm: Change vgic resource size error to info
     
-    This patch adds the AppliedMicro X-Gene SOC PCIe controller driver.
-    X-Gene PCIe controller supports maximum up to 8 lanes and GEN3 speed.
-    X-Gene SOC supports maximum 5 PCIe ports.
+    From: Donald Dutile <ddutile at redhat.com>
     
-    Signed-off-by: Tanmay Inamdar <tinamdar at apm.com>
+    A new check was added to upstream to ensure a full
+    kernel page was allocated to the vgic.  The check failed
+    kvm configuration if the condition wasn't met. An arm64
+    kernel with 64K pagesize and certain early firmware will
+    fail this test. Change error to info & continue configuration
+    for now.
+    
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 1cc0c322237d3b58b08fe39e79e6c2e2f90a8c98
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:44:00 2014 +0100
+commit 2b5dd4609e947b418afbbeae95da7f34594bc048
+Author: Wei Huang <wei at redhat.com>
+Date:   Sat Nov 22 10:38:45 2014 -0500
 
-    arm64: Add architectural support for PCI
+    KVM/ACPI: Enable ACPI support for KVM virt GIC
     
-    Use the generic host bridge functions to provide support for
-    PCI Express on arm64.
+    This patches enables ACPI support for KVM virtual GIC. KVM parses
+    ACPI table for virt GIC related information when DT table is not
+    present. This is done by retrieving the information defined in
+    generic_interrupt entry of MADT table.
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
+    Note: Alexander Spyridakis from Virtual Open System posts a
+    _very_ similar patch to enable acpi-kvm. This patch borrows some
+    ideas from his patch.
+    
+    Signed-off-by: Wei Huang <wei at redhat.com>
+    [combined with subsequent patch to use acpi_disabled]
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit aba1eca911a87959eb4be515110f7a6b8692e9a4
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:34 2014 +0100
+commit 756fc31666a4a3094727da5274fc0705a05f13a3
+Author: Wei Huang <wei at redhat.com>
+Date:   Sat Nov 22 10:18:57 2014 -0500
 
-    pci: Remap I/O bus resources into CPU space with pci_remap_iospace()
+    KVM/ACPI: Enable ACPI support for virt arch timer
     
-    Introduce a default implementation for remapping PCI bus I/O resources
-    onto the CPU address space. Architectures with special needs may
-    provide their own version, but most should be able to use this one.
+    This patches enables ACPI support for KVM virtual arch_timer. It
+    allows KVM to parse ACPI table for virt arch_timer PPI when DT table
+    is not present. This is done by retrieving the information from
+    arch_timer_ppi array in arm_arch_timer driver.
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
+    Signed-off-by: Wei Huang <wei at redhat.com>
+    [combined with subsequent patch to use acpi_disabled]
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit e1eacc3da10ca19eff1f88fb342a13586092b613
-Author: Liviu Dudau <liviu at dudau.co.uk>
-Date:   Tue Jul 1 21:50:50 2014 +0100
+commit b189108603f6db4a11e0c30050e840e8bb36f098
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Tue Nov 18 21:52:34 2014 +0100
 
-    pci: Add support for creating a generic host_bridge from device tree
+    arm, arm64: KVM: handle potential incoherency of readonly memslots
+    
+    Upstream posting:
+    http://thread.gmane.org/gmane.comp.emulators.kvm.devel/129475/focus=129477
+    
+    Readonly memslots are often used to implement emulation of ROMs and
+    NOR flashes, in which case the guest may legally map these regions as
+    uncached.
+    To deal with the incoherency associated with uncached guest mappings,
+    treat all readonly memslots as incoherent, and ensure that pages that
+    belong to regions tagged as such are flushed to DRAM before being passed
+    to the guest.
     
-    Several platforms use a rather generic version of parsing
-    the device tree to find the host bridge ranges. Move the common code
-    into the generic PCI code and use it to create a pci_host_bridge
-    structure that can be used by arch code.
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    
+    Acadia backport notes:
+    
+    - we have a few more conflicts here. The main thing is that our
+      kvm_arch_prepare_memory_region() is "empty" at the moment; in upstream
+      Ard introduced performance related, host device related code there, in
+      commit 8eef91239.
+    
+      What we certainly need to grab from commit 8eef91239 is the acquiring of
+      "kvm->mmu_lock" (which is visible in the upstream patch context too),
+      and the filtering against
     
-    Based on early attempts by Andrew Murray to unify the code.
-    Used powerpc and microblaze PCI code as starting point.
+        (change != KVM_MR_CREATE && change != KVM_MR_MOVE)
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
-    Tested-by: Tanmay Inamdar <tinamdar at apm.com>
+      near the top of the function (which is not visible in the upstream patch
+      context). (If (change == KVM_MR_DELETE), then the caller has set up
+      "memslot" in such a way that calling stage2_flush_memslot() on it is
+      invalid, and it would actually crash the host -- speaking from
+      experience. :))
+    
+    - The hunk that seems to matter in practice, in my testing on Mustang, is
+      the "fault_ipa_uncached" assignment one (which  affects the the
+      demand-paged case, ie. the coherent_cache_guest_page() function,
+      modified in the previous patch).
+    
+      The kvm_arch_prepare_memory_region() hunk exists for completeness of
+      implementation, and while it could certainly make a difference, I've
+      never seen it make one, in my testing. We should pick it up nonetheless.
+    
+    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
 
-commit aee55d507eb451223b51b52e6617b06b8e518ea6
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:32 2014 +0100
+commit 8ab19d68b49c2f6a9f0e6226c51bf9b2fe553022
+Author: Laszlo Ersek <lersek at redhat.com>
+Date:   Tue Nov 18 21:52:33 2014 +0100
 
-    pci: of: Parse and map the IRQ when adding the PCI device.
+    arm, arm64: KVM: allow forced dcache flush on page faults
+    
+    Upstream posting:
+    http://thread.gmane.org/gmane.comp.emulators.kvm.devel/129475/focus=129476
     
-    Enhance the default implementation of pcibios_add_device() to
-    parse and map the IRQ of the device if a DT binding is available.
+    From: Laszlo Ersek <lersek at redhat.com>
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
+    To allow handling of incoherent memslots in a subsequent patch, this
+    patch adds a paramater 'ipa_uncached' to cache_coherent_guest_page()
+    so that we can instruct it to flush the page's contents to DRAM even
+    if the guest has caching globally enabled.
+    
+    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    
+    Acadia backport notes:
+    - minimal context conflict in user_mem_abort(): upstream passes
+    
+        pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE)
+    
+      as last parameter of stage2_set_pte(), while we do a direct comparison.
+    
+      (See upstream commit 3d08c629, "arm: kvm: STRICT_MM_TYPECHECKS fix for
+      user_mem_abort".)
+    
+    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
 
-commit 0cf0470962f0498b598ff44e0c671407df54b22e
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:31 2014 +0100
+commit 1ac87393dff5d6fb10edfba84dfff89f57a7224a
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Tue Nov 18 21:52:32 2014 +0100
 
-    pci: Introduce a domain number for pci_host_bridge.
+    kvm: add a memslot flag for incoherent memory regions
     
-    Make it easier to discover the domain number of a bus by storing
-    the number in pci_host_bridge for the root bus. Several architectures
-    have their own way of storing this information, so it makes sense
-    to try to unify the code. While at this, add a new function that
-    creates a root bus in a given domain and make pci_create_root_bus()
-    a wrapper around this function.
+    Upstream posting:
+    http://thread.gmane.org/gmane.comp.emulators.kvm.devel/129475
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
-    Tested-by: Tanmay Inamdar <tinamdar at apm.com>
+    Memory regions may be incoherent with the caches, typically when the
+    guest has mapped a host system RAM backed memory region as uncached.
+    Add a flag KVM_MEMSLOT_INCOHERENT so that we can tag these memslots
+    and handle them appropriately when mapping them.
+    
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
 
-commit 1bc8fcf01469c202b4aea5f1d0a3a75c9302f3e2
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:30 2014 +0100
+commit 2a0a5cbf98c94e2906d9a357a63fbbb153488e1c
+Author: Tom Lendacky <thomas.lendacky at amd.com>
+Date:   Mon Sep 15 17:02:52 2014 -0600
 
-    pci: Create pci_host_bridge before its associated bus in pci_create_root_bus.
+    amd-xgbe: AMD 10GbE driver APCI support for A0
     
-    Before commit 7b5436635800 the pci_host_bridge was created before the root bus.
-    As that commit has added a needless dependency on the bus for pci_alloc_host_bridge()
-    the creation order has been changed for no good reason. Revert the order of
-    creation as we are going to depend on the pci_host_bridge structure to retrieve the
-    domain number of the root bus.
+    This patch provides ACPI support for the AMD 10GbE device driver
+    and AMD 10GbE phy driver.
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
-    Acked-by: Grant Likely <grant.likely at linaro.org>
-    Tested-by: Tanmay Inamdar <tinamdar at apm.com>
+    Signed-off-by: Tom Lendacky <thomas.lendacky at amd.com>
+
+commit 807e95abb96e7868e1c8e863a92298937a69d437
+Author: Mark Salter <msalter at redhat.com>
+Date:   Tue Oct 7 12:54:08 2014 -0400
+
+    xgene acpi network - first cut
 
-commit 55353327169dc08c1047d994e00b8a38630f5a8d
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:29 2014 +0100
+commit bdecd2af5d4234ed50042ab28a21736edcec6d41
+Author: Geert Uytterhoeven <geert+renesas at glider.be>
+Date:   Thu Nov 6 12:23:23 2014 +0100
 
-    pci: OF: Fix the conversion of IO ranges into IO resources.
+    leds: leds-gpio: Fix legacy GPIO number case
     
-    The ranges property for a host bridge controller in DT describes
-    the mapping between the PCI bus address and the CPU physical address.
-    The resources framework however expects that the IO resources start
-    at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
-    The conversion from pci ranges to resources failed to take that into account.
+    In the legacy case, led_dat->gpiod is initialized correctly, but
+    overwritten later by template->gpiod, which is NULL, causing leds-gpio
+    to fail with:
     
-    In the process move the function into drivers/of/address.c as it now
-    depends on pci_address_to_pio() code and make it return an error message.
+        gpiod_direction_output: invalid GPIO
+        leds-gpio: probe of leds-gpio failed with error -22
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
-    Tested-by: Tanmay Inamdar <tinamdar at apm.com>
+    Move the initialization of led_dat->gpiod from template->gpiod up, and
+    always use led_dat->gpiod later, to fix this.
+    
+    Fixes: 5c51277a9ababfa4 (leds: leds-gpio: Add support for GPIO descriptors)
+    Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
+    Reviewed-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit 34079a20796d5c74e2984c37a99baef4871709a6
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:28 2014 +0100
+commit 42b0d1b64cdf1c8d37e69ff7cff45852f7a16f65
+Author: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+Date:   Wed Nov 5 00:29:07 2014 +0100
 
-    pci: Introduce pci_register_io_range() helper function.
-    
-    Some architectures do not have a simple view of the PCI I/O space
-    and instead use a range of CPU addresses that map to bus addresses. For
-    some architectures these ranges will be expressed by OF bindings
-    in a device tree file.
+    ACPI / property: Drop size_prop from acpi_dev_get_property_reference()
+    
+    The size_prop argument of the recently added function
+    acpi_dev_get_property_reference() is not used by the only current
+    caller of that function and is very unlikely to be used at any time
+    going forward.
+    
+    Namely, for a property whose value is a list of items each containing
+    a references to a device object possibly accompanied by some integers,
+    the number of items in the list can always be computed as the number
+    of elements of type ACPI_TYPE_LOCAL_REFERENCE in the property package.
+    Thus it should never be necessary to provide an additional "cells"
+    property with a value equal to the number of items in that list.  It
+    also should never be necessary to provide a "cells" property specifying
+    how many integers are supposed to be following each reference.
+    
+    For this reason, drop the size_prop argument from
+    acpi_dev_get_property_reference() and update its caller accordingly.
+    
+    Link: http://marc.info/?l=linux-kernel&m=141511255610556&w=2
+    Suggested-by: Grant Likely <grant.likely at linaro.org>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Acked-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Tested-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit c3f29cda7420da6a721d40d116f369cfc1533d38
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Fri Oct 31 13:40:58 2014 +0200
+
+    leds: leds-gpio: Convert gpio_blink_set() to use GPIO descriptors
+    
+    Commit 21f2aae91e902aad ("leds: leds-gpio: Add support for GPIO
+    descriptors") already converted most of the driver to use GPIO descriptors.
+    What is still missing is the platform specific hook gpio_blink_set() and
+    board files which pass legacy GPIO numbers to this driver in platform data.
+    
+    In this patch we handle the former and convert gpio_blink_set() to take
+    GPIO descriptor instead. In order to do this we convert the existing four
+    users to accept GPIO descriptor and translate it to legacy GPIO number in
+    the platform code. This effectively "pushes" legacy GPIO number usage from
+    the driver to platforms.
+    
+    Also add comment to the remaining block describing that it is legacy code
+    path and we are getting rid of it eventually.
+    
+    Suggested-by: Linus Walleij <linus.walleij at linaro.org>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Andrew Lunn <andrew at lunn.ch>
+    Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
+    Acked-by: Alexandre Courbot <acourbot at nvidia.com>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit 4117b39d39f59d2497ceac1091ec54aa3056cb4f
+Author: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+Date:   Mon Nov 3 23:39:57 2014 +0100
+
+    ACPI / GPIO: Document ACPI GPIO mappings API
     
-    Introduce a pci_register_io_range() helper function with a generic
-    implementation that can be used by such architectures to keep track
-    of the I/O ranges described by the PCI bindings. If the PCI_IOBASE
-    macro is not defined that signals lack of support for PCI and we
-    return an error.
+    Document the previously introduced method that can be used by device
+    drivers to provide the GPIO subsystem with mappings between GPIO names
+    (connection IDs) and GpioIo()/GpioInt() resources in _CRS.
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+    Reviewed-by: Mika Westerberg <mika.westerberg at linux.intel.com>
 
-commit a81abc095ab4b9b90e446ddbd59247e23df9d4ad
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:27 2014 +0100
+commit d9345c86ad290bb4ca98b37520f94fc8075b2b94
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Mon Oct 27 12:15:14 2014 +0200
 
-    pci: Export find_pci_host_bridge() function.
+    net: rfkill: gpio: Add default GPIO driver mappings for ACPI
+    
+    The driver uses devm_gpiod_get_index(..., index) so that the index refers
+    directly to the GpioIo resource under the ACPI device. The problem with
+    this is that if the ordering changes we get wrong GPIOs.
+    
+    With ACPI 5.1 _DSD we can now use names instead to reference GPIOs
+    analogous to Device Tree. However, we still have systems out there that do
+    not provide _DSD at all. These systems must be supported as well.
+    
+    Luckily we now have acpi_dev_add_driver_gpios() that can be used to provide
+    mappings for systems where _DSD is not provided and still take advantage of
+    _DSD if it exists.
     
-    This is a useful function and we should make it visible outside the
-    generic PCI code. Export it as a GPL symbol.
+    This patch changes the driver to create default GPIO mappings if we are
+    running on ACPI system.
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
-    Tested-by: Tanmay Inamdar <tinamdar at apm.com>
+    While there we can drop the indices completely and use devm_gpiod_get()
+    with name instead.
+    
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Reviewed-by: Johannes Berg <johannes at sipsolutions.net>
+    Acked-by: John W. Linville <linville at tuxdriver.com>
+    Acked-by: Linus Walleij <linus.walleij at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit 22cb8c44e198b7e3f3299324edbcaa1389016d52
+Author: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+Date:   Mon Nov 3 23:39:41 2014 +0100
 
-commit 78361698444e81bedbf30ec2b7aae1afd110d11f
-Author: Liviu Dudau <Liviu.Dudau at arm.com>
-Date:   Tue Jul 1 19:43:26 2014 +0100
+    ACPI / GPIO: Driver GPIO mappings for ACPI GPIOs
+    
+    Provide a way for device drivers using GPIOs described by ACPI
+    GpioIo resources in _CRS to tell the GPIO subsystem what names
+    (connection IDs) to associate with specific GPIO pins defined
+    in there.
+    
+    To do that, a driver needs to define a mapping table as a
+    NULL-terminated array of struct acpi_gpio_mapping objects
+    that each contain a name, a pointer to an array of line data
+    (struct acpi_gpio_params) objects and the size of that array.
+    
+    Each struct acpi_gpio_params object consists of three fields,
+    crs_entry_index, line_index, active_low, representing the index of
+    the target GpioIo()/GpioInt() resource in _CRS starting from zero,
+    the index of the target line in that resource starting from zero,
+    and the active-low flag for that line, respectively.
+    
+    Next, the mapping table needs to be passed as the second
+    argument to acpi_dev_add_driver_gpios() that will register it with
+    the ACPI device object pointed to by its first argument.  That
+    should be done in the driver's .probe() routine.
+    
+    On removal, the driver should unregister its GPIO mapping table
+    by calling acpi_dev_remove_driver_gpios() on the ACPI device
+    object where that table was previously registered.
+    
+    Included are fixes from Mika Westerberg.
+    
+    Acked-by: Alexandre Courbot <acourbot at nvidia.com>
+    Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-    Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
+commit c70e2807a8bacbdfed992b58ca24eb152a778a01
+Author: Aaron Lu <aaron.lu at intel.com>
+Date:   Tue Oct 21 13:34:00 2014 +0200
+
+    input: gpio_keys_polled: Make use of device property API
     
-    The inline version of ioport_map() that gets used when !CONFIG_GENERIC_IOMAP
-    is wrong. It returns a mapped (i.e. virtual) address that can start from
-    zero and completely ignores the PCI_IOBASE and IO_SPACE_LIMIT that most
-    architectures that use !CONFIG_GENERIC_MAP define.
+    Make use of device property API in this driver so that both OF based
+    system and ACPI based system can use this driver.
     
-    Signed-off-by: Liviu Dudau <Liviu.Dudau at arm.com>
-    Acked-by: Arnd Bergmann <arnd at arndb.de>
-    Tested-by: Tanmay Inamdar <tinamdar at apm.com>
+    Signed-off-by: Aaron Lu <aaron.lu at intel.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Dmitry Torokhov <dmitry.torokhov at gmail.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit 5540bbe2eca72e37be2e6a1c18e2fc7e73f0eab6
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:50 2014 +0100
+commit 29257e751014d0d43f78bcfecd9a56a603096c95
+Author: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+Date:   Mon Oct 27 23:30:10 2014 +0100
 
-    arm64: KVM: vgic: enable GICv2 emulation on top on GICv3 hardware
+    leds: leds-gpio: Make use of device property API
+    
+    Make use of device property API in this driver so that both OF and ACPI
+    based system can use the same driver.
     
-    Add the last missing bits that enable GICv2 emulation on top of
-    GICv3 hardware.
+    This change contains material from Max Eliaser and Mika Westerberg.
     
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Bryan Wu <cooloney at gmail.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit 08ddbc9678ce8465f17acc8e1b1b67442593d1b5
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Tue Oct 21 13:33:59 2014 +0200
 
-commit f057aaf81a7df641bcaa992965a257e3260ad36e
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:49 2014 +0100
+    gpio: Support for unified device properties interface
+    
+    Some drivers need to deal with only firmware representation of its
+    GPIOs. An example would be a GPIO button array driver where each button
+    is described as a separate firmware node in device tree. Typically these
+    child nodes do not have physical representation in the Linux device
+    model.
+    
+    In order to help device drivers to handle such firmware child nodes we
+    add dev[m]_get_named_gpiod_from_child() that takes a child firmware
+    node pointer as its second argument (the first one is the parent device
+    itself), finds the GPIO using whatever is the underlying firmware
+    method, and requests the GPIO properly.
+    
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Alexandre Courbot <acourbot at nvidia.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit 880614f83402ae8b408f33cb252505da0760f3e5
+Author: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+Date:   Tue Nov 4 14:03:59 2014 +0100
+
+    Driver core: Unified interface for firmware node properties
+    
+    Add new generic routines are provided for retrieving properties from
+    device description objects in the platform firmware in case there are
+    no struct device objects for them (either those objects have not been
+    created yet or they do not exist at all).
+    
+    The following functions are provided:
+    
+    fwnode_property_present()
+    fwnode_property_read_u8()
+    fwnode_property_read_u16()
+    fwnode_property_read_u32()
+    fwnode_property_read_u64()
+    fwnode_property_read_string()
+    fwnode_property_read_u8_array()
+    fwnode_property_read_u16_array()
+    fwnode_property_read_u32_array()
+    fwnode_property_read_u64_array()
+    fwnode_property_read_string_array()
+    
+    in analogy with the corresponding functions for struct device added
+    previously.  For all of them, the first argument is a pointer to struct
+    fwnode_handle (new type) that allows a device description object
+    (depending on what platform firmware interface is in use) to be
+    obtained.
+    
+    Add a new macro device_for_each_child_node() for iterating over the
+    children of the device description object associated with a given
+    device and a new function device_get_child_node_count() returning the
+    number of a given device's child nodes.
+    
+    The interface covers both ACPI and Device Trees.
+    
+    Suggested-by: Grant Likely <grant.likely at linaro.org>
+    Acked-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit b5923f9dc379c1861a70d8836c7d9976d9521390
+Author: Aaron Lu <aaron.lu at intel.com>
+Date:   Tue Oct 21 23:30:25 2014 +0200
+
+    input: gpio_keys_polled: Add support for GPIO descriptors
+    
+    GPIO descriptors are the preferred way over legacy GPIO numbers
+    nowadays. Convert the driver to use GPIO descriptors internally but
+    still allow passing legacy GPIO numbers from platform data to support
+    existing platforms.
+    
+    Signed-off-by: Aaron Lu <aaron.lu at intel.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Alexandre Courbot <acourbot at nvidia.com>
+    Reviewed-by: Linus Walleij <linus.walleij at linaro.org>
+    Acked-by: Dmitry Torokhov <dmitry.torokhov at gmail.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit 5c3c4fe36a05672113646f8fb839e4c91256ef5d
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Mon Oct 27 23:29:32 2014 +0100
 
-    arm64: KVM: vgic: add GICv3 world switch
+    leds: leds-gpio: Add support for GPIO descriptors
     
-    Introduce the GICv3 world switch code used to save/restore the
-    GICv3 context.
+    GPIO descriptors are the preferred way over legacy GPIO numbers
+    nowadays. Convert the driver to use GPIO descriptors internally but
+    still allow passing legacy GPIO numbers from platform data to support
+    existing platforms.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Alexandre Courbot <acourbot at nvidia.com>
+    Acked-by: Bryan Wu <cooloney at gmail.com>
+    Acked-by: Arnd Bergmann <arnd at arndb.de>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit 7f1b8a791bb375933fdc8420cd08f127d07dd259
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:48 2014 +0100
+commit 8105c03352f32060c765837cbb7d619e075289d9
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Tue Oct 21 13:33:56 2014 +0200
 
-    KVM: ARM: vgic: add the GICv3 backend
+    gpio: sch: Consolidate core and resume banks
     
-    Introduce the support code for emulating a GICv2 on top of GICv3
-    hardware.
+    This is actually a single device with two sets of identical registers,
+    which just happen to start from a different offset. Instead of having
+    separate GPIO chips created we consolidate them to be single GPIO chip.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    In addition having a single GPIO chip allows us to handle ACPI GPIO
+    translation in the core in a more generic way, since the two GPIO chips
+    share the same parent ACPI device.
+    
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Linus Walleij <linus.walleij at linaro.org>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit ce0e2672808ce2805d0aadfd12d94e2dd6be5ab9
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Wed Oct 29 15:41:01 2014 +0100
+
+    gpio / ACPI: Add support for _DSD device properties
+    
+    With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
+    other things as well) returned by _CRS. Previously we were only able to
+    use integer index to find the corresponding GPIO, which is pretty error
+    prone if the order changes.
+    
+    With _DSD we can now query GPIOs using name instead of an integer index,
+    like the below example shows:
+    
+      // Bluetooth device with reset and shutdown GPIOs
+      Device (BTH)
+      {
+          Name (_HID, ...)
+    
+          Name (_CRS, ResourceTemplate ()
+          {
+              GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+                      "\\_SB.GPO0", 0, ResourceConsumer) {15}
+              GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+                      "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
+          })
+    
+          Name (_DSD, Package ()
+          {
+              ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+              Package ()
+    	  {
+                  Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
+                  Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
+              }
+          })
+      }
+    
+    The format of the supported GPIO property is:
+    
+      Package () { "name", Package () { ref, index, pin, active_low }}
+    
+      ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
+            typically this is the device itself (BTH in our case).
+      index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
+      pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
+      active_low - If 1 the GPIO is marked as active_low.
+    
+    Since ACPI GpioIo() resource does not have field saying whether it is
+    active low or high, the "active_low" argument can be used here. Setting
+    it to 1 marks the GPIO as active low.
+    
+    In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
+    resource, second pin in that resource with the GPIO number of 31.
+    
+    This patch implements necessary support to gpiolib for extracting GPIOs
+    using _DSD device properties.
+    
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Linus Walleij <linus.walleij at linaro.org>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit 74428905c3b450eab53a21bee74236501629a443
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:47 2014 +0100
+commit e072a051ef3a5d612949dc22ca71e40dbe978ed1
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Tue Oct 21 13:33:56 2014 +0200
 
-    arm64: KVM: move HCR_EL2.{IMO, FMO} manipulation into the vgic switch code
+    misc: at25: Make use of device property API
     
-    GICv3 requires the IMO and FMO bits to be tightly coupled with some
-    of the interrupt controller's register switch.
+    Make use of device property API in this driver so that both DT and ACPI
+    based systems can use this driver.
     
-    In order to have similar code paths, move the manipulation of these
-    bits to the GICv2 switch code.
+    In addition we hard-code the name of the chip to be "at25" for the
+    reason that there is no common mechanism to fetch name of the firmware
+    node. The only existing user (arch/arm/boot/dts/phy3250.dts) uses the
+    same name so it should continue to work.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit b691c1f97f1fb5b29c3ae4cc836fdbefe61a11ff
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:46 2014 +0100
+commit e176d66bf1a8e613e501dae1fc6798e1a42b7062
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Tue Oct 21 13:33:56 2014 +0200
 
-    arm64: KVM: split GICv2 world switch from hyp code
+    ACPI: Allow drivers to match using Device Tree compatible property
     
-    Move the GICv2 world switch code into its own file, and add the
-    necessary indirection to the arm64 switch code.
+    We have lots of existing Device Tree enabled drivers and allocating
+    separate _HID for each is not feasible. Instead we allocate special _HID
+    "PRP0001" that means that the match should be done using Device Tree
+    compatible property using driver's .of_match_table instead if the driver
+    is missing .acpi_match_table.
     
-    Also introduce a new type field to the vgic_params structure.
+    If there is a need to distinguish from where the device is enumerated
+    (DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+
+commit e30b98eab5645fa42d372cc1be44e22db5f5e9b8
+Author: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+Date:   Tue Nov 4 01:28:56 2014 +0100
+
+    Driver core: Unified device properties interface for platform firmware
+    
+    Add a uniform interface by which device drivers can request device
+    properties from the platform firmware by providing a property name
+    and the corresponding data type.  The purpose of it is to help to
+    write portable code that won't depend on any particular platform
+    firmware interface.
+    
+    The following general helper functions are added:
+    
+    device_property_present()
+    device_property_read_u8()
+    device_property_read_u16()
+    device_property_read_u32()
+    device_property_read_u64()
+    device_property_read_string()
+    device_property_read_u8_array()
+    device_property_read_u16_array()
+    device_property_read_u32_array()
+    device_property_read_u64_array()
+    device_property_read_string_array()
+    
+    The first one allows the caller to check if the given property is
+    present.  The next 5 of them allow single-valued properties of
+    various types to be retrieved in a uniform way.  The remaining 5 are
+    for reading properties with multiple values (arrays of either numbers
+    or strings).
+    
+    The interface covers both ACPI and Device Trees.
+    
+    This change set includes material from Mika Westerberg and Aaron Lu.
+    
+    Signed-off-by: Aaron Lu <aaron.lu at intel.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Acked-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit d3f4563f1bebed7f60f714bdab640e477a081c4b
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:45 2014 +0100
+commit a8762c178234b62dce5e55df8de8528857a47bb7
+Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+Date:   Tue Oct 21 13:33:55 2014 +0200
 
-    arm64: KVM: remove __kvm_hyp_code_{start, end} from hyp.S
+    ACPI: Add support for device specific properties
+    
+    Device Tree is used in many embedded systems to describe the system
+    configuration to the OS. It supports attaching properties or name-value
+    pairs to the devices it describe. With these properties one can pass
+    additional information to the drivers that would not be available
+    otherwise.
+    
+    ACPI is another configuration mechanism (among other things) typically
+    seen, but not limited to, x86 machines. ACPI allows passing arbitrary
+    data from methods but there has not been mechanism equivalent to Device
+    Tree until the introduction of _DSD in the recent publication of the
+    ACPI 5.1 specification.
+    
+    In order to facilitate ACPI usage in systems where Device Tree is
+    typically used, it would be beneficial to standardize a way to retrieve
+    Device Tree style properties from ACPI devices, which is what we do in
+    this patch.
+    
+    If a given device described in ACPI namespace wants to export properties it
+    must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
+    that returns the properties in a package of packages. For example:
+    
+    	Name (_DSD, Package () {
+    		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+    		Package () {
+    			Package () {"name1", <VALUE1>},
+    			Package () {"name2", <VALUE2>},
+    			...
+    		}
+    	})
     
-    We already have __hyp_text_{start,end} to express the boundaries
-    of the HYP text section, and __kvm_hyp_code_{start,end} are getting
-    in the way of a more modular world switch code.
+    The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
+    and is documented in the ACPI 5.1 companion document called "_DSD
+    Implementation Guide" [1], [2].
     
-    Just turn __kvm_hyp_code_{start,end} into #defines mapping the
-    linker-emited symbols.
+    We add several helper functions that can be used to extract these
+    properties and convert them to different Linux data types.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    The ultimate goal is that we only have one device property API that
+    retrieves the requested properties from Device Tree or from ACPI
+    transparent to the caller.
+    
+    [1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
+    [2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+    
+    Reviewed-by: Hanjun Guo <hanjun.guo at linaro.org>
+    Reviewed-by: Josh Triplett <josh at joshtriplett.org>
+    Reviewed-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Darren Hart <dvhart at linux.intel.com>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
+    Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
+    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 
-commit 8ede261e09ad25ab8229d5efb476d5b4f6dc6434
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:44 2014 +0100
+commit a9240791b83abd372e4efb77f20444c27a56ebae
+Author: Mark Salter <msalter at redhat.com>
+Date:   Tue Sep 30 17:19:24 2014 -0400
 
-    KVM: ARM: vgic: revisit implementation of irqchip_in_kernel
+    arm64: avoid need for console= to enable serial console
+    
+    Tell kernel to prefer one of the serial ports on platforms
+    pl011, 8250, or sbsa uarts. console= on command line will
+    override these assumed preferences. This is just a hack to
+    get the behavior we want from SPCR table support. Once SPCR
+    is supported, we can drop this.
     
-    So far, irqchip_in_kernel() was implemented by testing the value of
-    vctrl_base, which worked fine with GICv2.
+    Signed-off-by: Mark Salter <msalter at redhat.com>
+
+commit 6fee3b2bd2ad6349e7bb3082393bf6355e01ce6f
+Author: Tom Lendacky <thomas.lendacky at amd.com>
+Date:   Tue Sep 9 23:33:17 2014 -0400
+
+    drivers: net: AMD Seattle XGBE PHY support for A0 silicon
     
-    With GICv3, this field is useless, as we're using system registers
-    instead of a emmory mapped interface. To solve this, add a boolean
-    flag indicating if the we're using a vgic or not.
+    This patch modifies the upstream AMD XGBE PHY driver to support
+    A0 Seattle silicon in currently shipping systems. The upstream
+    Linux driver is targetted for Seattle B0 silicon.
     
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit ff7faf70feb47e5f1cf1e0f0d02e0f2807da11f5
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:43 2014 +0100
+commit 0a0eea6d358d51ab381e2945c0e9db2f6cc06157
+Author: Tom Lendacky <thomas.lendacky at amd.com>
+Date:   Tue Sep 9 23:34:07 2014 -0400
 
-    KVM: ARM: vgic: split GICv2 backend from the main vgic code
+    drivers: net: AMD Seattle XGBE 10GbE support for A0 silicon
     
-    Brutally hack the innocent vgic code, and move the GICv2 specific code
-    to its own file, using vgic_ops and vgic_params as a way to pass
-    information between the two blocks.
+    This patch modifies the upstream AMD 10GbE XGBE Ethernet driver to
+    support A0 Seattle silicon in currently shipping systems. The
+    upstream Linux driver is targetted for Seattle B0 silicon.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 63480283c0e1dc92f506e5e5306be0ac9b239499
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:42 2014 +0100
+commit ff93b53f3ca8748529855d421bf79329086544cd
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Fri Jul 26 17:55:02 2013 +0100
 
-    KVM: ARM: introduce vgic_params structure
+    virtio-mmio: add ACPI probing
     
-    Move all the data specific to a given GIC implementation into its own
-    little structure.
+    Added the match table and pointers for ACPI probing to the driver.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
 
-commit dcb20f9b66d5615a3e7e492424fa7953c1fe9f01
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:41 2014 +0100
+commit 5315cb5a532e900612ac1202507551761e8bd13c
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Wed Jul 24 11:29:48 2013 +0100
 
-    KVM: ARM: vgic: introduce vgic_enable
+    net: smc91x: add ACPI probing support.
     
-    Move the code dealing with enabling the VGIC on to vgic_ops.
+    Add device ID LINA0003 for this device and add the match table.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    As its a platform device it needs no other code and will be probed in by
+    acpi_platform once device ID is added.
+    
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
 
-commit 67e3bcf8dd823eec79c74bc993fa62fb08b1acea
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:40 2014 +0100
+commit 640f607f1fa10c7c0cd6025dde8883d02fc9b411
+Author: Mark Salter <msalter at redhat.com>
+Date:   Sun Sep 14 09:44:44 2014 -0400
 
-    KVM: ARM: vgic: abstract VMCR access
+    Revert "ahci_xgene: Skip the PHY and clock initialization if already configured by the firmware."
     
-    Instead of directly messing with with the GICH_VMCR bits for the CPU
-    interface save/restore code, add accessors that encode/decode the
-    entire set of registers exposed by VMCR.
+    This reverts commit 0bed13bebd6c99d097796d2ca6c4f10fb5b2eabc.
     
-    Not the most efficient thing, but given that this code is only used
-    by the save/restore code, performance is far from being critical.
+    Temporarily revert for backwards compatibility with rh-0.12-1 firmware
+
+commit e8afbea7e3e11f37c234770d72725894f92de415
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Aug 11 13:46:43 2014 -0400
+
+    xgene: add support for ACPI-probed serial port
+
+commit 3d0ad3e452a81a32842d85dbb88078b74582efb5
+Author: Mark Salter <msalter at redhat.com>
+Date:   Sat Aug 9 12:01:20 2014 -0400
+
+    sata/xgene: support acpi probing
     
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 67caf34f138a4f2516a2afcd5657add2eaaf0ab4
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:39 2014 +0100
+commit a42353df5a2f741e8d2e356c3f053aac8d3eff0e
+Author: Mark Salter <msalter at redhat.com>
+Date:   Thu Sep 18 15:05:23 2014 -0400
 
-    KVM: ARM: vgic: move underflow handling to vgic_ops
+    arm64: add sev to parking protocol
     
-    Move the code dealing with LR underflow handling to its own functions,
-    and make them accessible through vgic_ops.
+    Parking protocol wakes secondary cores with an interrupt.
+    This patch adds an additional sev() to send an event. This
+    is a temporary hack for APM Mustang board and not intended
+    for upstream.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 30acb0a340d388135ae89bed7e248bad203ec876
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:38 2014 +0100
+commit d81f088880b9d763a7006e40dff6bb526c534255
+Author: Mark Salter <msalter at redhat.com>
+Date:   Tue Sep 9 22:59:48 2014 -0400
 
-    KVM: ARM: vgic: abstract MISR decoding
+    arm64: add parking protocol support
     
-    Instead of directly dealing with the GICH_MISR bits, move the code to
-    its own function and use a couple of public flags to represent the
-    actual state.
+    This is a first-cut effort at parking protocol support. It is
+    very much a work in progress (as is the spec it is based on).
+    This code deviates from the current spec in a number of ways
+    to work around current firmware issues and issues with kernels
+    using 64K page sizes.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    caveat utilitor
+    
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 464cbe47011e07b654d161ab4d4bdd05b4d025b3
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:37 2014 +0100
+commit 475b6ce1555e1146761b53c550f2ac019311739f
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Thu Aug 28 14:26:16 2014 -0400
 
-    KVM: ARM: vgic: abstract EISR bitmap access
+    ARM64 / ACPI: Introduce some PCI functions when PCI is enabled
     
-    Move the GICH_EISR access to its own function.
+    Introduce some PCI functions to make ACPI can be compiled when
+    CONFIG_PCI is enabled, these functions should be revisited when
+    implemented on ARM64.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+    [fixed up for 3.17-rc]
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 33930dc5f401e9fc2268c2f128853eb5275e7ab1
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:36 2014 +0100
+commit cb6ebe40936adc5c3154abbec6f89ccb8a0536b7
+Author: Al Stone <ahs3 at redhat.com>
+Date:   Thu Aug 28 13:14:16 2014 -0400
 
-    KVM: ARM: vgic: abstract access to the ELRSR bitmap
+    Fix arm64 compilation error in PNP code
     
-    Move the GICH_ELRSR access to its own functions, and add them to
-    the vgic_ops structure.
+    Signed-off-by: Mark Salter <msalter at redhat.com>
+
+commit b7fc0378e13207a53a3e8466ba6329cfbcaa0526
+Author: Suravee Suthikulpanit <Suravee.Suthikulpanit at amd.com>
+Date:   Tue Sep 9 15:37:15 2014 -0500
+
+    ata: ahci_platform: Add ACPI support for AMD Seattle SATA controller
+    
+    This patch adds ACPI support for non-PCI SATA contoller in ahci_platform driver.
+    It adds ACPI matching table in ahci_platform to support AMD Seattle SATA controller
+    with following ASL structure in DSDT:
+    
+        Device (SATA0)
+        {
+          Name(_HID, "AMDI0600")	// Seattle AHSATA
+          Name (_CCA, 1)		// Cache-coherent controller
+          Name (_CRS, ResourceTemplate ()
+          {
+            Memory32Fixed (ReadWrite, 0xE0300000, 0x00010000)
+            Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive,,,) { 387 }
+          })
+        }
+    
+    Since ATA driver should not require PCI support for ATA_ACPI,
+    this patch also removes dependency in the driver/ata/Kconfig.
+    
+    Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit at amd.com>
+
+commit c5b655e6af273a61e7ec3653deb3550ae4f7abf1
+Author: Mark Salter <msalter at redhat.com>
+Date:   Wed Nov 19 10:08:29 2014 -0500
+
+    tty/sbsauart: make ttySBSA the active console device
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    The sbsauart driver doesn't register itself as a console
+    until module_initcall time. This allows the virtual console
+    driver to register the active console if no console= is
+    given on the cmdline. This patch allows ttySBSA to take
+    over the active console device role from any existing
+    console device if no console= is given on the cmdline.
+    
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 0dca962ccd5b96fb7174880c1bc25085dcc09927
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:35 2014 +0100
+commit 6bee52af3d281d91b871f6876138fa51a41f0472
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Wed Aug 13 13:47:18 2014 +0100
 
-    KVM: ARM: vgic: introduce vgic_ops and LR manipulation primitives
+    tty: SBSA compatible UART
+    
+    This is a subset of pl011 UART which does not supprt DMA or baud rate
+    changing.  It does, however, provide earlycon support (i.e., using
+    "earlycon=ttySBSA" on the kernel command line).
     
-    In order to split the various register manipulation from the main vgic
-    code, introduce a vgic_ops structure, and start by abstracting the
-    LR manipulation code with a couple of accessors.
+    It is specified in the Server Base System Architecture document from
+    ARM.
     
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
 
-commit e66aa6cbdaa25764c58ba8d21da8d1b7d75e7570
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:34 2014 +0100
+commit a66f13e7c17cf7283b9987da2349c0a5c204fa4b
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Sep 8 11:58:46 2014 -0400
 
-    KVM: arm/arm64: vgic: move GICv2 registers to their own structure
+    acpi: fix acpi_os_ioremap for arm64
     
-    In order to make way for the GICv3 registers, move the v2-specific
-    registers to their own structure.
+    The acpi_os_ioremap() function may be used to map normal RAM or IO
+    regions. The current implementation simply uses ioremap_cache(). This
+    will work for some architectures, but arm64 ioremap_cache() cannot be
+    used to map IO regions which don't support caching. So for arm64, use
+    ioremap() for non-RAM regions.
     
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit b04259737c6bb38592c02c93e939fd53909dad04
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:33 2014 +0100
+commit b00f36975b651c0afbddee49e84109694e610f43
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Mon Sep 8 10:36:44 2014 -0400
 
-    arm64: boot protocol documentation update for GICv3
+    acpi: add arm to the platforms that use ioremap
     
-    Linux has some requirements that must be satisfied in order to boot
-    on a system built with a GICv3.
+    Now with the base changes to the arm memory mapping it is safe
+    to convert to using ioremap to map in the tables.
     
-    Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Al Stone <al.stone at linaro.org>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
 
-commit a864693311bd4305214d966b7ca0e0015216c2c4
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:32 2014 +0100
+commit 4f6ca522fc13d8c13c844a2c2f9eafe091a336a9
+Author: Mark Salter <msalter at redhat.com>
+Date:   Mon Sep 8 17:04:28 2014 -0400
 
-    arm64: GICv3 device tree binding documentation
+    acpi/arm64: NOT FOR UPSTREAM - remove EXPERT dependency
     
-    Add the necessary documentation to support GICv3.
+    For convenience to keep existing configs working, remove
+    CONFIG_EXPERT dependency from ACPI for ARM64. This shouldn't
+    go upstream just yet.
     
-    Cc: Thomas Gleixner <tglx at linutronix.de>
-    Cc: Mark Rutland <mark.rutland at arm.com>
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Acked-by: Rob Herring <robh at kernel.org>
-    Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
-
-commit af3035d3ddddb6e19bac9295f0c785bb2c8e718c
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:31 2014 +0100
-
-    irqchip: arm64: Initial support for GICv3
-    
-    The Generic Interrupt Controller (version 3) offers services that are
-    similar to GICv2, with a number of additional features:
-    - Affinity routing based on the CPU MPIDR (ARE)
-    - System register for the CPU interfaces (SRE)
-    - Support for more that 8 CPUs
-    - Locality-specific Peripheral Interrupts (LPIs)
-    - Interrupt Translation Services (ITS)
-    
-    This patch adds preliminary support for GICv3 with ARE and SRE,
-    non-secure mode only. It relies on higher exception levels to grant ARE
-    and SRE access.
-    
-    Support for LPI and ITS will be added at a later time.
-    
-    Cc: Thomas Gleixner <tglx at linutronix.de>
-    Cc: Jason Cooper <jason at lakedaemon.net>
-    Reviewed-by: Zi Shen Lim <zlim at broadcom.com>
-    Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Reviewed-by: Tirumalesh Chalamarla <tchalamarla at cavium.com>
-    Reviewed-by: Yun Wu <wuyun.wu at huawei.com>
-    Reviewed-by: Zhen Lei <thunder.leizhen at huawei.com>
-    Tested-by: Tirumalesh Chalamarla<tchalamarla at cavium.com>
-    Tested-by: Radha Mohan Chintakuntla <rchintakuntla at cavium.com>
-    Acked-by: Radha Mohan Chintakuntla <rchintakuntla at cavium.com>
-    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit c50b02761c3ad5d37ce8fffe7c0bf6b46d23109e
-Author: Marc Zyngier <marc.zyngier at arm.com>
-Date:   Mon Jun 30 16:01:30 2014 +0100
+commit 91eaa3c5387ebcf698b070a4c21e39e5240699ba
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Fri Oct 17 21:37:14 2014 +0800
 
-    irqchip: ARM: GIC: Move some bits of GICv2 to a library-type file
+    Documentation: ACPI for ARM64
     
-    A few GICv2 low-level function are actually very useful to GICv3,
-    and it makes some sense to share them across the two drivers.
-    They end-up in their own file, with an additional parameter used
-    to ensure an optional synchronization (unused on GICv2).
+    Add documentation for the guidelines of how to use ACPI
+    on ARM64.
     
-    Cc: Thomas Gleixner <tglx at linutronix.de>
-    Cc: Jason Cooper <jason at lakedaemon.net>
-    Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
-    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Al Stone <al.stone at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 6a6033cdcbf6022c2848e2181ed6d8b7545af02e
-Author: Mark Salter <msalter at redhat.com>
-Date:   Tue Jun 24 23:16:45 2014 -0400
+commit ef17919599275fd58edb255ecf69807653cdd763
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Fri Oct 17 21:37:13 2014 +0800
 
-    perf: fix arm64 build error
+    ARM64 / ACPI: Enable ARM64 in Kconfig
     
-    I'm seeing the following build error on arm64:
+    Add Kconfigs to build ACPI on ARM64, and make ACPI available on ARM64.
     
-      In file included from util/event.c:3:0:
-      util/event.h:95:17: error: 'PERF_REGS_MAX' undeclared here (not in a function)
-        u64 cache_regs[PERF_REGS_MAX];
-                     ^
+    acpi_idle driver is x86/IA64 dependent now, so make CONFIG_ACPI_PROCESSOR
+    depend on X86 || IA64, and implement it on ARM64 in the future.
     
-    This patch adds a PEFF_REGS_MAX definition for arm64.
+    Reviewed-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Al Stone <al.stone at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+
+commit 7d78ff059af78cc5a80576314c38584834557fc1
+Author: Al Stone <al.stone at linaro.org>
+Date:   Fri Oct 17 21:37:12 2014 +0800
+
+    ARM64 / ACPI: Select ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64
     
-    Signed-off-by: Mark Salter <msalter at redhat.com>
+    ACPI reduced hardware mode is disabled by default, but ARM64
+    can only run properly in ACPI hardware reduced mode, so select
+    ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64.
+    
+    Reviewed-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Al Stone <al.stone at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 1de8987fa549d421576c1b61282c4041c8c78a5f
-Author: Mark Salter <msalter at redhat.com>
-Date:   Tue Jun 24 09:50:28 2014 -0400
+commit 8a387ea5071c9d8bdaf5305320130022ec1d4f7d
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:11 2014 +0800
 
-    arm64: use EFI as last resort for reboot and poweroff
+    ARM64 / ACPI: Parse GTDT to initialize arch timer
     
-    Wire in support for EFI reboot and poweroff functions. We use these
-    only if no other mechanism has been registered with arm_pm_reboot
-    and/or pm_power_off respectively.
+    Using the information presented by GTDT to initialize the arch
+    timer (not memory-mapped).
     
-    Signed-off-by: Mark Salter <msalter at redhat.com>
+    Originally-by: Amit Daniel Kachhap <amit.daniel at samsung.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 1c973051e86625be7ffb3db90d4a70b9ca4199c6
-Author: Matt Fleming <matt.fleming at intel.com>
-Date:   Fri Jun 13 12:39:55 2014 +0100
+commit 7523c8b3b0d23629781c4581272c0647fa543af5
+Author: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+Date:   Fri Oct 17 21:37:10 2014 +0800
 
-    x86/reboot: Add EFI reboot quirk for ACPI Hardware Reduced flag
+    ARM64 / ACPI: Add GICv2 specific ACPI boot support
     
-    It appears that the BayTrail-T class of hardware requires EFI in order
-    to powerdown and reboot and no other reliable method exists.
+    ACPI kernel uses MADT table for proper GIC initialization. It needs to
+    parse GIC related subtables, collect CPU interface and distributor
+    addresses and call driver initialization function (which is hardware
+    abstraction agnostic). In a similar way, FDT initialize GICv1/2.
     
-    This quirk is generally applicable to all hardware that has the ACPI
-    Hardware Reduced bit set, since usually ACPI would be the preferred
-    method.
+    NOTE: This commit allow to initialize GICv1/2 basic functionality.
+    GICv2 vitalization extension, GICv3/4 and ITS are considered as next
+    steps.
     
-    Cc: Len Brown <len.brown at intel.com>
-    Cc: Mark Salter <msalter at redhat.com>
-    Cc: "Rafael J. Wysocki" <rafael.j.wysocki at intel.com>
-    Signed-off-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 621b2a0f1df86bd2f147799303b94575f3acee95
-Author: Matt Fleming <matt.fleming at intel.com>
-Date:   Fri Jun 13 12:35:21 2014 +0100
+commit 743691994f2fb03bc05f539a42ba6ccccb5d18b8
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:09 2014 +0800
 
-    efi/reboot: Allow powering off machines using EFI
+    ARM64 / ACPI: Introduce ACPI_IRQ_MODEL_GIC and register device's gsi
     
-    Not only can EfiResetSystem() be used to reboot, it can also be used to
-    power down machines.
+    Introduce ACPI_IRQ_MODEL_GIC which is needed for ARM64 as GIC is
+    used, and then register device's gsi with the core IRQ subsystem.
     
-    By and large, this functionality doesn't work very well across the range
-    of EFI machines in the wild, so it should definitely only be used as a
-    last resort. In an ideal world, this wouldn't be needed at all.
+    acpi_register_gsi() is similar to DT based irq_of_parse_and_map(),
+    since gsi is unique in the system, so use hwirq number directly
+    for the mapping.
     
-    Unfortunately, we're starting to see machines where EFI is the *only*
-    reliable way to power down, and nothing else, not PCI, not ACPI, works.
+    Originally-by: Amit Daniel Kachhap <amit.daniel at samsung.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+
+commit 0c4d9983cb7b50351aad0aa32e8b6134adaabb0d
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:08 2014 +0800
+
+    ACPI / processor: Make it possible to get CPU hardware ID via GICC
     
-    efi_poweroff_required() should be implemented on a per-architecture
-    basis, since exactly when we should be using EFI runtime services is a
-    platform-specific decision. There's no analogue for reboot because each
-    architecture handles reboot very differently - the x86 code in
-    particular is pretty complex.
+    Introduce a new function map_gicc_mpidr() to allow MPIDRs to be obtained
+    from the GICC Structure introduced by ACPI 5.1.
     
-    Patches to enable this for specific classes of hardware will be
-    submitted separately.
+    MPIDR is the CPU hardware ID as local APIC ID on x86 platform, so we use
+    MPIDR not the GIC CPU interface ID to identify CPUs.
     
-    Cc: Mark Salter <msalter at redhat.com>
-    Signed-off-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 6b2e219b20933cad5d5ba34f7af4efc5317c0fb9
-Author: Matt Fleming <matt.fleming at intel.com>
-Date:   Fri Jun 13 12:22:22 2014 +0100
+commit cb6b980abe388e25e357f73c5780aa1cf1b2e337
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:07 2014 +0800
 
-    efi/reboot: Add generic wrapper around EfiResetSystem()
+    ARM64 / ACPI: Parse MADT for SMP initialization
     
-    Implement efi_reboot(), which is really just a wrapper around the
-    EfiResetSystem() EFI runtime service, but it does at least allow us to
-    funnel all callers through a single location.
+    MADT contains the information for MPIDR which is essential for
+    SMP initialization, parse the GIC cpu interface structures to
+    get the MPIDR value and map it to cpu_logical_map(), and add
+    enabled cpu with valid MPIDR into cpu_possible_map.
     
-    It also simplifies the callsites since users no longer need to check to
-    see whether EFI_RUNTIME_SERVICES are enabled.
+    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.
     
-    Cc: Tony Luck <tony.luck at intel.com>
-    Cc: Mark Salter <msalter at redhat.com>
-    Signed-off-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
 
-commit d0d41b99122d97f81ad05868dff38ccf0a3ffd33
-Author: Saurabh Tangri <saurabh.tangri at intel.com>
-Date:   Mon Jun 2 05:18:35 2014 -0700
+commit 74a72e003ae388f460294a0910a536aced8ce93c
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:06 2014 +0800
 
-    x86/efi: Move all workarounds to a separate file quirks.c
+    ACPI / table: Print GIC information when MADT is parsed
+    
+    When MADT is parsed, print GIC information to make the boot
+    log look pretty:
+    
+    ACPI: GICC (acpi_id[0x0000] address[00000000e112f000] MPDIR[0x0] enabled)
+    ACPI: GICC (acpi_id[0x0001] address[00000000e112f000] MPDIR[0x1] enabled)
+    ...
+    ACPI: GICC (acpi_id[0x0201] address[00000000e112f000] MPDIR[0x201] enabled)
     
-    Currently, it's difficult to find all the workarounds that are
-    applied when running on EFI, because they're littered throughout
-    various code paths. This change moves all of them into a separate
-    file with the hope that it will be come the single location for all
-    our well documented quirks.
+    These information will be very helpful to bring up early systems to
+    see if acpi_id and MPIDR are matched or not as spec defined.
     
-    Signed-off-by: Saurabh Tangri <saurabh.tangri at intel.com>
-    Signed-off-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
 
-commit b5e3a1e8825abb0406ead0e85436df4df20ddcdb
-Author: Don Dutile <ddutile at redhat.com>
-Date:   Tue Mar 25 20:22:26 2014 -0400
+commit 059facbd0f0664aaaf6d732ce02b2f56ea6ad98f
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:05 2014 +0800
 
-    pmu: Adding support for Xgene PMUs
+    ARM64 / ACPI: Parse FADT table to get PSCI flags for PSCI init
+    
+    There are two flags: PSCI_COMPLIANT and PSCI_USE_HVC. When set,
+    the former signals to the OS that the firmware is PSCI compliant.
+    The latter selects the appropriate conduit for PSCI calls by
+    toggling between Hypervisor Calls (HVC) and Secure Monitor Calls
+    (SMC).
+    
+    FADT table contains such information, parse FADT to get the flags
+    for PSCI init. Since ACPI 5.1 doesn't support self defined PSCI
+    function IDs, which means that only PSCI 0.2+ is supported in ACPI.
+    
+    At the same time, only ACPI 5.1 or higher verison supports PSCI,
+    and FADT Major.Minor version was introduced in ACPI 5.1, so we
+    will check the version and only parse FADT table with version >= 5.1.
+    
+    If firmware provides ACPI tables with ACPI version less than 5.1,
+    OS will be messed up with those information and have no way to init
+    smp and GIC, so disable ACPI if we get an FADT table with version
+    less that 5.1.
+    
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+
+commit 7ec63267bb1630c62e5f7fd2eb75a9a31131c89a
+Author: Hanjun Guo <hanjun.guo at linaro.org>
+Date:   Fri Oct 17 21:37:04 2014 +0800
+
+    ARM64 / ACPI: Make PCI optional for ACPI on ARM64
     
-    Message-id: <1395778948-47814-2-git-send-email-ddutile at redhat.com>
-    Patchwork-id: 78602
-    O-Subject: [PATCH 1/3] pmu: Adding support for Xgene PMUs
-    Bugzilla: 1079110
+    As PCI for ARM64 is not ready, so introduce some stub functions
+    to make PCI optional for ACPI, and make ACPI core run without
+    CONFIG_PCI on ARM64.
     
-    Backport of these two posted (but not upstream) patches.
-    Combined into single patch due to gic-patch dependency.
+    Since ACPI on X86 and IA64 depends on PCI and this patch only makes
+    PCI optional for ARM64, it will not break anything on X86 and IA64.
     
-    Signed-off-by: Donald Dutile <ddutile at redhat.com>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 9f4c27693bb120a3134e3e7e8d452fb02d023e2b
-Author: Mark Salter <msalter at redhat.com>
-Date:   Sun Jun 15 09:06:55 2014 -0400
+commit 2f1dd91e7866f2b617af29e9973b88b2cc2e00d6
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Fri Oct 17 21:37:03 2014 +0800
 
-    arm64: fix up APM Mustang devicetree
+    ARM64 / ACPI: If we chose to boot from acpi then disable FDT
     
-    These are changes needed when loading device tree blob built with
-    kernel. i.e. with grub. These are not needed when using devicetree
-    from Tianocore which will be fixed up at tianocore runtime.
+    If the early boot methods of acpi are happy that we have valid ACPI
+    tables and acpi=force has been passed, then do not unflat devicetree
+    effectively disabling further hardware probing from DT.
     
-    Signed-off-by: Mark Salter <msalter at redhat.com>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+
+commit 6941a3cced9ca3d29e6e9c8b0f43917526b74789
+Author: Al Stone <al.stone at linaro.org>
+Date:   Fri Oct 17 21:37:02 2014 +0800
+
+    ARM64 / ACPI: Introduce early_param for "acpi" and pass acpi=force to enable ACPI
+    
+    Introduce one early parameters "off" and "force" for "acpi", acpi=off
+    will be the default behavior for ARM64, so introduce acpi=force to
+    enable ACPI on ARM64.
+    
+    Disable ACPI before early parameters parsed, and enable it to pass
+    "acpi=force" if people want use ACPI on ARM64. This ensures DT be
+    the prefer one if ACPI table and DT both are provided at this moment.
+    
+    Signed-off-by: Al Stone <al.stone at linaro.org>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 1f3a5b228be88be3f734d7a43db3b3f81e160443
-Author: Iyappan Subramanian <isubramanian at apm.com>
-Date:   Mon Jul 14 15:18:05 2014 -0700
+commit 8764d6bd07827a2a29eaaa382fc397527ad1ba19
+Author: Graeme Gregory <graeme.gregory at linaro.org>
+Date:   Fri Oct 17 21:37:01 2014 +0800
 
-    drivers: net: Add APM X-Gene SoC ethernet driver support.
+    ARM64 / ACPI: Introduce sleep-arm.c
     
-    This patch adds network driver for APM X-Gene SoC ethernet.
+    ACPI 5.1 does not currently support S states for ARM64 hardware but
+    ACPI code will call acpi_target_system_state() for device power
+    managment, so introduce sleep-arm.c to allow other drivers to function
+    until S states are defined.
     
-    Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
-    Signed-off-by: Ravi Patel <rapatel at apm.com>
-    Signed-off-by: Keyur Chudgar <kchudgar at apm.com>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
+
+commit 37144fd61ca68e9d542e875187739c982c8d3662
+Author: Al Stone <al.stone at linaro.org>
+Date:   Fri Oct 17 21:37:00 2014 +0800
+
+    ARM64 / ACPI: Get RSDP and ACPI boot-time tables
+    
+    As we want to get ACPI tables to parse and then use the information
+    for system initialization, we should get the RSDP (Root System
+    Description Pointer) first, it then locates Extended Root Description
+    Table (XSDT) which contains all the 64-bit physical address that
+    pointer to other boot-time tables.
+    
+    Introduce acpi.c and its related head file in this patch to provide
+    fundamental needs of extern variables and functions for ACPI core,
+    and then get boot-time tables as needed.
+      - asm/acenv.h for arch specific ACPICA environments and
+        implementation, It is needed unconditionally by ACPI core;
+      - asm/acpi.h for arch specific variables and functions needed by
+        ACPI driver core;
+      - acpi.c for ARM64 related ACPI implementation for ACPI driver
+        core;
+    
+    acpi_boot_table_init() is introduced to get RSDP and boot-time tables,
+    it will be called in setup_arch() before paging_init(), so we should
+    use eary_memremap() mechanism here to get the RSDP and all the table
+    pointers.
+    
+    Signed-off-by: Al Stone <al.stone at linaro.org>
+    Signed-off-by: Graeme Gregory <graeme.gregory at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 54b3fe04c4a953eeb6907ffe9f57aae282f59457
-Author: Iyappan Subramanian <isubramanian at apm.com>
-Date:   Mon Jul 14 15:18:04 2014 -0700
+commit a4f035d2876b41b6f224321da6b6278de577d4c5
+Author: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+Date:   Fri Oct 17 21:36:59 2014 +0800
 
-    dts: Add bindings for APM X-Gene SoC ethernet driver
+    ACPI / table: Count matched and successfully parsed entries without specifying max entries
     
-    This patch adds bindings for APM X-Gene SoC ethernet driver.
+    It is very useful to traverse all available table entries without max
+    number of expected entries type. Current acpi_parse_entries()
+    implementation gives that feature but it does not count those entries,
+    it returns 0 instead, so fix it to count matched and successfully
+    entries and return it.
     
-    Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
-    Signed-off-by: Ravi Patel <rapatel at apm.com>
-    Signed-off-by: Keyur Chudgar <kchudgar at apm.com>
+    NOTE: This change has no impact to x86 and ia64 archs since existing code
+    checks for error occurrence only (acpi_parse_entries(...,0) < 0).
+    
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit 85125c4e1c1b1ef53d6cb77966efa89062540f43
-Author: Iyappan Subramanian <isubramanian at apm.com>
-Date:   Mon Jul 14 15:18:03 2014 -0700
+commit b3055f38d52f5be0103b436a1b04fbf3947aaa39
+Author: Ashwin Chaugule <ashwin.chaugule at linaro.org>
+Date:   Fri Oct 17 21:36:58 2014 +0800
 
-    Documentation: dts: Add bindings for APM X-Gene SoC ethernet driver
+    ACPI / table: Add new function to get table entries
     
-    This patch adds documentation for APM X-Gene SoC ethernet DTS binding.
+    The acpi_table_parse() function has a callback that
+    passes a pointer to a table_header. Add a new function
+    which takes this pointer and parses its entries. This
+    eliminates the need to re-traverse all the tables for
+    each call. e.g. as in acpi_table_parse_madt() which is
+    normally called after acpi_table_parse().
     
-    Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
-    Signed-off-by: Ravi Patel <rapatel at apm.com>
-    Signed-off-by: Keyur Chudgar <kchudgar at apm.com>
+    Acked-by: Grant Likely <grant.likely at linaro.org>
+    Signed-off-by: Ashwin Chaugule <ashwin.chaugule at linaro.org>
+    Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
+    Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
 
-commit fe8ec437eedc45384c23e1e12a09baa82d24fa16
-Author: Iyappan Subramanian <isubramanian at apm.com>
-Date:   Mon Jul 14 15:18:02 2014 -0700
+commit fff62dfc1d7ab6ad3d528b008413fd116d208150
+Author: Mark Salter <msalter at redhat.com>
+Date:   Sat Nov 8 22:25:48 2014 -0500
 
-    MAINTAINERS: Add entry for APM X-Gene SoC ethernet driver
+    arm64: use UEFI for reboot
     
-    This patch adds a MAINTAINERS entry for APM X-Gene SoC
-    ethernet driver.
+    Wire in support for UEFI reboot. We want UEFI reboot to have
+    highest priority for capsule support.
     
-    Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
-    Signed-off-by: Ravi Patel <rapatel at apm.com>
-    Signed-off-by: Keyur Chudgar <kchudgar at apm.com>
+    Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 237639e43c3d6587985a736f33264e129123d7a5
+commit 997a0488adb3f525aedb678b584f2733f43e248e
 Author: Mark Salter <msalter at redhat.com>
-Date:   Fri Jul 25 15:14:32 2014 -0400
+Date:   Sat Nov 8 15:25:41 2014 -0500
 
-    arm/kvm: WIP fix for stage2 pgd memory leak
+    arm64: use UEFI as last resort for poweroff
+    
+    Wire in support for poweroff via UEFI.
     
     Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 0794e2900e5e4be4b7aa0b389e6b0bf8b55c5cd7
+commit 5b823d4bf52286f97dc76683b533ae5c08763897
 Author: Mark Salter <msalter at redhat.com>
 Date:   Thu Jul 17 13:34:50 2014 -0400
 
@@ -779,24 +1360,7 @@ Date:   Thu Jul 17 13:34:50 2014 -0400
     
     Signed-off-by: Mark Salter <msalter at redhat.com>
 
-commit 7adf85b63608b8bea1148f2faa84f475252a9e43
-Author: Mark Salter <msalter at redhat.com>
-Date:   Fri Jul 25 15:32:05 2014 -0400
-
-    rtc: ia64: allow other architectures to use EFI RTC
-    
-    Currently, the rtc-efi driver is restricted to ia64 only.  Newer
-    architectures with EFI support may want to also use that driver. This
-    patch moves the platform device setup from ia64 into drivers/rtc and allow
-    any architecture with CONFIG_EFI=y to use the rtc-efi driver.
-    
-    Signed-off-by: Mark Salter <msalter at redhat.com>
-    Cc: Alessandro Zummo <a.zummo at towertech.it>
-    Cc: Tony Luck <tony.luck at intel.com>
-    Cc: Fenghua Yu <fenghua.yu at intel.com>
-    Cc: Andrew Morton <akpm at linux-foundation.org>
-
-commit 3b2f96c7a6bfbd46e7dee1d7000081422a7983ce
+commit f866806e1ca75a0efc62cda59559286faa7c9926
 Author: Kyle McMartin <kmcmarti at redhat.com>
 Date:   Tue May 13 22:25:26 2014 -0400
 
@@ -866,9314 +1430,11936 @@ Date:   Tue May 13 22:25:26 2014 -0400
     Signed-off-by: Kyle McMartin <kmcmarti at redhat.com>
     Signed-off-by: Donald Dutile <ddutile at redhat.com>
 
-commit 4b866971e92b925a44da8d876cb57864942a90b8
-Author: Mark Salter <msalter at redhat.com>
-Date:   Thu Jul 24 15:56:15 2014 +0100
-
-    arm64: fix soft lockup due to large tlb flush range
-    
-    Under certain loads, this soft lockup has been observed:
-    
-       BUG: soft lockup - CPU#2 stuck for 22s! [ip6tables:1016]
-       Modules linked in: ip6t_rpfilter ip6t_REJECT cfg80211 rfkill xt_conntrack ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw vfat fat efivarfs xfs libcrc32c
-    
-       CPU: 2 PID: 1016 Comm: ip6tables Not tainted 3.13.0-0.rc7.30.sa2.aarch64 #1
-       task: fffffe03e81d1400 ti: fffffe03f01f8000 task.ti: fffffe03f01f8000
-       PC is at __cpu_flush_kern_tlb_range+0xc/0x40
-       LR is at __purge_vmap_area_lazy+0x28c/0x3ac
-       pc : [<fffffe000009c5cc>] lr : [<fffffe0000182710>] pstate: 80000145
-       sp : fffffe03f01fbb70
-       x29: fffffe03f01fbb70 x28: fffffe03f01f8000
-       x27: fffffe0000b19000 x26: 00000000000000d0
-       x25: 000000000000001c x24: fffffe03f01fbc50
-       x23: fffffe03f01fbc58 x22: fffffe03f01fbc10
-       x21: fffffe0000b2a3f8 x20: 0000000000000802
-       x19: fffffe0000b2a3c8 x18: 000003fffdf52710
-       x17: 000003ff9d8bb910 x16: fffffe000050fbfc
-       x15: 0000000000005735 x14: 000003ff9d7e1a5c
-       x13: 0000000000000000 x12: 000003ff9d7e1a5c
-       x11: 0000000000000007 x10: fffffe0000c09af0
-       x9 : fffffe0000ad1000 x8 : 000000000000005c
-       x7 : fffffe03e8624000 x6 : 0000000000000000
-       x5 : 0000000000000000 x4 : 0000000000000000
-       x3 : fffffe0000c09cc8 x2 : 0000000000000000
-       x1 : 000fffffdfffca80 x0 : 000fffffcd742150
-    
-    The __cpu_flush_kern_tlb_range() function looks like:
-    
-      ENTRY(__cpu_flush_kern_tlb_range)
-    	dsb	sy
-    	lsr	x0, x0, #12
-    	lsr	x1, x1, #12
-      1:	tlbi	vaae1is, x0
-    	add	x0, x0, #1
-    	cmp	x0, x1
-    	b.lo	1b
-    	dsb	sy
-    	isb
-    	ret
-      ENDPROC(__cpu_flush_kern_tlb_range)
-    
-    The above soft lockup shows the PC at tlbi insn with:
-    
-      x0 = 0x000fffffcd742150
-      x1 = 0x000fffffdfffca80
-    
-    So __cpu_flush_kern_tlb_range has 0x128ba930 tlbi flushes left
-    after it has already been looping for 23 seconds!.
-    
-    Looking up one frame at __purge_vmap_area_lazy(), there is:
-    
-    	...
-    	list_for_each_entry_rcu(va, &vmap_area_list, list) {
-    		if (va->flags & VM_LAZY_FREE) {
-    			if (va->va_start < *start)
-    				*start = va->va_start;
-    			if (va->va_end > *end)
-    				*end = va->va_end;
-    			nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
-    			list_add_tail(&va->purge_list, &valist);
-    			va->flags |= VM_LAZY_FREEING;
-    			va->flags &= ~VM_LAZY_FREE;
-    		}
-    	}
-    	...
-    	if (nr || force_flush)
-    		flush_tlb_kernel_range(*start, *end);
-    
-    So if two areas are being freed, the range passed to
-    flush_tlb_kernel_range() may be as large as the vmalloc
-    space. For arm64, this is ~240GB for 4k pagesize and ~2TB
-    for 64kpage size.
-    
-    This patch works around this problem by adding a loop limit.
-    If the range is larger than the limit, use flush_tlb_all()
-    rather than flushing based on individual pages. The limit
-    chosen is arbitrary as the TLB size is implementation
-    specific and not accessible in an architected way. The aim
-    of the arbitrary limit is to avoid soft lockup.
+commit a68d368ceb495cabafe82cdd0b83ec1e271a7f9d
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Fri Nov 7 14:12:34 2014 +0000
+
+    arm64: kvm: eliminate literal pool entries
     
-    Signed-off-by: Mark Salter <msalter at redhat.com>
-    [catalin.marinas at arm.com: commit log update]
-    [catalin.marinas at arm.com: marginal optimisation]
-    [catalin.marinas at arm.com: changed to MAX_TLB_RANGE and added comment]
-    Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
-
-diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
-index 37fc4f6..da1d4bf 100644
---- a/Documentation/arm64/booting.txt
-+++ b/Documentation/arm64/booting.txt
-@@ -141,6 +141,14 @@ Before jumping into the kernel, the following conditions must be met:
-   the kernel image will be entered must be initialised by software at a
-   higher exception level to prevent execution in an UNKNOWN state.
- 
-+  For systems with a GICv3 interrupt controller:
-+  - If EL3 is present:
-+    ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1.
-+    ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1.
-+  - If the kernel is entered at EL1:
-+    ICC.SRE_EL2.Enable (bit 3) must be initialised to 0b1
-+    ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b1.
-+
- The requirements described above for CPU mode, caches, MMUs, architected
- timers, coherency and system registers apply to all CPUs.  All CPUs must
- enter the kernel in the same exception level.
-diff --git a/Documentation/devicetree/bindings/arm/gic-v3.txt b/Documentation/devicetree/bindings/arm/gic-v3.txt
-new file mode 100644
-index 0000000..33cd05e
---- /dev/null
-+++ b/Documentation/devicetree/bindings/arm/gic-v3.txt
-@@ -0,0 +1,79 @@
-+* ARM Generic Interrupt Controller, version 3
-+
-+AArch64 SMP cores are often associated with a GICv3, providing Private
-+Peripheral Interrupts (PPI), Shared Peripheral Interrupts (SPI),
-+Software Generated Interrupts (SGI), and Locality-specific Peripheral
-+Interrupts (LPI).
-+
-+Main node required properties:
-+
-+- compatible : should at least contain  "arm,gic-v3".
-+- interrupt-controller : Identifies the node as an interrupt controller
-+- #interrupt-cells : Specifies the number of cells needed to encode an
-+  interrupt source. Must be a single cell with a value of at least 3.
-+
-+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
-+  interrupts. Other values are reserved for future use.
-+
-+  The 2nd cell contains the interrupt number for the interrupt type.
-+  SPI interrupts are in the range [0-987]. PPI interrupts are in the
-+  range [0-15].
-+
-+  The 3rd cell is the flags, encoded as follows:
-+	bits[3:0] trigger type and level flags.
-+		1 = edge triggered
-+		4 = level triggered
-+
-+  Cells 4 and beyond are reserved for future use. When the 1st cell
-+  has a value of 0 or 1, cells 4 and beyond act as padding, and may be
-+  ignored. It is recommended that padding cells have a value of 0.
-+
-+- reg : Specifies base physical address(s) and size of the GIC
-+  registers, in the following order:
-+  - GIC Distributor interface (GICD)
-+  - GIC Redistributors (GICR), one range per redistributor region
-+  - GIC CPU interface (GICC)
-+  - GIC Hypervisor interface (GICH)
-+  - GIC Virtual CPU interface (GICV)
-+
-+  GICC, GICH and GICV are optional.
-+
-+- interrupts : Interrupt source of the VGIC maintenance interrupt.
-+
-+Optional
-+
-+- redistributor-stride : If using padding pages, specifies the stride
-+  of consecutive redistributors. Must be a multiple of 64kB.
-+
-+- #redistributor-regions: The number of independent contiguous regions
-+  occupied by the redistributors. Required if more than one such
-+  region is present.
-+
-+Examples:
-+
-+	gic: interrupt-controller at 2cf00000 {
-+		compatible = "arm,gic-v3";
-+		#interrupt-cells = <3>;
-+		interrupt-controller;
-+		reg = <0x0 0x2f000000 0 0x10000>,	// GICD
-+		      <0x0 0x2f100000 0 0x200000>,	// GICR
-+		      <0x0 0x2c000000 0 0x2000>,	// GICC
-+		      <0x0 0x2c010000 0 0x2000>,	// GICH
-+		      <0x0 0x2c020000 0 0x2000>;	// GICV
-+		interrupts = <1 9 4>;
-+	};
-+
-+	gic: interrupt-controller at 2c010000 {
-+		compatible = "arm,gic-v3";
-+		#interrupt-cells = <3>;
-+		interrupt-controller;
-+		redistributor-stride = <0x0 0x40000>;	// 256kB stride
-+		#redistributor-regions = <2>;
-+		reg = <0x0 0x2c010000 0 0x10000>,	// GICD
-+		      <0x0 0x2d000000 0 0x800000>,	// GICR 1: CPUs 0-31
-+		      <0x0 0x2e000000 0 0x800000>;	// GICR 2: CPUs 32-63
-+		      <0x0 0x2c040000 0 0x2000>,	// GICC
-+		      <0x0 0x2c060000 0 0x2000>,	// GICH
-+		      <0x0 0x2c080000 0 0x2000>;	// GICV
-+		interrupts = <1 9 4>;
-+	};
-diff --git a/Documentation/devicetree/bindings/net/apm-xgene-enet.txt b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
-new file mode 100644
-index 0000000..3e2a295
---- /dev/null
-+++ b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
-@@ -0,0 +1,72 @@
-+APM X-Gene SoC Ethernet nodes
-+
-+Ethernet nodes are defined to describe on-chip ethernet interfaces in
-+APM X-Gene SoC.
-+
-+Required properties:
-+- compatible:		Should be "apm,xgene-enet"
-+- reg: Address and length of the register set for the device. It contains the
-+       information of registers in the same order as described by reg-names
-+- reg-names: Should contain the register set names
-+  "enet_csr":		Ethernet control and status register address space
-+  "ring_csr":		Descriptor ring control and status register address space
-+  "ring_cmd":		Descriptor ring command register address space
-+- interrupts:		Ethernet main interrupt
-+- clocks:		Reference to the clock entry.
-+- local-mac-address:	MAC address assigned to this device
-+- phy-connection-type:	Interface type between ethernet device and PHY device
-+- phy-handle:		Reference to a PHY node connected to this device
-+
-+- mdio: 		Device tree subnode with the following required
-+			properties:
-+
-+	- compatible: Must be "apm,xgene-mdio".
-+	- #address-cells: Must be <1>.
-+	- #size-cells: Must be <0>.
-+
-+	For the phy on the mdio bus, there must be a node with the following
-+	fields:
-+
-+	- compatible: PHY identifier.  Please refer ./phy.txt for the format.
-+	- reg: The ID number for the phy.
-+
-+Optional properties:
-+- status		: Should be "ok" or "disabled" for enabled/disabled.
-+			  Default is "ok".
-+
-+
-+Example:
-+	menetclk: menetclk {
-+		compatible = "apm,xgene-device-clock";
-+		clock-output-names = "menetclk";
-+		status = "ok";
-+	};
-+
-+	menet: ethernet at 17020000 {
-+		compatible = "apm,xgene-enet";
-+		status = "disabled";
-+		reg = <0x0 0x17020000 0x0 0xd100>,
-+		      <0x0 0X17030000 0x0 0X400>,
-+		      <0x0 0X10000000 0x0 0X200>;
-+		reg-names = "enet_csr", "ring_csr", "ring_cmd";
-+		interrupts = <0x0 0x3c 0x4>;
-+		clocks = <&menetclk 0>;
-+		local-mac-address = [00 01 73 00 00 01];
-+		phy-connection-type = "rgmii";
-+		phy-handle = <&menetphy>;
-+		mdio {
-+			compatible = "apm,xgene-mdio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			menetphy: menetphy at 3 {
-+				compatible = "ethernet-phy-id001c.c915";
-+				reg = <0x3>;
-+			};
-+
-+		};
-+	};
-+
-+/* Board-specific peripheral configurations */
-+&menet {
-+        status = "ok";
-+};
-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
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/xgene-pci.txt
-@@ -0,0 +1,52 @@
-+* AppliedMicro X-Gene PCIe interface
-+
-+Required properties:
-+- device_type: set to "pci"
-+- compatible: should contain "apm,xgene-pcie" to identify the core.
-+- reg: A list of physical base address and length for each set of controller
-+       registers. Must contain an entry for each entry in the reg-names
-+       property.
-+- reg-names: Must include the following entries:
-+  "csr": controller configuration registers.
-+  "cfg": pcie configuration space registers.
-+- #address-cells: set to <3>
-+- #size-cells: set to <2>
-+- ranges: ranges for the outbound memory, I/O regions.
-+- dma-ranges: ranges for the inbound memory regions.
-+- #interrupt-cells: set to <1>
-+- interrupt-map-mask and interrupt-map: standard PCI properties
-+	to define the mapping of the PCIe interface to interrupt
-+	numbers.
-+- clocks: from common clock binding: handle to pci clock.
-+
-+Optional properties:
-+- status: Either "ok" or "disabled".
-+
-+Example:
-+
-+SoC specific DT Entry:
-+	pcie0: pcie at 1f2b0000 {
-+		status = "disabled";
-+		device_type = "pci";
-+		compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-+		#interrupt-cells = <1>;
-+		#size-cells = <2>;
-+		#address-cells = <3>;
-+		reg = < 0x00 0x1f2b0000 0x0 0x00010000   /* Controller registers */
-+			0xe0 0xd0000000 0x0 0x00200000>; /* 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>;
-+		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>;
-+		clocks = <&pcie0clk 0>;
-+	};
-+
-+Board specific DT Entry:
-+	&pcie0 {
-+		status = "ok";
-+	};
-diff --git a/MAINTAINERS b/MAINTAINERS
-index 86efa7e..14a3ef1 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -699,6 +699,14 @@ S:	Maintained
- F:	drivers/net/appletalk/
- F:	net/appletalk/
- 
-+APPLIED MICRO (APM) X-GENE SOC ETHERNET DRIVER
-+M:	Iyappan Subramanian <isubramanian at apm.com>
-+M:	Keyur Chudgar <kchudgar at apm.com>
-+M:	Ravi Patel <rapatel at apm.com>
-+S:	Supported
-+F:	drivers/net/ethernet/apm/xgene/
-+F:	Documentation/devicetree/bindings/net/apm-xgene-enet.txt
-+
- APTINA CAMERA SENSOR PLL
- M:	Laurent Pinchart <Laurent.pinchart at ideasonboard.com>
- L:	linux-media at vger.kernel.org
-@@ -6851,6 +6859,13 @@ S:	Maintained
- F:	Documentation/devicetree/bindings/pci/host-generic-pci.txt
- F:	drivers/pci/host/pci-host-generic.c
- 
-+PCI DRIVER FOR APPLIEDMICRO XGENE
-+M:	Tanmay Inamdar <tinamdar at apm.com>
-+L:	linux-pci at vger.kernel.org
-+L:	linux-arm-kernel at lists.infradead.org
-+S:	Maintained
-+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/kvm_host.h b/arch/arm/include/asm/kvm_host.h
-index 193ceaf..d6d5227 100644
---- a/arch/arm/include/asm/kvm_host.h
-+++ b/arch/arm/include/asm/kvm_host.h
-@@ -225,6 +225,11 @@ static inline int kvm_arch_dev_ioctl_check_extension(long ext)
- 	return 0;
- }
- 
-+static inline void vgic_arch_setup(const struct vgic_params *vgic)
-+{
-+	BUG_ON(vgic->type != VGIC_V2);
-+}
-+
- int kvm_perf_init(void);
- int kvm_perf_teardown(void);
- 
-diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
-index 85598b5..713e807 100644
---- a/arch/arm/kernel/asm-offsets.c
-+++ b/arch/arm/kernel/asm-offsets.c
-@@ -182,13 +182,13 @@ int main(void)
-   DEFINE(VCPU_HYP_PC,		offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
- #ifdef CONFIG_KVM_ARM_VGIC
-   DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
--  DEFINE(VGIC_CPU_HCR,		offsetof(struct vgic_cpu, vgic_hcr));
--  DEFINE(VGIC_CPU_VMCR,		offsetof(struct vgic_cpu, vgic_vmcr));
--  DEFINE(VGIC_CPU_MISR,		offsetof(struct vgic_cpu, vgic_misr));
--  DEFINE(VGIC_CPU_EISR,		offsetof(struct vgic_cpu, vgic_eisr));
--  DEFINE(VGIC_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_elrsr));
--  DEFINE(VGIC_CPU_APR,		offsetof(struct vgic_cpu, vgic_apr));
--  DEFINE(VGIC_CPU_LR,		offsetof(struct vgic_cpu, vgic_lr));
-+  DEFINE(VGIC_V2_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
-+  DEFINE(VGIC_V2_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
-+  DEFINE(VGIC_V2_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
-+  DEFINE(VGIC_V2_CPU_EISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
-+  DEFINE(VGIC_V2_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
-+  DEFINE(VGIC_V2_CPU_APR,	offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
-+  DEFINE(VGIC_V2_CPU_LR,	offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
-   DEFINE(VGIC_CPU_NR_LR,	offsetof(struct vgic_cpu, nr_lr));
- #ifdef CONFIG_KVM_ARM_TIMER
-   DEFINE(VCPU_TIMER_CNTV_CTL,	offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
-diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
-index 789bca9..f7057ed 100644
---- a/arch/arm/kvm/Makefile
-+++ b/arch/arm/kvm/Makefile
-@@ -21,4 +21,5 @@ obj-y += kvm-arm.o init.o interrupts.o
- obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
- obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
- obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
-+obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
- obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
-diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
-index 76af9302..e4eaf30 100644
---- a/arch/arm/kvm/interrupts_head.S
-+++ b/arch/arm/kvm/interrupts_head.S
-@@ -421,14 +421,14 @@ vcpu	.req	r0		@ vcpu pointer always in r0
- 	ldr	r9, [r2, #GICH_ELRSR1]
- 	ldr	r10, [r2, #GICH_APR]
- 
--	str	r3, [r11, #VGIC_CPU_HCR]
--	str	r4, [r11, #VGIC_CPU_VMCR]
--	str	r5, [r11, #VGIC_CPU_MISR]
--	str	r6, [r11, #VGIC_CPU_EISR]
--	str	r7, [r11, #(VGIC_CPU_EISR + 4)]
--	str	r8, [r11, #VGIC_CPU_ELRSR]
--	str	r9, [r11, #(VGIC_CPU_ELRSR + 4)]
--	str	r10, [r11, #VGIC_CPU_APR]
-+	str	r3, [r11, #VGIC_V2_CPU_HCR]
-+	str	r4, [r11, #VGIC_V2_CPU_VMCR]
-+	str	r5, [r11, #VGIC_V2_CPU_MISR]
-+	str	r6, [r11, #VGIC_V2_CPU_EISR]
-+	str	r7, [r11, #(VGIC_V2_CPU_EISR + 4)]
-+	str	r8, [r11, #VGIC_V2_CPU_ELRSR]
-+	str	r9, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
-+	str	r10, [r11, #VGIC_V2_CPU_APR]
- 
- 	/* Clear GICH_HCR */
- 	mov	r5, #0
-@@ -436,7 +436,7 @@ vcpu	.req	r0		@ vcpu pointer always in r0
- 
- 	/* Save list registers */
- 	add	r2, r2, #GICH_LR0
--	add	r3, r11, #VGIC_CPU_LR
-+	add	r3, r11, #VGIC_V2_CPU_LR
- 	ldr	r4, [r11, #VGIC_CPU_NR_LR]
- 1:	ldr	r6, [r2], #4
- 	str	r6, [r3], #4
-@@ -463,9 +463,9 @@ vcpu	.req	r0		@ vcpu pointer always in r0
- 	add	r11, vcpu, #VCPU_VGIC_CPU
- 
- 	/* We only restore a minimal set of registers */
--	ldr	r3, [r11, #VGIC_CPU_HCR]
--	ldr	r4, [r11, #VGIC_CPU_VMCR]
--	ldr	r8, [r11, #VGIC_CPU_APR]
-+	ldr	r3, [r11, #VGIC_V2_CPU_HCR]
-+	ldr	r4, [r11, #VGIC_V2_CPU_VMCR]
-+	ldr	r8, [r11, #VGIC_V2_CPU_APR]
- 
- 	str	r3, [r2, #GICH_HCR]
- 	str	r4, [r2, #GICH_VMCR]
-@@ -473,7 +473,7 @@ vcpu	.req	r0		@ vcpu pointer always in r0
- 
- 	/* Restore list registers */
- 	add	r2, r2, #GICH_LR0
--	add	r3, r11, #VGIC_CPU_LR
-+	add	r3, r11, #VGIC_V2_CPU_LR
- 	ldr	r4, [r11, #VGIC_CPU_NR_LR]
- 1:	ldr	r6, [r3], #4
- 	str	r6, [r2], #4
-diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
-index 839f48c..23871dd 100644
---- a/arch/arm64/Kconfig
-+++ b/arch/arm64/Kconfig
-@@ -11,6 +11,7 @@ config ARM64
- 	select ARM_AMBA
- 	select ARM_ARCH_TIMER
- 	select ARM_GIC
-+	select ARM_GIC_V3
- 	select BUILDTIME_EXTABLE_SORT
- 	select CLONE_BACKWARDS
- 	select COMMON_CLK
-@@ -76,7 +77,7 @@ config MMU
- 	def_bool y
- 
- config NO_IOPORT_MAP
--	def_bool y
-+	def_bool y if !PCI
- 
- config STACKTRACE_SUPPORT
- 	def_bool y
-@@ -151,6 +152,23 @@ 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
-+	  here, the kernel will include drivers and infrastructure code
-+	  to support PCIe bus devices.
-+
-+config PCI_DOMAINS
-+	def_bool PCI
-+
-+config PCI_SYSCALL
-+	def_bool PCI
-+
-+source "drivers/pci/Kconfig"
-+source "drivers/pci/pcie/Kconfig"
-+source "drivers/pci/hotplug/Kconfig"
-+
- endmenu
- 
- menu "Kernel Features"
-diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
-index 6541962..0cb67fc 100644
---- a/arch/arm64/boot/dts/apm-mustang.dts
-+++ b/arch/arm64/boot/dts/apm-mustang.dts
-@@ -28,3 +28,15 @@
- &serial0 {
- 	status = "ok";
- };
-+
-+&menet {
-+	status = "ok";
-+};
-+
-+&pcie0clk {
-+	status = "ok";
-+};
-+
-+&pcie0 {
-+	status = "ok";
-+};
-diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
-index 40aa96c..fb2ee54 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>;
-@@ -167,14 +172,13 @@
- 				clock-output-names = "ethclk";
- 			};
- 
--			eth8clk: eth8clk {
-+			menetclk: menetclk {
- 				compatible = "apm,xgene-device-clock";
- 				#clock-cells = <1>;
- 				clocks = <&ethclk 0>;
--				clock-names = "eth8clk";
- 				reg = <0x0 0x1702C000 0x0 0x1000>;
- 				reg-names = "csr-reg";
--				clock-output-names = "eth8clk";
-+				clock-output-names = "menetclk";
- 			};
- 
- 			sataphy1clk: sataphy1clk at 1f21c000 {
-@@ -270,6 +274,161 @@
- 				enable-mask = <0x2>;
- 				clock-output-names = "rtcclk";
- 			};
-+
-+			pcie0clk: pcie0clk at 1f2bc000 {
-+				status = "disabled";
-+				compatible = "apm,xgene-device-clock";
-+				#clock-cells = <1>;
-+				clocks = <&socplldiv2 0>;
-+				reg = <0x0 0x1f2bc000 0x0 0x1000>;
-+				reg-names = "csr-reg";
-+				clock-output-names = "pcie0clk";
-+			};
-+
-+			pcie1clk: pcie1clk at 1f2cc000 {
-+				status = "disabled";
-+				compatible = "apm,xgene-device-clock";
-+				#clock-cells = <1>;
-+				clocks = <&socplldiv2 0>;
-+				reg = <0x0 0x1f2cc000 0x0 0x1000>;
-+				reg-names = "csr-reg";
-+				clock-output-names = "pcie1clk";
-+			};
-+
-+			pcie2clk: pcie2clk at 1f2dc000 {
-+				status = "disabled";
-+				compatible = "apm,xgene-device-clock";
-+				#clock-cells = <1>;
-+				clocks = <&socplldiv2 0>;
-+				reg = <0x0 0x1f2dc000 0x0 0x1000>;
-+				reg-names = "csr-reg";
-+				clock-output-names = "pcie2clk";
-+			};
-+
-+			pcie3clk: pcie3clk at 1f50c000 {
-+				status = "disabled";
-+				compatible = "apm,xgene-device-clock";
-+				#clock-cells = <1>;
-+				clocks = <&socplldiv2 0>;
-+				reg = <0x0 0x1f50c000 0x0 0x1000>;
-+				reg-names = "csr-reg";
-+				clock-output-names = "pcie3clk";
-+			};
-+
-+			pcie4clk: pcie4clk at 1f51c000 {
-+				status = "disabled";
-+				compatible = "apm,xgene-device-clock";
-+				#clock-cells = <1>;
-+				clocks = <&socplldiv2 0>;
-+				reg = <0x0 0x1f51c000 0x0 0x1000>;
-+				reg-names = "csr-reg";
-+				clock-output-names = "pcie4clk";
-+			};
-+		};
-+
-+		pcie0: pcie at 1f2b0000 {
-+			status = "disabled";
-+			device_type = "pci";
-+			compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-+			#interrupt-cells = <1>;
-+			#size-cells = <2>;
-+			#address-cells = <3>;
-+			reg = < 0x00 0x1f2b0000 0x0 0x00010000   /* Controller registers */
-+				0xe0 0xd0000000 0x0 0x00200000>; /* 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>;
-+			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>;
-+			clocks = <&pcie0clk 0>;
-+		};
-+
-+		pcie1: pcie at 1f2c0000 {
-+			status = "disabled";
-+			device_type = "pci";
-+			compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-+			#interrupt-cells = <1>;
-+			#size-cells = <2>;
-+			#address-cells = <3>;
-+			reg = < 0x00 0x1f2c0000 0x0 0x00010000   /* Controller registers */
-+				0xd0 0xd0000000 0x0 0x00200000>; /* 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>;
-+			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>;
-+			clocks = <&pcie1clk 0>;
-+		};
-+
-+		pcie2: pcie at 1f2d0000 {
-+			status = "disabled";
-+			device_type = "pci";
-+			compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-+			#interrupt-cells = <1>;
-+			#size-cells = <2>;
-+			#address-cells = <3>;
-+			reg =  < 0x00 0x1f2d0000 0x0 0x00010000   /* Controller registers */
-+				 0x90 0xd0000000 0x0 0x00200000>; /* 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>;
-+			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>;
-+			clocks = <&pcie2clk 0>;
-+		};
-+
-+		pcie3: pcie at 1f500000 {
-+			status = "disabled";
-+			device_type = "pci";
-+			compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-+			#interrupt-cells = <1>;
-+			#size-cells = <2>;
-+			#address-cells = <3>;
-+			reg = < 0x00 0x1f500000 0x0 0x00010000   /* Controller registers */
-+				0xa0 0xd0000000 0x0 0x00200000>; /* 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>;
-+			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>;
-+			clocks = <&pcie3clk 0>;
-+		};
-+
-+		pcie4: pcie at 1f510000 {
-+			status = "disabled";
-+			device_type = "pci";
-+			compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-+			#interrupt-cells = <1>;
-+			#size-cells = <2>;
-+			#address-cells = <3>;
-+			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>;
-+			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>;
-+			clocks = <&pcie4clk 0>;
- 		};
- 
- 		serial0: serial at 1c020000 {
-@@ -278,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>;
- 		};
-@@ -397,5 +556,30 @@
- 			#clock-cells = <1>;
- 			clocks = <&rtcclk 0>;
- 		};
-+
-+		menet: ethernet at 17020000 {
-+			compatible = "apm,xgene-enet";
-+			status = "disabled";
-+			reg = <0x0 0x17020000 0x0 0xd100>,
-+			      <0x0 0X17030000 0x0 0X400>,
-+			      <0x0 0X10000000 0x0 0X200>;
-+			reg-names = "enet_csr", "ring_csr", "ring_cmd";
-+			interrupts = <0x0 0x3c 0x4>;
-+			dma-coherent;
-+			clocks = <&menetclk 0>;
-+			local-mac-address = [00 00 00 00 00 00];
-+			phy-connection-type = "rgmii";
-+			phy-handle = <&menetphy>;
-+			mdio {
-+				compatible = "apm,xgene-mdio";
-+				#address-cells = <1>;
-+				#size-cells = <0>;
-+				menetphy: menetphy at 3 {
-+					compatible = "ethernet-phy-id001c.c915";
-+					reg = <0x3>;
-+				};
-+
-+			};
-+		};
- 	};
- };
-diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
-index 0b3fcf8..07cb417 100644
---- a/arch/arm64/include/asm/Kbuild
-+++ b/arch/arm64/include/asm/Kbuild
-@@ -29,6 +29,7 @@ generic-y += mman.h
- generic-y += msgbuf.h
- generic-y += mutex.h
- generic-y += pci.h
-+generic-y += pci-bridge.h
- generic-y += poll.h
- generic-y += preempt.h
- generic-y += resource.h
-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
-+++ b/arch/arm64/include/asm/elf.h
-@@ -114,7 +114,8 @@ typedef struct user_fpsimd_state elf_fpregset_t;
-  */
- #define elf_check_arch(x)		((x)->e_machine == EM_AARCH64)
- 
--#define elf_read_implies_exec(ex,stk)	(stk != EXSTACK_DISABLE_X)
-+#define elf_read_implies_exec(ex,stk)	(test_thread_flag(TIF_32BIT) \
-+					 ? (stk == EXSTACK_ENABLE_X) : 0)
- 
- #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
---- 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)
- /*
-  *  I/O port access primitives.
-  */
--#define IO_SPACE_LIMIT		0xffff
-+#define arch_has_dev_port()	(1)
-+#define IO_SPACE_LIMIT		0x1ffffff
- #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 3d69030..cc83520 100644
---- a/arch/arm64/include/asm/kvm_arm.h
-+++ b/arch/arm64/include/asm/kvm_arm.h
-@@ -76,9 +76,10 @@
-  */
- #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
- 			 HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
--			 HCR_AMO | HCR_IMO | HCR_FMO | \
--			 HCR_SWIO | HCR_TIDCP | HCR_RW)
-+			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
- #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
-+#define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
-+
- 
- /* Hyp System Control Register (SCTLR_EL2) bits */
- #define SCTLR_EL2_EE	(1 << 25)
-diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
-index 9fcd54b..a28c35b 100644
---- a/arch/arm64/include/asm/kvm_asm.h
-+++ b/arch/arm64/include/asm/kvm_asm.h
-@@ -18,6 +18,8 @@
- #ifndef __ARM_KVM_ASM_H__
- #define __ARM_KVM_ASM_H__
- 
-+#include <asm/virt.h>
-+
- /*
-  * 0 is reserved as an invalid value.
-  * Order *must* be kept in sync with the hyp switch code.
-@@ -96,13 +98,21 @@ extern char __kvm_hyp_init_end[];
- 
- extern char __kvm_hyp_vector[];
- 
--extern char __kvm_hyp_code_start[];
--extern char __kvm_hyp_code_end[];
-+#define	__kvm_hyp_code_start	__hyp_text_start
-+#define	__kvm_hyp_code_end	__hyp_text_end
- 
- extern void __kvm_flush_vm_context(void);
- extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
- 
- extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
-+
-+extern u64 __vgic_v3_get_ich_vtr_el2(void);
-+
-+extern char __save_vgic_v2_state[];
-+extern char __restore_vgic_v2_state[];
-+extern char __save_vgic_v3_state[];
-+extern char __restore_vgic_v3_state[];
-+
- #endif
- 
- #endif /* __ARM_KVM_ASM_H__ */
-diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
-index 92242ce..4ae9213 100644
---- a/arch/arm64/include/asm/kvm_host.h
-+++ b/arch/arm64/include/asm/kvm_host.h
-@@ -200,4 +200,32 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
- 		     hyp_stack_ptr, vector_ptr);
- }
- 
-+struct vgic_sr_vectors {
-+	void	*save_vgic;
-+	void	*restore_vgic;
+    Replace two instances of 'ldr xN, =(constant)' in the world switch
+    hot path with 'mov' instructions.
+    
+    Acked-by: Marc Zyngier <marc.zyngier at arm.com>
+    Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 246a31b3a8f065e831a6d8d9fd96f3a8e17dbdb9
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Fri Nov 7 14:12:33 2014 +0000
+
+    arm64: ftrace: eliminate literal pool entries
+    
+    Replace ldr xN, =<symbol> with adrp/add or adrp/ldr [as appropriate]
+    in the implementation of _mcount(), which may be called very often.
+    
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit ecd0f8e21514e8ac758ed16a188faaa4c5ef75c7
+Author: Mark Rutland <mark.rutland at arm.com>
+Date:   Tue Nov 4 10:50:16 2014 +0000
+
+    arm64: log physical ID of boot CPU
+    
+    In certain debugging scenarios it's useful to know the physical ID (i.e.
+    the MPIDR_EL1.Aff* fields) of the boot CPU, but we don't currently log
+    this as we do for 32-bit ARM kernels.
+    
+    This patch makes the kernel log the physical ID of the boot CPU early in
+    the boot process. The CPU logical map initialisation is folded in to
+    smp_setup_processor_id (which contrary to its name is also called by UP
+    kernels). This is called before setup_arch, so should not adversely
+    affect existing cpu_logical_map users.
+    
+    Acked-by: Sudeep Holla <sudeep.holla at arm.com>
+    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
+    Acked-by: Lorenzo Pieralisis <lorenzo.pieralisi at arm.com>
+    Signed-off-by: Mark Rutland <mark.rutland at arm.com>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 2899d6ea451eb0037427bbf430069f73cb76becc
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Mon Nov 3 16:50:01 2014 +0000
+
+    arm64/crypto: use crypto instructions to generate AES key schedule
+    
+    This patch implements the AES key schedule generation using ARMv8
+    Crypto Instructions. It replaces the table based C implementation
+    in aes_generic.ko, which means we can drop the dependency on that
+    module.
+    
+    Tested-by: Steve Capper <steve.capper at linaro.org>
+    Acked-by: Steve Capper <steve.capper at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 67b1122c25f0c7a9a126ebabcd2085ef99640c13
+Author: Geoff Levand <geoff at infradead.org>
+Date:   Fri Oct 31 23:06:47 2014 +0000
+
+    arm64/kvm: Fix assembler compatibility of macros
+    
+    Some of the macros defined in kvm_arm.h are useful in assembly files, but are
+    not compatible with the assembler.  Change any C language integer constant
+    definitions using appended U, UL, or ULL to the UL() preprocessor macro.  Also,
+    add a preprocessor include of the asm/memory.h file which defines the UL()
+    macro.
+    
+    Fixes build errors like these when using kvm_arm.h in assembly
+    source files:
+    
+      Error: unexpected characters following instruction at operand 3 -- `and x0,x1,#((1U<<25)-1)'
+    
+    Acked-by: Mark Rutland <mark.rutland at arm.com>
+    Signed-off-by: Geoff Levand <geoff at infradead.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 6a3c07e9aa03b7fbec14ab8bc21fce8590f12d83
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Tue Oct 28 12:24:20 2014 +0000
+
+    arm64/dt: add machine name to kernel call stack dump output
+    
+    This installs the machine name as recorded by setup_machine_fdt()
+    as dump stack arch description. This results in the string to be
+    included in call stack dumps, as is shown here:
+    
+      ...
+      Bad mode in Synchronous Abort handler detected, code 0x84000005
+      CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.18.0-rc2+ #548
+    > Hardware name: linux,dummy-virt (DT)
+      task: ffffffc07c870000 ti: ffffffc07c878000 task.ti: ffffffc07c878000
+      PC is at 0x0
+      ...
+    
+    Note that systems that support DMI/SMBIOS may override this later.
+    
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 7c0569a739d0f1dd8ffd709cf37c53bb42143687
+Author: Steve Capper <steve.capper at linaro.org>
+Date:   Fri Oct 24 13:22:20 2014 +0100
+
+    arm64: xchg: Implement cmpxchg_double
+    
+    The arm64 architecture has the ability to exclusively load and store
+    a pair of registers from an address (ldxp/stxp). Also the SLUB can take
+    advantage of a cmpxchg_double implementation to avoid taking some
+    locks.
+    
+    This patch provides an implementation of cmpxchg_double for 64-bit
+    pairs, and activates the logic required for the SLUB to use these
+    functions (HAVE_ALIGNED_STRUCT_PAGE and HAVE_CMPXCHG_DOUBLE).
+    
+    Also definitions of this_cpu_cmpxchg_8 and this_cpu_cmpxchg_double_8
+    are wired up to cmpxchg_local and cmpxchg_double_local (rather than the
+    stock implementations that perform non-atomic operations with
+    interrupts disabled) as they are used by the SLUB.
+    
+    On a Juno platform running on only the A57s I get quite a noticeable
+    performance improvement with 5 runs of hackbench on v3.17:
+    
+             Baseline | With Patch
+     -----------------+-----------
+     Mean    119.2312 | 106.1782
+     StdDev    0.4919 |   0.4494
+    
+    (times taken to complete `./hackbench 100 process 1000', in seconds)
+    
+    Signed-off-by: Steve Capper <steve.capper at linaro.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 7acf53bfb80c2823d233c14d33cfd2d119713b89
+Author: Joonwoo Park <joonwoop at codeaurora.org>
+Date:   Tue Oct 21 01:59:03 2014 +0100
+
+    arm64: optimize memcpy_{from,to}io() and memset_io()
+    
+    Optimize memcpy_{from,to}io() and memset_io() by transferring in 64 bit
+    as much as possible with minimized barrier usage.  This simplest
+    optimization brings faster throughput compare to current byte-by-byte read
+    and write with barrier in the loop.  Code's skeleton is taken from the
+    powerpc.
+    
+    Link: http://lkml.kernel.org/p/20141020133304.GH23751@e104818-lin.cambridge.arm.com
+    Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
+    Reviewed-by: Trilok Soni <tsoni at codeaurora.org>
+    Signed-off-by: Joonwoo Park <joonwoop at codeaurora.org>
+    Signed-off-by: Will Deacon <will.deacon at arm.com>
+
+commit 1971c19fb2a38a1d94cedada404760a917c36cd4
+Author: Mark Rutland <mark.rutland at arm.com>
+Date:   Thu Oct 23 16:33:33 2014 +0100
+
+    efi: efi-stub: notify on DTB absence
+    
+    In the absence of a DTB configuration table, the EFI stub will happily
+    continue attempting to boot a kernel, despite the fact that this kernel
+    may not function without a description of the hardware. In this case, as
+    with a typo'd "dtb=" option (e.g. "dbt=") or many other possible
+    failures, the only output seen by the user will be the rather terse
+    output from the EFI stub:
+    
+    EFI stub: Booting Linux Kernel...
+    
+    To aid those attempting to debug such failures, this patch adds a notice
+    when no DTB is found, making the output more helpful:
+    
+    EFI stub: Booting Linux Kernel...
+    EFI stub: Generating empty DTB
+    
+    Additionally, a positive acknowledgement is added when a user-specified
+    DTB is in use:
+    
+    EFI stub: Booting Linux Kernel...
+    EFI stub: Using DTB from command line
+    
+    Similarly, a positive acknowledgement is added when a DTB from a
+    configuration table is in use:
+    
+    EFI stub: Booting Linux Kernel...
+    EFI stub: Using DTB from configuration table
+    
+    Signed-off-by: Mark Rutland <mark.rutland at arm.com>
+    Acked-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Acked-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+    Acked-by: Roy Franz <roy.franz at linaro.org>
+    Acked-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 7652016ff98e614ed2e3abac19b996af02434293
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Wed Oct 15 09:36:50 2014 +0200
+
+    arm64: dmi: set DMI string as dump stack arch description
+    
+    This sets the DMI string, containing system type, serial number,
+    firmware version etc. as dump stack arch description, so that oopses
+    and other kernel stack dumps automatically have this information
+    included, if available.
+    
+    Tested-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Acked-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 2586f232bd388d2223f3c7bcba446b2bd25d8e3d
+Author: Yi Li <yi.li at linaro.org>
+Date:   Sat Oct 4 23:46:43 2014 +0800
+
+    arm64: dmi: Add SMBIOS/DMI support
+    
+    SMBIOS is important for server hardware vendors. It implements a spec for
+    providing descriptive information about the platform. Things like serial
+    numbers, physical layout of the ports, build configuration data, and the like.
+    
+    Signed-off-by: Yi Li <yi.li at linaro.org>
+    Tested-by: Suravee Suthikulpanit <suravee.suthikulpanit at amd.com>
+    Tested-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 16b52b24f3d7a4f1555e4233398172b32306c1e4
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Tue Oct 14 16:41:27 2014 +0200
+
+    dmi: add support for SMBIOS 3.0 64-bit entry point
+    
+    The DMTF SMBIOS reference spec v3.0.0 defines a new 64-bit entry point,
+    which enables support for SMBIOS structure tables residing at a physical
+    offset over 4 GB. This is especially important for upcoming arm64
+    platforms whose system RAM resides entirely above the 4 GB boundary.
+    
+    For the UEFI case, this code attempts to detect the new SMBIOS 3.0
+    header magic at the offset passed in the SMBIOS3_TABLE_GUID UEFI
+    configuration table. If this configuration table is not provided, or
+    if we fail to parse the header, we fall back to using the legacy
+    SMBIOS_TABLE_GUID configuration table. This is in line with the spec,
+    that allows both configuration tables to be provided, but mandates that
+    they must point to the same structure table, unless the version pointed
+    to by the 64-bit entry point is a superset of the 32-bit one.
+    
+    For the non-UEFI case, the detection logic is modified to look for the
+    SMBIOS 3.0 header magic before it looks for the legacy header magic.
+    
+    Note that this patch is based on version 3.0.0d [draft] of the
+    specification, which is expected not to deviate from the final version
+    in ways that would affect the correctness of this implementation.
+    
+    Tested-by: Suravee Suthikulpanit <suravee.suthikulpanit at amd.com>
+    Acked-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Tested-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Cc: Andrew Morton <akpm at linux-foundation.org>
+    Cc: Tony Luck <tony.luck at intel.com>
+    Acked-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 016f4b4f5cee9ddd8c243a36c220a65bdfb82dc8
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Tue Oct 14 16:34:47 2014 +0200
+
+    efi: dmi: add support for SMBIOS 3.0 UEFI configuration table
+    
+    This adds support to the UEFI side for detecting the presence of
+    a SMBIOS 3.0 64-bit entry point. This allows the actual SMBIOS
+    structure table to reside at a physical offset over 4 GB, which
+    cannot be supported by the legacy SMBIOS 32-bit entry point.
+    
+    Since the firmware can legally provide both entry points, store
+    the SMBIOS 3.0 entry point in a separate variable, and let the
+    DMI decoding layer decide which one will be used.
+    
+    Tested-by: Suravee Suthikulpanit <suravee.suthikulpanit at amd.com>
+    Acked-by: Leif Lindholm <leif.lindholm at linaro.org>
+    Acked-by: Matt Fleming <matt.fleming at intel.com>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit ac627ea950e853f0a3f91607fb16cb9477f434d7
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Fri Oct 17 12:44:11 2014 +0200
+
+    arm64/efi: drop redundant set_bit(EFI_CONFIG_TABLES)
+    
+    The EFI_CONFIG_TABLES bit already gets set by efi_config_init(),
+    so there is no reason to set it again after this function returns
+    successfully.
+    
+    Acked-by: Will Deacon <will.deacon at arm.com>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 850ba08a3f4756a8340edadd4fdeccd881813ba5
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Mon Oct 20 15:31:57 2014 +0200
+
+    arm64/efi: invert UEFI memory region reservation logic
+    
+    Instead of reserving the memory regions based on which types we know
+    need to be reserved, consider only regions of the following types as
+    free for general use by the OS:
+    
+    EFI_LOADER_CODE
+    EFI_LOADER_DATA
+    EFI_BOOT_SERVICES_CODE
+    EFI_BOOT_SERVICES_DATA
+    EFI_CONVENTIONAL_MEMORY
+    
+    Note that this also fixes a problem with the original code, which would
+    misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it
+    does not have the EFI_MEMORY_RUNTIME attribute set. However, it is
+    perfectly legal for the firmware not to request a virtual mapping for
+    EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in
+    which case the EFI_MEMORY_RUNTIME attribute would not be set.
+    
+    Acked-by: Roy Franz <roy.franz at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 2787807ca4f5f7df82a5c54312753b157e8c052e
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Fri Oct 10 18:42:55 2014 +0200
+
+    arm64/efi: set PE/COFF file alignment to 512 bytes
+    
+    Change our PE/COFF header to use the minimum file alignment of
+    512 bytes (0x200), as mandated by the PE/COFF spec v8.3
+    
+    Also update the linker script so that the Image file itself is also a
+    round multiple of FileAlignment.
+    
+    Acked-by: Catalin Marinas <catalin.marinas at arm.com>
+    Acked-by: Roy Franz <roy.franz at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 7bd0585d9ab62d9787c389d3b62141b76319e5f7
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Fri Oct 10 11:25:24 2014 +0200
+
+    arm64/efi: set PE/COFF section alignment to 4 KB
+    
+    Position independent AArch64 code needs to be linked and loaded at the
+    same relative offset from a 4 KB boundary, or adrp/add and adrp/ldr
+    pairs will not work correctly. (This is how PC relative symbol
+    references with a 4 GB reach are emitted)
+    
+    We need to declare this in the PE/COFF header, otherwise the PE/COFF
+    loader may load the Image and invoke the stub at an offset which
+    violates this rule.
+    
+    Reviewed-by: Roy Franz <roy.franz at linaro.org>
+    Acked-by: Mark Rutland <mark.rutland at arm.com>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+commit 5a0edb2dbdf9327322ae57e8e16d162c2a371318
+Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+Date:   Wed Oct 8 16:11:27 2014 +0200
+
+    arm64/efi: efistub: jump to 'stext' directly, not through the header
+    
+    After the EFI stub has done its business, it jumps into the kernel by
+    branching to offset #0 of the loaded Image, which is where it expects
+    to find the header containing a 'branch to stext' instruction.
+    
+    However, the UEFI spec 2.1.1 states the following regarding PE/COFF
+    image loading:
+    "A UEFI image is loaded into memory through the LoadImage() Boot
+    Service. This service loads an image with a PE32+ format into memory.
+    This PE32+ loader is required to load all sections of the PE32+ image
+    into memory."
+    
+    In other words, it is /not/ required to load parts of the image that are
+    not covered by a PE/COFF section, so it may not have loaded the header
+    at the expected offset, as it is not covered by any PE/COFF section.
+    
+    So instead, jump to 'stext' directly, which is at the base of the
+    PE/COFF .text section, by supplying a symbol 'stext_offset' to
+    efi-entry.o which contains the relative offset of stext into the Image.
+    Also replace other open coded calculations of the same value with a
+    reference to 'stext_offset'
+    
+    Acked-by: Mark Rutland <mark.rutland at arm.com>
+    Acked-by: Roy Franz <roy.franz at linaro.org>
+    Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
+
+ Documentation/acpi/gpio-properties.txt           |  96 +++
+ Documentation/arm64/arm-acpi.txt                 | 323 ++++++++++
+ Documentation/gpio/consumer.txt                  |  18 +
+ Documentation/kernel-parameters.txt              |   3 +-
+ arch/arm/include/asm/kvm_mmu.h                   |   5 +-
+ arch/arm/kvm/mmu.c                               |  22 +-
+ arch/arm/mach-s3c24xx/h1940-bluetooth.c          |   4 +-
+ arch/arm/mach-s3c24xx/h1940.h                    |   4 +-
+ arch/arm/mach-s3c24xx/mach-h1940.c               |   3 +-
+ arch/arm/mach-s3c24xx/mach-rx1950.c              |   3 +-
+ arch/arm/plat-orion/gpio.c                       |   3 +-
+ arch/arm/plat-orion/include/plat/orion-gpio.h    |   5 +-
+ arch/arm64/Kconfig                               |  22 +
+ arch/arm64/Makefile                              |   1 +
+ arch/arm64/crypto/Kconfig                        |   5 +-
+ arch/arm64/crypto/aes-ce-ccm-glue.c              |   4 +-
+ arch/arm64/crypto/aes-ce-cipher.c                | 112 +++-
+ arch/arm64/crypto/aes-ce-setkey.h                |   5 +
+ arch/arm64/crypto/aes-glue.c                     |  18 +-
+ arch/arm64/include/asm/acenv.h                   |  18 +
+ arch/arm64/include/asm/acpi.h                    | 102 +++
+ arch/arm64/include/asm/cmpxchg.h                 |  71 +++
+ arch/arm64/include/asm/cpu_ops.h                 |   1 +
+ arch/arm64/include/asm/dmi.h                     |  31 +
+ arch/arm64/include/asm/elf.h                     |   3 +-
+ arch/arm64/include/asm/kvm_arm.h                 |  21 +-
+ arch/arm64/include/asm/kvm_mmu.h                 |   5 +-
+ arch/arm64/include/asm/pci.h                     |  51 ++
+ arch/arm64/include/asm/psci.h                    |   3 +-
+ arch/arm64/include/asm/smp.h                     |  10 +-
+ arch/arm64/kernel/Makefile                       |   4 +-
+ arch/arm64/kernel/acpi.c                         | 398 ++++++++++++
+ arch/arm64/kernel/cpu_ops.c                      |   8 +-
+ arch/arm64/kernel/efi-entry.S                    |   3 +-
+ arch/arm64/kernel/efi.c                          |  74 ++-
+ arch/arm64/kernel/entry-ftrace.S                 |  21 +-
+ arch/arm64/kernel/head.S                         |  24 +-
+ arch/arm64/kernel/io.c                           |  66 +-
+ arch/arm64/kernel/pci.c                          |  97 ++-
+ arch/arm64/kernel/psci.c                         |  78 ++-
+ arch/arm64/kernel/setup.c                        |  51 +-
+ arch/arm64/kernel/smp.c                          |   2 +-
+ arch/arm64/kernel/smp_parking_protocol.c         | 110 ++++
+ arch/arm64/kernel/time.c                         |   7 +
+ arch/arm64/kernel/vmlinux.lds.S                  |  17 +
+ arch/arm64/kvm/hyp.S                             |   4 +-
+ arch/arm64/mm/dma-mapping.c                      | 112 ++++
+ arch/arm64/pci/Makefile                          |   2 +
+ arch/arm64/pci/mmconfig.c                        | 292 +++++++++
+ arch/arm64/pci/pci.c                             | 461 ++++++++++++++
+ drivers/acpi/Kconfig                             |   6 +-
+ drivers/acpi/Makefile                            |   7 +-
+ drivers/acpi/bus.c                               |   3 +
+ drivers/acpi/internal.h                          |  11 +
+ drivers/acpi/osl.c                               |   6 +-
+ drivers/acpi/processor_core.c                    |  37 ++
+ drivers/acpi/property.c                          | 551 ++++++++++++++++
+ drivers/acpi/scan.c                              | 129 +++-
+ 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/base/Makefile                            |   2 +-
+ drivers/base/property.c                          | 431 +++++++++++++
+ drivers/clocksource/arm_arch_timer.c             | 120 +++-
+ drivers/firmware/dmi_scan.c                      |  79 ++-
+ drivers/firmware/efi/efi.c                       |   4 +
+ drivers/firmware/efi/libstub/arm-stub.c          |  11 +-
+ drivers/gpio/devres.c                            |  32 +
+ drivers/gpio/gpio-sch.c                          | 293 ++++-----
+ drivers/gpio/gpiolib-acpi.c                      | 117 +++-
+ drivers/gpio/gpiolib.c                           |  85 ++-
+ drivers/gpio/gpiolib.h                           |   7 +-
+ drivers/input/keyboard/gpio_keys_polled.c        | 112 ++--
+ drivers/iommu/arm-smmu.c                         |   8 +-
+ drivers/irqchip/irq-gic-v3.c                     |  10 +
+ drivers/irqchip/irq-gic.c                        | 116 ++++
+ drivers/irqchip/irqchip.c                        |   3 +
+ drivers/leds/leds-gpio.c                         | 140 ++--
+ drivers/misc/eeprom/at25.c                       |  34 +-
+ drivers/net/ethernet/amd/Kconfig                 |   2 +-
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c         |  16 +-
+ drivers/net/ethernet/amd/xgbe/xgbe-drv.c         |   3 +
+ drivers/net/ethernet/amd/xgbe/xgbe-main.c        | 289 +++++++--
+ drivers/net/ethernet/amd/xgbe/xgbe-mdio.c        |  20 +-
+ drivers/net/ethernet/amd/xgbe/xgbe-ptp.c         |   4 +-
+ drivers/net/ethernet/amd/xgbe/xgbe.h             |  13 +
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   |  69 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c |  68 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h |   1 +
+ drivers/net/ethernet/smsc/smc91x.c               |  10 +
+ drivers/net/phy/Kconfig                          |   2 +-
+ drivers/net/phy/amd-xgbe-phy.c                   | 777 ++++++++++++-----------
+ drivers/of/base.c                                |  33 +
+ drivers/pci/host/pci-xgene.c                     | 167 +++++
+ drivers/pnp/resource.c                           |   2 +
+ drivers/tty/Kconfig                              |   6 +
+ drivers/tty/Makefile                             |   1 +
+ drivers/tty/sbsauart.c                           | 358 +++++++++++
+ drivers/tty/serial/8250/8250_dw.c                |   9 +
+ drivers/virtio/virtio_mmio.c                     |  12 +-
+ drivers/xen/efi.c                                |   1 +
+ include/acpi/acpi_bus.h                          |  30 +
+ include/acpi/acpi_io.h                           |   6 +
+ include/asm-generic/vmlinux.lds.h                |   7 +
+ include/kvm/arm_vgic.h                           |  20 +-
+ include/linux/acpi.h                             | 141 +++-
+ include/linux/clocksource.h                      |   6 +
+ include/linux/efi.h                              |   6 +-
+ include/linux/gpio/consumer.h                    |   7 +
+ include/linux/gpio_keys.h                        |   3 +
+ include/linux/irqchip/arm-gic-acpi.h             |  31 +
+ include/linux/irqchip/arm-gic.h                  |   2 +
+ include/linux/kvm_host.h                         |   1 +
+ include/linux/leds.h                             |   3 +-
+ include/linux/of.h                               |  34 +
+ include/linux/pci.h                              |  37 +-
+ include/linux/property.h                         | 143 +++++
+ net/rfkill/rfkill-gpio.c                         |  18 +-
+ virt/kvm/arm/arch_timer.c                        | 107 ++--
+ virt/kvm/arm/vgic-v2.c                           |  86 ++-
+ virt/kvm/arm/vgic-v3.c                           |   8 +-
+ virt/kvm/arm/vgic.c                              |  30 +-
+ 125 files changed, 6843 insertions(+), 1117 deletions(-)
+
+diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt
+new file mode 100644
+index 0000000..ae36fcf
+--- /dev/null
++++ b/Documentation/acpi/gpio-properties.txt
+@@ -0,0 +1,96 @@
++_DSD Device Properties Related to GPIO
++--------------------------------------
++
++With the release of ACPI 5.1 and the _DSD configuration objecte names
++can finally be given to GPIOs (and other things as well) returned by
++_CRS.  Previously, we were only able to use an integer index to find
++the corresponding GPIO, which is pretty error prone (it depends on
++the _CRS output ordering, for example).
++
++With _DSD we can now query GPIOs using a name instead of an integer
++index, like the ASL example below shows:
++
++  // Bluetooth device with reset and shutdown GPIOs
++  Device (BTH)
++  {
++      Name (_HID, ...)
++
++      Name (_CRS, ResourceTemplate ()
++      {
++          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
++                  "\\_SB.GPO0", 0, ResourceConsumer) {15}
++          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
++                  "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
++      })
++
++      Name (_DSD, Package ()
++      {
++          ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
++          Package ()
++	  {
++              Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
++              Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
++          }
++      })
++  }
++
++The format of the supported GPIO property is:
++
++  Package () { "name", Package () { ref, index, pin, active_low }}
++
++  ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
++        typically this is the device itself (BTH in our case).
++  index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
++  pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
++  active_low - If 1 the GPIO is marked as active_low.
++
++Since ACPI GpioIo() resource does not have a field saying whether it is
++active low or high, the "active_low" argument can be used here.  Setting
++it to 1 marks the GPIO as active low.
++
++In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
++resource, second pin in that resource with the GPIO number of 31.
++
++ACPI GPIO Mappings Provided by Drivers
++--------------------------------------
++
++There are systems in which the ACPI tables do not contain _DSD but provide _CRS
++with GpioIo()/GpioInt() resources and device drivers still need to work with
++them.
++
++In those cases ACPI device identification objects, _HID, _CID, _CLS, _SUB, _HRV,
++available to the driver can be used to identify the device and that is supposed
++to be sufficient to determine the meaning and purpose of all of the GPIO lines
++listed by the GpioIo()/GpioInt() resources returned by _CRS.  In other words,
++the driver is supposed to know what to use the GpioIo()/GpioInt() resources for
++once it has identified the device.  Having done that, it can simply assign names
++to the GPIO lines it is going to use and provide the GPIO subsystem with a
++mapping between those names and the ACPI GPIO resources corresponding to them.
++
++To do that, the driver needs to define a mapping table as a NULL-terminated
++array of struct acpi_gpio_mapping objects that each contain a name, a pointer
++to an array of line data (struct acpi_gpio_params) objects and the size of that
++array.  Each struct acpi_gpio_params object consists of three fields,
++crs_entry_index, line_index, active_low, representing the index of the target
++GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target
++line in that resource starting from zero, and the active-low flag for that line,
++respectively, in analogy with the _DSD GPIO property format specified above.
++
++For the example Bluetooth device discussed previously the data structures in
++question would look like this:
++
++static const struct acpi_gpio_params reset_gpio = { 1, 1, false };
++static const struct acpi_gpio_params shutdown_gpio = { 0, 0, false };
++
++static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = {
++  { "reset-gpio", &reset_gpio, 1 },
++  { "shutdown-gpio", &shutdown_gpio, 1 },
++  { },
 +};
 +
-+static inline void vgic_arch_setup(const struct vgic_params *vgic)
-+{
-+	extern struct vgic_sr_vectors __vgic_sr_vectors;
-+
-+	switch(vgic->type)
-+	{
-+	case VGIC_V2:
-+		__vgic_sr_vectors.save_vgic	= __save_vgic_v2_state;
-+		__vgic_sr_vectors.restore_vgic	= __restore_vgic_v2_state;
-+		break;
-+
-+#ifdef CONFIG_ARM_GIC_V3
-+	case VGIC_V3:
-+		__vgic_sr_vectors.save_vgic	= __save_vgic_v3_state;
-+		__vgic_sr_vectors.restore_vgic	= __restore_vgic_v3_state;
-+		break;
-+#endif
-+
-+	default:
-+		BUG();
-+	}
-+}
-+
- #endif /* __ARM64_KVM_HOST_H__ */
-diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
-index 7d29847..d7f77ff 100644
---- a/arch/arm64/include/asm/kvm_mmu.h
-+++ b/arch/arm64/include/asm/kvm_mmu.h
-@@ -122,8 +122,16 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
- }
- 
- #define kvm_pgd_addr_end(addr, end)	pgd_addr_end(addr, end)
--#define kvm_pud_addr_end(addr, end)	pud_addr_end(addr, end)
--#define kvm_pmd_addr_end(addr, end)	pmd_addr_end(addr, end)
-+
-+#define kvm_pud_addr_end(addr, end)					\
-+({	unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK;	\
-+	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
-+})
-+
-+#define kvm_pmd_addr_end(addr, end)					\
-+({	unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK;	\
-+	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
-+})
- 
- struct kvm;
- 
-diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
++Next, the mapping table needs to be passed as the second argument to
++acpi_dev_add_driver_gpios() that will register it with the ACPI device object
++pointed to by its first argument.  That should be done in the driver's .probe()
++routine.  On removal, the driver should unregister its GPIO mapping table by
++calling acpi_dev_remove_driver_gpios() on the ACPI device object where that
++table was previously registered.
+diff --git a/Documentation/arm64/arm-acpi.txt b/Documentation/arm64/arm-acpi.txt
 new file mode 100644
-index 0000000..3f7856e
+index 0000000..17cf96d
 --- /dev/null
-+++ b/arch/arm64/include/asm/pci.h
-@@ -0,0 +1,49 @@
-+#ifndef __ASM_PCI_H
-+#define __ASM_PCI_H
-+#ifdef __KERNEL__
++++ b/Documentation/arm64/arm-acpi.txt
+@@ -0,0 +1,323 @@
++ACPI on ARMv8 Servers
++---------------------
++ACPI can be used for ARMv8 general purpose servers designed to follow
++the ARM SBSA (Server Base System Architecture) specification, currently 
++available to those with an ARM login at http://silver.arm.com.
 +
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/dma-mapping.h>
++The ARMv8 kernel implements the reduced hardware model of ACPI version
++5.1 and its corresponding errata.  Links to the specification and all
++external documents it refers to are managed by the UEFI Forum.  The
++specification is available at http://www.uefi.org/specifications and
++external documents can be found via http://www.uefi.org/acpi.
 +
-+#include <asm/io.h>
-+#include <asm-generic/pci-bridge.h>
-+#include <asm-generic/pci-dma-compat.h>
++If an ARMv8 system does not meet the requirements of the SBSA, or cannot
++be described using the mechanisms defined in the required ACPI specifications,
++then it is likely that Device Tree (DT) is more suitable than ACPI for the
++hardware.
 +
-+#define PCIBIOS_MIN_IO		0x1000
-+#define PCIBIOS_MIN_MEM		0
 +
-+struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus);
++Relationship with Device Tree
++-----------------------------
++ACPI support in drivers and subsystems for ARMv8 should never be mutually
++exclusive with DT support at compile time.
 +
-+/*
-+ * Set to 1 if the kernel should re-assign all PCI bus numbers
-+ */
-+#define pcibios_assign_all_busses() \
-+	(pci_has_flag(PCI_REASSIGN_ALL_BUS))
++At boot time the kernel will only use one description method depending on
++parameters passed from the bootloader (including kernel bootargs).
 +
-+/*
-+ * PCI address space differs from physical memory address space
-+ */
-+#define PCI_DMA_BUS_IS_PHYS	(0)
++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).
 +
-+extern int isa_dma_bridge_buggy;
++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
++-------------------------
++The only defined method for passing ACPI tables to the kernel on ARMv8
++is via the UEFI system configuration table.
++
++Processing of ACPI tables may be disabled by passing acpi=off on the kernel
++command line; this is the default behavior.  If acpi=force is used, the kernel
++will ONLY use device configuration information contained in the ACPI tables.
++
++In order for the kernel to load and use ACPI tables, the UEFI implementation
++MUST set the ACPI_20_TABLE_GUID to point to the RSDP table (the table with
++the ACPI signature "RSD PTR ").  If this pointer is incorrect and acpi=force
++is used, the kernel will disable ACPI and try to use DT to boot.
++
++If the pointer to the RSDP table is correct, the table will be mapped into
++the kernel by the ACPI core, using the address provided by UEFI.
++
++The ACPI core will then locate and map in all other ACPI tables provided by
++using the addresses in the RSDP table to find the XSDT (eXtended System 
++Description Table).  The XSDT in turn provides the addresses to all other
++ACPI tables provided by the system firmware; the ACPI core will then traverse
++this table and map in the tables listed.
++
++The ACPI core will ignore any provided RSDT (Root System Description Table).
++RSDTs have been deprecated and are ignored on arm64 since they only allow 
++for 32-bit addresses.
++
++Further, the ACPI core will only use the 64-bit address fields in the FADT
++(Fixed ACPI Description Table).  Any 32-bit address fields in the FADT will
++be ignored on arm64.
++
++Hardware reduced mode (see Section 4.1 of the ACPI 5.1 specification) will
++be enforced by the ACPI core on arm64.  Doing so allows the ACPI core to
++run less complex code since it no longer has to provide support for legacy
++hardware from other architectures.
++
++For the ACPI core to operate properly, and in turn provide the information
++the kernel needs to configure devices, it expects to find the following
++tables (all section numbers refer to the ACPI 5.1 specfication):
++
++    -- RSDP (Root System Description Pointer), section 5.2.5
++
++    -- XSDT (eXtended System Description Table), section 5.2.8
++
++    -- FACS (Firmware ACPI Control Structure), section 5.2.10
++
++    -- FADT (Fixed ACPI Description Table), section 5.2.9
++
++    -- DSDT (Differentiated System Description Table), section
++       5.2.11.1
++
++    -- MADT (Multiple APIC Description Table), section 5.2.12
++
++    -- GTDT (Generic Timer Description Table), section 5.2.24
++
++    -- If PCI is supported, the MCFG (Memory mapped ConFiGuration
++       Table), section 5.2.6, specifically Table 5-31.
++
++If the above tables are not all present, the kernel may or may not be
++able to boot properly since it may not be able to configure all of the
++devices available.
++
++
++ACPI Detection
++--------------
++Drivers should determine their probe() type by checking for a null
++value for ACPI_HANDLE, or checking .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 can contain less information than is typically provided via a Device
++Tree description for the same device.  This is also one of the reasons that
++ACPI can be useful -- the driver takes into account that it may have less
++detailed information about the device and uses sensible defaults instead.
++If done properly in the driver, the hardware can change and improve over
++time without the driver having to change at all.
++
++Clocks provide an excellent example.  In DT, clocks need to be specified
++and the drivers need to take them into account.  In ACPI, the assumption
++is that UEFI will leave the device in a reasonable default state, including
++any clock settings.  If for some reason the driver needs to change a clock
++value, this can be done in an ACPI method; all the driver needs to do is
++invoke the method and not concern itself with what the method needs to do
++to change the clock.  Changing the hardware can then take place over time
++by changing what the ACPI method does, and not the driver.
++
++ACPI drivers should only look at one specific ASL object -- the _DSD object
++-- for device driver parameters (known in DT as "bindings", or "Device 
++Properties" in ACPI).  Not all DT bindings will be recognized.  The UEFI
++Forum provides a mechanism for registering such bindings [URL TBD by ASWG]
++so that they may be used on any operating system supporting ACPI.  Device
++properties that have not been registered with the UEFI Forum should not be
++used.
++
++Drivers should look for device properties in the _DSD object ONLY; the _DSD
++object is described in the ACPI specification section 6.2.5, but more
++specifically, use the _DSD Device Properties UUID:
++
++   -- UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301
++   
++   -- http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf)
++
++The kernel has an interface for looking up device properties in a manner 
++independent of whether DT or ACPI is being used and that interface should
++be used; it can eliminate some duplication of code paths in driver probing
++functions and discourage divergence between DT bindings and ACPI device
++properties.
++
++ACPI tables are described with a formal language called ASL, the ACPI
++Source Language (section 19 of the specification).  This means that there
++are always multiple ways to describe the same thing -- including device
++properties.  For example, device properties could use an ASL construct
++that looks like this: Name(KEY0, "value0").  An ACPI device driver would
++then retrieve the value of the property by evaluating the KEY0 object.
++However, using Name() this way has multiple problems: (1) ACPI limits
++names ("KEY0") to four characters unlike DT; (2) there is no industry
++wide registry that maintains a list of names, minimzing re-use; (3)
++there is also no registry for the definition of property values ("value0"),
++again making re-use difficult; and (4) how does one maintain backward
++compatibility as new hardware comes out?  The _DSD method was created
++to solve precisely these sorts of problems; Linux drivers should ALWAYS
++use the _DSD method for device properties and nothing else.
++
++The _DSM object (ACPI Section 9.14.1) could also be used for conveying
++device properties to a driver.  Linux drivers should only expect it to
++be used if _DSD cannot represent the data required, and there is no way
++to create a new UUID for the _DSD object.  Note that there is even less
++regulation of the use of _DSM than there is of _DSD.  Drivers that depend
++on the contents of _DSM objects will be more difficult to maintain over
++time because of this.
++
++The _DSD object is a very flexible mechanism in ACPI, as are the registered
++Device Properties.  This flexibility allows _DSD to cover more than just the
++generic server case and care should be taken in device drivers not to expect
++it to replicate highly specific embedded behaviour from DT.
++
++Both DT bindings and ACPI device properties for device drivers have review
++processes.  Use them.  And, before creating new device properties, check to
++be sure that they have not been defined before and either registered in the
++Linux kernel documentation or the UEFI Forum.  If the device drivers supports
++ACPI and DT, please make sure the device properties are consistent in both
++places.
++
++
++Programmable Power Control Resources
++------------------------------------
++Programmable power control resources include such resources as voltage/current
++providers (regulators) and clock sources.
++
++The kernel assumes that power control of these resources is represented with
++Power Resource Objects (ACPI section 7.1).  The ACPI core will then handle
++correctly enabling and disabling resources as they are needed.  In order to
++get that to work, ACPI assumes each device has defined D-states and that these
++can be controlled through the optional ACPI methods _PS0, _PS1, _PS2, and _PS3;
++in ACPI, _PS0 is the method to invoke to turn a device full on, and _PS3 is for
++turning a device full off.
++
++The kernel ACPI code will also assume that the _PS? methods follow the normal
++ACPI rules for such methods:
++
++   -- 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 or enabled in the _PS0 method should be disabled
++      or de-allocated in the _PS3 method.
++
++   -- Firmware will leave the resources in a reasonable state before handing
++      over control to the kernel.
++
++Such code in _PS? methods will of course be very platform specific.  But,
++this allows the driver to abstract out the interface for operating the device
++and avoid having to read special non-standard values from ACPI tables. Further,
++abstracting the use of these resources allows the hardware to change over time
++without requiring updates to the driver.
++
++
++Clocks
++------
++ACPI makes the assumption that clocks are initialized by the firmware -- 
++UEFI, in this case -- to some working value before control is handed over
++to the kernel.  This has implications for devices such as UARTs, or SoC
++driven LCD displays, for example.
++
++When the kernel boots, the clock is assumed to be set to reasonable
++working value.  If for some reason the frequency needs to change -- e.g.,
++throttling for power management -- the device driver should expect that 
++process to be abstracted out into some ACPI method that can be invoked 
++(please see the ACPI specification for further recommendations on standard
++methods to be expected).  If is not, there is no direct way for ACPI to
++control the clocks.
++
++
++Driver Recommendations
++----------------------
++DO NOT remove any DT handling when adding ACPI support for a driver.  The
++same device may be used on many different systems.
++
++DO try to structure the driver so that it is data driven.  That is, set up
++a struct containing internal per-device state based on defaults and whatever
++else must be discovered by the driver probe function.  Then, have the rest
++of the driver operate off of the contents of that struct.  Doing so should
++allow most divergence between ACPI and DT functionality to be kept local to
++the probe function instead of being scattered throughout the driver.  For
++example:
++
++static int device_probe_dt(struct platform_device *pdev)
++{
++	/* DT specific functionality */
++	...
++}
++
++static int device_probe_acpi(struct platform_device *pdev)
++{
++	/* ACPI specific functionality */
++	...
++}
 +
-+#ifdef CONFIG_PCI
-+static inline int pci_domain_nr(struct pci_bus *bus)
++static int device_probe(stuct platform_device *pdev)
 +{
-+	struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
++	...
++	struct device_node node = pdev->dev.of_node;
++	...
 +
-+	if (bridge)
-+		return bridge->domain_nr;
-+
-+	return 0;
++	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 */
++	...
 +}
 +
-+static inline int pci_proc_domain(struct pci_bus *bus)
-+{
-+	return 1;
-+}
-+#endif  /* CONFIG_PCI */
++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:
 +
-+#endif  /* __KERNEL__ */
-+#endif  /* __ASM_PCI_H */
-diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
-index b9349c4..ecbd081 100644
---- a/arch/arm64/include/asm/tlbflush.h
-+++ b/arch/arm64/include/asm/tlbflush.h
-@@ -98,8 +98,8 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
- 	dsb(ish);
++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 fully defined for ARM in the 5.1 version
++of the ACPI specification and are expected to be worked through in the 
++UEFI ACPI Specification Working Group (ASWG):
++
++   -- 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
++
++Participation in this group is open to all UEFI members.  Please see
++http://www.uefi.org/workinggroup for details on group membership.
++
++It is the intent of the ARMv8 ACPI kernel code to follow the ACPI specification
++as closely as possible, and to only implement functionality that complies with
++the released standards from UEFI ASWG.  As a practical matter, there will be
++vendors that provide bad ACPI tables or violate the standards in some way.
++If this is because of errors, quirks and fixups may be necessary, but will
++be avoided if possible.  If there are features missing from ACPI that preclude
++it from being used on a platform, ECRs (Engineering Change Requests) should be
++submitted to ASWG and go through the normal approval process; for those that
++are not UEFI members, many other members of the Linux community are and would
++likely be willing to assist in submitting ECRs.
+diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt
+index 6ce5441..859918d 100644
+--- a/Documentation/gpio/consumer.txt
++++ b/Documentation/gpio/consumer.txt
+@@ -219,6 +219,24 @@ part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are system wakeup
+ capabilities.
+ 
+ 
++GPIOs and ACPI
++==============
++
++On ACPI systems, GPIOs are described by GpioIo()/GpioInt() resources listed by
++the _CRS configuration objects of devices.  Those resources do not provide
++connection IDs (names) for GPIOs, so it is necessary to use an additional
++mechanism for this purpose.
++
++Systems compliant with ACPI 5.1 or newer may provide a _DSD configuration object
++which, among other things, may be used to provide connection IDs for specific
++GPIOs described by the GpioIo()/GpioInt() resources in _CRS.  If that is the
++case, it will be handled by the GPIO subsystem automatically.  However, if the
++_DSD is not present, the mappings between GpioIo()/GpioInt() resources and GPIO
++connection IDs need to be provided by device drivers.
++
++For details refer to Documentation/acpi/gpio-properties.txt
++
++
+ Interacting With the Legacy GPIO Subsystem
+ ==========================================
+ Many kernel subsystems still handle GPIOs using the legacy integer-based
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index 479f332..6187d9b 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,ARM64]
+ 			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" or "acpi=force" are available
+ 
+ 			See also Documentation/power/runtime_pm.txt, pci=noacpi
+ 
+diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
+index acb0d57..f867060 100644
+--- a/arch/arm/include/asm/kvm_mmu.h
++++ b/arch/arm/include/asm/kvm_mmu.h
+@@ -161,9 +161,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
  }
  
--static inline void flush_tlb_range(struct vm_area_struct *vma,
--					unsigned long start, unsigned long end)
-+static inline void __flush_tlb_range(struct vm_area_struct *vma,
-+				     unsigned long start, unsigned long end)
+ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
+-					     unsigned long size)
++					     unsigned long size,
++					     bool ipa_uncached)
  {
- 	unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48;
- 	unsigned long addr;
-@@ -112,7 +112,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
- 	dsb(ish);
- }
+-	if (!vcpu_has_cache_enabled(vcpu))
++	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
+ 		kvm_flush_dcache_to_poc((void *)hva, size);
+ 	
+ 	/*
+diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
+index 8664ff1..8fa2060 100644
+--- a/arch/arm/kvm/mmu.c
++++ b/arch/arm/kvm/mmu.c
+@@ -853,6 +853,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+ 	struct vm_area_struct *vma;
+ 	pfn_t pfn;
+ 	pgprot_t mem_type = PAGE_S2;
++	bool fault_ipa_uncached;
+ 
+ 	write_fault = kvm_is_write_fault(vcpu);
+ 	if (fault_status == FSC_PERM && !write_fault) {
+@@ -919,6 +920,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+ 	if (!hugetlb && !force_pte)
+ 		hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
+ 
++	fault_ipa_uncached = memslot->flags & KVM_MEMSLOT_INCOHERENT;
++
+ 	if (hugetlb) {
+ 		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
+ 		new_pmd = pmd_mkhuge(new_pmd);
+@@ -926,7 +929,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+ 			kvm_set_s2pmd_writable(&new_pmd);
+ 			kvm_set_pfn_dirty(pfn);
+ 		}
+-		coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE);
++		coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE,
++					  fault_ipa_uncached);
+ 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
+ 	} else {
+ 		pte_t new_pte = pfn_pte(pfn, mem_type);
+@@ -934,7 +938,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+ 			kvm_set_s2pte_writable(&new_pte);
+ 			kvm_set_pfn_dirty(pfn);
+ 		}
+-		coherent_cache_guest_page(vcpu, hva, PAGE_SIZE);
++		coherent_cache_guest_page(vcpu, hva, PAGE_SIZE,
++					  fault_ipa_uncached);
+ 		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte,
+ 			pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE));
+ 	}
+@@ -1245,6 +1250,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
+ 	    (KVM_PHYS_SIZE >> PAGE_SHIFT))
+ 		return -EFAULT;
  
--static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-+static inline void __flush_tlb_kernel_range(unsigned long start, unsigned long end)
++	spin_lock(&kvm->mmu_lock);
++	stage2_flush_memslot(kvm, memslot);
++	spin_unlock(&kvm->mmu_lock);
++
+ 	/*
+ 	 * A memory region could potentially cover multiple VMAs, and any holes
+ 	 * between them, so iterate over all of them to find out if we can map
+@@ -1310,6 +1319,15 @@ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
+ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
+ 			    unsigned long npages)
  {
- 	unsigned long addr;
- 	start >>= 12;
-@@ -125,6 +125,29 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
++	/*
++	 * Readonly memslots are not incoherent with the caches by definition,
++	 * but in practice, they are used mostly to emulate ROMs or NOR flashes
++	 * that the guest may consider devices and hence map as uncached.
++	 * To prevent incoherency issues in these cases, tag all readonly
++	 * regions as incoherent.
++	 */
++	if (slot->flags & KVM_MEM_READONLY)
++		slot->flags |= KVM_MEMSLOT_INCOHERENT;
+ 	return 0;
  }
  
- /*
-+ * This is meant to avoid soft lock-ups on large TLB flushing ranges and not
-+ * necessarily a performance improvement.
-+ */
-+#define MAX_TLB_RANGE	(1024UL << PAGE_SHIFT)
-+
-+static inline void flush_tlb_range(struct vm_area_struct *vma,
-+				   unsigned long start, unsigned long end)
-+{
-+	if ((end - start) <= MAX_TLB_RANGE)
-+		__flush_tlb_range(vma, start, end);
-+	else
-+		flush_tlb_mm(vma->vm_mm);
-+}
+diff --git a/arch/arm/mach-s3c24xx/h1940-bluetooth.c b/arch/arm/mach-s3c24xx/h1940-bluetooth.c
+index b4d14b8..9c8b127 100644
+--- a/arch/arm/mach-s3c24xx/h1940-bluetooth.c
++++ b/arch/arm/mach-s3c24xx/h1940-bluetooth.c
+@@ -41,7 +41,7 @@ static void h1940bt_enable(int on)
+ 		mdelay(10);
+ 		gpio_set_value(S3C2410_GPH(1), 0);
+ 
+-		h1940_led_blink_set(-EINVAL, GPIO_LED_BLINK, NULL, NULL);
++		h1940_led_blink_set(NULL, GPIO_LED_BLINK, NULL, NULL);
+ 	}
+ 	else {
+ 		gpio_set_value(S3C2410_GPH(1), 1);
+@@ -50,7 +50,7 @@ static void h1940bt_enable(int on)
+ 		mdelay(10);
+ 		gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 0);
+ 
+-		h1940_led_blink_set(-EINVAL, GPIO_LED_NO_BLINK_LOW, NULL, NULL);
++		h1940_led_blink_set(NULL, GPIO_LED_NO_BLINK_LOW, NULL, NULL);
+ 	}
+ }
+ 
+diff --git a/arch/arm/mach-s3c24xx/h1940.h b/arch/arm/mach-s3c24xx/h1940.h
+index 2950cc4..596d9f6 100644
+--- a/arch/arm/mach-s3c24xx/h1940.h
++++ b/arch/arm/mach-s3c24xx/h1940.h
+@@ -19,8 +19,10 @@
+ #define H1940_SUSPEND_RESUMEAT		(0x30081000)
+ #define H1940_SUSPEND_CHECK		(0x30080000)
+ 
++struct gpio_desc;
++
+ extern void h1940_pm_return(void);
+-extern int h1940_led_blink_set(unsigned gpio, int state,
++extern int h1940_led_blink_set(struct gpio_desc *desc, int state,
+ 			       unsigned long *delay_on,
+ 			       unsigned long *delay_off);
+ 
+diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
+index d35ddc1..d40d4f5 100644
+--- a/arch/arm/mach-s3c24xx/mach-h1940.c
++++ b/arch/arm/mach-s3c24xx/mach-h1940.c
+@@ -359,10 +359,11 @@ static struct platform_device h1940_battery = {
+ 
+ static DEFINE_SPINLOCK(h1940_blink_spin);
+ 
+-int h1940_led_blink_set(unsigned gpio, int state,
++int h1940_led_blink_set(struct gpio_desc *desc, int state,
+ 	unsigned long *delay_on, unsigned long *delay_off)
+ {
+ 	int blink_gpio, check_gpio1, check_gpio2;
++	int gpio = desc ? desc_to_gpio(desc) : -EINVAL;
+ 
+ 	switch (gpio) {
+ 	case H1940_LATCH_LED_GREEN:
+diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
+index c3f2682..1d35ff3 100644
+--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
++++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
+@@ -250,9 +250,10 @@ static void rx1950_disable_charger(void)
+ 
+ static DEFINE_SPINLOCK(rx1950_blink_spin);
+ 
+-static int rx1950_led_blink_set(unsigned gpio, int state,
++static int rx1950_led_blink_set(struct gpio_desc *desc, int state,
+ 	unsigned long *delay_on, unsigned long *delay_off)
+ {
++	int gpio = desc_to_gpio(desc);
+ 	int blink_gpio, check_gpio;
+ 
+ 	switch (gpio) {
+diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
+index e048f61..e53fc8d 100644
+--- a/arch/arm/plat-orion/gpio.c
++++ b/arch/arm/plat-orion/gpio.c
+@@ -306,9 +306,10 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
+ 
+ #define ORION_BLINK_HALF_PERIOD 100 /* ms */
+ 
+-int orion_gpio_led_blink_set(unsigned gpio, int state,
++int orion_gpio_led_blink_set(struct gpio_desc *desc, int state,
+ 	unsigned long *delay_on, unsigned long *delay_off)
+ {
++	unsigned gpio = desc_to_gpio(desc);
+ 
+ 	if (delay_on && delay_off && !*delay_on && !*delay_off)
+ 		*delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
+diff --git a/arch/arm/plat-orion/include/plat/orion-gpio.h b/arch/arm/plat-orion/include/plat/orion-gpio.h
+index e763988..e856b07 100644
+--- a/arch/arm/plat-orion/include/plat/orion-gpio.h
++++ b/arch/arm/plat-orion/include/plat/orion-gpio.h
+@@ -14,12 +14,15 @@
+ #include <linux/init.h>
+ #include <linux/types.h>
+ #include <linux/irqdomain.h>
 +
-+static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-+{
-+	if ((end - start) <= MAX_TLB_RANGE)
-+		__flush_tlb_kernel_range(start, end);
-+	else
-+		flush_tlb_all();
-+}
++struct gpio_desc;
 +
-+/*
-  * On AArch64, the cache coherency is handled via the set_pte_at() function.
+ /*
+  * Orion-specific GPIO API extensions.
   */
- static inline void update_mmu_cache(struct vm_area_struct *vma,
-diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
-index 215ad46..7a5df52 100644
---- a/arch/arm64/include/asm/virt.h
-+++ b/arch/arm64/include/asm/virt.h
-@@ -50,6 +50,10 @@ static inline bool is_hyp_mode_mismatched(void)
- 	return __boot_cpu_mode[0] != __boot_cpu_mode[1];
- }
+ void orion_gpio_set_unused(unsigned pin);
+ void orion_gpio_set_blink(unsigned pin, int blink);
+-int orion_gpio_led_blink_set(unsigned gpio, int state,
++int orion_gpio_led_blink_set(struct gpio_desc *desc, int state,
+ 	unsigned long *delay_on, unsigned long *delay_off);
  
-+/* The section containing the hypervisor text */
-+extern char __hyp_text_start[];
-+extern char __hyp_text_end[];
+ #define GPIO_INPUT_OK		(1 << 0)
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 9532f8d..80a82ac 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -4,6 +4,7 @@ config ARM64
+ 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+ 	select ARCH_HAS_SG_CHAIN
+ 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
++	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+ 	select ARCH_USE_CMPXCHG_LOCKREF
+ 	select ARCH_SUPPORTS_ATOMIC_RMW
+ 	select ARCH_WANT_OPTIONAL_GPIOLIB
+@@ -34,6 +35,7 @@ config ARM64
+ 	select GENERIC_TIME_VSYSCALL
+ 	select HANDLE_DOMAIN_IRQ
+ 	select HARDIRQS_SW_RESEND
++	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
+ 	select HAVE_ARCH_AUDITSYSCALL
+ 	select HAVE_ARCH_JUMP_LABEL
+ 	select HAVE_ARCH_KGDB
+@@ -41,6 +43,7 @@ config ARM64
+ 	select HAVE_BPF_JIT
+ 	select HAVE_C_RECORDMCOUNT
+ 	select HAVE_CC_STACKPROTECTOR
++	select HAVE_CMPXCHG_DOUBLE
+ 	select HAVE_DEBUG_BUGVERBOSE
+ 	select HAVE_DEBUG_KMEMLEAK
+ 	select HAVE_DMA_API_DEBUG
+@@ -185,6 +188,9 @@ config PCI_DOMAINS_GENERIC
+ config PCI_SYSCALL
+ 	def_bool PCI
+ 
++config PCI_MMCONFIG
++	def_bool y if PCI && ACPI
++
+ source "drivers/pci/Kconfig"
+ source "drivers/pci/pcie/Kconfig"
+ source "drivers/pci/hotplug/Kconfig"
+@@ -268,6 +274,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
+@@ -401,6 +410,17 @@ config EFI
+ 	  allow the kernel to be booted as an EFI application. This
+ 	  is only useful on systems that have UEFI firmware.
+ 
++config DMI
++	bool "Enable support for SMBIOS (DMI) tables"
++	depends on EFI
++	default y
++	help
++	  This enables SMBIOS/DMI feature for systems.
 +
- #endif /* __ASSEMBLY__ */
++	  This option is only useful on systems that have UEFI firmware.
++	  However, even with this option, the resultant kernel should
++	  continue to boot on existing non-UEFI platforms.
++
+ endmenu
  
- #endif /* ! __ASM__VIRT_H */
-diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
-index cdaedad..36b117a 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
- 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
+ menu "Userspace binary formats"
+@@ -454,6 +474,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 20901ff..983d72a 100644
+--- a/arch/arm64/Makefile
++++ b/arch/arm64/Makefile
+@@ -49,6 +49,7 @@ core-$(CONFIG_NET) += arch/arm64/net/
+ 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/crypto/Kconfig b/arch/arm64/crypto/Kconfig
+index 5562652..a38b02c 100644
+--- a/arch/arm64/crypto/Kconfig
++++ b/arch/arm64/crypto/Kconfig
+@@ -27,20 +27,19 @@ config CRYPTO_AES_ARM64_CE
+ 	tristate "AES core cipher using ARMv8 Crypto Extensions"
+ 	depends on ARM64 && KERNEL_MODE_NEON
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_AES
+ 
+ config CRYPTO_AES_ARM64_CE_CCM
+ 	tristate "AES in CCM mode using ARMv8 Crypto Extensions"
+ 	depends on ARM64 && KERNEL_MODE_NEON
+ 	select CRYPTO_ALGAPI
+-	select CRYPTO_AES
++	select CRYPTO_AES_ARM64_CE
+ 	select CRYPTO_AEAD
+ 
+ config CRYPTO_AES_ARM64_CE_BLK
+ 	tristate "AES in ECB/CBC/CTR/XTS modes using ARMv8 Crypto Extensions"
+ 	depends on ARM64 && KERNEL_MODE_NEON
+ 	select CRYPTO_BLKCIPHER
+-	select CRYPTO_AES
++	select CRYPTO_AES_ARM64_CE
+ 	select CRYPTO_ABLK_HELPER
+ 
+ config CRYPTO_AES_ARM64_NEON_BLK
+diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c
+index 9e6cdde..0ac73b8 100644
+--- a/arch/arm64/crypto/aes-ce-ccm-glue.c
++++ b/arch/arm64/crypto/aes-ce-ccm-glue.c
+@@ -16,6 +16,8 @@
+ #include <linux/crypto.h>
+ #include <linux/module.h>
  
- obj-y					+= $(arm64-obj-y) vdso/
- obj-m					+= $(arm64-obj-m)
-diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
-index 646f888..e74654c 100644
---- a/arch/arm64/kernel/asm-offsets.c
-+++ b/arch/arm64/kernel/asm-offsets.c
-@@ -129,13 +129,24 @@ int main(void)
-   DEFINE(KVM_TIMER_ENABLED,	offsetof(struct kvm, arch.timer.enabled));
-   DEFINE(VCPU_KVM,		offsetof(struct kvm_vcpu, kvm));
-   DEFINE(VCPU_VGIC_CPU,		offsetof(struct kvm_vcpu, arch.vgic_cpu));
--  DEFINE(VGIC_CPU_HCR,		offsetof(struct vgic_cpu, vgic_hcr));
--  DEFINE(VGIC_CPU_VMCR,		offsetof(struct vgic_cpu, vgic_vmcr));
--  DEFINE(VGIC_CPU_MISR,		offsetof(struct vgic_cpu, vgic_misr));
--  DEFINE(VGIC_CPU_EISR,		offsetof(struct vgic_cpu, vgic_eisr));
--  DEFINE(VGIC_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_elrsr));
--  DEFINE(VGIC_CPU_APR,		offsetof(struct vgic_cpu, vgic_apr));
--  DEFINE(VGIC_CPU_LR,		offsetof(struct vgic_cpu, vgic_lr));
-+  DEFINE(VGIC_SAVE_FN,		offsetof(struct vgic_sr_vectors, save_vgic));
-+  DEFINE(VGIC_RESTORE_FN,	offsetof(struct vgic_sr_vectors, restore_vgic));
-+  DEFINE(VGIC_SR_VECTOR_SZ,	sizeof(struct vgic_sr_vectors));
-+  DEFINE(VGIC_V2_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
-+  DEFINE(VGIC_V2_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
-+  DEFINE(VGIC_V2_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
-+  DEFINE(VGIC_V2_CPU_EISR,	offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
-+  DEFINE(VGIC_V2_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
-+  DEFINE(VGIC_V2_CPU_APR,	offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
-+  DEFINE(VGIC_V2_CPU_LR,	offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
-+  DEFINE(VGIC_V3_CPU_HCR,	offsetof(struct vgic_cpu, vgic_v3.vgic_hcr));
-+  DEFINE(VGIC_V3_CPU_VMCR,	offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr));
-+  DEFINE(VGIC_V3_CPU_MISR,	offsetof(struct vgic_cpu, vgic_v3.vgic_misr));
-+  DEFINE(VGIC_V3_CPU_EISR,	offsetof(struct vgic_cpu, vgic_v3.vgic_eisr));
-+  DEFINE(VGIC_V3_CPU_ELRSR,	offsetof(struct vgic_cpu, vgic_v3.vgic_elrsr));
-+  DEFINE(VGIC_V3_CPU_AP0R,	offsetof(struct vgic_cpu, vgic_v3.vgic_ap0r));
-+  DEFINE(VGIC_V3_CPU_AP1R,	offsetof(struct vgic_cpu, vgic_v3.vgic_ap1r));
-+  DEFINE(VGIC_V3_CPU_LR,	offsetof(struct vgic_cpu, vgic_v3.vgic_lr));
-   DEFINE(VGIC_CPU_NR_LR,	offsetof(struct vgic_cpu, nr_lr));
-   DEFINE(KVM_VTTBR,		offsetof(struct kvm, arch.vttbr));
-   DEFINE(KVM_VGIC_VCTRL,	offsetof(struct kvm, arch.vgic.vctrl_base));
-diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
-index e786e6c..320ef48 100644
---- a/arch/arm64/kernel/efi-stub.c
-+++ b/arch/arm64/kernel/efi-stub.c
-@@ -58,20 +58,16 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
- 	kernel_size = _edata - _text;
- 	if (*image_addr != (dram_base + TEXT_OFFSET)) {
- 		kernel_memsize = kernel_size + (_end - _edata);
--		status = efi_relocate_kernel(sys_table, image_addr,
--					     kernel_size, kernel_memsize,
--					     dram_base + TEXT_OFFSET,
--					     PAGE_SIZE);
-+		status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET,
-+				       SZ_2M, reserve_addr);
- 		if (status != EFI_SUCCESS) {
- 			pr_efi_err(sys_table, "Failed to relocate kernel\n");
- 			return status;
- 		}
--		if (*image_addr != (dram_base + TEXT_OFFSET)) {
--			pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
--			efi_free(sys_table, kernel_memsize, *image_addr);
--			return EFI_ERROR;
--		}
--		*image_size = kernel_memsize;
-+		memcpy((void *)*reserve_addr + TEXT_OFFSET, (void *)*image_addr,
-+		       kernel_size);
-+		*image_addr = *reserve_addr + TEXT_OFFSET;
-+		*reserve_size = kernel_memsize + TEXT_OFFSET;
- 	}
++#include "aes-ce-setkey.h"
++
+ static int num_rounds(struct crypto_aes_ctx *ctx)
+ {
+ 	/*
+@@ -48,7 +50,7 @@ static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
+ 	struct crypto_aes_ctx *ctx = crypto_aead_ctx(tfm);
+ 	int ret;
  
+-	ret = crypto_aes_expand_key(ctx, in_key, key_len);
++	ret = ce_aes_expandkey(ctx, in_key, key_len);
+ 	if (!ret)
+ 		return 0;
+ 
+diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c
+index 2075e1a..ce47792 100644
+--- a/arch/arm64/crypto/aes-ce-cipher.c
++++ b/arch/arm64/crypto/aes-ce-cipher.c
+@@ -14,6 +14,8 @@
+ #include <linux/crypto.h>
+ #include <linux/module.h>
  
-diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
-index 14db1f6..453b7f8 100644
---- a/arch/arm64/kernel/efi.c
-+++ b/arch/arm64/kernel/efi.c
-@@ -467,3 +467,14 @@ static int __init arm64_enter_virtual_mode(void)
- 	return 0;
- }
- early_initcall(arm64_enter_virtual_mode);
++#include "aes-ce-setkey.h"
 +
+ MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
+ MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel at linaro.org>");
+ MODULE_LICENSE("GPL v2");
+@@ -124,6 +126,114 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
+ 	kernel_neon_end();
+ }
+ 
 +/*
-+ * If nothing else is handling pm_power_off, use EFI
-+ *
-+ * This is called from a late_initcall after other mechanisms
-+ * have had a chance to register a handler.
++ * aes_sub() - use the aese instruction to perform the AES sbox substitution
++ *             on each byte in 'input'
 + */
-+bool efi_poweroff_required(void)
++static u32 aes_sub(u32 input)
 +{
-+	return pm_power_off == NULL;
++	u32 ret;
++
++	__asm__("dup	v1.4s, %w[in]		;"
++		"movi	v0.16b, #0		;"
++		"aese	v0.16b, v1.16b		;"
++		"umov	%w[out], v0.4s[0]	;"
++
++	:	[out]	"=r"(ret)
++	:	[in]	"r"(input)
++	:		"v0","v1");
++
++	return ret;
 +}
-diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
-index a2c1195..8df59be 100644
---- a/arch/arm64/kernel/head.S
-+++ b/arch/arm64/kernel/head.S
-@@ -22,6 +22,7 @@
- 
- #include <linux/linkage.h>
- #include <linux/init.h>
-+#include <linux/irqchip/arm-gic-v3.h>
- 
- #include <asm/assembler.h>
- #include <asm/ptrace.h>
-@@ -156,7 +157,7 @@ optional_header:
- 	.short	0x20b				// PE32+ format
- 	.byte	0x02				// MajorLinkerVersion
- 	.byte	0x14				// MinorLinkerVersion
--	.long	_edata - stext			// SizeOfCode
-+	.long	_end - stext			// SizeOfCode
- 	.long	0				// SizeOfInitializedData
- 	.long	0				// SizeOfUninitializedData
- 	.long	efi_stub_entry - efi_head	// AddressOfEntryPoint
-@@ -174,7 +175,7 @@ extra_header_fields:
- 	.short	0				// MinorSubsystemVersion
- 	.long	0				// Win32VersionValue
- 
--	.long	_edata - efi_head		// SizeOfImage
-+	.long	_end - efi_head			// SizeOfImage
- 
- 	// Everything before the kernel image is considered part of the header
- 	.long	stext - efi_head		// SizeOfHeaders
-@@ -221,7 +222,7 @@ section_table:
- 	.byte	0
- 	.byte	0
- 	.byte	0        		// end of 0 padding of section name
--	.long	_edata - stext		// VirtualSize
-+	.long	_end - stext		// VirtualSize
- 	.long	stext - efi_head	// VirtualAddress
- 	.long	_edata - stext		// SizeOfRawData
- 	.long	stext - efi_head	// PointerToRawData
-@@ -295,6 +296,23 @@ CPU_LE(	bic	x0, x0, #(3 << 24)	)	// Clear the EE and E0E bits for EL1
- 	msr	cnthctl_el2, x0
- 	msr	cntvoff_el2, xzr		// Clear virtual offset
- 
-+#ifdef CONFIG_ARM_GIC_V3
-+	/* GICv3 system register access */
-+	mrs	x0, id_aa64pfr0_el1
-+	ubfx	x0, x0, #24, #4
-+	cmp	x0, #1
-+	b.ne	3f
-+
-+	mrs	x0, ICC_SRE_EL2
-+	orr	x0, x0, #ICC_SRE_EL2_SRE	// Set ICC_SRE_EL2.SRE==1
-+	orr	x0, x0, #ICC_SRE_EL2_ENABLE	// Set ICC_SRE_EL2.Enable==1
-+	msr	ICC_SRE_EL2, x0
-+	isb					// Make sure SRE is now set
-+	msr	ICH_HCR_EL2, xzr		// Reset ICC_HCR_EL2 to defaults
-+
-+3:
-+#endif
 +
- 	/* Populate ID registers. */
- 	mrs	x0, midr_el1
- 	mrs	x1, mpidr_el1
-diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
-index 0959611..a272f33 100644
---- a/arch/arm64/kernel/hyp-stub.S
-+++ b/arch/arm64/kernel/hyp-stub.S
-@@ -19,6 +19,7 @@
- 
- #include <linux/init.h>
- #include <linux/linkage.h>
-+#include <linux/irqchip/arm-gic-v3.h>
++int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
++		     unsigned int key_len)
++{
++	/*
++	 * The AES key schedule round constants
++	 */
++	static u8 const rcon[] = {
++		0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
++	};
++
++	u32 kwords = key_len / sizeof(u32);
++	struct aes_block *key_enc, *key_dec;
++	int i, j;
++
++	if (key_len != AES_KEYSIZE_128 &&
++	    key_len != AES_KEYSIZE_192 &&
++	    key_len != AES_KEYSIZE_256)
++		return -EINVAL;
++
++	memcpy(ctx->key_enc, in_key, key_len);
++	ctx->key_length = key_len;
++
++	kernel_neon_begin_partial(2);
++	for (i = 0; i < sizeof(rcon); i++) {
++		u32 *rki = ctx->key_enc + (i * kwords);
++		u32 *rko = rki + kwords;
++
++		rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
++		rko[1] = rko[0] ^ rki[1];
++		rko[2] = rko[1] ^ rki[2];
++		rko[3] = rko[2] ^ rki[3];
++
++		if (key_len == AES_KEYSIZE_192) {
++			if (i >= 7)
++				break;
++			rko[4] = rko[3] ^ rki[4];
++			rko[5] = rko[4] ^ rki[5];
++		} else if (key_len == AES_KEYSIZE_256) {
++			if (i >= 6)
++				break;
++			rko[4] = aes_sub(rko[3]) ^ rki[4];
++			rko[5] = rko[4] ^ rki[5];
++			rko[6] = rko[5] ^ rki[6];
++			rko[7] = rko[6] ^ rki[7];
++		}
++	}
++
++	/*
++	 * Generate the decryption keys for the Equivalent Inverse Cipher.
++	 * This involves reversing the order of the round keys, and applying
++	 * the Inverse Mix Columns transformation on all but the first and
++	 * the last one.
++	 */
++	key_enc = (struct aes_block *)ctx->key_enc;
++	key_dec = (struct aes_block *)ctx->key_dec;
++	j = num_rounds(ctx);
++
++	key_dec[0] = key_enc[j];
++	for (i = 1, j--; j > 0; i++, j--)
++		__asm__("ld1	{v0.16b}, %[in]		;"
++			"aesimc	v1.16b, v0.16b		;"
++			"st1	{v1.16b}, %[out]	;"
++
++		:	[out]	"=Q"(key_dec[i])
++		:	[in]	"Q"(key_enc[j])
++		:		"v0","v1");
++	key_dec[i] = key_enc[0];
++
++	kernel_neon_end();
++	return 0;
++}
++EXPORT_SYMBOL(ce_aes_expandkey);
++
++int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
++		  unsigned int key_len)
++{
++	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
++	int ret;
++
++	ret = ce_aes_expandkey(ctx, in_key, key_len);
++	if (!ret)
++		return 0;
++
++	tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++	return -EINVAL;
++}
++EXPORT_SYMBOL(ce_aes_setkey);
++
+ static struct crypto_alg aes_alg = {
+ 	.cra_name		= "aes",
+ 	.cra_driver_name	= "aes-ce",
+@@ -135,7 +245,7 @@ static struct crypto_alg aes_alg = {
+ 	.cra_cipher = {
+ 		.cia_min_keysize	= AES_MIN_KEY_SIZE,
+ 		.cia_max_keysize	= AES_MAX_KEY_SIZE,
+-		.cia_setkey		= crypto_aes_set_key,
++		.cia_setkey		= ce_aes_setkey,
+ 		.cia_encrypt		= aes_cipher_encrypt,
+ 		.cia_decrypt		= aes_cipher_decrypt
+ 	}
+diff --git a/arch/arm64/crypto/aes-ce-setkey.h b/arch/arm64/crypto/aes-ce-setkey.h
+new file mode 100644
+index 0000000..f08a647
+--- /dev/null
++++ b/arch/arm64/crypto/aes-ce-setkey.h
+@@ -0,0 +1,5 @@
++
++int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
++		  unsigned int key_len);
++int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
++		     unsigned int key_len);
+diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c
+index 79cd911..801aae3 100644
+--- a/arch/arm64/crypto/aes-glue.c
++++ b/arch/arm64/crypto/aes-glue.c
+@@ -16,9 +16,13 @@
+ #include <linux/module.h>
+ #include <linux/cpufeature.h>
+ 
++#include "aes-ce-setkey.h"
++
+ #ifdef USE_V8_CRYPTO_EXTENSIONS
+ #define MODE			"ce"
+ #define PRIO			300
++#define aes_setkey		ce_aes_setkey
++#define aes_expandkey		ce_aes_expandkey
+ #define aes_ecb_encrypt		ce_aes_ecb_encrypt
+ #define aes_ecb_decrypt		ce_aes_ecb_decrypt
+ #define aes_cbc_encrypt		ce_aes_cbc_encrypt
+@@ -30,6 +34,8 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
+ #else
+ #define MODE			"neon"
+ #define PRIO			200
++#define aes_setkey		crypto_aes_set_key
++#define aes_expandkey		crypto_aes_expand_key
+ #define aes_ecb_encrypt		neon_aes_ecb_encrypt
+ #define aes_ecb_decrypt		neon_aes_ecb_decrypt
+ #define aes_cbc_encrypt		neon_aes_cbc_encrypt
+@@ -79,10 +85,10 @@ static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	int ret;
  
- #include <asm/assembler.h>
- #include <asm/ptrace.h>
-diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+-	ret = crypto_aes_expand_key(&ctx->key1, in_key, key_len / 2);
++	ret = aes_expandkey(&ctx->key1, in_key, key_len / 2);
+ 	if (!ret)
+-		ret = crypto_aes_expand_key(&ctx->key2, &in_key[key_len / 2],
+-					    key_len / 2);
++		ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
++				    key_len / 2);
+ 	if (!ret)
+ 		return 0;
+ 
+@@ -288,7 +294,7 @@ static struct crypto_alg aes_algs[] = { {
+ 		.min_keysize	= AES_MIN_KEY_SIZE,
+ 		.max_keysize	= AES_MAX_KEY_SIZE,
+ 		.ivsize		= AES_BLOCK_SIZE,
+-		.setkey		= crypto_aes_set_key,
++		.setkey		= aes_setkey,
+ 		.encrypt	= ecb_encrypt,
+ 		.decrypt	= ecb_decrypt,
+ 	},
+@@ -306,7 +312,7 @@ static struct crypto_alg aes_algs[] = { {
+ 		.min_keysize	= AES_MIN_KEY_SIZE,
+ 		.max_keysize	= AES_MAX_KEY_SIZE,
+ 		.ivsize		= AES_BLOCK_SIZE,
+-		.setkey		= crypto_aes_set_key,
++		.setkey		= aes_setkey,
+ 		.encrypt	= cbc_encrypt,
+ 		.decrypt	= cbc_decrypt,
+ 	},
+@@ -324,7 +330,7 @@ static struct crypto_alg aes_algs[] = { {
+ 		.min_keysize	= AES_MIN_KEY_SIZE,
+ 		.max_keysize	= AES_MAX_KEY_SIZE,
+ 		.ivsize		= AES_BLOCK_SIZE,
+-		.setkey		= crypto_aes_set_key,
++		.setkey		= aes_setkey,
+ 		.encrypt	= ctr_encrypt,
+ 		.decrypt	= ctr_encrypt,
+ 	},
+diff --git a/arch/arm64/include/asm/acenv.h b/arch/arm64/include/asm/acenv.h
 new file mode 100644
-index 0000000..955d6d1
+index 0000000..b49166f
 --- /dev/null
-+++ b/arch/arm64/kernel/pci.c
-@@ -0,0 +1,38 @@
++++ b/arch/arm64/include/asm/acenv.h
+@@ -0,0 +1,18 @@
 +/*
-+ * Code borrowed from powerpc/kernel/pci-common.c
-+ *
-+ * Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
-+ * Copyright (C) 2014 ARM Ltd.
++ * ARM64 specific ACPICA environments and implementation
 + *
-+ * 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.
++ * 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.
 + */
 +
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/of_pci.h>
-+#include <linux/of_platform.h>
-+#include <linux/slab.h>
++#ifndef _ASM_ACENV_H
++#define _ASM_ACENV_H
 +
-+#include <asm/pci-bridge.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..6e692f4
+--- /dev/null
++++ b/arch/arm64/include/asm/acpi.h
+@@ -0,0 +1,102 @@
 +/*
-+ * Called after each bus is probed, but before its children are examined
++ *  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;
++}
++
++static inline void enable_acpi(void)
++{
++	acpi_disabled = 0;
++	acpi_pci_disabled = 0;
++	acpi_noirq = 0;
++}
++
++/* MPIDR value provided in GICC structure is 64 bits, but the
++ * existing apic_id (CPU hardware ID) using in acpi processor
++ * driver is 32-bit, to conform to the same datatype we need
++ * to repack the GICC structure MPIDR.
++ *
++ * Only 32 bits of MPIDR are used:
++ * 
++ * Bits [0:7] Aff0;
++ * Bits [8:15] Aff1;
++ * Bits [16:23] Aff2;
++ * Bits [32:39] Aff3;
 + */
-+void pcibios_fixup_bus(struct pci_bus *bus)
++static inline u32 pack_mpidr(u64 mpidr)
 +{
-+	/* nothing to do, expected to be removed in the future */
++	return (u32) ((mpidr & 0xff00000000) >> 8) | mpidr;
 +}
 +
 +/*
-+ * We don't have to worry about legacy ISA devices, so nothing to do here
++ * 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(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.
 + */
-+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
-+				resource_size_t size, resource_size_t align)
++static inline bool acpi_has_cpu_in_madt(void)
 +{
-+	return res->start;
++	return true;
 +}
-diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
-index 43b7c34..ec5cbbe 100644
---- a/arch/arm64/kernel/process.c
-+++ b/arch/arm64/kernel/process.c
-@@ -43,6 +43,7 @@
- #include <linux/hw_breakpoint.h>
- #include <linux/personality.h>
- #include <linux/notifier.h>
-+#include <linux/efi.h>
++
++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 void disable_acpi(void) { }
++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/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
+index ddb9d78..89e397b 100644
+--- a/arch/arm64/include/asm/cmpxchg.h
++++ b/arch/arm64/include/asm/cmpxchg.h
+@@ -19,6 +19,7 @@
+ #define __ASM_CMPXCHG_H
  
- #include <asm/compat.h>
- #include <asm/cacheflush.h>
-@@ -176,6 +177,11 @@ void machine_restart(char *cmd)
- 		arm_pm_restart(reboot_mode, cmd);
+ #include <linux/bug.h>
++#include <linux/mmdebug.h>
  
- 	/*
-+	 * If all else fails, try EFI
-+	 */
-+	efi_reboot(reboot_mode, cmd);
-+
-+	/*
- 	 * 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 @@
- #include <linux/init.h>
- #include <linux/of.h>
- #include <linux/smp.h>
-+#include <linux/types.h>
+ #include <asm/barrier.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)
+@@ -152,6 +153,51 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ 	return oldval;
+ }
  
- static int smp_spin_table_cpu_prepare(unsigned int cpu)
++#define system_has_cmpxchg_double()     1
++
++static inline int __cmpxchg_double(volatile void *ptr1, volatile void *ptr2,
++		unsigned long old1, unsigned long old2,
++		unsigned long new1, unsigned long new2, int size)
++{
++	unsigned long loop, lost;
++
++	switch (size) {
++	case 8:
++		VM_BUG_ON((unsigned long *)ptr2 - (unsigned long *)ptr1 != 1);
++		do {
++			asm volatile("// __cmpxchg_double8\n"
++			"	ldxp	%0, %1, %2\n"
++			"	eor	%0, %0, %3\n"
++			"	eor	%1, %1, %4\n"
++			"	orr	%1, %0, %1\n"
++			"	mov	%w0, #0\n"
++			"	cbnz	%1, 1f\n"
++			"	stxp	%w0, %5, %6, %2\n"
++			"1:\n"
++				: "=&r"(loop), "=&r"(lost), "+Q" (*(u64 *)ptr1)
++				: "r" (old1), "r"(old2), "r"(new1), "r"(new2));
++		} while (loop);
++		break;
++	default:
++		BUILD_BUG();
++	}
++
++	return !lost;
++}
++
++static inline int __cmpxchg_double_mb(volatile void *ptr1, volatile void *ptr2,
++			unsigned long old1, unsigned long old2,
++			unsigned long new1, unsigned long new2, int size)
++{
++	int ret;
++
++	smp_mb();
++	ret = __cmpxchg_double(ptr1, ptr2, old1, old2, new1, new2, size);
++	smp_mb();
++
++	return ret;
++}
++
+ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
+ 					 unsigned long new, int size)
  {
--	void **release_addr;
-+	__le64 __iomem *release_addr;
+@@ -182,6 +228,31 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
+ 	__ret; \
+ })
+ 
++#define cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \
++({\
++	int __ret;\
++	__ret = __cmpxchg_double_mb((ptr1), (ptr2), (unsigned long)(o1), \
++			(unsigned long)(o2), (unsigned long)(n1), \
++			(unsigned long)(n2), sizeof(*(ptr1)));\
++	__ret; \
++})
++
++#define cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \
++({\
++	int __ret;\
++	__ret = __cmpxchg_double((ptr1), (ptr2), (unsigned long)(o1), \
++			(unsigned long)(o2), (unsigned long)(n1), \
++			(unsigned long)(n2), sizeof(*(ptr1)));\
++	__ret; \
++})
++
++#define this_cpu_cmpxchg_8(ptr, o, n) \
++	cmpxchg_local(raw_cpu_ptr(&(ptr)), o, n)
++
++#define this_cpu_cmpxchg_double_8(ptr1, ptr2, o1, o2, n1, n2) \
++	cmpxchg_double_local(raw_cpu_ptr(&(ptr1)), raw_cpu_ptr(&(ptr2)), \
++				o1, o2, n1, n2)
++
+ #define cmpxchg64(ptr,o,n)		cmpxchg((ptr),(o),(n))
+ #define cmpxchg64_local(ptr,o,n)	cmpxchg_local((ptr),(o),(n))
  
- 	if (!cpu_release_addr[cpu])
- 		return -ENODEV;
+diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
+index 6f8e2ef..978f567 100644
+--- a/arch/arm64/include/asm/cpu_ops.h
++++ b/arch/arm64/include/asm/cpu_ops.h
+@@ -64,6 +64,7 @@ struct cpu_operations {
+ };
  
--	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
-+	 * existing linear mapping, we can use it to cover both cases. In
-+	 * either case the memory will be MT_NORMAL.
-+	 */
-+	release_addr = ioremap_cache(cpu_release_addr[cpu],
-+				     sizeof(*release_addr));
-+	if (!release_addr)
-+		return -ENOMEM;
+ extern const struct cpu_operations *cpu_ops[NR_CPUS];
++const struct cpu_operations *cpu_get_ops(const char *name);
+ int __init cpu_read_ops(struct device_node *dn, int cpu);
+ void __init cpu_read_bootcpu_ops(void);
  
- 	/*
- 	 * 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)
- 	 * boot-loader's endianess before jumping. This is mandated by
- 	 * the boot protocol.
- 	 */
--	release_addr[0] = (void *) cpu_to_le64(__pa(secondary_holding_pen));
--
--	__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));
+diff --git a/arch/arm64/include/asm/dmi.h b/arch/arm64/include/asm/dmi.h
+new file mode 100644
+index 0000000..69d37d8
+--- /dev/null
++++ b/arch/arm64/include/asm/dmi.h
+@@ -0,0 +1,31 @@
++/*
++ * arch/arm64/include/asm/dmi.h
++ *
++ * Copyright (C) 2013 Linaro Limited.
++ * Written by: Yi Li (yi.li at linaro.org)
++ *
++ * based on arch/ia64/include/asm/dmi.h
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++
++#ifndef __ASM_DMI_H
++#define __ASM_DMI_H
++
++#include <linux/io.h>
++#include <linux/slab.h>
++
++/*
++ * According to section 2.3.6 of the UEFI spec, the firmware should not
++ * request a virtual mapping for configuration tables such as SMBIOS.
++ * This means we have to map them before use.
++ */
++#define dmi_early_remap(x, l)		ioremap_cache(x, l)
++#define dmi_early_unmap(x, l)		iounmap(x)
++#define dmi_remap(x, l)			ioremap_cache(x, l)
++#define dmi_unmap(x)			iounmap(x)
++#define dmi_alloc(l)			kzalloc(l, GFP_KERNEL)
++
++#endif
+diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
+index 1f65be3..c0f89a0 100644
+--- a/arch/arm64/include/asm/elf.h
++++ b/arch/arm64/include/asm/elf.h
+@@ -114,7 +114,8 @@ typedef struct user_fpsimd_state elf_fpregset_t;
+  */
+ #define elf_check_arch(x)		((x)->e_machine == EM_AARCH64)
  
- 	/*
- 	 * Send an event to wake up the secondary CPU.
- 	 */
- 	sev();
+-#define elf_read_implies_exec(ex,stk)	(stk != EXSTACK_DISABLE_X)
++#define elf_read_implies_exec(ex,stk)	(test_thread_flag(TIF_32BIT) \
++					 ? (stk == EXSTACK_ENABLE_X) : 0)
  
-+	iounmap(release_addr);
-+
- 	return 0;
- }
+ #define CORE_DUMP_USE_REGSET
+ #define ELF_EXEC_PAGESIZE	PAGE_SIZE
+diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
+index 7fd3e27..8afb863 100644
+--- a/arch/arm64/include/asm/kvm_arm.h
++++ b/arch/arm64/include/asm/kvm_arm.h
+@@ -18,6 +18,7 @@
+ #ifndef __ARM64_KVM_ARM_H__
+ #define __ARM64_KVM_ARM_H__
  
-diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
-index 72a9fd5..32a0961 100644
---- a/arch/arm64/kvm/Makefile
-+++ b/arch/arm64/kvm/Makefile
-@@ -20,4 +20,8 @@ kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
- kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o
- 
- kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
-+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
-+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
-+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
-+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o
- kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
-diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
-index b0d1512..5945f3b 100644
---- a/arch/arm64/kvm/hyp.S
-+++ b/arch/arm64/kvm/hyp.S
-@@ -16,7 +16,6 @@
-  */
++#include <asm/memory.h>
+ #include <asm/types.h>
  
- #include <linux/linkage.h>
--#include <linux/irqchip/arm-gic.h>
+ /* Hyp Configuration Register (HCR) bits */
+@@ -160,9 +161,9 @@
+ #endif
  
- #include <asm/assembler.h>
- #include <asm/memory.h>
-@@ -36,9 +35,6 @@
- 	.pushsection	.hyp.text, "ax"
- 	.align	PAGE_SHIFT
+ #define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
+-#define VTTBR_BADDR_MASK  (((1LLU << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
+-#define VTTBR_VMID_SHIFT  (48LLU)
+-#define VTTBR_VMID_MASK	  (0xffLLU << VTTBR_VMID_SHIFT)
++#define VTTBR_BADDR_MASK  (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
++#define VTTBR_VMID_SHIFT  (UL(48))
++#define VTTBR_VMID_MASK	  (UL(0xFF) << VTTBR_VMID_SHIFT)
+ 
+ /* Hyp System Trap Register */
+ #define HSTR_EL2_TTEE	(1 << 16)
+@@ -185,13 +186,13 @@
+ 
+ /* Exception Syndrome Register (ESR) bits */
+ #define ESR_EL2_EC_SHIFT	(26)
+-#define ESR_EL2_EC		(0x3fU << ESR_EL2_EC_SHIFT)
+-#define ESR_EL2_IL		(1U << 25)
++#define ESR_EL2_EC		(UL(0x3f) << ESR_EL2_EC_SHIFT)
++#define ESR_EL2_IL		(UL(1) << 25)
+ #define ESR_EL2_ISS		(ESR_EL2_IL - 1)
+ #define ESR_EL2_ISV_SHIFT	(24)
+-#define ESR_EL2_ISV		(1U << ESR_EL2_ISV_SHIFT)
++#define ESR_EL2_ISV		(UL(1) << ESR_EL2_ISV_SHIFT)
+ #define ESR_EL2_SAS_SHIFT	(22)
+-#define ESR_EL2_SAS		(3U << ESR_EL2_SAS_SHIFT)
++#define ESR_EL2_SAS		(UL(3) << ESR_EL2_SAS_SHIFT)
+ #define ESR_EL2_SSE		(1 << 21)
+ #define ESR_EL2_SRT_SHIFT	(16)
+ #define ESR_EL2_SRT_MASK	(0x1f << ESR_EL2_SRT_SHIFT)
+@@ -205,16 +206,16 @@
+ #define ESR_EL2_FSC_TYPE	(0x3c)
+ 
+ #define ESR_EL2_CV_SHIFT	(24)
+-#define ESR_EL2_CV		(1U << ESR_EL2_CV_SHIFT)
++#define ESR_EL2_CV		(UL(1) << ESR_EL2_CV_SHIFT)
+ #define ESR_EL2_COND_SHIFT	(20)
+-#define ESR_EL2_COND		(0xfU << ESR_EL2_COND_SHIFT)
++#define ESR_EL2_COND		(UL(0xf) << ESR_EL2_COND_SHIFT)
+ 
+ 
+ #define FSC_FAULT	(0x04)
+ #define FSC_PERM	(0x0c)
+ 
+ /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
+-#define HPFAR_MASK	(~0xFUL)
++#define HPFAR_MASK	(~UL(0xf))
+ 
+ #define ESR_EL2_EC_UNKNOWN	(0x00)
+ #define ESR_EL2_EC_WFI		(0x01)
+diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
+index 0caf7a5..123b521 100644
+--- a/arch/arm64/include/asm/kvm_mmu.h
++++ b/arch/arm64/include/asm/kvm_mmu.h
+@@ -243,9 +243,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
+ }
  
--__kvm_hyp_code_start:
--	.globl __kvm_hyp_code_start
--
- .macro save_common_regs
- 	// x2: base address for cpu context
- 	// x3: tmp register
-@@ -339,11 +335,8 @@ __kvm_hyp_code_start:
- .endm
+ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
+-					     unsigned long size)
++					     unsigned long size,
++					     bool ipa_uncached)
+ {
+-	if (!vcpu_has_cache_enabled(vcpu))
++	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
+ 		kvm_flush_dcache_to_poc((void *)hva, size);
  
- .macro activate_traps
--	ldr	x2, [x0, #VCPU_IRQ_LINES]
--	ldr	x1, [x0, #VCPU_HCR_EL2]
--	orr	x2, x2, x1
--	msr	hcr_el2, x2
--
-+	ldr     x2, [x0, #VCPU_HCR_EL2]
-+	msr     hcr_el2, x2
- 	ldr	x2, =(CPTR_EL2_TTA)
- 	msr	cptr_el2, x2
+ 	if (!icache_is_aliasing()) {		/* PIPT */
+diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
+index 872ba93..2f287a6 100644
+--- a/arch/arm64/include/asm/pci.h
++++ b/arch/arm64/include/asm/pci.h
+@@ -33,5 +33,56 @@ static inline int pci_proc_domain(struct pci_bus *bus)
+ }
+ #endif  /* CONFIG_PCI */
  
-@@ -379,100 +372,33 @@ __kvm_hyp_code_start:
- .endm
++/* "PCI MMCONFIG %04x [bus %02x-%02x]" */
++#define PCI_MMCFG_RESOURCE_NAME_LEN (22 + 4 + 2 + 2)
++
++#define PCI_MMCFG_BUS_OFFSET(bus)      ((bus) << 20)
++
++struct acpi_device;
++
++struct pci_sysdata {
++	int		domain;		/* PCI domain */
++	int		node;		/* NUMA node */
++	struct acpi_device *companion;	/* ACPI companion device */
++	void		*iommu;		/* IOMMU private data */
++};
++
++struct acpi_pci_root;
++struct pci_mmcfg_region;
++
++typedef int (*acpi_mcfg_fixup_t)(struct acpi_pci_root *root,
++				 struct pci_mmcfg_region *cfg);
++
++struct pci_mmcfg_region {
++	struct list_head list;
++	struct resource res;
++	int (*read)(struct pci_mmcfg_region *cfg, unsigned int bus,
++		    unsigned int devfn, int reg, int len, u32 *value);
++	int (*write)(struct pci_mmcfg_region *cfg, unsigned int bus,
++		     unsigned int devfn, int reg, int len, u32 value);
++	acpi_mcfg_fixup_t fixup;
++	void *data;
++	u64 address;
++	char __iomem *virt;
++	u16 segment;
++	u8 start_bus;
++	u8 end_bus;
++	char name[PCI_MMCFG_RESOURCE_NAME_LEN];
++};
++
++struct acpi_mcfg_fixup {
++	char oem_id[7];
++	char oem_table_id[9];
++	acpi_mcfg_fixup_t hook;
++};
++
++/* Designate a routine to fix up buggy MCFG */
++#define DECLARE_ACPI_MCFG_FIXUP(oem_id, table_id, hook)	\
++	static const struct acpi_mcfg_fixup __acpi_fixup_##hook __used	\
++	__attribute__((__section__(".acpi_fixup_mcfg"), aligned((sizeof(void *))))) \
++	= { {oem_id}, {table_id}, hook };
++
++extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
++
+ #endif  /* __KERNEL__ */
+ #endif  /* __ASM_PCI_H */
+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 780f82c..3411561 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);
  
  /*
-- * Save the VGIC CPU state into memory
-- * x0: Register pointing to VCPU struct
-- * Do not corrupt x1!!!
-+ * Call into the vgic backend for state saving
+- * Setup the set of possible CPUs (via set_cpu_possible)
++ * Discover the set of possible CPUs and determine their
++ * SMP operations.
   */
- .macro save_vgic_state
--	/* Get VGIC VCTRL base into x2 */
--	ldr	x2, [x0, #VCPU_KVM]
--	kern_hyp_va	x2
--	ldr	x2, [x2, #KVM_VGIC_VCTRL]
--	kern_hyp_va	x2
--	cbz	x2, 2f		// disabled
--
--	/* Compute the address of struct vgic_cpu */
--	add	x3, x0, #VCPU_VGIC_CPU
--
--	/* Save all interesting registers */
--	ldr	w4, [x2, #GICH_HCR]
--	ldr	w5, [x2, #GICH_VMCR]
--	ldr	w6, [x2, #GICH_MISR]
--	ldr	w7, [x2, #GICH_EISR0]
--	ldr	w8, [x2, #GICH_EISR1]
--	ldr	w9, [x2, #GICH_ELRSR0]
--	ldr	w10, [x2, #GICH_ELRSR1]
--	ldr	w11, [x2, #GICH_APR]
--CPU_BE(	rev	w4,  w4  )
--CPU_BE(	rev	w5,  w5  )
--CPU_BE(	rev	w6,  w6  )
--CPU_BE(	rev	w7,  w7  )
--CPU_BE(	rev	w8,  w8  )
--CPU_BE(	rev	w9,  w9  )
--CPU_BE(	rev	w10, w10 )
--CPU_BE(	rev	w11, w11 )
--
--	str	w4, [x3, #VGIC_CPU_HCR]
--	str	w5, [x3, #VGIC_CPU_VMCR]
--	str	w6, [x3, #VGIC_CPU_MISR]
--	str	w7, [x3, #VGIC_CPU_EISR]
--	str	w8, [x3, #(VGIC_CPU_EISR + 4)]
--	str	w9, [x3, #VGIC_CPU_ELRSR]
--	str	w10, [x3, #(VGIC_CPU_ELRSR + 4)]
--	str	w11, [x3, #VGIC_CPU_APR]
--
--	/* Clear GICH_HCR */
--	str	wzr, [x2, #GICH_HCR]
--
--	/* Save list registers */
--	add	x2, x2, #GICH_LR0
--	ldr	w4, [x3, #VGIC_CPU_NR_LR]
--	add	x3, x3, #VGIC_CPU_LR
--1:	ldr	w5, [x2], #4
--CPU_BE(	rev	w5, w5 )
--	str	w5, [x3], #4
--	sub	w4, w4, #1
--	cbnz	w4, 1b
--2:
-+	adr	x24, __vgic_sr_vectors
-+	ldr	x24, [x24, VGIC_SAVE_FN]
-+	kern_hyp_va	x24
-+	blr	x24
-+	mrs	x24, hcr_el2
-+	mov	x25, #HCR_INT_OVERRIDE
-+	neg	x25, x25
-+	and	x24, x24, x25
-+	msr	hcr_el2, x24
- .endm
+-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.
+@@ -51,6 +52,11 @@ extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
+ extern void (*__smp_cross_call)(const struct cpumask *, unsigned int);
  
  /*
-- * Restore the VGIC CPU state from memory
-- * x0: Register pointing to VCPU struct
-+ * Call into the vgic backend for state restoring
++ * 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.
   */
- .macro restore_vgic_state
--	/* Get VGIC VCTRL base into x2 */
--	ldr	x2, [x0, #VCPU_KVM]
--	kern_hyp_va	x2
--	ldr	x2, [x2, #KVM_VGIC_VCTRL]
--	kern_hyp_va	x2
--	cbz	x2, 2f		// disabled
--
--	/* Compute the address of struct vgic_cpu */
--	add	x3, x0, #VCPU_VGIC_CPU
--
--	/* We only restore a minimal set of registers */
--	ldr	w4, [x3, #VGIC_CPU_HCR]
--	ldr	w5, [x3, #VGIC_CPU_VMCR]
--	ldr	w6, [x3, #VGIC_CPU_APR]
--CPU_BE(	rev	w4, w4 )
--CPU_BE(	rev	w5, w5 )
--CPU_BE(	rev	w6, w6 )
--
--	str	w4, [x2, #GICH_HCR]
--	str	w5, [x2, #GICH_VMCR]
--	str	w6, [x2, #GICH_APR]
--
--	/* Restore list registers */
--	add	x2, x2, #GICH_LR0
--	ldr	w4, [x3, #VGIC_CPU_NR_LR]
--	add	x3, x3, #VGIC_CPU_LR
--1:	ldr	w5, [x3], #4
--CPU_BE(	rev	w5, w5 )
--	str	w5, [x2], #4
--	sub	w4, w4, #1
--	cbnz	w4, 1b
--2:
-+	mrs	x24, hcr_el2
-+	ldr	x25, [x0, #VCPU_IRQ_LINES]
-+	orr	x24, x24, #HCR_INT_OVERRIDE
-+	orr	x24, x24, x25
-+	msr	hcr_el2, x24
-+	adr	x24, __vgic_sr_vectors
-+	ldr	x24, [x24, #VGIC_RESTORE_FN]
-+	kern_hyp_va	x24
-+	blr	x24
- .endm
- 
- .macro save_timer_state
-@@ -653,6 +579,12 @@ ENTRY(__kvm_flush_vm_context)
- 	ret
- ENDPROC(__kvm_flush_vm_context)
- 
-+	// struct vgic_sr_vectors __vgi_sr_vectors;
-+	.align 3
-+ENTRY(__vgic_sr_vectors)
-+	.skip	VGIC_SR_VECTOR_SZ
-+ENDPROC(__vgic_sr_vectors)
-+
- __kvm_hyp_panic:
- 	// Guess the context by looking at VTTBR:
- 	// If zero, then we're already a host.
-@@ -880,7 +812,4 @@ ENTRY(__kvm_hyp_vector)
- 	ventry	el1_error_invalid		// Error 32-bit EL1
- ENDPROC(__kvm_hyp_vector)
- 
--__kvm_hyp_code_end:
--	.globl	__kvm_hyp_code_end
--
- 	.popsection
-diff --git a/arch/arm64/kvm/vgic-v2-switch.S b/arch/arm64/kvm/vgic-v2-switch.S
+ asmlinkage void secondary_start_kernel(void);
+diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
+index 5bd029b..f4ba4fe 100644
+--- a/arch/arm64/kernel/Makefile
++++ b/arch/arm64/kernel/Makefile
+@@ -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
+@@ -31,6 +32,7 @@ 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..ae21177
+index 0000000..06a96be
 --- /dev/null
-+++ b/arch/arm64/kvm/vgic-v2-switch.S
-@@ -0,0 +1,133 @@
++++ b/arch/arm64/kernel/acpi.c
+@@ -0,0 +1,398 @@
 +/*
-+ * Copyright (C) 2012,2013 - ARM Ltd
-+ * Author: Marc Zyngier <marc.zyngier at arm.com>
-+ *
-+ * 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.
++ *  ARM64 Specific Low-Level ACPI Boot Support
 + *
-+ * 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.
++ *  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>
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ *  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/linkage.h>
-+#include <linux/irqchip/arm-gic.h>
++#define pr_fmt(fmt) "ACPI: " fmt
 +
-+#include <asm/assembler.h>
-+#include <asm/memory.h>
-+#include <asm/asm-offsets.h>
-+#include <asm/kvm.h>
-+#include <asm/kvm_asm.h>
-+#include <asm/kvm_arm.h>
-+#include <asm/kvm_mmu.h>
++#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>
++
++int acpi_noirq;			/* skip ACPI IRQ initialization */
++int acpi_disabled;
++EXPORT_SYMBOL(acpi_disabled);
 +
-+	.text
-+	.pushsection	.hyp.text, "ax"
++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];
 +
 +/*
-+ * Save the VGIC CPU state into memory
-+ * x0: Register pointing to VCPU struct
-+ * Do not corrupt x1!!!
++ * Since we're on ARM, the default interrupt routing model
++ * clearly has to be GIC.
 + */
-+ENTRY(__save_vgic_v2_state)
-+__save_vgic_v2_state:
-+	/* Get VGIC VCTRL base into x2 */
-+	ldr	x2, [x0, #VCPU_KVM]
-+	kern_hyp_va	x2
-+	ldr	x2, [x2, #KVM_VGIC_VCTRL]
-+	kern_hyp_va	x2
-+	cbz	x2, 2f		// disabled
-+
-+	/* Compute the address of struct vgic_cpu */
-+	add	x3, x0, #VCPU_VGIC_CPU
-+
-+	/* Save all interesting registers */
-+	ldr	w4, [x2, #GICH_HCR]
-+	ldr	w5, [x2, #GICH_VMCR]
-+	ldr	w6, [x2, #GICH_MISR]
-+	ldr	w7, [x2, #GICH_EISR0]
-+	ldr	w8, [x2, #GICH_EISR1]
-+	ldr	w9, [x2, #GICH_ELRSR0]
-+	ldr	w10, [x2, #GICH_ELRSR1]
-+	ldr	w11, [x2, #GICH_APR]
-+CPU_BE(	rev	w4,  w4  )
-+CPU_BE(	rev	w5,  w5  )
-+CPU_BE(	rev	w6,  w6  )
-+CPU_BE(	rev	w7,  w7  )
-+CPU_BE(	rev	w8,  w8  )
-+CPU_BE(	rev	w9,  w9  )
-+CPU_BE(	rev	w10, w10 )
-+CPU_BE(	rev	w11, w11 )
-+
-+	str	w4, [x3, #VGIC_V2_CPU_HCR]
-+	str	w5, [x3, #VGIC_V2_CPU_VMCR]
-+	str	w6, [x3, #VGIC_V2_CPU_MISR]
-+	str	w7, [x3, #VGIC_V2_CPU_EISR]
-+	str	w8, [x3, #(VGIC_V2_CPU_EISR + 4)]
-+	str	w9, [x3, #VGIC_V2_CPU_ELRSR]
-+	str	w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)]
-+	str	w11, [x3, #VGIC_V2_CPU_APR]
-+
-+	/* Clear GICH_HCR */
-+	str	wzr, [x2, #GICH_HCR]
-+
-+	/* Save list registers */
-+	add	x2, x2, #GICH_LR0
-+	ldr	w4, [x3, #VGIC_CPU_NR_LR]
-+	add	x3, x3, #VGIC_V2_CPU_LR
-+1:	ldr	w5, [x2], #4
-+CPU_BE(	rev	w5, w5 )
-+	str	w5, [x3], #4
-+	sub	w4, w4, #1
-+	cbnz	w4, 1b
-+2:
-+	ret
-+ENDPROC(__save_vgic_v2_state)
++enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_GIC;
 +
 +/*
-+ * Restore the VGIC CPU state from memory
-+ * x0: Register pointing to VCPU struct
++ * __acpi_map_table() will be called before page_init(), so early_ioremap()
++ * or early_memremap() should be called here to for ACPI table mapping.
 + */
-+ENTRY(__restore_vgic_v2_state)
-+__restore_vgic_v2_state:
-+	/* Get VGIC VCTRL base into x2 */
-+	ldr	x2, [x0, #VCPU_KVM]
-+	kern_hyp_va	x2
-+	ldr	x2, [x2, #KVM_VGIC_VCTRL]
-+	kern_hyp_va	x2
-+	cbz	x2, 2f		// disabled
-+
-+	/* Compute the address of struct vgic_cpu */
-+	add	x3, x0, #VCPU_VGIC_CPU
-+
-+	/* We only restore a minimal set of registers */
-+	ldr	w4, [x3, #VGIC_V2_CPU_HCR]
-+	ldr	w5, [x3, #VGIC_V2_CPU_VMCR]
-+	ldr	w6, [x3, #VGIC_V2_CPU_APR]
-+CPU_BE(	rev	w4, w4 )
-+CPU_BE(	rev	w5, w5 )
-+CPU_BE(	rev	w6, w6 )
-+
-+	str	w4, [x2, #GICH_HCR]
-+	str	w5, [x2, #GICH_VMCR]
-+	str	w6, [x2, #GICH_APR]
-+
-+	/* Restore list registers */
-+	add	x2, x2, #GICH_LR0
-+	ldr	w4, [x3, #VGIC_CPU_NR_LR]
-+	add	x3, x3, #VGIC_V2_CPU_LR
-+1:	ldr	w5, [x3], #4
-+CPU_BE(	rev	w5, w5 )
-+	str	w5, [x2], #4
-+	sub	w4, w4, #1
-+	cbnz	w4, 1b
-+2:
-+	ret
-+ENDPROC(__restore_vgic_v2_state)
-+
-+	.popsection
-diff --git a/arch/arm64/kvm/vgic-v3-switch.S b/arch/arm64/kvm/vgic-v3-switch.S
-new file mode 100644
-index 0000000..21e68f6
---- /dev/null
-+++ b/arch/arm64/kvm/vgic-v3-switch.S
-@@ -0,0 +1,267 @@
-+/*
-+ * Copyright (C) 2012,2013 - ARM Ltd
-+ * Author: Marc Zyngier <marc.zyngier at arm.com>
-+ *
-+ * 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/linkage.h>
-+#include <linux/irqchip/arm-gic-v3.h>
-+
-+#include <asm/assembler.h>
-+#include <asm/memory.h>
-+#include <asm/asm-offsets.h>
-+#include <asm/kvm.h>
-+#include <asm/kvm_asm.h>
-+#include <asm/kvm_arm.h>
-+
-+	.text
-+	.pushsection	.hyp.text, "ax"
-+
-+/*
-+ * We store LRs in reverse order to let the CPU deal with streaming
-+ * access. Use this macro to make it look saner...
-+ */
-+#define LR_OFFSET(n)	(VGIC_V3_CPU_LR + (15 - n) * 8)
-+
-+/*
-+ * Save the VGIC CPU state into memory
-+ * x0: Register pointing to VCPU struct
-+ * Do not corrupt x1!!!
-+ */
-+.macro	save_vgic_v3_state
-+	// Compute the address of struct vgic_cpu
-+	add	x3, x0, #VCPU_VGIC_CPU
-+
-+	// Make sure stores to the GIC via the memory mapped interface
-+	// are now visible to the system register interface
-+	dsb	st
-+
-+	// Save all interesting registers
-+	mrs	x4, ICH_HCR_EL2
-+	mrs	x5, ICH_VMCR_EL2
-+	mrs	x6, ICH_MISR_EL2
-+	mrs	x7, ICH_EISR_EL2
-+	mrs	x8, ICH_ELSR_EL2
-+
-+	str	w4, [x3, #VGIC_V3_CPU_HCR]
-+	str	w5, [x3, #VGIC_V3_CPU_VMCR]
-+	str	w6, [x3, #VGIC_V3_CPU_MISR]
-+	str	w7, [x3, #VGIC_V3_CPU_EISR]
-+	str	w8, [x3, #VGIC_V3_CPU_ELRSR]
-+
-+	msr	ICH_HCR_EL2, xzr
-+
-+	mrs	x21, ICH_VTR_EL2
-+	mvn	w22, w21
-+	ubfiz	w23, w22, 2, 4	// w23 = (15 - ListRegs) * 4
-+
-+	adr	x24, 1f
-+	add	x24, x24, x23
-+	br	x24
-+
-+1:
-+	mrs	x20, ICH_LR15_EL2
-+	mrs	x19, ICH_LR14_EL2
-+	mrs	x18, ICH_LR13_EL2
-+	mrs	x17, ICH_LR12_EL2
-+	mrs	x16, ICH_LR11_EL2
-+	mrs	x15, ICH_LR10_EL2
-+	mrs	x14, ICH_LR9_EL2
-+	mrs	x13, ICH_LR8_EL2
-+	mrs	x12, ICH_LR7_EL2
-+	mrs	x11, ICH_LR6_EL2
-+	mrs	x10, ICH_LR5_EL2
-+	mrs	x9, ICH_LR4_EL2
-+	mrs	x8, ICH_LR3_EL2
-+	mrs	x7, ICH_LR2_EL2
-+	mrs	x6, ICH_LR1_EL2
-+	mrs	x5, ICH_LR0_EL2
-+
-+	adr	x24, 1f
-+	add	x24, x24, x23
-+	br	x24
-+
-+1:
-+	str	x20, [x3, #LR_OFFSET(15)]
-+	str	x19, [x3, #LR_OFFSET(14)]
-+	str	x18, [x3, #LR_OFFSET(13)]
-+	str	x17, [x3, #LR_OFFSET(12)]
-+	str	x16, [x3, #LR_OFFSET(11)]
-+	str	x15, [x3, #LR_OFFSET(10)]
-+	str	x14, [x3, #LR_OFFSET(9)]
-+	str	x13, [x3, #LR_OFFSET(8)]
-+	str	x12, [x3, #LR_OFFSET(7)]
-+	str	x11, [x3, #LR_OFFSET(6)]
-+	str	x10, [x3, #LR_OFFSET(5)]
-+	str	x9, [x3, #LR_OFFSET(4)]
-+	str	x8, [x3, #LR_OFFSET(3)]
-+	str	x7, [x3, #LR_OFFSET(2)]
-+	str	x6, [x3, #LR_OFFSET(1)]
-+	str	x5, [x3, #LR_OFFSET(0)]
-+
-+	tbnz	w21, #29, 6f	// 6 bits
-+	tbz	w21, #30, 5f	// 5 bits
-+				// 7 bits
-+	mrs	x20, ICH_AP0R3_EL2
-+	str	w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)]
-+	mrs	x19, ICH_AP0R2_EL2
-+	str	w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)]
-+6:	mrs	x18, ICH_AP0R1_EL2
-+	str	w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)]
-+5:	mrs	x17, ICH_AP0R0_EL2
-+	str	w17, [x3, #VGIC_V3_CPU_AP0R]
-+
-+	tbnz	w21, #29, 6f	// 6 bits
-+	tbz	w21, #30, 5f	// 5 bits
-+				// 7 bits
-+	mrs	x20, ICH_AP1R3_EL2
-+	str	w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)]
-+	mrs	x19, ICH_AP1R2_EL2
-+	str	w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)]
-+6:	mrs	x18, ICH_AP1R1_EL2
-+	str	w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)]
-+5:	mrs	x17, ICH_AP1R0_EL2
-+	str	w17, [x3, #VGIC_V3_CPU_AP1R]
-+
-+	// Restore SRE_EL1 access and re-enable SRE at EL1.
-+	mrs	x5, ICC_SRE_EL2
-+	orr	x5, x5, #ICC_SRE_EL2_ENABLE
-+	msr	ICC_SRE_EL2, x5
-+	isb
-+	mov	x5, #1
-+	msr	ICC_SRE_EL1, x5
-+.endm
-+
-+/*
-+ * Restore the VGIC CPU state from memory
-+ * x0: Register pointing to VCPU struct
-+ */
-+.macro	restore_vgic_v3_state
-+	// Disable SRE_EL1 access. Necessary, otherwise
-+	// ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens...
-+	msr	ICC_SRE_EL1, xzr
-+	isb
-+
-+	// Compute the address of struct vgic_cpu
-+	add	x3, x0, #VCPU_VGIC_CPU
-+
-+	// Restore all interesting registers
-+	ldr	w4, [x3, #VGIC_V3_CPU_HCR]
-+	ldr	w5, [x3, #VGIC_V3_CPU_VMCR]
-+
-+	msr	ICH_HCR_EL2, x4
-+	msr	ICH_VMCR_EL2, x5
-+
-+	mrs	x21, ICH_VTR_EL2
-+
-+	tbnz	w21, #29, 6f	// 6 bits
-+	tbz	w21, #30, 5f	// 5 bits
-+				// 7 bits
-+	ldr	w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)]
-+	msr	ICH_AP1R3_EL2, x20
-+	ldr	w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)]
-+	msr	ICH_AP1R2_EL2, x19
-+6:	ldr	w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)]
-+	msr	ICH_AP1R1_EL2, x18
-+5:	ldr	w17, [x3, #VGIC_V3_CPU_AP1R]
-+	msr	ICH_AP1R0_EL2, x17
-+
-+	tbnz	w21, #29, 6f	// 6 bits
-+	tbz	w21, #30, 5f	// 5 bits
-+				// 7 bits
-+	ldr	w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)]
-+	msr	ICH_AP0R3_EL2, x20
-+	ldr	w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)]
-+	msr	ICH_AP0R2_EL2, x19
-+6:	ldr	w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)]
-+	msr	ICH_AP0R1_EL2, x18
-+5:	ldr	w17, [x3, #VGIC_V3_CPU_AP0R]
-+	msr	ICH_AP0R0_EL2, x17
-+
-+	and	w22, w21, #0xf
-+	mvn	w22, w21
-+	ubfiz	w23, w22, 2, 4	// w23 = (15 - ListRegs) * 4
-+
-+	adr	x24, 1f
-+	add	x24, x24, x23
-+	br	x24
-+
-+1:
-+	ldr	x20, [x3, #LR_OFFSET(15)]
-+	ldr	x19, [x3, #LR_OFFSET(14)]
-+	ldr	x18, [x3, #LR_OFFSET(13)]
-+	ldr	x17, [x3, #LR_OFFSET(12)]
-+	ldr	x16, [x3, #LR_OFFSET(11)]
-+	ldr	x15, [x3, #LR_OFFSET(10)]
-+	ldr	x14, [x3, #LR_OFFSET(9)]
-+	ldr	x13, [x3, #LR_OFFSET(8)]
-+	ldr	x12, [x3, #LR_OFFSET(7)]
-+	ldr	x11, [x3, #LR_OFFSET(6)]
-+	ldr	x10, [x3, #LR_OFFSET(5)]
-+	ldr	x9, [x3, #LR_OFFSET(4)]
-+	ldr	x8, [x3, #LR_OFFSET(3)]
-+	ldr	x7, [x3, #LR_OFFSET(2)]
-+	ldr	x6, [x3, #LR_OFFSET(1)]
-+	ldr	x5, [x3, #LR_OFFSET(0)]
-+
-+	adr	x24, 1f
-+	add	x24, x24, x23
-+	br	x24
-+
-+1:
-+	msr	ICH_LR15_EL2, x20
-+	msr	ICH_LR14_EL2, x19
-+	msr	ICH_LR13_EL2, x18
-+	msr	ICH_LR12_EL2, x17
-+	msr	ICH_LR11_EL2, x16
-+	msr	ICH_LR10_EL2, x15
-+	msr	ICH_LR9_EL2,  x14
-+	msr	ICH_LR8_EL2,  x13
-+	msr	ICH_LR7_EL2,  x12
-+	msr	ICH_LR6_EL2,  x11
-+	msr	ICH_LR5_EL2,  x10
-+	msr	ICH_LR4_EL2,   x9
-+	msr	ICH_LR3_EL2,   x8
-+	msr	ICH_LR2_EL2,   x7
-+	msr	ICH_LR1_EL2,   x6
-+	msr	ICH_LR0_EL2,   x5
-+
-+	// Ensure that the above will have reached the
-+	// (re)distributors. This ensure the guest will read
-+	// the correct values from the memory-mapped interface.
-+	isb
-+	dsb	sy
-+
-+	// Prevent the guest from touching the GIC system registers
-+	mrs	x5, ICC_SRE_EL2
-+	and	x5, x5, #~ICC_SRE_EL2_ENABLE
-+	msr	ICC_SRE_EL2, x5
-+.endm
-+
-+ENTRY(__save_vgic_v3_state)
-+	save_vgic_v3_state
-+	ret
-+ENDPROC(__save_vgic_v3_state)
-+
-+ENTRY(__restore_vgic_v3_state)
-+	restore_vgic_v3_state
-+	ret
-+ENDPROC(__restore_vgic_v3_state)
-+
-+ENTRY(__vgic_v3_get_ich_vtr_el2)
-+	mrs	x0, ICH_VTR_EL2
-+	ret
-+ENDPROC(__vgic_v3_get_ich_vtr_el2)
-+
-+	.popsection
-diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
-index 55d4ba4..deed6fa 100644
---- a/arch/ia64/kernel/process.c
-+++ b/arch/ia64/kernel/process.c
-@@ -662,7 +662,7 @@ void
- machine_restart (char *restart_cmd)
- {
- 	(void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
--	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
-+	efi_reboot(REBOOT_WARM, NULL);
- }
- 
- void
-diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
-index 71c52bc..a149c67 100644
---- a/arch/ia64/kernel/time.c
-+++ b/arch/ia64/kernel/time.c
-@@ -384,21 +384,6 @@ static struct irqaction timer_irqaction = {
- 	.name =		"timer"
- };
- 
--static struct platform_device rtc_efi_dev = {
--	.name = "rtc-efi",
--	.id = -1,
--};
--
--static int __init rtc_init(void)
--{
--	if (platform_device_register(&rtc_efi_dev) < 0)
--		printk(KERN_ERR "unable to register rtc device...\n");
--
--	/* not necessarily an error */
--	return 0;
--}
--module_init(rtc_init);
--
- void read_persistent_clock(struct timespec *ts)
- {
- 	efi_gettimeofday(ts);
-diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
-index 1eb5f64..5d71d0e 100644
---- a/arch/x86/include/asm/efi.h
-+++ b/arch/x86/include/asm/efi.h
-@@ -104,6 +104,8 @@ extern void __init runtime_code_page_mkexec(void);
- extern void __init efi_runtime_mkexec(void);
- extern void __init efi_dump_pagetable(void);
- extern void __init efi_apply_memmap_quirks(void);
-+extern int __init efi_reuse_config(u64 tables, int nr_tables);
-+extern void efi_delete_dummy_variable(void);
- 
- struct efi_setup_data {
- 	u64 fw_vendor;
-@@ -156,6 +158,8 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
- 	return EFI_SUCCESS;
- }
- #endif /* CONFIG_EFI_MIXED */
-+
-+extern bool efi_reboot_required(void);
- #else
- /*
-  * IF EFI is not configured, have the EFI calls return -ENOSYS.
-@@ -168,6 +172,10 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
- #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5)		(-ENOSYS)
- #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6)	(-ENOSYS)
- static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
-+static inline bool efi_reboot_required(void)
++char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 +{
-+	return false;
-+}
- #endif /* CONFIG_EFI */
- 
- #endif /* _ASM_X86_EFI_H */
-diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
-index 52b1157..17962e6 100644
---- a/arch/x86/kernel/reboot.c
-+++ b/arch/x86/kernel/reboot.c
-@@ -28,6 +28,7 @@
- #include <linux/mc146818rtc.h>
- #include <asm/realmode.h>
- #include <asm/x86_init.h>
-+#include <asm/efi.h>
- 
- /*
-  * Power off function, if any
-@@ -401,12 +402,25 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
- 
- static int __init reboot_init(void)
- {
-+	int rv;
-+
- 	/*
- 	 * Only do the DMI check if reboot_type hasn't been overridden
- 	 * on the command line
- 	 */
--	if (reboot_default)
--		dmi_check_system(reboot_dmi_table);
-+	if (!reboot_default)
-+		return 0;
-+
-+	/*
-+	 * The DMI quirks table takes precedence. If no quirks entry
-+	 * matches and the ACPI Hardware Reduced bit is set, force EFI
-+	 * reboot.
-+	 */
-+	rv = dmi_check_system(reboot_dmi_table);
-+
-+	if (!rv && efi_reboot_required())
-+		reboot_type = BOOT_EFI;
-+
- 	return 0;
- }
- core_initcall(reboot_init);
-@@ -528,11 +542,7 @@ static void native_machine_emergency_restart(void)
- 			break;
- 
- 		case BOOT_EFI:
--			if (efi_enabled(EFI_RUNTIME_SERVICES))
--				efi.reset_system(reboot_mode == REBOOT_WARM ?
--						 EFI_RESET_WARM :
--						 EFI_RESET_COLD,
--						 EFI_SUCCESS, 0, NULL);
-+			efi_reboot(reboot_mode, NULL);
- 			reboot_type = BOOT_BIOS;
- 			break;
- 
-diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
-index d51045a..2846aaa 100644
---- a/arch/x86/platform/efi/Makefile
-+++ b/arch/x86/platform/efi/Makefile
-@@ -1,4 +1,4 @@
--obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
-+obj-$(CONFIG_EFI) 		+= quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
- obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
- obj-$(CONFIG_EARLY_PRINTK_EFI)	+= early_printk.o
- obj-$(CONFIG_EFI_MIXED)		+= efi_thunk_$(BITS).o
-diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
-index 87fc96b..f852443 100644
---- a/arch/x86/platform/efi/efi.c
-+++ b/arch/x86/platform/efi/efi.c
-@@ -56,13 +56,6 @@
- 
- #define EFI_DEBUG
- 
--#define EFI_MIN_RESERVE 5120
--
--#define EFI_DUMMY_GUID \
--	EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
--
--static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
--
- struct efi_memory_map memmap;
- 
- static struct efi efi_phys __initdata;
-@@ -95,15 +88,6 @@ static int __init setup_add_efi_memmap(char *arg)
- }
- early_param("add_efi_memmap", setup_add_efi_memmap);
- 
--static bool efi_no_storage_paranoia;
--
--static int __init setup_storage_paranoia(char *arg)
--{
--	efi_no_storage_paranoia = true;
--	return 0;
--}
--early_param("efi_no_storage_paranoia", setup_storage_paranoia);
--
- static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
- {
- 	unsigned long flags;
-@@ -392,37 +376,6 @@ static void __init print_efi_memmap(void)
- #endif  /*  EFI_DEBUG  */
- }
- 
--void __init efi_reserve_boot_services(void)
--{
--	void *p;
--
--	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
--		efi_memory_desc_t *md = p;
--		u64 start = md->phys_addr;
--		u64 size = md->num_pages << EFI_PAGE_SHIFT;
--
--		if (md->type != EFI_BOOT_SERVICES_CODE &&
--		    md->type != EFI_BOOT_SERVICES_DATA)
--			continue;
--		/* Only reserve where possible:
--		 * - Not within any already allocated areas
--		 * - Not over any memory area (really needed, if above?)
--		 * - Not within any part of the kernel
--		 * - Not the bios reserved area
--		*/
--		if ((start + size > __pa_symbol(_text)
--				&& start <= __pa_symbol(_end)) ||
--			!e820_all_mapped(start, start+size, E820_RAM) ||
--			memblock_is_region_reserved(start, size)) {
--			/* Could not reserve, skip it */
--			md->num_pages = 0;
--			memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
--				     start, start+size-1);
--		} else
--			memblock_reserve(start, size);
--	}
--}
--
- void __init efi_unmap_memmap(void)
- {
- 	clear_bit(EFI_MEMMAP, &efi.flags);
-@@ -432,29 +385,6 @@ void __init efi_unmap_memmap(void)
- 	}
- }
- 
--void __init efi_free_boot_services(void)
--{
--	void *p;
--
--	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
--		efi_memory_desc_t *md = p;
--		unsigned long long start = md->phys_addr;
--		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
--
--		if (md->type != EFI_BOOT_SERVICES_CODE &&
--		    md->type != EFI_BOOT_SERVICES_DATA)
--			continue;
--
--		/* Could not reserve boot area */
--		if (!size)
--			continue;
--
--		free_bootmem_late(start, size);
--	}
--
--	efi_unmap_memmap();
--}
--
- static int __init efi_systab_init(void *phys)
- {
- 	if (efi_enabled(EFI_64BIT)) {
-@@ -649,62 +579,6 @@ static int __init efi_memmap_init(void)
- 	return 0;
- }
- 
--/*
-- * A number of config table entries get remapped to virtual addresses
-- * after entering EFI virtual mode. However, the kexec kernel requires
-- * their physical addresses therefore we pass them via setup_data and
-- * correct those entries to their respective physical addresses here.
-- *
-- * Currently only handles smbios which is necessary for some firmware
-- * implementation.
-- */
--static int __init efi_reuse_config(u64 tables, int nr_tables)
--{
--	int i, sz, ret = 0;
--	void *p, *tablep;
--	struct efi_setup_data *data;
--
--	if (!efi_setup)
--		return 0;
--
--	if (!efi_enabled(EFI_64BIT))
--		return 0;
--
--	data = early_memremap(efi_setup, sizeof(*data));
--	if (!data) {
--		ret = -ENOMEM;
--		goto out;
--	}
--
--	if (!data->smbios)
--		goto out_memremap;
--
--	sz = sizeof(efi_config_table_64_t);
--
--	p = tablep = early_memremap(tables, nr_tables * sz);
--	if (!p) {
--		pr_err("Could not map Configuration table!\n");
--		ret = -ENOMEM;
--		goto out_memremap;
--	}
--
--	for (i = 0; i < efi.systab->nr_tables; i++) {
--		efi_guid_t guid;
--
--		guid = ((efi_config_table_64_t *)p)->guid;
--
--		if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
--			((efi_config_table_64_t *)p)->table = data->smbios;
--		p += sz;
--	}
--	early_iounmap(tablep, nr_tables * sz);
--
--out_memremap:
--	early_iounmap(data, sizeof(*data));
--out:
--	return ret;
--}
--
- void __init efi_init(void)
- {
- 	efi_char16_t *c16;
-@@ -1057,11 +931,7 @@ static void __init kexec_enter_virtual_mode(void)
- 		runtime_code_page_mkexec();
- 
- 	/* clean DUMMY object */
--	efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
--			 EFI_VARIABLE_NON_VOLATILE |
--			 EFI_VARIABLE_BOOTSERVICE_ACCESS |
--			 EFI_VARIABLE_RUNTIME_ACCESS,
--			 0, NULL);
-+	efi_delete_dummy_variable();
- #endif
- }
- 
-@@ -1179,11 +1049,7 @@ static void __init __efi_enter_virtual_mode(void)
- 	free_pages((unsigned long)new_memmap, pg_shift);
- 
- 	/* clean DUMMY object */
--	efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
--			 EFI_VARIABLE_NON_VOLATILE |
--			 EFI_VARIABLE_BOOTSERVICE_ACCESS |
--			 EFI_VARIABLE_RUNTIME_ACCESS,
--			 0, NULL);
-+	efi_delete_dummy_variable();
- }
- 
- void __init efi_enter_virtual_mode(void)
-@@ -1230,86 +1096,6 @@ u64 efi_mem_attributes(unsigned long phys_addr)
- 	return 0;
- }
- 
--/*
-- * Some firmware implementations refuse to boot if there's insufficient space
-- * in the variable store. Ensure that we never use more than a safe limit.
-- *
-- * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
-- * store.
-- */
--efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
--{
--	efi_status_t status;
--	u64 storage_size, remaining_size, max_size;
--
--	if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
--		return 0;
--
--	status = efi.query_variable_info(attributes, &storage_size,
--					 &remaining_size, &max_size);
--	if (status != EFI_SUCCESS)
--		return status;
--
--	/*
--	 * We account for that by refusing the write if permitting it would
--	 * reduce the available space to under 5KB. This figure was provided by
--	 * Samsung, so should be safe.
--	 */
--	if ((remaining_size - size < EFI_MIN_RESERVE) &&
--		!efi_no_storage_paranoia) {
--
--		/*
--		 * Triggering garbage collection may require that the firmware
--		 * generate a real EFI_OUT_OF_RESOURCES error. We can force
--		 * that by attempting to use more space than is available.
--		 */
--		unsigned long dummy_size = remaining_size + 1024;
--		void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
--
--		if (!dummy)
--			return EFI_OUT_OF_RESOURCES;
--
--		status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
--					  EFI_VARIABLE_NON_VOLATILE |
--					  EFI_VARIABLE_BOOTSERVICE_ACCESS |
--					  EFI_VARIABLE_RUNTIME_ACCESS,
--					  dummy_size, dummy);
--
--		if (status == EFI_SUCCESS) {
--			/*
--			 * This should have failed, so if it didn't make sure
--			 * that we delete it...
--			 */
--			efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
--					 EFI_VARIABLE_NON_VOLATILE |
--					 EFI_VARIABLE_BOOTSERVICE_ACCESS |
--					 EFI_VARIABLE_RUNTIME_ACCESS,
--					 0, dummy);
--		}
--
--		kfree(dummy);
--
--		/*
--		 * The runtime code may now have triggered a garbage collection
--		 * run, so check the variable info again
--		 */
--		status = efi.query_variable_info(attributes, &storage_size,
--						 &remaining_size, &max_size);
--
--		if (status != EFI_SUCCESS)
--			return status;
--
--		/*
--		 * There still isn't enough room, so return an error
--		 */
--		if (remaining_size - size < EFI_MIN_RESERVE)
--			return EFI_OUT_OF_RESOURCES;
--	}
--
--	return EFI_SUCCESS;
--}
--EXPORT_SYMBOL_GPL(efi_query_variable_store);
--
- static int __init parse_efi_cmdline(char *str)
- {
- 	if (*str == '=')
-@@ -1321,22 +1107,3 @@ static int __init parse_efi_cmdline(char *str)
- 	return 0;
- }
- early_param("efi", parse_efi_cmdline);
--
--void __init efi_apply_memmap_quirks(void)
--{
--	/*
--	 * Once setup is done earlier, unmap the EFI memory map on mismatched
--	 * firmware/kernel architectures since there is no support for runtime
--	 * services.
--	 */
--	if (!efi_runtime_supported()) {
--		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
--		efi_unmap_memmap();
--	}
--
--	/*
--	 * UV doesn't support the new EFI pagetable mapping yet.
--	 */
--	if (is_uv_system())
--		set_bit(EFI_OLD_MEMMAP, &efi.flags);
--}
-diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
-new file mode 100644
-index 0000000..1b9c4c3
---- /dev/null
-+++ b/arch/x86/platform/efi/quirks.c
-@@ -0,0 +1,290 @@
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/time.h>
-+#include <linux/types.h>
-+#include <linux/efi.h>
-+#include <linux/slab.h>
-+#include <linux/memblock.h>
-+#include <linux/bootmem.h>
-+#include <linux/acpi.h>
-+#include <asm/efi.h>
-+#include <asm/uv/uv.h>
-+
-+#define EFI_MIN_RESERVE 5120
-+
-+#define EFI_DUMMY_GUID \
-+	EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
-+
-+static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
-+
-+static bool efi_no_storage_paranoia;
++	if (!phys || !size)
++		return NULL;
 +
-+/*
-+ * Some firmware implementations refuse to boot if there's insufficient
-+ * space in the variable store. The implementation of garbage collection
-+ * in some FW versions causes stale (deleted) variables to take up space
-+ * longer than intended and space is only freed once the store becomes
-+ * almost completely full.
-+ *
-+ * Enabling this option disables the space checks in
-+ * efi_query_variable_store() and forces garbage collection.
-+ *
-+ * Only enable this option if deleting EFI variables does not free up
-+ * space in your variable store, e.g. if despite deleting variables
-+ * you're unable to create new ones.
-+ */
-+static int __init setup_storage_paranoia(char *arg)
-+{
-+	efi_no_storage_paranoia = true;
-+	return 0;
++	return early_memremap(phys, size);
 +}
-+early_param("efi_no_storage_paranoia", setup_storage_paranoia);
 +
-+/*
-+ * Deleting the dummy variable which kicks off garbage collection
-+*/
-+void efi_delete_dummy_variable(void)
++void __init __acpi_unmap_table(char *map, unsigned long size)
 +{
-+	efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
-+			 EFI_VARIABLE_NON_VOLATILE |
-+			 EFI_VARIABLE_BOOTSERVICE_ACCESS |
-+			 EFI_VARIABLE_RUNTIME_ACCESS,
-+			 0, NULL);
++	if (!map || !size)
++		return;
++
++	early_memunmap(map, size);
 +}
 +
-+/*
-+ * Some firmware implementations refuse to boot if there's insufficient space
-+ * in the variable store. Ensure that we never use more than a safe limit.
++/**
++ * 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
 + *
-+ * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
-+ * store.
++ * Returns the logical cpu number which maps to MPIDR
 + */
-+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
++static int acpi_map_gic_cpu_interface(u64 mpidr, u64 parked_addr, u8 enabled)
 +{
-+	efi_status_t status;
-+	u64 storage_size, remaining_size, max_size;
++	int cpu;
 +
-+	if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
-+		return 0;
++	if (mpidr == INVALID_HWID) {
++		pr_info("Skip MADT cpu entry with invalid MPIDR\n");
++		return -EINVAL;
++	}
 +
-+	status = efi.query_variable_info(attributes, &storage_size,
-+					 &remaining_size, &max_size);
-+	if (status != EFI_SUCCESS)
-+		return status;
++	total_cpus++;
++	if (!enabled)
++		return -EINVAL;
 +
-+	/*
-+	 * We account for that by refusing the write if permitting it would
-+	 * reduce the available space to under 5KB. This figure was provided by
-+	 * Samsung, so should be safe.
-+	 */
-+	if ((remaining_size - size < EFI_MIN_RESERVE) &&
-+		!efi_no_storage_paranoia) {
++	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) {
 +		/*
-+		 * Triggering garbage collection may require that the firmware
-+		 * generate a real EFI_OUT_OF_RESOURCES error. We can force
-+		 * that by attempting to use more space than is available.
++		 * Duplicate MPIDRs are a recipe for disaster. Scan
++		 * all initialized entries and check for
++		 * duplicates. If any is found just ignore the CPU.
 +		 */
-+		unsigned long dummy_size = remaining_size + 1024;
-+		void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
-+
-+		if (!dummy)
-+			return EFI_OUT_OF_RESOURCES;
-+
-+		status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
-+					  EFI_VARIABLE_NON_VOLATILE |
-+					  EFI_VARIABLE_BOOTSERVICE_ACCESS |
-+					  EFI_VARIABLE_RUNTIME_ACCESS,
-+					  dummy_size, dummy);
-+
-+		if (status == EFI_SUCCESS) {
-+			/*
-+			 * This should have failed, so if it didn't make sure
-+			 * that we delete it...
-+			 */
-+			efi_delete_dummy_variable();
++		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;
++			}
 +		}
-+
-+		kfree(dummy);
-+
++		
++		/* allocate a logical cpu id for the new comer */
++		cpu = cpumask_next_zero(-1, cpu_possible_mask);
++	} else {
 +		/*
-+		 * The runtime code may now have triggered a garbage collection
-+		 * run, so check the variable info again
++		 * First GICC entry must be BSP as ACPI spec said
++		 * in section 5.2.12.15
 +		 */
-+		status = efi.query_variable_info(attributes, &storage_size,
-+						 &remaining_size, &max_size);
-+
-+		if (status != EFI_SUCCESS)
-+			return status;
++		if  (cpu_logical_map(0) != mpidr) {
++			pr_err("First GICC entry with MPIDR 0x%llx is not BSP\n",
++			       mpidr);
++			return -EINVAL;
++		}
 +
 +		/*
-+		 * There still isn't enough room, so return an error
++		 * boot_cpu_init() already hold bit 0 in cpu_present_mask
++		 * for BSP, no need to allocate again.
 +		 */
-+		if (remaining_size - size < EFI_MIN_RESERVE)
-+			return EFI_OUT_OF_RESOURCES;
++		cpu = 0;
 +	}
 +
-+	return EFI_SUCCESS;
-+}
-+EXPORT_SYMBOL_GPL(efi_query_variable_store);
++	parked_address[cpu] = parked_addr;
 +
-+/*
-+ * The UEFI specification makes it clear that the operating system is free to do
-+ * whatever it wants with boot services code after ExitBootServices() has been
-+ * called. Ignoring this recommendation a significant bunch of EFI implementations 
-+ * continue calling into boot services code (SetVirtualAddressMap). In order to 
-+ * work around such buggy implementations we reserve boot services region during 
-+ * EFI init and make sure it stays executable. Then, after SetVirtualAddressMap(), it
-+* is discarded.
-+*/
-+void __init efi_reserve_boot_services(void)
-+{
-+	void *p;
-+
-+	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-+		efi_memory_desc_t *md = p;
-+		u64 start = md->phys_addr;
-+		u64 size = md->num_pages << EFI_PAGE_SHIFT;
-+
-+		if (md->type != EFI_BOOT_SERVICES_CODE &&
-+		    md->type != EFI_BOOT_SERVICES_DATA)
-+			continue;
-+		/* Only reserve where possible:
-+		 * - Not within any already allocated areas
-+		 * - Not over any memory area (really needed, if above?)
-+		 * - Not within any part of the kernel
-+		 * - Not the bios reserved area
-+		*/
-+		if ((start + size > __pa_symbol(_text)
-+				&& start <= __pa_symbol(_end)) ||
-+			!e820_all_mapped(start, start+size, E820_RAM) ||
-+			memblock_is_region_reserved(start, size)) {
-+			/* Could not reserve, skip it */
-+			md->num_pages = 0;
-+			memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
-+				     start, start+size-1);
-+		} else
-+			memblock_reserve(start, size);
-+	}
-+}
-+
-+void __init efi_free_boot_services(void)
-+{
-+	void *p;
-+
-+	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-+		efi_memory_desc_t *md = p;
-+		unsigned long long start = md->phys_addr;
-+		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
-+
-+		if (md->type != EFI_BOOT_SERVICES_CODE &&
-+		    md->type != EFI_BOOT_SERVICES_DATA)
-+			continue;
++	/* CPU 0 was already initialized */
++	if (cpu) {
++		cpu_ops[cpu] = cpu_get_ops(boot_method);
++		if (!cpu_ops[cpu])
++			return -EINVAL;
 +
-+		/* Could not reserve boot area */
-+		if (!size)
-+			continue;
++		if (cpu_ops[cpu]->cpu_init(NULL, cpu))
++			return -EOPNOTSUPP;
++
++		/* map the logical cpu id to cpu MPIDR */
++		cpu_logical_map(cpu) = mpidr;
 +
-+		free_bootmem_late(start, size);
++		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);
 +	}
 +
-+	efi_unmap_memmap();
++	enabled_cpus++;
++	return cpu;
 +}
 +
-+/*
-+ * A number of config table entries get remapped to virtual addresses
-+ * after entering EFI virtual mode. However, the kexec kernel requires
-+ * their physical addresses therefore we pass them via setup_data and
-+ * correct those entries to their respective physical addresses here.
-+ *
-+ * Currently only handles smbios which is necessary for some firmware
-+ * implementation.
-+ */
-+int __init efi_reuse_config(u64 tables, int nr_tables)
++static int __init
++acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
++				const unsigned long end)
 +{
-+	int i, sz, ret = 0;
-+	void *p, *tablep;
-+	struct efi_setup_data *data;
-+
-+	if (!efi_setup)
-+		return 0;
++	struct acpi_madt_generic_interrupt *processor;
 +
-+	if (!efi_enabled(EFI_64BIT))
-+		return 0;
++	processor = (struct acpi_madt_generic_interrupt *)header;
 +
-+	data = early_memremap(efi_setup, sizeof(*data));
-+	if (!data) {
-+		ret = -ENOMEM;
-+		goto out;
-+	}
++	if (BAD_MADT_ENTRY(processor, end))
++		return -EINVAL;
 +
-+	if (!data->smbios)
-+		goto out_memremap;
++	acpi_table_print_madt_entry(header);
 +
-+	sz = sizeof(efi_config_table_64_t);
++	acpi_map_gic_cpu_interface(processor->arm_mpidr & MPIDR_HWID_BITMASK,
++		processor->parked_address, processor->flags & ACPI_MADT_ENABLED);
 +
-+	p = tablep = early_memremap(tables, nr_tables * sz);
-+	if (!p) {
-+		pr_err("Could not map Configuration table!\n");
-+		ret = -ENOMEM;
-+		goto out_memremap;
-+	}
++	return 0;
++}
 +
-+	for (i = 0; i < efi.systab->nr_tables; i++) {
-+		efi_guid_t guid;
++/* Parse GIC cpu interface entries in MADT for SMP init */
++void __init acpi_smp_init_cpus(void)
++{
++	int count;
 +
-+		guid = ((efi_config_table_64_t *)p)->guid;
++	/*
++	 * 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 (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
-+			((efi_config_table_64_t *)p)->table = data->smbios;
-+		p += sz;
++	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;
 +	}
-+	early_iounmap(tablep, nr_tables * sz);
 +
-+out_memremap:
-+	early_iounmap(data, sizeof(*data));
-+out:
-+	return ret;
++	/* Make boot-up look pretty */
++	pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus);
 +}
 +
-+void __init efi_apply_memmap_quirks(void)
++int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 +{
-+	/*
-+	 * Once setup is done earlier, unmap the EFI memory map on mismatched
-+	 * firmware/kernel architectures since there is no support for runtime
-+	 * services.
-+	 */
-+	if (!efi_runtime_supported()) {
-+		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
-+		efi_unmap_memmap();
-+	}
++	*irq = irq_find_mapping(NULL, gsi);
 +
-+	/*
-+	 * UV doesn't support the new EFI pagetable mapping yet.
-+	 */
-+	if (is_uv_system())
-+		set_bit(EFI_OLD_MEMMAP, &efi.flags);
++	return 0;
 +}
++EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 +
 +/*
-+ * For most modern platforms the preferred method of powering off is via
-+ * ACPI. However, there are some that are known to require the use of
-+ * EFI runtime services and for which ACPI does not work at all.
-+ *
-+ * Using EFI is a last resort, to be used only if no other option
-+ * exists.
++ * success: return IRQ number (>0)
++ * failure: return =< 0
 + */
-+bool efi_reboot_required(void)
++int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 +{
-+	if (!acpi_gbl_reduced_hardware)
-+		return false;
-+
-+	efi_reboot_quirk_mode = EFI_RESET_WARM;
-+	return true;
-+}
-+
-+bool efi_poweroff_required(void)
-+{
-+	return !!acpi_gbl_reduced_hardware;
-+}
-diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
-index ee3a365..f9431b4 100644
---- a/drivers/ata/ahci_xgene.c
-+++ b/drivers/ata/ahci_xgene.c
-@@ -131,7 +131,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);
-diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
-index 9553496..c135154 100644
---- a/drivers/firmware/efi/Makefile
-+++ b/drivers/firmware/efi/Makefile
-@@ -1,7 +1,7 @@
- #
- # Makefile for linux kernel
- #
--obj-$(CONFIG_EFI)			+= efi.o vars.o
-+obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o
- obj-$(CONFIG_EFI_VARS)			+= efivars.o
- obj-$(CONFIG_EFI_VARS_PSTORE)		+= efi-pstore.o
- obj-$(CONFIG_UEFI_CPER)			+= cper.o
-diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c
-new file mode 100644
-index 0000000..f94fb95
---- /dev/null
-+++ b/drivers/firmware/efi/reboot.c
-@@ -0,0 +1,55 @@
-+/*
-+ * Copyright (C) 2014 Intel Corporation; author Matt Fleming
-+ */
-+#include <linux/efi.h>
-+#include <linux/reboot.h>
-+
-+int efi_reboot_quirk_mode = -1;
-+
-+void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
-+{
-+	int efi_mode;
-+
-+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
-+		return;
-+
-+	switch (reboot_mode) {
-+	case REBOOT_WARM:
-+	case REBOOT_SOFT:
-+		efi_mode = EFI_RESET_WARM;
-+		break;
-+	default:
-+		efi_mode = EFI_RESET_COLD;
-+		break;
-+	}
-+
-+	/*
-+	 * If a quirk forced an EFI reset mode, always use that.
-+	 */
-+	if (efi_reboot_quirk_mode != -1)
-+		efi_mode = efi_reboot_quirk_mode;
-+
-+	efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);
-+}
-+
-+bool __weak efi_poweroff_required(void)
-+{
-+	return false;
-+}
-+
-+static void efi_power_off(void)
-+{
-+	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
-+}
-+
-+static int __init efi_shutdown_init(void)
-+{
-+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
-+		return -ENODEV;
-+
-+	if (efi_poweroff_required())
-+		pm_power_off = efi_power_off;
-+
-+	return 0;
-+}
-+late_initcall(efi_shutdown_init);
-diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
-index bbb746e..7f0c2a3 100644
---- a/drivers/irqchip/Kconfig
-+++ b/drivers/irqchip/Kconfig
-@@ -10,6 +10,11 @@ config ARM_GIC
- config GIC_NON_BANKED
- 	bool
- 
-+config ARM_GIC_V3
-+	bool
-+	select IRQ_DOMAIN
-+	select MULTI_IRQ_HANDLER
-+
- config ARM_NVIC
- 	bool
- 	select IRQ_DOMAIN
-diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
-index 62a13e5..c57e642 100644
---- a/drivers/irqchip/Makefile
-+++ b/drivers/irqchip/Makefile
-@@ -15,7 +15,8 @@ obj-$(CONFIG_ORION_IRQCHIP)		+= irq-orion.o
- obj-$(CONFIG_ARCH_SUNXI)		+= irq-sun4i.o
- obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi-nmi.o
- obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
--obj-$(CONFIG_ARM_GIC)			+= irq-gic.o
-+obj-$(CONFIG_ARM_GIC)			+= irq-gic.o irq-gic-common.o
-+obj-$(CONFIG_ARM_GIC_V3)		+= irq-gic-v3.o irq-gic-common.o
- obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
- obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
- obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
-diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
-new file mode 100644
-index 0000000..60ac704
---- /dev/null
-+++ b/drivers/irqchip/irq-gic-common.c
-@@ -0,0 +1,115 @@
-+/*
-+ * Copyright (C) 2002 ARM Limited, All Rights Reserved.
-+ *
-+ * 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/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/irqchip/arm-gic.h>
-+
-+#include "irq-gic-common.h"
-+
-+void gic_configure_irq(unsigned int irq, unsigned int type,
-+		       void __iomem *base, void (*sync_access)(void))
-+{
-+	u32 enablemask = 1 << (irq % 32);
-+	u32 enableoff = (irq / 32) * 4;
-+	u32 confmask = 0x2 << ((irq % 16) * 2);
-+	u32 confoff = (irq / 16) * 4;
-+	bool enabled = false;
-+	u32 val;
++	unsigned int irq;
++	unsigned int irq_type;
 +
 +	/*
-+	 * Read current configuration register, and insert the config
-+	 * for "irq", depending on "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];
 +	 */
-+	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
-+	if (type == IRQ_TYPE_LEVEL_HIGH)
-+		val &= ~confmask;
-+	else if (type == IRQ_TYPE_EDGE_RISING)
-+		val |= confmask;
 +
-+	/*
-+	 * As recommended by the spec, disable the interrupt before changing
-+	 * the configuration
-+	 */
-+	if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
-+		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
-+		if (sync_access)
-+			sync_access();
-+		enabled = true;
-+	}
++	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;
 +
 +	/*
-+	 * Write back the new configuration, and possibly re-enable
-+	 * the interrupt.
++	 * Since only one GIC is supported in ACPI 5.0, we can
++	 * create mapping refer to the default domain
 +	 */
-+	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
-+
-+	if (enabled)
-+		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
++	irq = irq_create_mapping(NULL, gsi);
++	if (!irq)
++		return irq;
 +
-+	if (sync_access)
-+		sync_access();
++	/* 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 __init gic_dist_config(void __iomem *base, int gic_irqs,
-+			    void (*sync_access)(void))
++void acpi_unregister_gsi(u32 gsi)
 +{
-+	unsigned int i;
-+
-+	/*
-+	 * Set all global interrupts to be level triggered, active low.
-+	 */
-+	for (i = 32; i < gic_irqs; i += 16)
-+		writel_relaxed(0, base + GIC_DIST_CONFIG + i / 4);
-+
-+	/*
-+	 * Set priority on all global interrupts.
-+	 */
-+	for (i = 32; i < gic_irqs; i += 4)
-+		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i);
-+
-+	/*
-+	 * Disable all interrupts.  Leave the PPI and SGIs alone
-+	 * as they are enabled by redistributor registers.
-+	 */
-+	for (i = 32; i < gic_irqs; i += 32)
-+		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i / 8);
-+
-+	if (sync_access)
-+		sync_access();
 +}
++EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 +
-+void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
++static int __init acpi_parse_fadt(struct acpi_table_header *table)
 +{
-+	int i;
++	struct acpi_table_fadt *fadt = (struct acpi_table_fadt *)table;
 +
 +	/*
-+	 * Deal with the banked PPI and SGI interrupts - disable all
-+	 * PPI interrupts, ensure all SGI interrupts are enabled.
++	 * 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 newer revision
++	 * to get arm boot flags, or we will disable ACPI.
 +	 */
-+	writel_relaxed(0xffff0000, base + GIC_DIST_ENABLE_CLEAR);
-+	writel_relaxed(0x0000ffff, base + GIC_DIST_ENABLE_SET);
++	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("No boot method, will not bring up secondary CPUs\n");
++		return -EOPNOTSUPP;
++	}
 +
-+	/*
-+	 * Set priority on PPI and SGI interrupts
-+	 */
-+	for (i = 0; i < 32; i += 4)
-+		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
++	pr_warn("Unsupported FADT revision %d.%d, should be 5.1+, will disable ACPI\n",
++		table->revision, fadt->minor_revision);
++	disable_acpi();
 +
-+	if (sync_access)
-+		sync_access();
++	return -EINVAL;
 +}
-diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
-new file mode 100644
-index 0000000..b41f024
---- /dev/null
-+++ b/drivers/irqchip/irq-gic-common.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2002 ARM Limited, All Rights Reserved.
-+ *
-+ * 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/>.
-+ */
-+
-+#ifndef _IRQ_GIC_COMMON_H
-+#define _IRQ_GIC_COMMON_H
-+
-+#include <linux/of.h>
-+#include <linux/irqdomain.h>
 +
-+void gic_configure_irq(unsigned int irq, unsigned int type,
-+                       void __iomem *base, void (*sync_access)(void));
-+void gic_dist_config(void __iomem *base, int gic_irqs,
-+		     void (*sync_access)(void));
-+void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
-+
-+#endif /* _IRQ_GIC_COMMON_H */
-diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
-new file mode 100644
-index 0000000..81519ba
---- /dev/null
-+++ b/drivers/irqchip/irq-gic-v3.c
-@@ -0,0 +1,692 @@
 +/*
-+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
-+ * Author: Marc Zyngier <marc.zyngier at arm.com>
-+ *
-+ * 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.
++ * 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
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ * 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;
 +
-+#include <linux/cpu.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/percpu.h>
-+#include <linux/slab.h>
-+
-+#include <linux/irqchip/arm-gic-v3.h>
-+
-+#include <asm/cputype.h>
-+#include <asm/exception.h>
-+#include <asm/smp_plat.h>
-+
-+#include "irq-gic-common.h"
-+#include "irqchip.h"
-+
-+struct gic_chip_data {
-+	void __iomem		*dist_base;
-+	void __iomem		**redist_base;
-+	void __percpu __iomem	**rdist;
-+	struct irq_domain	*domain;
-+	u64			redist_stride;
-+	u32			redist_regions;
-+	unsigned int		irq_nr;
-+};
-+
-+static struct gic_chip_data gic_data __read_mostly;
-+
-+#define gic_data_rdist()		(this_cpu_ptr(gic_data.rdist))
-+#define gic_data_rdist_rd_base()	(*gic_data_rdist())
-+#define gic_data_rdist_sgi_base()	(gic_data_rdist_rd_base() + SZ_64K)
-+
-+/* Our default, arbitrary priority value. Linux only uses one anyway. */
-+#define DEFAULT_PMR_VALUE	0xf0
++	/* Initialize the ACPI boot-time table parser. */
++	if (acpi_table_init()) {
++		disable_acpi();
++		return;
++	}
 +
-+static inline unsigned int gic_irq(struct irq_data *d)
-+{
-+	return d->hwirq;
++	if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
++		pr_err("Can't find FADT or error happened during parsing FADT\n");
 +}
 +
-+static inline int gic_irq_in_rdist(struct irq_data *d)
++void __init acpi_gic_init(void)
 +{
-+	return gic_irq(d) < 32;
-+}
++	struct acpi_table_header *table;
++	acpi_status status;
++	acpi_size tbl_size;
++	int err;
 +
-+static inline void __iomem *gic_dist_base(struct irq_data *d)
-+{
-+	if (gic_irq_in_rdist(d))	/* SGI+PPI -> SGI_base for this CPU */
-+		return gic_data_rdist_sgi_base();
++	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
++	if (ACPI_FAILURE(status)) {
++		const char *msg = acpi_format_exception(status);
 +
-+	if (d->hwirq <= 1023)		/* SPI -> dist_base */
-+		return gic_data.dist_base;
++		pr_err("Failed to get MADT table, %s\n", msg);
++		return;
++	}
 +
-+	if (d->hwirq >= 8192)
-+		BUG();		/* LPI Detected!!! */
++	err = gic_v2_acpi_init(table);
++	if (err)
++		pr_err("Failed to initialize GIC IRQ controller");
 +
-+	return NULL;
++	early_acpi_os_unmap_memory((char *)table, tbl_size);
 +}
 +
-+static void gic_do_wait_for_rwp(void __iomem *base)
++/*
++ * Parked Address in ACPI GIC structure will be used as the CPU
++ * release address
++ */
++int acpi_get_cpu_parked_address(int cpu, u64 *addr)
 +{
-+	u32 count = 1000000;	/* 1s! */
++	if (!addr || !parked_address[cpu])
++		return -EINVAL;
 +
-+	while (readl_relaxed(base + GICD_CTLR) & GICD_CTLR_RWP) {
-+		count--;
-+		if (!count) {
-+			pr_err_ratelimited("RWP timeout, gone fishing\n");
-+			return;
-+		}
-+		cpu_relax();
-+		udelay(1);
-+	};
-+}
++	*addr = parked_address[cpu];
 +
-+/* Wait for completion of a distributor change */
-+static void gic_dist_wait_for_rwp(void)
-+{
-+	gic_do_wait_for_rwp(gic_data.dist_base);
++	return 0;
 +}
 +
-+/* Wait for completion of a redistributor change */
-+static void gic_redist_wait_for_rwp(void)
++static int __init parse_acpi(char *arg)
 +{
-+	gic_do_wait_for_rwp(gic_data_rdist_rd_base());
-+}
++	if (!arg)
++		return -EINVAL;
 +
-+/* Low level accessors */
-+static u64 gic_read_iar(void)
-+{
-+	u64 irqstat;
++	/* "acpi=off" disables both ACPI table parsing and interpreter */
++	if (strcmp(arg, "off") == 0)
++		disable_acpi();
++	else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
++		enable_acpi();
++	else
++		return -EINVAL;	/* Core will print when we return error */
 +
-+	asm volatile("mrs %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
-+	return irqstat;
++	return 0;
 +}
++early_param("acpi", parse_acpi);
 +
-+static void gic_write_pmr(u64 val)
++int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
 +{
-+	asm volatile("msr " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val));
++	return -1;
 +}
 +
-+static void gic_write_ctlr(u64 val)
++int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 +{
-+	asm volatile("msr " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val));
-+	isb();
++	/* TBD */
++	return -EINVAL;
 +}
++EXPORT_SYMBOL(acpi_register_ioapic);
 +
-+static void gic_write_grpen1(u64 val)
++int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 +{
-+	asm volatile("msr " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" (val));
-+	isb();
++	/* TBD */
++	return -EINVAL;
 +}
++EXPORT_SYMBOL(acpi_unregister_ioapic);
 +
-+static void gic_write_sgi1r(u64 val)
-+{
-+	asm volatile("msr " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
-+}
+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-entry.S b/arch/arm64/kernel/efi-entry.S
+index d18a449..8ce9b05 100644
+--- a/arch/arm64/kernel/efi-entry.S
++++ b/arch/arm64/kernel/efi-entry.S
+@@ -61,7 +61,8 @@ ENTRY(efi_stub_entry)
+ 	 */
+ 	mov	x20, x0		// DTB address
+ 	ldr	x0, [sp, #16]	// relocated _text address
+-	mov	x21, x0
++	ldr	x21, =stext_offset
++	add	x21, x0, x21
+ 
+ 	/*
+ 	 * Calculate size of the kernel Image (same for original and copy).
+diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
+index 95c49eb..f9de195 100644
+--- a/arch/arm64/kernel/efi.c
++++ b/arch/arm64/kernel/efi.c
+@@ -11,6 +11,7 @@
+  *
+  */
+ 
++#include <linux/dmi.h>
+ #include <linux/efi.h>
+ #include <linux/export.h>
+ #include <linux/memblock.h>
+@@ -112,8 +113,6 @@ static int __init uefi_init(void)
+ 		efi.systab->hdr.revision & 0xffff, vendor);
+ 
+ 	retval = efi_config_init(NULL);
+-	if (retval == 0)
+-		set_bit(EFI_CONFIG_TABLES, &efi.flags);
+ 
+ out:
+ 	early_memunmap(efi.systab,  sizeof(efi_system_table_t));
+@@ -125,17 +124,17 @@ out:
+  */
+ static __init int is_reserve_region(efi_memory_desc_t *md)
+ {
+-	if (!is_normal_ram(md))
++	switch (md->type) {
++	case EFI_LOADER_CODE:
++	case EFI_LOADER_DATA:
++	case EFI_BOOT_SERVICES_CODE:
++	case EFI_BOOT_SERVICES_DATA:
++	case EFI_CONVENTIONAL_MEMORY:
+ 		return 0;
+-
+-	if (md->attribute & EFI_MEMORY_RUNTIME)
+-		return 1;
+-
+-	if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
+-	    md->type == EFI_RESERVED_TYPE)
+-		return 1;
+-
+-	return 0;
++	default:
++		break;
++	}
++	return is_normal_ram(md);
+ }
+ 
+ static __init void reserve_regions(void)
+@@ -471,3 +470,54 @@ err_unmap:
+ 	return -1;
+ }
+ early_initcall(arm64_enter_virtual_mode);
 +
-+static void gic_enable_sre(void)
++static int __init arm64_dmi_init(void)
 +{
-+	u64 val;
-+
-+	asm volatile("mrs %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
-+	val |= ICC_SRE_EL1_SRE;
-+	asm volatile("msr " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val));
-+	isb();
-+
 +	/*
-+	 * Need to check that the SRE bit has actually been set. If
-+	 * not, it means that SRE is disabled at EL2. We're going to
-+	 * die painfully, and there is nothing we can do about it.
-+	 *
-+	 * Kindly inform the luser.
++	 * On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to
++	 * be called early because dmi_id_init(), which is an arch_initcall
++	 * itself, depends on dmi_scan_machine() having been called already.
 +	 */
-+	asm volatile("mrs %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
-+	if (!(val & ICC_SRE_EL1_SRE))
-+		pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
-+}
-+
-+static void gic_enable_redist(void)
-+{
-+	void __iomem *rbase;
-+	u32 count = 1000000;	/* 1s! */
-+	u32 val;
-+
-+	rbase = gic_data_rdist_rd_base();
-+
-+	/* Wake up this CPU redistributor */
-+	val = readl_relaxed(rbase + GICR_WAKER);
-+	val &= ~GICR_WAKER_ProcessorSleep;
-+	writel_relaxed(val, rbase + GICR_WAKER);
-+
-+	while (readl_relaxed(rbase + GICR_WAKER) & GICR_WAKER_ChildrenAsleep) {
-+		count--;
-+		if (!count) {
-+			pr_err_ratelimited("redist didn't wake up...\n");
-+			return;
-+		}
-+		cpu_relax();
-+		udelay(1);
-+	};
++	dmi_scan_machine();
++	if (dmi_available)
++		dmi_set_dump_stack_arch_desc();
++	return 0;
 +}
++core_initcall(arm64_dmi_init);
 +
 +/*
-+ * Routines to disable, enable, EOI and route interrupts
++ * If nothing else is handling pm_power_off, use EFI
++ *
++ * When Guenter Roeck's power-off handler call chain patches land,
++ * we just need to return true unconditionally.
 + */
-+static void gic_poke_irq(struct irq_data *d, u32 offset)
++bool efi_poweroff_required(void)
 +{
-+	u32 mask = 1 << (gic_irq(d) % 32);
-+	void (*rwp_wait)(void);
-+	void __iomem *base;
-+
-+	if (gic_irq_in_rdist(d)) {
-+		base = gic_data_rdist_sgi_base();
-+		rwp_wait = gic_redist_wait_for_rwp;
-+	} else {
-+		base = gic_data.dist_base;
-+		rwp_wait = gic_dist_wait_for_rwp;
-+	}
-+
-+	writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
-+	rwp_wait();
++	return pm_power_off == NULL;
 +}
 +
-+static int gic_peek_irq(struct irq_data *d, u32 offset)
++static int arm64_efi_restart(struct notifier_block *this,
++			   unsigned long mode, void *cmd)
 +{
-+	u32 mask = 1 << (gic_irq(d) % 32);
-+	void __iomem *base;
-+
-+	if (gic_irq_in_rdist(d))
-+		base = gic_data_rdist_sgi_base();
-+	else
-+		base = gic_data.dist_base;
-+
-+	return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
++	efi_reboot(reboot_mode, cmd);
++	return NOTIFY_DONE;
 +}
 +
-+static void gic_mask_irq(struct irq_data *d)
-+{
-+	gic_poke_irq(d, GICD_ICENABLER);
-+}
++static struct notifier_block arm64_efi_restart_nb = {
++	.notifier_call = arm64_efi_restart,
++	.priority = INT_MAX,
++};
 +
-+static void gic_unmask_irq(struct irq_data *d)
++static int __init arm64_register_efi_restart(void)
 +{
-+	gic_poke_irq(d, GICD_ISENABLER);
-+}
++	int ret = 0;
 +
-+static void gic_eoi_irq(struct irq_data *d)
-+{
-+	gic_write_eoir(gic_irq(d));
++	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
++		ret = register_restart_handler(&arm64_efi_restart_nb);
++		if (ret)
++			pr_err("%s: cannot register restart handler, %d\n",
++			       __func__, ret);
++	}
++	return ret;
 +}
++late_initcall(arm64_register_efi_restart);
+diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
+index 38e704e..08cafc5 100644
+--- a/arch/arm64/kernel/entry-ftrace.S
++++ b/arch/arm64/kernel/entry-ftrace.S
+@@ -98,8 +98,8 @@
+ ENTRY(_mcount)
+ 	mcount_enter
+ 
+-	ldr	x0, =ftrace_trace_function
+-	ldr	x2, [x0]
++	adrp	x0, ftrace_trace_function
++	ldr	x2, [x0, #:lo12:ftrace_trace_function]
+ 	adr	x0, ftrace_stub
+ 	cmp	x0, x2			// if (ftrace_trace_function
+ 	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+@@ -115,14 +115,15 @@ skip_ftrace_call:			//   return;
+ 	mcount_exit			//   return;
+ 					// }
+ skip_ftrace_call:
+-	ldr	x1, =ftrace_graph_return
+-	ldr	x2, [x1]		//   if ((ftrace_graph_return
+-	cmp	x0, x2			//        != ftrace_stub)
+-	b.ne	ftrace_graph_caller
+-
+-	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+-	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+-	ldr	x0, =ftrace_graph_entry_stub
++	adrp	x1, ftrace_graph_return
++	ldr	x2, [x1, #:lo12:ftrace_graph_return]
++	cmp	x0, x2			//   if ((ftrace_graph_return
++	b.ne	ftrace_graph_caller	//        != ftrace_stub)
++
++	adrp	x1, ftrace_graph_entry	//     || (ftrace_graph_entry
++	adrp	x0, ftrace_graph_entry_stub //     != ftrace_graph_entry_stub))
++	ldr	x2, [x1, #:lo12:ftrace_graph_entry]
++	add	x0, x0, #:lo12:ftrace_graph_entry_stub
+ 	cmp	x0, x2
+ 	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+ 
+diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
+index 0a6e4f9..5a76e3a 100644
+--- a/arch/arm64/kernel/head.S
++++ b/arch/arm64/kernel/head.S
+@@ -132,6 +132,8 @@ efi_head:
+ #endif
+ 
+ #ifdef CONFIG_EFI
++	.globl	stext_offset
++	.set	stext_offset, stext - efi_head
+ 	.align 3
+ pe_header:
+ 	.ascii	"PE"
+@@ -155,12 +157,12 @@ optional_header:
+ 	.long	0				// SizeOfInitializedData
+ 	.long	0				// SizeOfUninitializedData
+ 	.long	efi_stub_entry - efi_head	// AddressOfEntryPoint
+-	.long	stext - efi_head		// BaseOfCode
++	.long	stext_offset			// BaseOfCode
+ 
+ extra_header_fields:
+ 	.quad	0				// ImageBase
+-	.long	0x20				// SectionAlignment
+-	.long	0x8				// FileAlignment
++	.long	0x1000				// SectionAlignment
++	.long	PECOFF_FILE_ALIGNMENT		// FileAlignment
+ 	.short	0				// MajorOperatingSystemVersion
+ 	.short	0				// MinorOperatingSystemVersion
+ 	.short	0				// MajorImageVersion
+@@ -172,7 +174,7 @@ extra_header_fields:
+ 	.long	_end - efi_head			// SizeOfImage
+ 
+ 	// Everything before the kernel image is considered part of the header
+-	.long	stext - efi_head		// SizeOfHeaders
++	.long	stext_offset			// SizeOfHeaders
+ 	.long	0				// CheckSum
+ 	.short	0xa				// Subsystem (EFI application)
+ 	.short	0				// DllCharacteristics
+@@ -217,16 +219,24 @@ section_table:
+ 	.byte	0
+ 	.byte	0        		// end of 0 padding of section name
+ 	.long	_end - stext		// VirtualSize
+-	.long	stext - efi_head	// VirtualAddress
++	.long	stext_offset		// VirtualAddress
+ 	.long	_edata - stext		// SizeOfRawData
+-	.long	stext - efi_head	// PointerToRawData
++	.long	stext_offset		// PointerToRawData
+ 
+ 	.long	0		// PointerToRelocations (0 for executables)
+ 	.long	0		// PointerToLineNumbers (0 for executables)
+ 	.short	0		// NumberOfRelocations  (0 for executables)
+ 	.short	0		// NumberOfLineNumbers  (0 for executables)
+ 	.long	0xe0500020	// Characteristics (section flags)
+-	.align 5
 +
-+static int gic_set_type(struct irq_data *d, unsigned int type)
-+{
-+	unsigned int irq = gic_irq(d);
-+	void (*rwp_wait)(void);
-+	void __iomem *base;
-+
-+	/* Interrupt configuration for SGIs can't be changed */
-+	if (irq < 16)
-+		return -EINVAL;
-+
-+	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
-+		return -EINVAL;
++	/*
++	 * EFI will load stext onwards at the 4k section alignment
++	 * described in the PE/COFF header. To ensure that instruction
++	 * sequences using an adrp and a :lo12: immediate will function
++	 * correctly at this alignment, we must ensure that stext is
++	 * placed at a 4k boundary in the Image to begin with.
++	 */
++	.align 12
+ #endif
+ 
+ ENTRY(stext)
+diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c
+index 7d37ead..354be2a 100644
+--- a/arch/arm64/kernel/io.c
++++ b/arch/arm64/kernel/io.c
+@@ -25,12 +25,26 @@
+  */
+ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
+ {
+-	unsigned char *t = to;
+-	while (count) {
++	while (count && (!IS_ALIGNED((unsigned long)from, 8) ||
++			 !IS_ALIGNED((unsigned long)to, 8))) {
++		*(u8 *)to = __raw_readb(from);
++		from++;
++		to++;
+ 		count--;
+-		*t = readb(from);
+-		t++;
++	}
 +
-+	if (gic_irq_in_rdist(d)) {
-+		base = gic_data_rdist_sgi_base();
-+		rwp_wait = gic_redist_wait_for_rwp;
-+	} else {
-+		base = gic_data.dist_base;
-+		rwp_wait = gic_dist_wait_for_rwp;
++	while (count >= 8) {
++		*(u64 *)to = __raw_readq(from);
++		from += 8;
++		to += 8;
++		count -= 8;
++	}
++
++	while (count) {
++		*(u8 *)to = __raw_readb(from);
+ 		from++;
++		to++;
++		count--;
+ 	}
+ }
+ EXPORT_SYMBOL(__memcpy_fromio);
+@@ -40,12 +54,26 @@ EXPORT_SYMBOL(__memcpy_fromio);
+  */
+ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
+ {
+-	const unsigned char *f = from;
+-	while (count) {
++	while (count && (!IS_ALIGNED((unsigned long)to, 8) ||
++			 !IS_ALIGNED((unsigned long)from, 8))) {
++		__raw_writeb(*(volatile u8 *)from, to);
++		from++;
++		to++;
+ 		count--;
+-		writeb(*f, to);
+-		f++;
 +	}
 +
-+	gic_configure_irq(irq, type, base, rwp_wait);
++	while (count >= 8) {
++		__raw_writeq(*(volatile u64 *)from, to);
++		from += 8;
++		to += 8;
++		count -= 8;
++	}
 +
-+	return 0;
-+}
++	while (count) {
++		__raw_writeb(*(volatile u8 *)from, to);
++		from++;
+ 		to++;
++		count--;
+ 	}
+ }
+ EXPORT_SYMBOL(__memcpy_toio);
+@@ -55,10 +83,28 @@ EXPORT_SYMBOL(__memcpy_toio);
+  */
+ void __memset_io(volatile void __iomem *dst, int c, size_t count)
+ {
+-	while (count) {
++	u64 qc = (u8)c;
++
++	qc |= qc << 8;
++	qc |= qc << 16;
++	qc |= qc << 32;
++
++	while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
++		__raw_writeb(c, dst);
++		dst++;
+ 		count--;
+-		writeb(c, dst);
++	}
++
++	while (count >= 8) {
++		__raw_writeq(qc, dst);
++		dst += 8;
++		count -= 8;
++	}
 +
-+static u64 gic_mpidr_to_affinity(u64 mpidr)
++	while (count) {
++		__raw_writeb(c, dst);
+ 		dst++;
++		count--;
+ 	}
+ }
+ EXPORT_SYMBOL(__memset_io);
+diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
+index ce5836c..978cd21 100644
+--- a/arch/arm64/kernel/pci.c
++++ b/arch/arm64/kernel/pci.c
+@@ -17,6 +17,8 @@
+ #include <linux/of_pci.h>
+ #include <linux/of_platform.h>
+ #include <linux/slab.h>
++#include <linux/acpi.h>
++#include <linux/pci-acpi.h>
+ 
+ #include <asm/pci-bridge.h>
+ 
+@@ -37,34 +39,99 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+ 	return res->start;
+ }
+ 
++int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 +{
-+	u64 aff;
++	struct pci_sysdata *sd;
 +
-+	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
-+	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
-+	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8  |
-+	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
++	if (!acpi_disabled) {
++		sd = bridge->bus->sysdata;
++		ACPI_COMPANION_SET(&bridge->dev, sd->companion);
++	}
++	return 0;
++}
 +
-+	return aff;
+ /*
+  * 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);
++	if (acpi_disabled)
++		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+ 
+ 	return 0;
+ }
+ 
++void pcibios_add_bus(struct pci_bus *bus)
++{
++	if (!acpi_disabled)
++		acpi_pci_add_bus(bus);
++}
+ 
+-#ifdef CONFIG_PCI_DOMAINS_GENERIC
+-static bool dt_domain_found = false;
++void pcibios_remove_bus(struct pci_bus *bus)
++{
++	if (!acpi_disabled)
++		acpi_pci_remove_bus(bus);
 +}
 +
-+static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
++int pcibios_enable_irq(struct pci_dev *dev)
 +{
-+	u64 irqnr;
++	if (!acpi_disabled && !pci_dev_msi_enabled(dev))
++		acpi_pci_irq_enable(dev);
++	return 0;
++}
 +
-+	do {
-+		irqnr = gic_read_iar();
++int pcibios_disable_irq(struct pci_dev *dev)
++{
++	if (!acpi_disabled && !pci_dev_msi_enabled(dev))
++		acpi_pci_irq_disable(dev);
++	return 0;
++}
+ 
++int pcibios_enable_device(struct pci_dev *dev, int bars)
++{
++	int err;
 +
-+		if (likely(irqnr > 15 && irqnr < 1020)) {
-+			u64 irq = irq_find_mapping(gic_data.domain, irqnr);
-+			if (likely(irq)) {
-+				handle_IRQ(irq, regs);
-+				continue;
-+			}
++	err = pci_enable_resources(dev, bars);
++	if (err < 0)
++		return err;
 +
-+			WARN_ONCE(true, "Unexpected SPI received!\n");
-+			gic_write_eoir(irqnr);
-+		}
-+		if (irqnr < 16) {
-+			gic_write_eoir(irqnr);
-+#ifdef CONFIG_SMP
-+			handle_IPI(irqnr, regs);
-+#else
-+			WARN_ONCE(true, "Unexpected SGI received!\n");
-+#endif
-+			continue;
-+		}
-+	} while (irqnr != ICC_IAR1_EL1_SPURIOUS);
++	if (!pci_dev_msi_enabled(dev))
++		return pcibios_enable_irq(dev);
++	return 0;
 +}
 +
-+static void __init gic_dist_init(void)
-+{
-+	unsigned int i;
-+	u64 affinity;
-+	void __iomem *base = gic_data.dist_base;
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
+ 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();
+-	}
++	int domain = -1;
+ 
+-	bus->domain_nr = domain;
++	if (acpi_disabled)
++		domain = of_get_pci_domain_nr(parent->of_node);
++	else {
++		struct pci_sysdata *sd = bus->sysdata;
 +
-+	/* Disable the distributor */
-+	writel_relaxed(0, base + GICD_CTLR);
-+	gic_dist_wait_for_rwp();
++		domain = sd->domain;
++	}
++	if (domain >= 0)
++		bus->domain_nr = domain;
+ }
+ #endif
 +
-+	gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
++static int __init pcibios_assign_resources(void)
++{
++	struct pci_bus *root_bus;
 +
-+	/* Enable distributor with ARE, Group1 */
-+	writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
-+		       base + GICD_CTLR);
++	if (acpi_disabled)
++		return 0;
 +
-+	/*
-+	 * Set all global interrupts to the boot CPU only. ARE must be
-+	 * enabled.
-+	 */
-+	affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
-+	for (i = 32; i < gic_data.irq_nr; i++)
-+		writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
++	list_for_each_entry(root_bus, &pci_root_buses, node) {
++		pcibios_resource_survey_bus(root_bus);
++		pci_assign_unassigned_root_bus_resources(root_bus);
++	}
++	return 0;
 +}
-+
-+static int gic_populate_rdist(void)
++/*
++ * fs_initcall comes after subsys_initcall, so we know acpi scan
++ * has run.
++ */
++fs_initcall(pcibios_assign_resources);
+diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
+index 663da77..2d0deda 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>
+@@ -24,6 +25,7 @@
+ #include <linux/slab.h>
+ #include <uapi/linux/psci.h>
+ 
++#include <asm/acpi.h>
+ #include <asm/compiler.h>
+ #include <asm/cpu_ops.h>
+ #include <asm/errno.h>
+@@ -304,6 +306,33 @@ static void psci_sys_poweroff(void)
+ 	invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+ }
+ 
++static void psci_0_2_set_functions(void)
 +{
-+	u64 mpidr = cpu_logical_map(smp_processor_id());
-+	u64 typer;
-+	u32 aff;
-+	int i;
++	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;
 +
-+	/*
-+	 * Convert affinity to a 32bit value that can be matched to
-+	 * GICR_TYPER bits [63:32].
-+	 */
-+	aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
-+	       MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
-+	       MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
-+	       MPIDR_AFFINITY_LEVEL(mpidr, 0));
-+
-+	for (i = 0; i < gic_data.redist_regions; i++) {
-+		void __iomem *ptr = gic_data.redist_base[i];
-+		u32 reg;
-+
-+		reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
-+		if (reg != GIC_PIDR2_ARCH_GICv3 &&
-+		    reg != GIC_PIDR2_ARCH_GICv4) { /* We're in trouble... */
-+			pr_warn("No redistributor present @%p\n", ptr);
-+			break;
-+		}
++	psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF;
++	psci_ops.cpu_off = psci_cpu_off;
 +
-+		do {
-+			typer = readq_relaxed(ptr + GICR_TYPER);
-+			if ((typer >> 32) == aff) {
-+				gic_data_rdist_rd_base() = ptr;
-+				pr_info("CPU%d: found redistributor %llx @%p\n",
-+					smp_processor_id(),
-+					(unsigned long long)mpidr, ptr);
-+				return 0;
-+			}
++	psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN64_CPU_ON;
++	psci_ops.cpu_on = psci_cpu_on;
 +
-+			if (gic_data.redist_stride) {
-+				ptr += gic_data.redist_stride;
-+			} else {
-+				ptr += SZ_64K * 2; /* Skip RD_base + SGI_base */
-+				if (typer & GICR_TYPER_VLPIS)
-+					ptr += SZ_64K * 2; /* Skip VLPI_base + reserved page */
-+			}
-+		} while (!(typer & GICR_TYPER_LAST));
-+	}
++	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;
 +
-+	/* We couldn't even deal with ourselves... */
-+	WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
-+	     smp_processor_id(), (unsigned long long)mpidr);
-+	return -ENODEV;
++	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;
 +}
 +
-+static void gic_cpu_init(void)
+ /*
+  * PSCI Function IDs for v0.2+ are well defined so use
+  * standard values.
+@@ -337,29 +366,7 @@ static int __init psci_0_2_init(struct device_node *np)
+ 		}
+ 	}
+ 
+-	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();
+ 
+ out_put_node:
+ 	of_node_put(np);
+@@ -412,7 +419,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;
+@@ -427,6 +434,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)
 +{
-+	void __iomem *rbase;
-+
-+	/* Register ourselves with the rest of the world */
-+	if (gic_populate_rdist())
-+		return;
++	if (!acpi_psci_present()) {
++		pr_info("is not implemented in ACPI.\n");
++		return -EOPNOTSUPP;
++	}
 +
-+	gic_enable_redist();
++	pr_info("probing for conduit method from ACPI.\n");
 +
-+	rbase = gic_data_rdist_sgi_base();
++	if (acpi_psci_use_hvc())
++		invoke_psci_fn = __invoke_psci_fn_hvc;
++	else
++		invoke_psci_fn = __invoke_psci_fn_smc;
 +
-+	gic_cpu_config(rbase, gic_redist_wait_for_rwp);
++	psci_0_2_set_functions();
 +
-+	/* Enable system registers */
-+	gic_enable_sre();
++	return 0;
++}
 +
-+	/* Set priority mask register */
-+	gic_write_pmr(DEFAULT_PMR_VALUE);
+ #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 2437196..914287d 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 <linux/personality.h>
+ 
+ #include <asm/fixmap.h>
+@@ -59,6 +60,7 @@
+ #include <asm/memblock.h>
+ #include <asm/psci.h>
+ #include <asm/efi.h>
++#include <asm/acpi.h>
+ 
+ unsigned int processor_id;
+ EXPORT_SYMBOL(processor_id);
+@@ -116,12 +118,16 @@ void __init early_print(const char *str, ...)
+ 
+ void __init smp_setup_processor_id(void)
+ {
++	u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
++	cpu_logical_map(0) = mpidr;
 +
-+	/* EOI deactivates interrupt too (mode 0) */
-+	gic_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);
+ 	/*
+ 	 * clear __my_cpu_offset on boot CPU to avoid hang caused by
+ 	 * using percpu variable early, for example, lockdep will
+ 	 * access percpu variable inside lock_release
+ 	 */
+ 	set_my_cpu_offset(0);
++	pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr);
+ }
+ 
+ bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+@@ -312,6 +318,7 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
+		while (true)
+ 			cpu_relax();
+ 	}
++	dump_stack_set_arch_desc("%s (DT)", machine_name);
+ }
+ 
+ /*
+@@ -378,6 +385,8 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	early_ioremap_init();
+ 
++	disable_acpi();
 +
-+	/* ... and let's hit the road... */
-+	gic_write_grpen1(1);
-+}
+ 	parse_early_param();
+ 
+ 	/*
+@@ -389,19 +398,27 @@ void __init setup_arch(char **cmdline_p)
+ 	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();
+	early_ioremap_reset();
+ 
+-	unflatten_device_tree();
+-
+-	psci_init();
++	if (acpi_disabled) {
++		unflatten_device_tree();
++		psci_dt_init();
++		cpu_read_bootcpu_ops();
 +#ifdef CONFIG_SMP
-+static int gic_secondary_init(struct notifier_block *nfb,
-+			      unsigned long action, void *hcpu)
-+{
-+	if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
-+		gic_cpu_init();
-+	return NOTIFY_OK;
-+}
++		of_smp_init_cpus();
++#endif
++	} else {
++		psci_acpi_init();
++		acpi_smp_init_cpus();
++	}
+ 
+-	cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
+-	cpu_read_bootcpu_ops();
+ #ifdef CONFIG_SMP
+-	smp_init_cpus();
+ 	smp_build_mpidr_hash();
+ #endif
+ 
+@@ -506,3 +523,25 @@ const struct seq_operations cpuinfo_op = {
+ 	.stop	= c_stop,
+ 	.show	= c_show
+ };
 +
 +/*
-+ * Notifier for enabling the GIC CPU interface. Set an arbitrarily high
-+ * priority because the GIC needs to be up before the ARM generic timers.
++ * Temporary hack to avoid need for console= on command line
 + */
-+static struct notifier_block gic_cpu_notifier = {
-+	.notifier_call = gic_secondary_init,
-+	.priority = 100,
-+};
-+
-+static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
-+				   u64 cluster_id)
++static int __init arm64_console_setup(void)
 +{
-+	int cpu = *base_cpu;
-+	u64 mpidr = cpu_logical_map(cpu);
-+	u16 tlist = 0;
-+
-+	while (cpu < nr_cpu_ids) {
-+		/*
-+		 * If we ever get a cluster of more than 16 CPUs, just
-+		 * scream and skip that CPU.
-+		 */
-+		if (WARN_ON((mpidr & 0xff) >= 16))
-+			goto out;
++	/* Allow cmdline to override our assumed preferences */
++	if (console_set_on_cmdline)
++		return 0;
 +
-+		tlist |= 1 << (mpidr & 0xf);
++	if (IS_ENABLED(CONFIG_SBSAUART_TTY))
++		add_preferred_console("ttySBSA", 0, "115200");
 +
-+		cpu = cpumask_next(cpu, mask);
-+		if (cpu == nr_cpu_ids)
-+			goto out;
++	if (IS_ENABLED(CONFIG_SERIAL_AMBA_PL011))
++		add_preferred_console("ttyAMA", 0, "115200");
 +
-+		mpidr = cpu_logical_map(cpu);
++	if (IS_ENABLED(CONFIG_SERIAL_8250))
++		add_preferred_console("ttyS", 0, "115200");
 +
-+		if (cluster_id != (mpidr & ~0xffUL)) {
-+			cpu--;
-+			goto out;
-+		}
-+	}
-+out:
-+	*base_cpu = cpu;
-+	return tlist;
++	return 0;
 +}
++early_initcall(arm64_console_setup);
+diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
+index b06d1d9..2988829 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>
 +
-+static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
-+{
-+	u64 val;
++#include <asm/cacheflush.h>
++#include <asm/cpu_ops.h>
++#include <asm/cputype.h>
++#include <asm/smp_plat.h>
 +
-+	val = (MPIDR_AFFINITY_LEVEL(cluster_id, 3) << 48	|
-+	       MPIDR_AFFINITY_LEVEL(cluster_id, 2) << 32	|
-+	       irq << 24			    		|
-+	       MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16	|
-+	       tlist);
++static phys_addr_t cpu_mailbox_addr[NR_CPUS];
 +
-+	pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val);
-+	gic_write_sgi1r(val);
-+}
++static void (*__smp_boot_wakeup)(int cpu);
 +
-+static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
++void set_smp_boot_wakeup_call(void (*fn)(int cpu))
 +{
-+	int cpu;
-+
-+	if (WARN_ON(irq >= 16))
-+		return;
++	__smp_boot_wakeup = fn;
++}
 +
++static int smp_parking_protocol_cpu_init(struct device_node *dn,
++					 unsigned int cpu)
++{
 +	/*
-+	 * Ensure that stores to Normal memory are visible to the
-+	 * other CPUs before issuing the IPI.
++	 * Determine the mailbox address.
 +	 */
-+	smp_wmb();
-+
-+	for_each_cpu_mask(cpu, *mask) {
-+		u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL;
-+		u16 tlist;
-+
-+		tlist = gic_compute_target_list(&cpu, mask, cluster_id);
-+		gic_send_sgi(cluster_id, tlist, irq);
++	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;
 +	}
 +
-+	/* Force the above writes to ICC_SGI1R_EL1 to be executed */
-+	isb();
-+}
++	pr_err("CPU %d: missing or invalid parking protocol mailbox\n", cpu);
 +
-+static void gic_smp_init(void)
-+{
-+	set_smp_cross_call(gic_raise_softirq);
-+	register_cpu_notifier(&gic_cpu_notifier);
++	return -1;
 +}
 +
-+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
-+			    bool force)
++static int smp_parking_protocol_cpu_prepare(unsigned int cpu)
 +{
-+	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
-+	void __iomem *reg;
-+	int enabled;
-+	u64 val;
++	return 0;
++}
 +
-+	if (gic_irq_in_rdist(d))
-+		return -EINVAL;
++struct parking_protocol_mailbox {
++	__le32 cpu_id;
++	__le32 reserved;
++	__le64 entry_point;
++};
 +
-+	/* If interrupt was enabled, disable it first */
-+	enabled = gic_peek_irq(d, GICD_ISENABLER);
-+	if (enabled)
-+		gic_mask_irq(d);
++static int smp_parking_protocol_cpu_boot(unsigned int cpu)
++{
++	struct parking_protocol_mailbox __iomem *mailbox;
 +
-+	reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
-+	val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
++	if (!cpu_mailbox_addr[cpu] || !__smp_boot_wakeup)
++		return -ENODEV;
 +
-+	writeq_relaxed(val, reg);
++	/*
++	 * 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;
 +
 +	/*
-+	 * If the interrupt was enabled, enabled it again. Otherwise,
-+	 * just wait for the distributor to have digested our changes.
++	 * 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.
 +	 */
-+	if (enabled)
-+		gic_unmask_irq(d);
-+	else
-+		gic_dist_wait_for_rwp();
++	writeq(__pa(secondary_entry), &mailbox->entry_point);
++	writel(cpu, &mailbox->cpu_id);
++	__flush_dcache_area(mailbox, sizeof(*mailbox));
++	__smp_boot_wakeup(cpu);
 +
-+	return IRQ_SET_MASK_OK;
-+}
-+#else
-+#define gic_set_affinity	NULL
-+#define gic_smp_init()		do { } while(0)
-+#endif
++	/* temp hack for broken firmware */
++	sev();
 +
-+static struct irq_chip gic_chip = {
-+	.name			= "GICv3",
-+	.irq_mask		= gic_mask_irq,
-+	.irq_unmask		= gic_unmask_irq,
-+	.irq_eoi		= gic_eoi_irq,
-+	.irq_set_type		= gic_set_type,
-+	.irq_set_affinity	= gic_set_affinity,
-+};
++	iounmap(mailbox);
 +
-+static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
-+			      irq_hw_number_t hw)
-+{
-+	/* SGIs are private to the core kernel */
-+	if (hw < 16)
-+		return -EPERM;
-+	/* PPIs */
-+	if (hw < 32) {
-+		irq_set_percpu_devid(irq);
-+		irq_set_chip_and_handler(irq, &gic_chip,
-+					 handle_percpu_devid_irq);
-+		set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
-+	}
-+	/* SPIs */
-+	if (hw >= 32 && hw < gic_data.irq_nr) {
-+		irq_set_chip_and_handler(irq, &gic_chip,
-+					 handle_fasteoi_irq);
-+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-+	}
-+	irq_set_chip_data(irq, d->host_data);
 +	return 0;
 +}
 +
-+static int gic_irq_domain_xlate(struct irq_domain *d,
-+				struct device_node *controller,
-+				const u32 *intspec, unsigned int intsize,
-+				unsigned long *out_hwirq, unsigned int *out_type)
-+{
-+	if (d->of_node != controller)
-+		return -EINVAL;
-+	if (intsize < 3)
-+		return -EINVAL;
-+
-+	switch(intspec[0]) {
-+	case 0:			/* SPI */
-+		*out_hwirq = intspec[1] + 32;
-+		break;
-+	case 1:			/* PPI */
-+		*out_hwirq = intspec[1] + 16;
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
-+
-+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
-+	return 0;
-+}
-+
-+static const struct irq_domain_ops gic_irq_domain_ops = {
-+	.map = gic_irq_domain_map,
-+	.xlate = gic_irq_domain_xlate,
++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/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>
+ 
+ #include <clocksource/arm_arch_timer.h>
+ 
+@@ -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/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
+index edf8715..4596f46 100644
+--- a/arch/arm64/kernel/vmlinux.lds.S
++++ b/arch/arm64/kernel/vmlinux.lds.S
+@@ -32,6 +32,22 @@ jiffies = jiffies_64;
+ 	*(.hyp.text)					\
+ 	VMLINUX_SYMBOL(__hyp_text_end) = .;
+ 
++/*
++ * The size of the PE/COFF section that covers the kernel image, which
++ * runs from stext to _edata, must be a round multiple of the PE/COFF
++ * FileAlignment, which we set to its minimum value of 0x200. 'stext'
++ * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
++ * boundary should be sufficient.
++ */
++PECOFF_FILE_ALIGNMENT = 0x200;
 +
-+static int __init gic_of_init(struct device_node *node, struct device_node *parent)
-+{
-+	void __iomem *dist_base;
-+	void __iomem **redist_base;
-+	u64 redist_stride;
-+	u32 redist_regions;
-+	u32 reg;
-+	int gic_irqs;
-+	int err;
-+	int i;
-+
-+	dist_base = of_iomap(node, 0);
-+	if (!dist_base) {
-+		pr_err("%s: unable to map gic dist registers\n",
-+			node->full_name);
-+		return -ENXIO;
-+	}
-+
-+	reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
-+	if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
-+		pr_err("%s: no distributor detected, giving up\n",
-+			node->full_name);
-+		err = -ENODEV;
-+		goto out_unmap_dist;
-+	}
-+
-+	if (of_property_read_u32(node, "#redistributor-regions", &redist_regions))
-+		redist_regions = 1;
++#ifdef CONFIG_EFI
++#define PECOFF_EDATA_PADDING	\
++	.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
++#else
++#define PECOFF_EDATA_PADDING
++#endif
 +
-+	redist_base = kzalloc(sizeof(*redist_base) * redist_regions, GFP_KERNEL);
-+	if (!redist_base) {
-+		err = -ENOMEM;
-+		goto out_unmap_dist;
-+	}
+ SECTIONS
+ {
+ 	/*
+@@ -103,6 +119,7 @@ SECTIONS
+ 	_data = .;
+ 	_sdata = .;
+ 	RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
++	PECOFF_EDATA_PADDING
+ 	_edata = .;
+ 
+ 	BSS_SECTION(0, 0, 0)
+diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
+index b72aa9f..fbe909f 100644
+--- a/arch/arm64/kvm/hyp.S
++++ b/arch/arm64/kvm/hyp.S
+@@ -761,10 +761,10 @@
+ .macro activate_traps
+ 	ldr     x2, [x0, #VCPU_HCR_EL2]
+ 	msr     hcr_el2, x2
+-	ldr	x2, =(CPTR_EL2_TTA)
++	mov	x2, #CPTR_EL2_TTA
+ 	msr	cptr_el2, x2
+ 
+-	ldr	x2, =(1 << 15)	// Trap CP15 Cr=15
++	mov	x2, #(1 << 15)	// Trap CP15 Cr=15
+ 	msr	hstr_el2, x2
+ 
+ 	mrs	x2, mdcr_el2
+diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
+index d920942..cf890e3 100644
+--- a/arch/arm64/mm/dma-mapping.c
++++ b/arch/arm64/mm/dma-mapping.c
+@@ -23,8 +23,14 @@
+ #include <linux/genalloc.h>
+ #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>
+ 
+@@ -423,10 +429,116 @@ out:
+ 	return -ENOMEM;
+ }
+ 
++#ifdef CONFIG_PCI
++static void arm64_of_set_dma_ops(void *_dev)
++{
++	struct device *dev = _dev;
 +
-+	for (i = 0; i < redist_regions; i++) {
-+		redist_base[i] = of_iomap(node, 1 + i);
-+		if (!redist_base[i]) {
-+			pr_err("%s: couldn't map region %d\n",
-+			       node->full_name, i);
-+			err = -ENODEV;
-+			goto out_unmap_rdist;
++	/*
++	 * PCI devices won't have an ACPI handle but the bridge will.
++	 * Search up the device chain until we find an of_node
++	 * to check.
++	 */
++	while (dev) {
++		if (dev->of_node) {
++			if (of_dma_is_coherent(dev->of_node))
++				set_dma_ops(_dev, &coherent_swiotlb_dma_ops);
++			break;
 +		}
++		dev = dev->parent;
 +	}
++}
++#else
++static inline arm64_of_set_dma_ops(void *_dev) {}
++#endif
 +
-+	if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
-+		redist_stride = 0;
 +
-+	gic_data.dist_base = dist_base;
-+	gic_data.redist_base = redist_base;
-+	gic_data.redist_regions = redist_regions;
-+	gic_data.redist_stride = redist_stride;
++#ifdef CONFIG_ACPI
++static void arm64_acpi_set_dma_ops(void *_dev)
++{
++	struct device *dev = _dev;
 +
 +	/*
-+	 * Find out how many interrupts are supported.
-+	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
++	 * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64
++	 * defaults to coherent. For PCI devices, the _CCA is only a default
++	 * setting. Individual devices on a PCIe bus may set transaction
++	 * ordering and caching attributes individually. Such drivers will
++	 * also be resonsible for using the correct DMA ops for the cache
++	 * conherence used.
++	 *
++	 * PCI devices won't have a handle but the bridge will.
++	 * Search up the device chain until we find an ACPI handle
++	 * to check.
 +	 */
-+	gic_irqs = readl_relaxed(gic_data.dist_base + GICD_TYPER) & 0x1f;
-+	gic_irqs = (gic_irqs + 1) * 32;
-+	if (gic_irqs > 1020)
-+		gic_irqs = 1020;
-+	gic_data.irq_nr = gic_irqs;
-+
-+	gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
-+					      &gic_data);
-+	gic_data.rdist = alloc_percpu(typeof(*gic_data.rdist));
-+
-+	if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdist)) {
-+		err = -ENOMEM;
-+		goto out_free;
++	while (dev) {
++		if (ACPI_HANDLE(dev)) {
++			acpi_status status;
++			int coherent;
++			struct dma_map_ops *ops;
++
++			status =  acpi_check_coherency(ACPI_HANDLE(dev),
++						       &coherent);
++			if (ACPI_FAILURE(status) || coherent)
++				ops = &coherent_swiotlb_dma_ops;
++			else
++				ops = &noncoherent_swiotlb_dma_ops;
++
++			set_dma_ops(_dev, ops);
++			break;
++		}
++		dev = dev->parent;
 +	}
++}
++#else
++static inline arm64_acpi_set_dma_ops(void *_dev) {}
++#endif
 +
-+	set_handle_irq(gic_handle_irq);
++static int dma_bus_notifier(struct notifier_block *nb,
++			    unsigned long event, void *_dev)
++{
++	if (event != BUS_NOTIFY_ADD_DEVICE)
++		return NOTIFY_DONE;
 +
-+	gic_smp_init();
-+	gic_dist_init();
-+	gic_cpu_init();
++	if (acpi_disabled)
++		arm64_of_set_dma_ops(_dev);
++	else
++		arm64_acpi_set_dma_ops(_dev);
 +
-+	return 0;
++	return NOTIFY_OK;
++}
 +
-+out_free:
-+	if (gic_data.domain)
-+		irq_domain_remove(gic_data.domain);
-+	free_percpu(gic_data.rdist);
-+out_unmap_rdist:
-+	for (i = 0; i < redist_regions; i++)
-+		if (redist_base[i])
-+			iounmap(redist_base[i]);
-+	kfree(redist_base);
-+out_unmap_dist:
-+	iounmap(dist_base);
-+	return err;
-+}
-+
-+IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
-diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
-index 7c131cf..1ddfdde 100644
---- a/drivers/irqchip/irq-gic.c
-+++ b/drivers/irqchip/irq-gic.c
-@@ -47,6 +47,7 @@
- #include <asm/exception.h>
- #include <asm/smp_plat.h>
- 
-+#include "irq-gic-common.h"
- #include "irqchip.h"
- 
- union gic_base {
-@@ -189,12 +190,6 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
- {
- 	void __iomem *base = gic_dist_base(d);
- 	unsigned int gicirq = gic_irq(d);
--	u32 enablemask = 1 << (gicirq % 32);
--	u32 enableoff = (gicirq / 32) * 4;
--	u32 confmask = 0x2 << ((gicirq % 16) * 2);
--	u32 confoff = (gicirq / 16) * 4;
--	bool enabled = false;
--	u32 val;
- 
- 	/* Interrupt configuration for SGIs can't be changed */
- 	if (gicirq < 16)
-@@ -208,25 +203,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
- 	if (gic_arch_extn.irq_set_type)
- 		gic_arch_extn.irq_set_type(d, type);
- 
--	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
--	if (type == IRQ_TYPE_LEVEL_HIGH)
--		val &= ~confmask;
--	else if (type == IRQ_TYPE_EDGE_RISING)
--		val |= confmask;
--
--	/*
--	 * As recommended by the spec, disable the interrupt before changing
--	 * the configuration
--	 */
--	if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
--		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
--		enabled = true;
--	}
--
--	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
--
--	if (enabled)
--		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
-+	gic_configure_irq(gicirq, type, base, NULL);
- 
- 	raw_spin_unlock(&irq_controller_lock);
- 
-@@ -388,12 +365,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
- 	writel_relaxed(0, base + GIC_DIST_CTRL);
- 
- 	/*
--	 * Set all global interrupts to be level triggered, active low.
--	 */
--	for (i = 32; i < gic_irqs; i += 16)
--		writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
--
--	/*
- 	 * Set all global interrupts to this CPU only.
- 	 */
- 	cpumask = gic_get_cpumask(gic);
-@@ -402,18 +373,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
- 	for (i = 32; i < gic_irqs; i += 4)
- 		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
- 
--	/*
--	 * Set priority on all global interrupts.
--	 */
--	for (i = 32; i < gic_irqs; i += 4)
--		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
--
--	/*
--	 * Disable all interrupts.  Leave the PPI and SGIs alone
--	 * as these enables are banked registers.
--	 */
--	for (i = 32; i < gic_irqs; i += 32)
--		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
-+	gic_dist_config(base, gic_irqs, NULL);
- 
- 	writel_relaxed(1, base + GIC_DIST_CTRL);
- }
-@@ -423,6 +383,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;
- 
- 	/*
-@@ -440,27 +401,32 @@ static void gic_cpu_init(struct gic_chip_data *gic)
- 		if (i != cpu)
- 			gic_cpu_map[i] &= ~cpu_mask;
- 
--	/*
--	 * Deal with the banked PPI and SGI interrupts - disable all
--	 * PPI interrupts, ensure all SGI interrupts are enabled.
--	 */
--	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
--	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
--
--	/*
--	 * Set priority on PPI and SGI interrupts
--	 */
--	for (i = 0; i < 32; i += 4)
--		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
-+	gic_cpu_config(dist_base, NULL);
- 
- 	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
--	writel_relaxed(1, base + GIC_CPU_CTRL);
++#ifdef CONFIG_ACPI
++static struct notifier_block platform_bus_nb = {
++	.notifier_call = dma_bus_notifier,
++};
 +
-+	ctrl_mask = readl(base + GIC_CPU_CTRL);
++static struct notifier_block amba_bus_nb = {
++	.notifier_call = dma_bus_notifier,
++};
++#endif
 +
-+	/* Mask out the gic v2 bypass bits */
-+	ctrl_mask &= 0x1e0;
++#ifdef CONFIG_PCI
++static struct notifier_block pci_bus_nb = {
++	.notifier_call = dma_bus_notifier,
++};
++#endif
 +
-+	/* Enable group 0 */
-+	ctrl_mask |= 0x1;
-+	writel_relaxed(ctrl_mask, base + GIC_CPU_CTRL);
- }
- 
- void gic_cpu_if_down(void)
+ static int __init swiotlb_late_init(void)
  {
-+	unsigned int ctrl_mask;
- 	void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]);
--	writel_relaxed(0, cpu_base + GIC_CPU_CTRL);
-+
-+	ctrl_mask = readl(cpu_base + GIC_CPU_CTRL);
+ 	size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
+ 
 +	/*
-+	 * Disable grp enable bit, leave the bypass bits alone as changing
-+	 * them could leave the system unstable
++	 * These must be registered before of_platform_populate().
 +	 */
-+	ctrl_mask &= 0x1e0;
-+	writel_relaxed(ctrl_mask, cpu_base + GIC_CPU_CTRL);
- }
- 
- #ifdef CONFIG_CPU_PM
-@@ -571,6 +537,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;
- 
-@@ -595,7 +562,15 @@ static void gic_cpu_restore(unsigned int gic_nr)
- 		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
- 
- 	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
--	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
-+
-+	ctrl_mask = readl(cpu_base + GIC_CPU_CTRL);
++#ifdef CONFIG_ACPI
++	bus_register_notifier(&platform_bus_type, &platform_bus_nb);
++	bus_register_notifier(&amba_bustype, &amba_bus_nb);
++#endif
 +
-+	/* Mask out the gic v2 bypass bits */
-+	ctrl_mask &= 0x1e0;
++#ifdef CONFIG_PCI
++	bus_register_notifier(&pci_bus_type, &pci_bus_nb);
++#endif
 +
-+	/* Enable group 0 */
-+	ctrl_mask |= 0x1;
-+	writel_relaxed(ctrl_mask, cpu_base + GIC_CPU_CTRL);
- }
+ 	dma_ops = &noncoherent_swiotlb_dma_ops;
  
- static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
-diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
-index edb7186..dc7406c 100644
---- a/drivers/net/ethernet/Kconfig
-+++ b/drivers/net/ethernet/Kconfig
-@@ -24,6 +24,7 @@ source "drivers/net/ethernet/allwinner/Kconfig"
- source "drivers/net/ethernet/alteon/Kconfig"
- source "drivers/net/ethernet/altera/Kconfig"
- source "drivers/net/ethernet/amd/Kconfig"
-+source "drivers/net/ethernet/apm/Kconfig"
- source "drivers/net/ethernet/apple/Kconfig"
- source "drivers/net/ethernet/arc/Kconfig"
- source "drivers/net/ethernet/atheros/Kconfig"
-diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
-index 58de333..224a018 100644
---- a/drivers/net/ethernet/Makefile
-+++ b/drivers/net/ethernet/Makefile
-@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
- obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
- obj-$(CONFIG_ALTERA_TSE) += altera/
- obj-$(CONFIG_NET_VENDOR_AMD) += amd/
-+obj-$(CONFIG_NET_XGENE) += apm/
- obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
- obj-$(CONFIG_NET_VENDOR_ARC) += arc/
- obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
-diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
-new file mode 100644
-index 0000000..ec63d70
---- /dev/null
-+++ b/drivers/net/ethernet/apm/Kconfig
-@@ -0,0 +1 @@
-+source "drivers/net/ethernet/apm/xgene/Kconfig"
-diff --git a/drivers/net/ethernet/apm/Makefile b/drivers/net/ethernet/apm/Makefile
-new file mode 100644
-index 0000000..65ce32a
---- /dev/null
-+++ b/drivers/net/ethernet/apm/Makefile
-@@ -0,0 +1,5 @@
-+#
-+# Makefile for APM X-GENE Ethernet driver.
-+#
-+
-+obj-$(CONFIG_NET_XGENE) += xgene/
-diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig
-new file mode 100644
-index 0000000..616dff6
---- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/Kconfig
-@@ -0,0 +1,9 @@
-+config NET_XGENE
-+	tristate "APM X-Gene SoC Ethernet Driver"
-+	select PHYLIB
-+	help
-+	  This is the Ethernet driver for the on-chip ethernet interface on the
-+	  APM X-Gene SoC.
-+
-+	  To compile this driver as a module, choose M here. This module will
-+	  be called xgene_enet.
-diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
+ 	return swiotlb_late_init_with_default_size(swiotlb_size);
+diff --git a/arch/arm64/pci/Makefile b/arch/arm64/pci/Makefile
 new file mode 100644
-index 0000000..c643e8a
+index 0000000..7038b51
 --- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/Makefile
-@@ -0,0 +1,6 @@
-+#
-+# Makefile for APM X-Gene Ethernet Driver.
-+#
-+
-+xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o
-+obj-$(CONFIG_NET_XGENE) += xgene-enet.o
-diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
++++ b/arch/arm64/pci/Makefile
+@@ -0,0 +1,2 @@
++obj-y                 += pci.o
++obj-$(CONFIG_ACPI)    += mmconfig.o
+diff --git a/arch/arm64/pci/mmconfig.c b/arch/arm64/pci/mmconfig.c
 new file mode 100644
-index 0000000..63f2aa5
+index 0000000..e83e0d5
 --- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
-@@ -0,0 +1,125 @@
-+/* Applied Micro X-Gene SoC Ethernet Driver
-+ *
-+ * Copyright (c) 2014, Applied Micro Circuits Corporation
-+ * Authors: Iyappan Subramanian <isubramanian 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.
++++ b/arch/arm64/pci/mmconfig.c
+@@ -0,0 +1,292 @@
++/*
++ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ * Borrowed heavily from x86
 + */
 +
-+#include <linux/ethtool.h>
-+#include "xgene_enet_main.h"
-+
-+struct xgene_gstrings_stats {
-+	char name[ETH_GSTRING_LEN];
-+	int offset;
-+};
-+
-+#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
-+
-+static const struct xgene_gstrings_stats gstrings_stats[] = {
-+	XGENE_STAT(rx_packets),
-+	XGENE_STAT(tx_packets),
-+	XGENE_STAT(rx_bytes),
-+	XGENE_STAT(tx_bytes),
-+	XGENE_STAT(rx_errors),
-+	XGENE_STAT(tx_errors),
-+	XGENE_STAT(rx_length_errors),
-+	XGENE_STAT(rx_crc_errors),
-+	XGENE_STAT(rx_frame_errors),
-+	XGENE_STAT(rx_fifo_errors)
-+};
++#include <linux/pci.h>
++#include <linux/acpi.h>
++#include <linux/init.h>
++#include <linux/bitmap.h>
++#include <linux/dmi.h>
++#include <linux/slab.h>
++#include <linux/mutex.h>
++#include <linux/rculist.h>
++#include <linux/rcupdate.h>
 +
-+#define XGENE_STATS_LEN		ARRAY_SIZE(gstrings_stats)
++#define PREFIX "PCI: "
 +
-+static void xgene_get_drvinfo(struct net_device *ndev,
-+			      struct ethtool_drvinfo *info)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct platform_device *pdev = pdata->pdev;
++/* Indicate if the mmcfg resources have been placed into the resource table. */
++static bool pci_mmcfg_running_state;
++static bool pci_mmcfg_arch_init_failed;
++static DEFINE_MUTEX(pci_mmcfg_lock);
 +
-+	strcpy(info->driver, "xgene_enet");
-+	strcpy(info->version, XGENE_DRV_VERSION);
-+	snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
-+	sprintf(info->bus_info, "%s", pdev->name);
-+}
++LIST_HEAD(pci_mmcfg_list);
 +
-+static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
++struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct phy_device *phydev = pdata->phy_dev;
++	struct pci_mmcfg_region *cfg;
 +
-+	if (phydev == NULL)
-+		return -ENODEV;
++	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
++		if (cfg->segment == segment &&
++		    cfg->start_bus <= bus && bus <= cfg->end_bus)
++			return cfg;
 +
-+	return phy_ethtool_gset(phydev, cmd);
++	return NULL;
 +}
 +
-+static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
++static void __iomem *mcfg_ioremap(struct pci_mmcfg_region *cfg)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct phy_device *phydev = pdata->phy_dev;
-+
-+	if (phydev == NULL)
-+		return -ENODEV;
++	void __iomem *addr;
++	u64 start, size;
++	int num_buses;
 +
-+	return phy_ethtool_sset(phydev, cmd);
++	start = cfg->address + PCI_MMCFG_BUS_OFFSET(cfg->start_bus);
++	num_buses = cfg->end_bus - cfg->start_bus + 1;
++	size = PCI_MMCFG_BUS_OFFSET(num_buses);
++	addr = ioremap_nocache(start, size);
++	if (addr)
++		addr -= PCI_MMCFG_BUS_OFFSET(cfg->start_bus);
++	return addr;
 +}
 +
-+static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
++void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
 +{
-+	int i;
-+	u8 *p = data;
-+
-+	if (stringset != ETH_SS_STATS)
-+		return;
-+
-+	for (i = 0; i < XGENE_STATS_LEN; i++) {
-+		memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
-+		p += ETH_GSTRING_LEN;
++	if (cfg && cfg->virt) {
++		iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
++		cfg->virt = NULL;
 +	}
 +}
 +
-+static int xgene_get_sset_count(struct net_device *ndev, int sset)
++void __init pci_mmcfg_arch_free(void)
 +{
-+	if (sset != ETH_SS_STATS)
-+		return -EINVAL;
++	struct pci_mmcfg_region *cfg;
 +
-+	return XGENE_STATS_LEN;
++	list_for_each_entry(cfg, &pci_mmcfg_list, list)
++		pci_mmcfg_arch_unmap(cfg);
 +}
 +
-+static void xgene_get_ethtool_stats(struct net_device *ndev,
-+				    struct ethtool_stats *dummy,
-+				    u64 *data)
++int pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
 +{
-+	void *pdata = netdev_priv(ndev);
-+	int i;
++	cfg->virt = mcfg_ioremap(cfg);
++	if (!cfg->virt) {
++		pr_err(PREFIX "can't map MMCONFIG at %pR\n", &cfg->res);
++		return -ENOMEM;
++	}
 +
-+	for (i = 0; i < XGENE_STATS_LEN; i++)
-+		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
++	return 0;
 +}
 +
-+static const struct ethtool_ops xgene_ethtool_ops = {
-+	.get_drvinfo = xgene_get_drvinfo,
-+	.get_settings = xgene_get_settings,
-+	.set_settings = xgene_set_settings,
-+	.get_link = ethtool_op_get_link,
-+	.get_strings = xgene_get_strings,
-+	.get_sset_count = xgene_get_sset_count,
-+	.get_ethtool_stats = xgene_get_ethtool_stats
-+};
-+
-+void xgene_enet_set_ethtool_ops(struct net_device *ndev)
++static void __init pci_mmconfig_remove(struct pci_mmcfg_region *cfg)
 +{
-+	ndev->ethtool_ops = &xgene_ethtool_ops;
++	if (cfg->res.parent)
++		release_resource(&cfg->res);
++	list_del(&cfg->list);
++	kfree(cfg);
 +}
-diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
-new file mode 100644
-index 0000000..e52af60
---- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
-@@ -0,0 +1,747 @@
-+/* Applied Micro X-Gene SoC Ethernet Driver
-+ *
-+ * Copyright (c) 2014, Applied Micro Circuits Corporation
-+ * Authors: Iyappan Subramanian <isubramanian at apm.com>
-+ *	    Ravi Patel <rapatel at apm.com>
-+ *	    Keyur Chudgar <kchudgar 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.
-+ *
-+ * 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 "xgene_enet_main.h"
-+#include "xgene_enet_hw.h"
-+
-+static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring)
++static void __init free_all_mmcfg(void)
 +{
-+	u32 *ring_cfg = ring->state;
-+	u64 addr = ring->dma;
-+	enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize;
-+
-+	ring_cfg[4] |= (1 << SELTHRSH_POS) &
-+			CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN);
-+	ring_cfg[3] |= ACCEPTLERR;
-+	ring_cfg[2] |= QCOHERENT;
++	struct pci_mmcfg_region *cfg, *tmp;
 +
-+	addr >>= 8;
-+	ring_cfg[2] |= (addr << RINGADDRL_POS) &
-+			CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN);
-+	addr >>= RINGADDRL_LEN;
-+	ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN);
-+	ring_cfg[3] |= ((u32) cfgsize << RINGSIZE_POS) &
-+			CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN);
++	pci_mmcfg_arch_free();
++	list_for_each_entry_safe(cfg, tmp, &pci_mmcfg_list, list)
++		pci_mmconfig_remove(cfg);
 +}
 +
-+static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring)
++static void list_add_sorted(struct pci_mmcfg_region *new)
 +{
-+	u32 *ring_cfg = ring->state;
-+	bool is_bufpool;
-+	u32 val;
++	struct pci_mmcfg_region *cfg;
 +
-+	is_bufpool = xgene_enet_is_bufpool(ring->id);
-+	val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR;
-+	ring_cfg[4] |= (val << RINGTYPE_POS) &
-+			CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN);
-+
-+	if (is_bufpool) {
-+		ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) &
-+				CREATE_MASK(RINGMODE_POS, RINGMODE_LEN);
++	/* keep list sorted by segment and starting bus number */
++	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
++		if (cfg->segment > new->segment ||
++		    (cfg->segment == new->segment &&
++		     cfg->start_bus >= new->start_bus)) {
++			list_add_tail_rcu(&new->list, &cfg->list);
++			return;
++		}
 +	}
++	list_add_tail_rcu(&new->list, &pci_mmcfg_list);
 +}
 +
-+static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring)
-+{
-+	u32 *ring_cfg = ring->state;
-+
-+	ring_cfg[3] |= RECOMBBUF;
-+	ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) &
-+			CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN);
-+	ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN);
-+}
-+
-+static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring,
-+				 u32 offset, u32 data)
++static struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
++						   int end, u64 addr)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
++	struct pci_mmcfg_region *new;
++	struct resource *res;
 +
-+	iowrite32(data, pdata->ring_csr_addr + offset);
-+}
++	if (addr == 0)
++		return NULL;
 +
-+static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
-+				 u32 offset, u32 *data)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
++	new = kzalloc(sizeof(*new), GFP_KERNEL);
++	if (!new)
++		return NULL;
 +
-+	*data = ioread32(pdata->ring_csr_addr + offset);
-+}
++	new->address = addr;
++	new->segment = segment;
++	new->start_bus = start;
++	new->end_bus = end;
 +
-+static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
-+{
-+	int i;
++	res = &new->res;
++	res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
++	res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
++	res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++	snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
++		 "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
++	res->name = new->name;
 +
-+	xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
-+	for (i = 0; i < NUM_RING_CONFIG; i++) {
-+		xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
-+				     ring->state[i]);
-+	}
++	return new;
 +}
 +
-+static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
++static struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start,
++							int end, u64 addr)
 +{
-+	memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG);
-+	xgene_enet_write_ring_state(ring);
-+}
++	struct pci_mmcfg_region *new;
 +
-+static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
-+{
-+	xgene_enet_ring_set_type(ring);
++	new = pci_mmconfig_alloc(segment, start, end, addr);
++	if (new) {
++		mutex_lock(&pci_mmcfg_lock);
++		list_add_sorted(new);
++		mutex_unlock(&pci_mmcfg_lock);
 +
-+	if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0)
-+		xgene_enet_ring_set_recombbuf(ring);
++		pr_info(PREFIX
++		       "MMCONFIG for domain %04x [bus %02x-%02x] at %pR "
++		       "(base %#lx)\n",
++		       segment, start, end, &new->res, (unsigned long)addr);
++	}
 +
-+	xgene_enet_ring_init(ring);
-+	xgene_enet_write_ring_state(ring);
++	return new;
 +}
 +
-+static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
-+{
-+	u32 ring_id_val, ring_id_buf;
-+	bool is_bufpool;
-+
-+	is_bufpool = xgene_enet_is_bufpool(ring->id);
-+
-+	ring_id_val = ring->id & GENMASK(9, 0);
-+	ring_id_val |= OVERWRITE;
-+
-+	ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
-+	ring_id_buf |= PREFETCH_BUF_EN;
-+	if (is_bufpool)
-+		ring_id_buf |= IS_BUFFER_POOL;
-+
-+	xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val);
-+	xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf);
-+}
++extern struct acpi_mcfg_fixup __start_acpi_mcfg_fixups[];
++extern struct acpi_mcfg_fixup __end_acpi_mcfg_fixups[];
 +
-+static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
++static int __init pci_parse_mcfg(struct acpi_table_header *header)
 +{
-+	u32 ring_id;
++	struct acpi_table_mcfg *mcfg;
++	struct acpi_mcfg_allocation *cfg_table, *cfg;
++	struct acpi_mcfg_fixup *fixup;
++	struct pci_mmcfg_region *new;
++	unsigned long i;
++	int entries;
 +
-+	ring_id = ring->id | OVERWRITE;
-+	xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id);
-+	xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
-+}
++	if (!header)
++		return -EINVAL;
 +
-+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
-+					struct xgene_enet_desc_ring *ring)
-+{
-+	u32 size = ring->size;
-+	u32 i, data;
-+	u64 *desc;
-+	bool is_bufpool;
++	mcfg = (struct acpi_table_mcfg *)header;
 +
-+	xgene_enet_clr_ring_state(ring);
-+	xgene_enet_set_ring_state(ring);
-+	xgene_enet_set_ring_id(ring);
++	/* how many config structures do we have */
++	free_all_mmcfg();
++	entries = 0;
++	i = header->length - sizeof(struct acpi_table_mcfg);
++	while (i >= sizeof(struct acpi_mcfg_allocation)) {
++		entries++;
++		i -= sizeof(struct acpi_mcfg_allocation);
++	}
++	if (entries == 0) {
++		pr_err(PREFIX "MMCONFIG has no entries\n");
++		return -ENODEV;
++	}
 +
-+	ring->slots = xgene_enet_get_numslots(ring->id, size);
++	fixup = __start_acpi_mcfg_fixups;
++	while (fixup < __end_acpi_mcfg_fixups) {
++		if (!strncmp(fixup->oem_id, header->oem_id, 6) &&
++		    !strncmp(fixup->oem_table_id, header->oem_table_id, 8))
++			break;
++		++fixup;
++	}
 +
-+	is_bufpool = xgene_enet_is_bufpool(ring->id);
-+	if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
-+		return ring;
++	cfg_table = (struct acpi_mcfg_allocation *) &mcfg[1];
++	for (i = 0; i < entries; i++) {
++		cfg = &cfg_table[i];
 +
-+	for (i = 0; i < ring->slots; i++) {
-+		desc = (u64 *)&ring->raw_desc[i];
-+		desc[EMPTY_SLOT_INDEX] = EMPTY_SLOT;
++		new = pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
++				       cfg->end_bus_number, cfg->address);
++		if (!new) {
++			pr_warn(PREFIX "no memory for MCFG entries\n");
++			free_all_mmcfg();
++			return -ENOMEM;
++		}
++		if (fixup < __end_acpi_mcfg_fixups)
++			new->fixup = fixup->hook;
 +	}
 +
-+	xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
-+	data |= BIT(31 - xgene_enet_ring_bufnum(ring->id));
-+	xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
-+
-+	return ring;
++	return 0;
 +}
 +
-+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
++int __init pci_mmcfg_arch_init(void)
 +{
-+	u32 data;
-+	bool is_bufpool;
-+
-+	is_bufpool = xgene_enet_is_bufpool(ring->id);
-+	if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
-+		goto out;
++	struct pci_mmcfg_region *cfg;
 +
-+	xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
-+	data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id));
-+	xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
++	list_for_each_entry(cfg, &pci_mmcfg_list, list)
++		if (pci_mmcfg_arch_map(cfg)) {
++			pci_mmcfg_arch_free();
++			return 0;
++		}
 +
-+out:
-+	xgene_enet_clr_desc_ring_id(ring);
-+	xgene_enet_clr_ring_state(ring);
++	return 1;
 +}
 +
-+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
-+			    struct xgene_enet_pdata *pdata,
-+			    enum xgene_enet_err_code status)
++static void __init __pci_mmcfg_init(int early)
 +{
-+	struct rtnl_link_stats64 *stats = &pdata->stats;
++	if (list_empty(&pci_mmcfg_list)) {
++		pr_info("No MCFG table found!\n");
++		pci_mmcfg_arch_init_failed = true;
++		return;
++	}
 +
-+	switch (status) {
-+	case INGRESS_CRC:
-+		stats->rx_crc_errors++;
-+		break;
-+	case INGRESS_CHECKSUM:
-+	case INGRESS_CHECKSUM_COMPUTE:
-+		stats->rx_errors++;
-+		break;
-+	case INGRESS_TRUNC_FRAME:
-+		stats->rx_frame_errors++;
-+		break;
-+	case INGRESS_PKT_LEN:
-+		stats->rx_length_errors++;
-+		break;
-+	case INGRESS_PKT_UNDER:
-+		stats->rx_frame_errors++;
-+		break;
-+	case INGRESS_FIFO_OVERRUN:
-+		stats->rx_fifo_errors++;
-+		break;
-+	default:
-+		break;
++	if (!pci_mmcfg_arch_init()) {
++		pr_info("pci_mmcfg_arch_init failed!\n");
++		free_all_mmcfg();
++		pci_mmcfg_arch_init_failed = true;
 +	}
 +}
 +
-+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
-+			      u32 offset, u32 val)
++void __init pci_mmcfg_early_init(void)
 +{
-+	void __iomem *addr = pdata->eth_csr_addr + offset;
++	acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
 +
-+	iowrite32(val, addr);
++	__pci_mmcfg_init(1);
 +}
 +
-+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
-+				  u32 offset, u32 val)
++static int __init pci_mmcfg_init(void)
 +{
-+	void __iomem *addr = pdata->eth_ring_if_addr + offset;
-+
-+	iowrite32(val, addr);
++	pci_mmcfg_early_init();
++	return 0;
 +}
++arch_initcall(pci_mmcfg_init);
 +
-+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
-+				   u32 offset, u32 val)
++void __init pci_mmcfg_late_init(void)
 +{
-+	void __iomem *addr = pdata->eth_diag_csr_addr + offset;
-+
-+	iowrite32(val, addr);
++	/* MMCONFIG hasn't been enabled yet, try again */
++	if (pci_mmcfg_arch_init_failed) {
++		acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
++		__pci_mmcfg_init(0);
++	}
 +}
 +
-+static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
-+				  u32 offset, u32 val)
++static int __init pci_mmcfg_late_insert_resources(void)
 +{
-+	void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
-+
-+	iowrite32(val, addr);
-+}
++	struct pci_mmcfg_region *cfg;
 +
-+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
-+				   void __iomem *cmd, void __iomem *cmd_done,
-+				   u32 wr_addr, u32 wr_data)
-+{
-+	u32 done;
-+	u8 wait = 10;
++	pci_mmcfg_running_state = true;
 +
-+	iowrite32(wr_addr, addr);
-+	iowrite32(wr_data, wr);
-+	iowrite32(XGENE_ENET_WR_CMD, cmd);
-+
-+	/* wait for write command to complete */
-+	while (!(done = ioread32(cmd_done)) && wait--)
-+		udelay(1);
-+
-+	if (!done)
-+		return false;
-+
-+	iowrite32(0, cmd);
-+
-+	return true;
-+}
-+
-+static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
-+				  u32 wr_addr, u32 wr_data)
-+{
-+	void __iomem *addr, *wr, *cmd, *cmd_done;
-+	bool ret;
-+
-+	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
-+	wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
-+	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
-+	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
++	/*
++	 * Attempt to insert the mmcfg resources but not with the busy flag
++	 * marked so it won't cause request errors when __request_region is
++	 * called.
++	 */
++	list_for_each_entry(cfg, &pci_mmcfg_list, list)
++		if (!cfg->res.parent)
++			insert_resource(&iomem_resource, &cfg->res);
 +
-+	ret = xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data);
-+	if (!ret)
-+		netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
-+			   wr_addr);
++	return 0;
 +}
 +
-+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
-+			      u32 offset, u32 *val)
-+{
-+	void __iomem *addr = pdata->eth_csr_addr + offset;
++/*
++ * Perform MMCONFIG resource insertion after PCI initialization to allow for
++ * misprogrammed MCFG tables that state larger sizes but actually conflict
++ * with other system resources.
++ */
++late_initcall(pci_mmcfg_late_insert_resources);
+diff --git a/arch/arm64/pci/pci.c b/arch/arm64/pci/pci.c
+new file mode 100644
+index 0000000..0166475
+--- /dev/null
++++ b/arch/arm64/pci/pci.c
+@@ -0,0 +1,461 @@
++#include <linux/acpi.h>
++#include <linux/of_address.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
 +
-+	*val = ioread32(addr);
-+}
++struct pci_root_info {
++	struct acpi_device *bridge;
++	char name[16];
++	unsigned int res_num;
++	struct resource *res;
++	resource_size_t *res_offset;
++	struct pci_sysdata sd;
++	u16 segment;
++	u8 start_bus;
++	u8 end_bus;
++};
 +
-+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
-+				   u32 offset, u32 *val)
++static char __iomem *pci_dev_base(struct pci_mmcfg_region *cfg,
++				  unsigned int bus, unsigned int devfn)
 +{
-+	void __iomem *addr = pdata->eth_diag_csr_addr + offset;
-+
-+	*val = ioread32(addr);
++	return cfg->virt + (PCI_MMCFG_BUS_OFFSET(bus) | (devfn << 12));
 +}
 +
-+static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
-+				  u32 offset, u32 *val)
++static int __raw_pci_read(struct pci_mmcfg_region *cfg, unsigned int bus,
++			  unsigned int devfn, int reg, int len, u32 *value)
 +{
-+	void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
++	char __iomem *addr = pci_dev_base(cfg, bus, devfn) + (reg & ~3);
++	int shift = (reg & 3) * 8;
++	u32 v;
 +
-+	*val = ioread32(addr);
++	v = readl(addr) >> shift;
++	switch (len) {
++	case 1:
++		*value = v & 0xff;
++		break;
++	case 2:
++		*value = v & 0xffff;
++		break;
++	case 4:
++		*value = v;
++		break;
++	}
++	return 0;
 +}
 +
-+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
-+				   void __iomem *cmd, void __iomem *cmd_done,
-+				   u32 rd_addr, u32 *rd_data)
++static int __raw_pci_write(struct pci_mmcfg_region *cfg, unsigned int bus,
++			   unsigned int devfn, int reg, int len, u32 value)
 +{
-+	u32 done;
-+	u8 wait = 10;
++	char __iomem *addr = pci_dev_base(cfg, bus, devfn) + (reg & ~3);
++	int mask = 0, shift = (reg & 3) * 8;
++	u32 v;
 +
-+	iowrite32(rd_addr, addr);
-+	iowrite32(XGENE_ENET_RD_CMD, cmd);
-+
-+	/* wait for read command to complete */
-+	while (!(done = ioread32(cmd_done)) && wait--)
-+		udelay(1);
-+
-+	if (!done)
-+		return false;
++	switch (len) {
++	case 1:
++		mask = 0xff << shift;
++		break;
++	case 2:
++		mask = 0xffff << shift;
++		break;
++	}
 +
-+	*rd_data = ioread32(rd);
-+	iowrite32(0, cmd);
++	if (mask) {
++		v = readl(addr) & ~mask;
++		writel(v | (value << shift), addr);
++	} else
++		writel(value, addr);
 +
-+	return true;
++	return 0;
 +}
 +
-+static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
-+				  u32 rd_addr, u32 *rd_data)
++/*
++ * raw_pci_read/write - Platform-specific PCI config space access.
++ */
++int raw_pci_read(unsigned int domain, unsigned int bus,
++		 unsigned int devfn, int reg, int len, u32 *val)
 +{
-+	void __iomem *addr, *rd, *cmd, *cmd_done;
-+	bool ret;
-+
-+	addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
-+	rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
-+	cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
-+	cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
-+
-+	ret = xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data);
-+	if (!ret)
-+		netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
-+			   rd_addr);
-+}
++	struct pci_mmcfg_region *cfg;
++	int ret;
 +
-+static int xgene_mii_phy_write(struct xgene_enet_pdata *pdata, int phy_id,
-+			       u32 reg, u16 data)
-+{
-+	u32 addr = 0, wr_data = 0;
-+	u32 done;
-+	u8 wait = 10;
++	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
++err:		*val = -1;
++		return -EINVAL;
++	}
 +
-+	PHY_ADDR_SET(&addr, phy_id);
-+	REG_ADDR_SET(&addr, reg);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
++	rcu_read_lock();
++	cfg = pci_mmconfig_lookup(domain, bus);
++	if (!cfg || !cfg->virt) {
++		rcu_read_unlock();
++		goto err;
++	}
 +
-+	PHY_CONTROL_SET(&wr_data, data);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, wr_data);
-+	do {
-+		usleep_range(5, 10);
-+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
-+	} while ((done & BUSY_MASK) && wait--);
++	if (cfg->read)
++		ret = (*cfg->read)(cfg, bus, devfn, reg, len, val);
++	else
++		ret = __raw_pci_read(cfg, bus, devfn, reg, len, val);
 +
-+	if (done & BUSY_MASK) {
-+		netdev_err(pdata->ndev, "MII_MGMT write failed\n");
-+		return -1;
-+	}
++	rcu_read_unlock();
 +
-+	return 0;
++	return ret;
 +}
 +
-+static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata,
-+			      u8 phy_id, u32 reg)
++int raw_pci_write(unsigned int domain, unsigned int bus,
++		  unsigned int devfn, int reg, int len, u32 val)
 +{
-+	u32 addr = 0;
-+	u32 data, done;
-+	u8 wait = 10;
++	struct pci_mmcfg_region *cfg;
++	int ret;
 +
-+	PHY_ADDR_SET(&addr, phy_id);
-+	REG_ADDR_SET(&addr, reg);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
-+	do {
-+		usleep_range(5, 10);
-+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
-+	} while ((done & BUSY_MASK) && wait--);
++	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
++		return -EINVAL;
 +
-+	if (done & BUSY_MASK) {
-+		netdev_err(pdata->ndev, "MII_MGMT read failed\n");
-+		return -1;
++	rcu_read_lock();
++	cfg = pci_mmconfig_lookup(domain, bus);
++	if (!cfg || !cfg->virt) {
++		rcu_read_unlock();
++		return -EINVAL;
 +	}
 +
-+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
-+
-+	return data;
-+}
-+
-+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
-+{
-+	u32 addr0, addr1;
-+	u8 *dev_addr = pdata->ndev->dev_addr;
++	if (cfg->write)
++		ret = (*cfg->write)(cfg, bus, devfn, reg, len, val);
++	else
++		ret = __raw_pci_write(cfg, bus, devfn, reg, len, val);
 +
-+	addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
-+		(dev_addr[1] << 8) | dev_addr[0];
-+	addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
-+	addr1 |= pdata->phy_addr & 0xFFFF;
++	rcu_read_unlock();
 +
-+	xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
-+	xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
++	return ret;
 +}
 +
-+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
++#ifdef CONFIG_ACPI
++static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
++		    int size, u32 *value)
 +{
-+	struct net_device *ndev = pdata->ndev;
-+	u32 data;
-+	u8 wait = 10;
-+
-+	xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
-+	do {
-+		usleep_range(100, 110);
-+		xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
-+	} while ((data != 0xffffffff) && wait--);
-+
-+	if (data != 0xffffffff) {
-+		netdev_err(ndev, "Failed to release memory from shutdown\n");
-+		return -ENODEV;
-+	}
-+
-+	return 0;
++	return raw_pci_read(pci_domain_nr(bus), bus->number,
++			    devfn, where, size, value);
 +}
 +
-+void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
++static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
++		     int size, u32 value)
 +{
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
++	return raw_pci_write(pci_domain_nr(bus), bus->number,
++			     devfn, where, size, value);
 +}
 +
-+void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
-+{
-+	u32 value, mc2;
-+	u32 intf_ctl, rgmii;
-+	u32 icm0, icm2;
-+
-+	xgene_gmac_reset(pdata);
-+
-+	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
-+	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
-+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2);
-+	xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
-+	xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
++struct pci_ops pci_root_ops = {
++	.read = pci_read,
++	.write = pci_write,
++};
 +
-+	switch (speed) {
-+	case SPEED_10:
-+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
-+		CFG_MACMODE_SET(&icm0, 0);
-+		CFG_WAITASYNCRD_SET(&icm2, 500);
-+		rgmii &= ~CFG_SPEED_1250;
-+		break;
-+	case SPEED_100:
-+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
-+		intf_ctl |= ENET_LHD_MODE;
-+		CFG_MACMODE_SET(&icm0, 1);
-+		CFG_WAITASYNCRD_SET(&icm2, 80);
-+		rgmii &= ~CFG_SPEED_1250;
-+		break;
-+	default:
-+		ENET_INTERFACE_MODE2_SET(&mc2, 2);
-+		intf_ctl |= ENET_GHD_MODE;
-+		CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
-+		xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
-+		value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
-+		xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
++static acpi_status resource_to_addr(struct acpi_resource *resource,
++				    struct acpi_resource_address64 *addr)
++{
++	acpi_status status;
++
++	memset(addr, 0, sizeof(*addr));
++	switch (resource->type) {
++	case ACPI_RESOURCE_TYPE_ADDRESS16:
++	case ACPI_RESOURCE_TYPE_ADDRESS32:
++	case ACPI_RESOURCE_TYPE_ADDRESS64:
++		status = acpi_resource_to_address64(resource, addr);
++		if (ACPI_SUCCESS(status) &&
++		    (addr->resource_type == ACPI_MEMORY_RANGE ||
++		    addr->resource_type == ACPI_IO_RANGE) &&
++		    addr->address_length > 0) {
++			return AE_OK;
++		}
 +		break;
 +	}
-+
-+	mc2 |= FULL_DUPLEX2;
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
-+	xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
-+
-+	xgene_gmac_set_mac_addr(pdata);
-+
-+	/* Adjust MDC clock frequency */
-+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value);
-+	MGMT_CLOCK_SEL_SET(&value, 7);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
-+
-+	/* Enable drop if bufpool not available */
-+	xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
-+	value |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
-+	xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value);
-+
-+	/* Rtype should be copied from FP */
-+	xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
-+	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
-+
-+	/* Rx-Tx traffic resume */
-+	xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
-+
-+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
-+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
-+
-+	xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
-+	value &= ~TX_DV_GATE_EN0;
-+	value &= ~RX_DV_GATE_EN0;
-+	value |= RESUME_RX0;
-+	xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value);
-+
-+	xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
++	return AE_ERROR;
 +}
 +
-+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
++static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 +{
-+	u32 val = 0xffffffff;
++	struct pci_root_info *info = data;
++	struct acpi_resource_address64 addr;
++	acpi_status status;
 +
-+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val);
-+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val);
-+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val);
-+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
++	status = resource_to_addr(acpi_res, &addr);
++	if (ACPI_SUCCESS(status))
++		info->res_num++;
++	return AE_OK;
 +}
 +
-+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
-+			   u32 dst_ring_num, u16 bufpool_id)
++static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 +{
-+	u32 cb;
-+	u32 fpsel;
++	struct pci_root_info *info = data;
++	struct resource *res;
++	struct acpi_resource_address64 addr;
++	acpi_status status;
++	unsigned long flags;
++	u64 start, end;
++
++	status = resource_to_addr(acpi_res, &addr);
++	if (!ACPI_SUCCESS(status))
++		return AE_OK;
++
++	if (addr.resource_type == ACPI_MEMORY_RANGE) {
++		flags = IORESOURCE_MEM;
++		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
++			flags |= IORESOURCE_PREFETCH;
++	} else if (addr.resource_type == ACPI_IO_RANGE) {
++		flags = IORESOURCE_IO;
++	} else
++		return AE_OK;
++
++	start = addr.minimum + addr.translation_offset;
++	end = addr.maximum + addr.translation_offset;
++
++	res = &info->res[info->res_num];
++	res->name = info->name;
++	res->flags = flags;
++	res->start = start;
++	res->end = end;
++
++	if (flags & IORESOURCE_IO) {
++		unsigned long port;
++		int err;
++
++		err = pci_register_io_range(start, addr.address_length);
++		if (err)
++			return AE_OK;
++
++		port = pci_address_to_pio(start);
++		if (port == (unsigned long)-1) {
++			res->start = -1;
++			res->end = -1;
++			return AE_OK;
++		}
 +
-+	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
++		res->start = port;
++		res->end = res->start + addr.address_length - 1;
 +
-+	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
-+	cb |= CFG_CLE_BYPASS_EN0;
-+	CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
-+	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb);
++		if (pci_remap_iospace(res, start) < 0)
++			return AE_OK;
 +
-+	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
-+	CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
-+	CFG_CLE_FPSEL0_SET(&cb, fpsel);
-+	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
-+}
++		info->res_offset[info->res_num] = 0;
++	} else
++		info->res_offset[info->res_num] = addr.translation_offset;
 +
-+void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
-+{
-+	u32 data;
++	info->res_num++;
 +
-+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
++	return AE_OK;
 +}
 +
-+void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
++static void coalesce_windows(struct pci_root_info *info, unsigned long type)
 +{
-+	u32 data;
++	int i, j;
++	struct resource *res1, *res2;
 +
-+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
-+}
++	for (i = 0; i < info->res_num; i++) {
++		res1 = &info->res[i];
++		if (!(res1->flags & type))
++			continue;
 +
-+void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
-+{
-+	u32 data;
++		for (j = i + 1; j < info->res_num; j++) {
++			res2 = &info->res[j];
++			if (!(res2->flags & type))
++				continue;
 +
-+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
++			/*
++			 * I don't like throwing away windows because then
++			 * our resources no longer match the ACPI _CRS, but
++			 * the kernel resource tree doesn't allow overlaps.
++			 */
++			if (resource_overlaps(res1, res2)) {
++				res2->start = min(res1->start, res2->start);
++				res2->end = max(res1->end, res2->end);
++				dev_info(&info->bridge->dev,
++					 "host bridge window expanded to %pR; %pR ignored\n",
++					 res2, res1);
++				res1->flags = 0;
++			}
++		}
++	}
 +}
 +
-+void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
++static void add_resources(struct pci_root_info *info,
++			  struct list_head *resources)
 +{
-+	u32 data;
++	int i;
++	struct resource *res, *root, *conflict;
 +
-+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
-+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
-+}
++	coalesce_windows(info, IORESOURCE_MEM);
++	coalesce_windows(info, IORESOURCE_IO);
 +
-+void xgene_enet_reset(struct xgene_enet_pdata *pdata)
-+{
-+	u32 val;
++	for (i = 0; i < info->res_num; i++) {
++		res = &info->res[i];
 +
-+	clk_prepare_enable(pdata->clk);
-+	clk_disable_unprepare(pdata->clk);
-+	clk_prepare_enable(pdata->clk);
-+	xgene_enet_ecc_init(pdata);
-+	xgene_enet_config_ring_if_assoc(pdata);
++		if (res->flags & IORESOURCE_MEM)
++			root = &iomem_resource;
++		else if (res->flags & IORESOURCE_IO)
++			root = &ioport_resource;
++		else
++			continue;
 +
-+	/* Enable auto-incr for scanning */
-+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val);
-+	val |= SCAN_AUTO_INCR;
-+	MGMT_CLOCK_SEL_SET(&val, 1);
-+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
++		conflict = insert_resource_conflict(root, res);
++		if (conflict)
++			dev_info(&info->bridge->dev,
++				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
++				 res, conflict->name, conflict);
++		else
++			pci_add_resource_offset(resources, res,
++						info->res_offset[i]);
++	}
 +}
 +
-+void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
++static void free_pci_root_info_res(struct pci_root_info *info)
 +{
-+	clk_disable_unprepare(pdata->clk);
++	kfree(info->res);
++	info->res = NULL;
++	kfree(info->res_offset);
++	info->res_offset = NULL;
++	info->res_num = 0;
 +}
 +
-+static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
++static void __release_pci_root_info(struct pci_root_info *info)
 +{
-+	struct xgene_enet_pdata *pdata = bus->priv;
-+	u32 val;
++	int i;
++	struct resource *res;
 +
-+	val = xgene_mii_phy_read(pdata, mii_id, regnum);
-+	netdev_dbg(pdata->ndev, "mdio_rd: bus=%d reg=%d val=%x\n",
-+		   mii_id, regnum, val);
++	for (i = 0; i < info->res_num; i++) {
++		res = &info->res[i];
 +
-+	return val;
-+}
++		if (!res->parent)
++			continue;
 +
-+static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
-+				 u16 val)
-+{
-+	struct xgene_enet_pdata *pdata = bus->priv;
-+	int ret;
++		if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
++			continue;
++
++		release_resource(res);
++	}
 +
-+	netdev_dbg(pdata->ndev, "mdio_wr: bus=%d reg=%d val=%x\n",
-+		   mii_id, regnum, val);
-+	ret = xgene_mii_phy_write(pdata, mii_id, regnum, val);
++	free_pci_root_info_res(info);
 +
-+	return ret;
++	kfree(info);
 +}
 +
-+static void xgene_enet_adjust_link(struct net_device *ndev)
++static void release_pci_root_info(struct pci_host_bridge *bridge)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct phy_device *phydev = pdata->phy_dev;
++	struct pci_root_info *info = bridge->release_data;
 +
-+	if (phydev->link) {
-+		if (pdata->phy_speed != phydev->speed) {
-+			xgene_gmac_init(pdata, phydev->speed);
-+			xgene_gmac_rx_enable(pdata);
-+			xgene_gmac_tx_enable(pdata);
-+			pdata->phy_speed = phydev->speed;
-+			phy_print_status(phydev);
-+		}
-+	} else {
-+		xgene_gmac_rx_disable(pdata);
-+		xgene_gmac_tx_disable(pdata);
-+		pdata->phy_speed = SPEED_UNKNOWN;
-+		phy_print_status(phydev);
-+	}
++	__release_pci_root_info(info);
 +}
 +
-+static int xgene_enet_phy_connect(struct net_device *ndev)
++static void probe_pci_root_info(struct pci_root_info *info,
++				struct acpi_device *device,
++				int busnum, int domain)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct device_node *phy_np;
-+	struct phy_device *phy_dev;
-+	struct device *dev = &pdata->pdev->dev;
++	size_t size;
 +
-+	phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
-+	if (!phy_np) {
-+		netdev_dbg(ndev, "No phy-handle found\n");
-+		return -ENODEV;
-+	}
++	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
++	info->bridge = device;
 +
-+	phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
-+				 0, pdata->phy_mode);
-+	if (!phy_dev) {
-+		netdev_err(ndev, "Could not connect to PHY\n");
-+		return  -ENODEV;
++	info->res_num = 0;
++	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
++				info);
++	if (!info->res_num)
++		return;
++
++	size = sizeof(*info->res) * info->res_num;
++	info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
++	if (!info->res) {
++		info->res_num = 0;
++		return;
 +	}
 +
-+	pdata->phy_speed = SPEED_UNKNOWN;
-+	phy_dev->supported &= ~SUPPORTED_10baseT_Half &
-+			      ~SUPPORTED_100baseT_Half &
-+			      ~SUPPORTED_1000baseT_Half;
-+	phy_dev->advertising = phy_dev->supported;
-+	pdata->phy_dev = phy_dev;
++	size = sizeof(*info->res_offset) * info->res_num;
++	info->res_num = 0;
++	info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
++	if (!info->res_offset) {
++		kfree(info->res);
++		info->res = NULL;
++		return;
++	}
 +
-+	return 0;
++	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
++				info);
 +}
 +
-+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
++/* Root bridge scanning */
++struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 +{
-+	struct net_device *ndev = pdata->ndev;
-+	struct device *dev = &pdata->pdev->dev;
-+	struct device_node *child_np;
-+	struct device_node *mdio_np = NULL;
-+	struct mii_bus *mdio_bus;
-+	int ret;
++	struct acpi_device *device = root->device;
++	struct pci_mmcfg_region *mcfg;
++	struct pci_root_info *info;
++	int domain = root->segment;
++	int busnum = root->secondary.start;
++	LIST_HEAD(resources);
++	struct pci_bus *bus;
++	struct pci_sysdata *sd;
++	int node;
 +
-+	for_each_child_of_node(dev->of_node, child_np) {
-+		if (of_device_is_compatible(child_np, "apm,xgene-mdio")) {
-+			mdio_np = child_np;
-+			break;
-+		}
++	/* we need mmconfig */
++	mcfg = pci_mmconfig_lookup(domain, busnum);
++	if (!mcfg) {
++		pr_err("pci_bus %04x:%02x has no MCFG table\n",
++		       domain, busnum);
++		return NULL;
 +	}
 +
-+	if (!mdio_np) {
-+		netdev_dbg(ndev, "No mdio node in the dts\n");
-+		return -1;
++	/* temporary hack */
++	if (mcfg->fixup)
++		(*mcfg->fixup)(root, mcfg);
++
++	if (domain && !pci_domains_supported) {
++		pr_warn("PCI %04x:%02x: multiple domains not supported.\n",
++			domain, busnum);
++		return NULL;
 +	}
 +
-+	mdio_bus = mdiobus_alloc();
-+	if (!mdio_bus)
-+		return -ENOMEM;
++	node = NUMA_NO_NODE;
 +
-+	mdio_bus->name = "APM X-Gene MDIO bus";
-+	mdio_bus->read = xgene_enet_mdio_read;
-+	mdio_bus->write = xgene_enet_mdio_write;
-+	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii",
-+		 ndev->name);
++	info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
++	if (!info) {
++		pr_warn("PCI %04x:%02x: ignored (out of memory)\n",
++			domain, busnum);
++		return NULL;
++	}
++	info->segment = domain;
++	info->start_bus = busnum;
++	info->end_bus = root->secondary.end;
 +
-+	mdio_bus->priv = pdata;
-+	mdio_bus->parent = &ndev->dev;
++	sd = &info->sd;
++	sd->domain = domain;
++	sd->node = node;
++	sd->companion = device;
 +
-+	ret = of_mdiobus_register(mdio_bus, mdio_np);
-+	if (ret) {
-+		netdev_err(ndev, "Failed to register MDIO bus\n");
-+		goto err;
-+	}
-+	pdata->mdio_bus = mdio_bus;
++	probe_pci_root_info(info, device, busnum, domain);
 +
-+	ret = xgene_enet_phy_connect(ndev);
-+	if (ret)
-+		goto err;
++	/* insert busn res at first */
++	pci_add_resource(&resources,  &root->secondary);
 +
-+	return ret;
++	/* then _CRS resources */
++	add_resources(info, &resources);
 +
-+err:
-+	mdiobus_free(mdio_bus);
++	bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
++	if (bus) {
++		pci_scan_child_bus(bus);
++		pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
++					    release_pci_root_info, info);
++	} else {
++		pci_free_resource_list(&resources);
++		__release_pci_root_info(info);
++	}
 +
-+	return ret;
-+}
++	/* After the PCI-E bus has been walked and all devices discovered,
++	 * configure any settings of the fabric that might be necessary.
++	 */
++	if (bus) {
++		struct pci_bus *child;
 +
-+int xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
++		list_for_each_entry(child, &bus->children, node)
++			pcie_bus_configure_settings(child);
++	}
++
++	if (bus && node != NUMA_NO_NODE)
++		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
++
++	return bus;
++}
++
++#endif /* CONFIG_ACPI */
+diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
+index b23fe37..555e226 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 c3b2fcb..5a21476 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
+@@ -47,6 +51,7 @@ acpi-y				+= int340x_thermal.o
+ acpi-y				+= power.o
+ acpi-y				+= event.o
+ acpi-y				+= sysfs.o
++acpi-y				+= property.o
+ acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o
+ acpi-$(CONFIG_DEBUG_FS)		+= debugfs.o
+ acpi-$(CONFIG_ACPI_NUMA)	+= numa.o
+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 447f6d6..c5ff8ba 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);
+@@ -173,4 +178,10 @@ static inline void suspend_nvs_restore(void) {}
+ bool acpi_osi_is_win8(void);
+ #endif
+ 
++/*--------------------------------------------------------------------------
++				Device properties
++  -------------------------------------------------------------------------- */
++void acpi_init_properties(struct acpi_device *adev);
++void acpi_free_properties(struct acpi_device *adev);
++
+ #endif /* _ACPI_INTERNAL_H_ */
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index 9964f70..5c480d5 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -336,11 +336,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
+ 	return NULL;
+ }
+ 
+-#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
+ 
+ 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 ef58f46..5c84e0d 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;
+ }
+ 
++/*
++ * On ARM platform, MPIDR value is the hardware ID as apic ID
++ * on Intel platforms
++ */
++static int map_gicc_mpidr(struct acpi_subtable_header *entry,
++		int device_declaration, u32 acpi_id, int *mpidr)
 +{
-+	struct mii_bus *mdio_bus;
++	struct acpi_madt_generic_interrupt *gicc =
++	    container_of(entry, struct acpi_madt_generic_interrupt, header);
 +
-+	mdio_bus = pdata->mdio_bus;
-+	mdiobus_unregister(mdio_bus);
-+	mdiobus_free(mdio_bus);
-+	pdata->mdio_bus = NULL;
++	if (!(gicc->flags & ACPI_MADT_ENABLED))
++		return -ENODEV;
 +
-+	return 0;
++	/* 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 -EINVAL;
 +}
-diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
++
+ static int map_madt_entry(int type, u32 acpi_id)
+ {
+ 	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/property.c b/drivers/acpi/property.c
 new file mode 100644
-index 0000000..2041313
+index 0000000..0d08373
 --- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
-@@ -0,0 +1,375 @@
-+/* Applied Micro X-Gene SoC Ethernet Driver
-+ *
-+ * Copyright (c) 2014, Applied Micro Circuits Corporation
-+ * Authors: Iyappan Subramanian <isubramanian at apm.com>
-+ *	    Ravi Patel <rapatel at apm.com>
-+ *	    Keyur Chudgar <kchudgar at apm.com>
++++ b/drivers/acpi/property.c
+@@ -0,0 +1,551 @@
++/*
++ * ACPI device specific properties support.
 + *
-+ * 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.
++ * Copyright (C) 2014, Intel Corporation
++ * All rights reserved.
 + *
-+ * 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.
++ * Authors: Mika Westerberg <mika.westerberg at linux.intel.com>
++ *          Darren Hart <dvhart at linux.intel.com>
++ *          Rafael J. Wysocki <rafael.j.wysocki at intel.com>
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ * 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 __XGENE_ENET_HW_H__
-+#define __XGENE_ENET_HW_H__
-+
-+#include "xgene_enet_main.h"
-+
-+struct xgene_enet_pdata;
-+struct xgene_enet_stats;
-+
-+/* clears and then set bits */
-+static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len)
-+{
-+	u32 end = start + len - 1;
-+	u32 mask = GENMASK(end, start);
-+
-+	*dst &= ~mask;
-+	*dst |= (val << start) & mask;
-+}
-+
-+static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
-+{
-+	return (val & GENMASK(end, start)) >> start;
-+}
-+
-+#define CSR_RING_ID		0x0008
-+#define OVERWRITE		BIT(31)
-+#define IS_BUFFER_POOL		BIT(20)
-+#define PREFETCH_BUF_EN		BIT(21)
-+#define CSR_RING_ID_BUF		0x000c
-+#define CSR_RING_NE_INT_MODE	0x017c
-+#define CSR_RING_CONFIG		0x006c
-+#define CSR_RING_WR_BASE	0x0070
-+#define NUM_RING_CONFIG		5
-+#define BUFPOOL_MODE		3
-+#define RM3			3
-+#define INC_DEC_CMD_ADDR	0x002c
-+#define UDP_HDR_SIZE		2
-+#define BUF_LEN_CODE_2K		0x5000
-+
-+#define CREATE_MASK(pos, len)		GENMASK((pos)+(len)-1, (pos))
-+#define CREATE_MASK_ULL(pos, len)	GENMASK_ULL((pos)+(len)-1, (pos))
-+
-+/* Empty slot soft signature */
-+#define EMPTY_SLOT_INDEX	1
-+#define EMPTY_SLOT		~0ULL
-+
-+#define WORK_DESC_SIZE		32
-+#define BUFPOOL_DESC_SIZE	16
-+
-+#define RING_OWNER_MASK		GENMASK(9, 6)
-+#define RING_BUFNUM_MASK	GENMASK(5, 0)
-+
-+#define SELTHRSH_POS		3
-+#define SELTHRSH_LEN		3
-+#define RINGADDRL_POS		5
-+#define RINGADDRL_LEN		27
-+#define RINGADDRH_POS		0
-+#define RINGADDRH_LEN		6
-+#define RINGSIZE_POS		23
-+#define RINGSIZE_LEN		3
-+#define RINGTYPE_POS		19
-+#define RINGTYPE_LEN		2
-+#define RINGMODE_POS		20
-+#define RINGMODE_LEN		3
-+#define RECOMTIMEOUTL_POS	28
-+#define RECOMTIMEOUTL_LEN	3
-+#define RECOMTIMEOUTH_POS	0
-+#define RECOMTIMEOUTH_LEN	2
-+#define NUMMSGSINQ_POS		1
-+#define NUMMSGSINQ_LEN		16
-+#define ACCEPTLERR		BIT(19)
-+#define QCOHERENT		BIT(4)
-+#define RECOMBBUF		BIT(27)
-+
-+#define BLOCK_ETH_CSR_OFFSET		0x2000
-+#define BLOCK_ETH_RING_IF_OFFSET	0x9000
-+#define BLOCK_ETH_CLKRST_CSR_OFFSET	0xC000
-+#define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000
-+
-+#define BLOCK_ETH_MAC_OFFSET		0x0000
-+#define BLOCK_ETH_STATS_OFFSET		0x0014
-+#define BLOCK_ETH_MAC_CSR_OFFSET	0x2800
-+
-+#define MAC_ADDR_REG_OFFSET		0x00
-+#define MAC_COMMAND_REG_OFFSET		0x04
-+#define MAC_WRITE_REG_OFFSET		0x08
-+#define MAC_READ_REG_OFFSET		0x0c
-+#define MAC_COMMAND_DONE_REG_OFFSET	0x10
-+
-+#define STAT_ADDR_REG_OFFSET		0x00
-+#define STAT_COMMAND_REG_OFFSET		0x04
-+#define STAT_WRITE_REG_OFFSET		0x08
-+#define STAT_READ_REG_OFFSET		0x0c
-+#define STAT_COMMAND_DONE_REG_OFFSET	0x10
-+
-+#define MII_MGMT_CONFIG_ADDR		0x20
-+#define MII_MGMT_COMMAND_ADDR		0x24
-+#define MII_MGMT_ADDRESS_ADDR		0x28
-+#define MII_MGMT_CONTROL_ADDR		0x2c
-+#define MII_MGMT_STATUS_ADDR		0x30
-+#define MII_MGMT_INDICATORS_ADDR	0x34
-+
-+#define BUSY_MASK			BIT(0)
-+#define READ_CYCLE_MASK			BIT(0)
-+#define PHY_CONTROL_SET(dst, val)	xgene_set_bits(dst, val, 0, 16)
-+
-+#define ENET_SPARE_CFG_REG_ADDR		0x0750
-+#define RSIF_CONFIG_REG_ADDR		0x0010
-+#define RSIF_RAM_DBG_REG0_ADDR		0x0048
-+#define RGMII_REG_0_ADDR		0x07e0
-+#define CFG_LINK_AGGR_RESUME_0_ADDR	0x07c8
-+#define DEBUG_REG_ADDR			0x0700
-+#define CFG_BYPASS_ADDR			0x0294
-+#define CLE_BYPASS_REG0_0_ADDR		0x0490
-+#define CLE_BYPASS_REG1_0_ADDR		0x0494
-+#define CFG_RSIF_FPBUFF_TIMEOUT_EN	BIT(31)
-+#define RESUME_TX			BIT(0)
-+#define CFG_SPEED_1250			BIT(24)
-+#define TX_PORT0			BIT(0)
-+#define CFG_BYPASS_UNISEC_TX		BIT(2)
-+#define CFG_BYPASS_UNISEC_RX		BIT(1)
-+#define CFG_CLE_BYPASS_EN0		BIT(31)
-+#define CFG_TXCLK_MUXSEL0_SET(dst, val)	xgene_set_bits(dst, val, 29, 3)
-+
-+#define CFG_CLE_IP_PROTOCOL0_SET(dst, val)	xgene_set_bits(dst, val, 16, 2)
-+#define CFG_CLE_DSTQID0_SET(dst, val)		xgene_set_bits(dst, val, 0, 12)
-+#define CFG_CLE_FPSEL0_SET(dst, val)		xgene_set_bits(dst, val, 16, 4)
-+#define CFG_MACMODE_SET(dst, val)		xgene_set_bits(dst, val, 18, 2)
-+#define CFG_WAITASYNCRD_SET(dst, val)		xgene_set_bits(dst, val, 0, 16)
-+#define ICM_CONFIG0_REG_0_ADDR		0x0400
-+#define ICM_CONFIG2_REG_0_ADDR		0x0410
-+#define RX_DV_GATE_REG_0_ADDR		0x05fc
-+#define TX_DV_GATE_EN0			BIT(2)
-+#define RX_DV_GATE_EN0			BIT(1)
-+#define RESUME_RX0			BIT(0)
-+#define ENET_CFGSSQMIWQASSOC_ADDR		0xe0
-+#define ENET_CFGSSQMIFPQASSOC_ADDR		0xdc
-+#define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR	0xf0
-+#define ENET_CFGSSQMIQMLITEWQASSOC_ADDR		0xf4
-+#define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR		0x70
-+#define ENET_BLOCK_MEM_RDY_ADDR			0x74
-+#define MAC_CONFIG_1_ADDR			0x00
-+#define MAC_CONFIG_2_ADDR			0x04
-+#define MAX_FRAME_LEN_ADDR			0x10
-+#define INTERFACE_CONTROL_ADDR			0x38
-+#define STATION_ADDR0_ADDR			0x40
-+#define STATION_ADDR1_ADDR			0x44
-+#define PHY_ADDR_SET(dst, val)			xgene_set_bits(dst, val, 8, 5)
-+#define REG_ADDR_SET(dst, val)			xgene_set_bits(dst, val, 0, 5)
-+#define ENET_INTERFACE_MODE2_SET(dst, val)	xgene_set_bits(dst, val, 8, 2)
-+#define MGMT_CLOCK_SEL_SET(dst, val)		xgene_set_bits(dst, val, 0, 3)
-+#define SOFT_RESET1			BIT(31)
-+#define TX_EN				BIT(0)
-+#define RX_EN				BIT(2)
-+#define ENET_LHD_MODE			BIT(25)
-+#define ENET_GHD_MODE			BIT(26)
-+#define FULL_DUPLEX2			BIT(0)
-+#define SCAN_AUTO_INCR			BIT(5)
-+#define TBYT_ADDR			0x38
-+#define TPKT_ADDR			0x39
-+#define TDRP_ADDR			0x45
-+#define TFCS_ADDR			0x47
-+#define TUND_ADDR			0x4a
-+
-+#define TSO_IPPROTO_TCP			1
-+#define	FULL_DUPLEX			2
-+
-+#define USERINFO_POS			0
-+#define USERINFO_LEN			32
-+#define FPQNUM_POS			32
-+#define FPQNUM_LEN			12
-+#define LERR_POS			60
-+#define LERR_LEN			3
-+#define STASH_POS			52
-+#define STASH_LEN			2
-+#define BUFDATALEN_POS			48
-+#define BUFDATALEN_LEN			12
-+#define DATAADDR_POS			0
-+#define DATAADDR_LEN			42
-+#define COHERENT_POS			63
-+#define HENQNUM_POS			48
-+#define HENQNUM_LEN			12
-+#define TYPESEL_POS			44
-+#define TYPESEL_LEN			4
-+#define ETHHDR_POS			12
-+#define IC_POS				35	/* Insert CRC */
-+#define TCPHDR_POS			0
-+#define TCPHDR_LEN			6
-+#define IPHDR_POS			6
-+#define IPHDR_LEN			6
-+#define EC_POS				22	/* Enable checksum */
-+#define IS_POS				24	/* IP protocol select */
-+
-+#define DATAADDR_MASK		CREATE_MASK_ULL(DATAADDR_POS, DATAADDR_LEN)
-+#define BUFDATALEN_MASK		CREATE_MASK_ULL(BUFDATALEN_POS, BUFDATALEN_LEN)
-+#define USERINFO_MASK		CREATE_MASK_ULL(USERINFO_POS, USERINFO_LEN)
-+#define FPQNUM_MASK		CREATE_MASK_ULL(FPQNUM_POS, FPQNUM_LEN)
-+#define LERR_MASK		CREATE_MASK_ULL(LERR_POS, LERR_LEN)
-+#define STASHING_MASK		CREATE_MASK_ULL(STASH_POS, STASH_LEN)
-+#define COHERENT_MASK		BIT_ULL(COHERENT_POS)
-+#define HENQNUM_MASK		CREATE_MASK_ULL(HENQNUM_POS, HENQNUM_LEN)
-+#define TCPHDR_MASK		CREATE_MASK(TCPHDR_POS, TCPHDR_LEN)
-+#define IPHDR_MASK		CREATE_MASK(IPHDR_POS, IPHDR_LEN)
-+#define EC_MASK			BIT(EC_POS)
-+#define IS_MASK			BIT(IS_POS)
-+#define INSERT_CRC		BIT_ULL(IC_POS)
-+#define TYPE_ETH_WORK_MESSAGE	BIT_ULL(44)
-+
-+struct xgene_enet_raw_desc {
-+	u64 m0;
-+	u64 m1;
-+	u64 m2;
-+	u64 m3;
-+};
++#include <linux/acpi.h>
++#include <linux/device.h>
++#include <linux/export.h>
++
++#include "internal.h"
 +
-+struct xgene_enet_raw_desc16 {
-+	u64 m0;
-+	u64 m1;
++/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
++static const u8 prp_uuid[16] = {
++	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
++	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
 +};
 +
-+static inline void xgene_enet_cpu_to_le64(void *desc_ptr, int count)
++static bool acpi_property_value_ok(const union acpi_object *value)
 +{
-+	u64 *desc = desc_ptr;
-+	int i;
++	int j;
++
++	/*
++	 * The value must be an integer, a string, a reference, or a package
++	 * whose every element must be an integer, a string, or a reference.
++	 */
++	switch (value->type) {
++	case ACPI_TYPE_INTEGER:
++	case ACPI_TYPE_STRING:
++	case ACPI_TYPE_LOCAL_REFERENCE:
++		return true;
++
++	case ACPI_TYPE_PACKAGE:
++		for (j = 0; j < value->package.count; j++)
++			switch (value->package.elements[j].type) {
++			case ACPI_TYPE_INTEGER:
++			case ACPI_TYPE_STRING:
++			case ACPI_TYPE_LOCAL_REFERENCE:
++				continue;
++
++			default:
++				return false;
++			}
 +
-+	for (i = 0; i < count; i++)
-+		desc[i] = cpu_to_le64(desc[i]);
++		return true;
++	}
++	return false;
 +}
 +
-+static inline void xgene_enet_le64_to_cpu(void *desc_ptr, int count)
++static bool acpi_properties_format_valid(const union acpi_object *properties)
 +{
-+	u64 *desc = desc_ptr;
 +	int i;
 +
-+	for (i = 0; i < count; i++)
-+		desc[i] = le64_to_cpu(desc[i]);
++	for (i = 0; i < properties->package.count; i++) {
++		const union acpi_object *property;
++
++		property = &properties->package.elements[i];
++		/*
++		 * Only two elements allowed, the first one must be a string and
++		 * the second one has to satisfy certain conditions.
++		 */
++		if (property->package.count != 2
++		    || property->package.elements[0].type != ACPI_TYPE_STRING
++		    || !acpi_property_value_ok(&property->package.elements[1]))
++			return false;
++	}
++	return true;
 +}
 +
-+static inline void xgene_enet_desc16_to_le64(void *desc_ptr)
++static void acpi_init_of_compatible(struct acpi_device *adev)
 +{
-+	u64 *desc;
++	const union acpi_object *of_compatible;
++	struct acpi_hardware_id *hwid;
++	bool acpi_of = false;
++	int ret;
 +
-+	desc = desc_ptr;
-+	desc[1] = cpu_to_le64(desc[1]);
-+}
++	/*
++	 * Check if the special PRP0001 ACPI ID is present and in that
++	 * case we fill in Device Tree compatible properties for this
++	 * device.
++	 */
++	list_for_each_entry(hwid, &adev->pnp.ids, list) {
++		if (!strcmp(hwid->id, "PRP0001")) {
++			acpi_of = true;
++			break;
++		}
++	}
 +
-+static inline void xgene_enet_le64_to_desc16(void *desc_ptr)
-+{
-+	u64 *desc;
++	if (!acpi_of)
++		return;
 +
-+	desc = desc_ptr;
-+	desc[1] = le64_to_cpu(desc[1]);
++	ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
++					  &of_compatible);
++	if (ret) {
++		ret = acpi_dev_get_property(adev, "compatible",
++					    ACPI_TYPE_STRING, &of_compatible);
++		if (ret) {
++			acpi_handle_warn(adev->handle,
++					 "PRP0001 requires compatible property\n");
++			return;
++		}
++	}
++	adev->data.of_compatible = of_compatible;
 +}
 +
-+enum xgene_enet_ring_cfgsize {
-+	RING_CFGSIZE_512B,
-+	RING_CFGSIZE_2KB,
-+	RING_CFGSIZE_16KB,
-+	RING_CFGSIZE_64KB,
-+	RING_CFGSIZE_512KB,
-+	RING_CFGSIZE_INVALID
-+};
++void acpi_init_properties(struct acpi_device *adev)
++{
++	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
++	const union acpi_object *desc;
++	acpi_status status;
++	int i;
 +
-+enum xgene_enet_ring_type {
-+	RING_DISABLED,
-+	RING_REGULAR,
-+	RING_BUFPOOL
-+};
++	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
++					    ACPI_TYPE_PACKAGE);
++	if (ACPI_FAILURE(status))
++		return;
 +
-+enum xgene_ring_owner {
-+	RING_OWNER_ETH0,
-+	RING_OWNER_CPU = 15,
-+	RING_OWNER_INVALID
-+};
++	desc = buf.pointer;
++	if (desc->package.count % 2)
++		goto fail;
 +
-+enum xgene_enet_ring_bufnum {
-+	RING_BUFNUM_REGULAR = 0x0,
-+	RING_BUFNUM_BUFPOOL = 0x20,
-+	RING_BUFNUM_INVALID
-+};
++	/* Look for the device properties UUID. */
++	for (i = 0; i < desc->package.count; i += 2) {
++		const union acpi_object *uuid, *properties;
 +
-+enum xgene_enet_cmd {
-+	XGENE_ENET_WR_CMD = BIT(31),
-+	XGENE_ENET_RD_CMD = BIT(30)
-+};
++		uuid = &desc->package.elements[i];
++		properties = &desc->package.elements[i + 1];
 +
-+enum xgene_enet_err_code {
-+	HBF_READ_DATA = 3,
-+	HBF_LL_READ = 4,
-+	BAD_WORK_MSG = 6,
-+	BUFPOOL_TIMEOUT = 15,
-+	INGRESS_CRC = 16,
-+	INGRESS_CHECKSUM = 17,
-+	INGRESS_TRUNC_FRAME = 18,
-+	INGRESS_PKT_LEN = 19,
-+	INGRESS_PKT_UNDER = 20,
-+	INGRESS_FIFO_OVERRUN = 21,
-+	INGRESS_CHECKSUM_COMPUTE = 26,
-+	ERR_CODE_INVALID
-+};
++		/*
++		 * The first element must be a UUID and the second one must be
++		 * a package.
++		 */
++		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
++		    || properties->type != ACPI_TYPE_PACKAGE)
++			break;
 +
-+static inline enum xgene_ring_owner xgene_enet_ring_owner(u16 id)
-+{
-+	return (id & RING_OWNER_MASK) >> 6;
-+}
++		if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
++			continue;
 +
-+static inline u8 xgene_enet_ring_bufnum(u16 id)
-+{
-+	return id & RING_BUFNUM_MASK;
-+}
++		/*
++		 * We found the matching UUID. Now validate the format of the
++		 * package immediately following it.
++		 */
++		if (!acpi_properties_format_valid(properties))
++			break;
 +
-+static inline bool xgene_enet_is_bufpool(u16 id)
-+{
-+	return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
-+}
++		adev->data.pointer = buf.pointer;
++		adev->data.properties = properties;
 +
-+static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
-+{
-+	bool is_bufpool = xgene_enet_is_bufpool(id);
++		acpi_init_of_compatible(adev);
++		return;
++	}
 +
-+	return (is_bufpool) ? size / BUFPOOL_DESC_SIZE :
-+		      size / WORK_DESC_SIZE;
++ fail:
++	dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
++	ACPI_FREE(buf.pointer);
 +}
 +
-+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
-+		struct xgene_enet_desc_ring *ring);
-+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring);
-+
-+void xgene_set_tx_desc(struct xgene_enet_desc_ring *ring,
-+		       struct xgene_enet_raw_desc *raw_desc);
-+void xgene_get_desc(struct xgene_enet_desc_ring *ring,
-+		    struct xgene_enet_raw_desc *raw_desc);
-+void xgene_get_bufpool_desc(struct xgene_enet_desc_ring *ring,
-+			    struct xgene_enet_raw_desc16 *raw_desc);
-+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
-+			    struct xgene_enet_pdata *pdata,
-+			    enum xgene_enet_err_code status);
-+
-+void xgene_enet_reset(struct xgene_enet_pdata *priv);
-+void xgene_gmac_reset(struct xgene_enet_pdata *priv);
-+void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed);
-+void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv);
-+void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv);
-+void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv);
-+void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv);
-+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata);
-+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
-+			   u32 dst_ring_num, u16 bufpool_id);
-+void xgene_gport_shutdown(struct xgene_enet_pdata *priv);
-+void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata);
-+
-+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
-+int xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
++void acpi_free_properties(struct acpi_device *adev)
++{
++	ACPI_FREE((void *)adev->data.pointer);
++	adev->data.of_compatible = NULL;
++	adev->data.pointer = NULL;
++	adev->data.properties = NULL;
++}
 +
-+#endif /* __XGENE_ENET_HW_H__ */
-diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
-new file mode 100644
-index 0000000..756523a
---- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
-@@ -0,0 +1,962 @@
-+/* Applied Micro X-Gene SoC Ethernet Driver
-+ *
-+ * Copyright (c) 2014, Applied Micro Circuits Corporation
-+ * Authors: Iyappan Subramanian <isubramanian at apm.com>
-+ *	    Ravi Patel <rapatel at apm.com>
-+ *	    Keyur Chudgar <kchudgar at apm.com>
++/**
++ * acpi_dev_get_property - return an ACPI property with given name
++ * @adev: ACPI device to get property
++ * @name: Name of the property
++ * @type: Expected property type
++ * @obj: Location to store the property value (if not %NULL)
 + *
-+ * 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.
++ * Look up a property with @name and store a pointer to the resulting ACPI
++ * object at the location pointed to by @obj if found.
 + *
-+ * 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.
++ * Callers must not attempt to free the returned objects.  These objects will be
++ * freed by the ACPI core automatically during the removal of @adev.
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ * Return: %0 if property with @name has been found (success),
++ *         %-EINVAL if the arguments are invalid,
++ *         %-ENODATA if the property doesn't exist,
++ *         %-EPROTO if the property value type doesn't match @type.
 + */
-+
-+#include "xgene_enet_main.h"
-+#include "xgene_enet_hw.h"
-+
-+static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
++int acpi_dev_get_property(struct acpi_device *adev, const char *name,
++			  acpi_object_type type, const union acpi_object **obj)
 +{
-+	struct xgene_enet_raw_desc16 *raw_desc;
++	const union acpi_object *properties;
 +	int i;
 +
-+	for (i = 0; i < buf_pool->slots; i++) {
-+		raw_desc = &buf_pool->raw_desc16[i];
-+
-+		/* Hardware expects descriptor in little endian format */
-+		raw_desc->m0 = cpu_to_le64(i |
-+			       (((u64)buf_pool->dst_ring_num << FPQNUM_POS) &
-+			       FPQNUM_MASK) | STASHING_MASK);
-+	}
-+}
++	if (!adev || !name)
++		return -EINVAL;
 +
-+static struct device *ndev_to_dev(struct net_device *ndev)
-+{
-+	return ndev->dev.parent;
-+}
++	if (!adev->data.pointer || !adev->data.properties)
++		return -ENODATA;
 +
-+static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
-+				     u32 nbuf)
-+{
-+	struct sk_buff *skb;
-+	struct xgene_enet_raw_desc16 *raw_desc;
-+	struct net_device *ndev;
-+	struct device *dev;
-+	dma_addr_t dma_addr;
-+	u32 tail = buf_pool->tail;
-+	u32 slots = buf_pool->slots - 1;
-+	u16 bufdatalen, len;
-+	int i;
++	properties = adev->data.properties;
++	for (i = 0; i < properties->package.count; i++) {
++		const union acpi_object *propname, *propvalue;
++		const union acpi_object *property;
 +
-+	ndev = buf_pool->ndev;
-+	dev = ndev_to_dev(buf_pool->ndev);
-+	bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
-+	len = XGENE_ENET_MAX_MTU;
++		property = &properties->package.elements[i];
 +
-+	for (i = 0; i < nbuf; i++) {
-+		raw_desc = &buf_pool->raw_desc16[tail];
++		propname = &property->package.elements[0];
++		propvalue = &property->package.elements[1];
 +
-+		skb = netdev_alloc_skb_ip_align(ndev, len);
-+		if (unlikely(!skb))
-+			return -ENOMEM;
-+		buf_pool->rx_skb[tail] = skb;
++		if (!strcmp(name, propname->string.pointer)) {
++			if (type != ACPI_TYPE_ANY && propvalue->type != type)
++				return -EPROTO;
++			else if (obj)
++				*obj = propvalue;
 +
-+		dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
-+		if (dma_mapping_error(dev, dma_addr)) {
-+			netdev_err(ndev, "DMA mapping error\n");
-+			dev_kfree_skb_any(skb);
-+			return -EINVAL;
++			return 0;
 +		}
-+
-+		raw_desc->m1 = cpu_to_le64((dma_addr & DATAADDR_MASK) |
-+			       (((u64)bufdatalen << BUFDATALEN_POS) &
-+			       BUFDATALEN_MASK) | COHERENT_MASK);
-+		tail = (tail + 1) & slots;
 +	}
-+
-+	iowrite32(nbuf, buf_pool->cmd);
-+	buf_pool->tail = tail;
-+
-+	return 0;
-+}
-+
-+static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
-+
-+	return ((u16)pdata->rm << 10) | ring->num;
-+}
-+
-+static u8 xgene_enet_hdr_len(const void *data)
-+{
-+	const struct ethhdr *eth = data;
-+
-+	return (eth->h_proto == htons(ETH_P_8021Q)) ? VLAN_ETH_HLEN : ETH_HLEN;
-+}
-+
-+static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
-+{
-+	u32 *cmd_base = ring->cmd_base;
-+	u32 ring_state, num_msgs;
-+
-+	ring_state = ioread32(&cmd_base[1]);
-+	num_msgs = ring_state & CREATE_MASK(NUMMSGSINQ_POS, NUMMSGSINQ_LEN);
-+
-+	return num_msgs >> NUMMSGSINQ_POS;
++	return -ENODATA;
 +}
++EXPORT_SYMBOL_GPL(acpi_dev_get_property);
 +
-+static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
++/**
++ * acpi_dev_get_property_array - return an ACPI array property with given name
++ * @adev: ACPI device to get property
++ * @name: Name of the property
++ * @type: Expected type of array elements
++ * @obj: Location to store a pointer to the property value (if not NULL)
++ *
++ * Look up an array property with @name and store a pointer to the resulting
++ * ACPI object at the location pointed to by @obj if found.
++ *
++ * Callers must not attempt to free the returned objects.  Those objects will be
++ * freed by the ACPI core automatically during the removal of @adev.
++ *
++ * Return: %0 if array property (package) with @name has been found (success),
++ *         %-EINVAL if the arguments are invalid,
++ *         %-ENODATA if the property doesn't exist,
++ *         %-EPROTO if the property is not a package or the type of its elements
++ *           doesn't match @type.
++ */
++int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
++				acpi_object_type type,
++				const union acpi_object **obj)
 +{
-+	struct xgene_enet_raw_desc16 *raw_desc;
-+	u32 slots = buf_pool->slots - 1;
-+	u32 tail = buf_pool->tail;
-+	u32 userinfo;
-+	int i, len;
-+
-+	len = xgene_enet_ring_len(buf_pool);
-+	for (i = 0; i < len; i++) {
-+		tail = (tail - 1) & slots;
-+		raw_desc = &buf_pool->raw_desc16[tail];
-+
-+		/* Hardware stores descriptor in little endian format */
-+		userinfo = le64_to_cpu(raw_desc->m0) & USERINFO_MASK;
-+		dev_kfree_skb_any(buf_pool->rx_skb[userinfo]);
-+	}
-+
-+	iowrite32(-len, buf_pool->cmd);
-+	buf_pool->tail = tail;
-+}
++	const union acpi_object *prop;
++	int ret, i;
 +
-+static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
-+{
-+	struct xgene_enet_desc_ring *rx_ring = data;
++	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
++	if (ret)
++		return ret;
 +
-+	if (napi_schedule_prep(&rx_ring->napi)) {
-+		disable_irq_nosync(irq);
-+		__napi_schedule(&rx_ring->napi);
++	if (type != ACPI_TYPE_ANY) {
++		/* Check that all elements are of correct type. */
++		for (i = 0; i < prop->package.count; i++)
++			if (prop->package.elements[i].type != type)
++				return -EPROTO;
 +	}
++	if (obj)
++		*obj = prop;
 +
-+	return IRQ_HANDLED;
++	return 0;
 +}
++EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
 +
-+static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
-+				    struct xgene_enet_raw_desc *raw_desc)
++/**
++ * acpi_dev_get_property_reference - returns handle to the referenced object
++ * @adev: ACPI device to get property
++ * @name: Name of the property
++ * @index: Index of the reference to return
++ * @args: Location to store the returned reference with optional arguments
++ *
++ * Find property with @name, verifify that it is a package containing at least
++ * one object reference and if so, store the ACPI device object pointer to the
++ * target object in @args->adev.  If the reference includes arguments, store
++ * them in the @args->args[] array.
++ *
++ * If there's more than one reference in the property value package, @index is
++ * used to select the one to return.
++ *
++ * Return: %0 on success, negative error code on failure.
++ */
++int acpi_dev_get_property_reference(struct acpi_device *adev,
++				    const char *name, size_t index,
++				    struct acpi_reference_args *args)
 +{
-+	struct sk_buff *skb;
-+	struct device *dev;
-+	u16 skb_index;
-+	u8 status;
-+	int ret = 0;
++	const union acpi_object *element, *end;
++	const union acpi_object *obj;
++	struct acpi_device *device;
++	int ret, idx = 0;
 +
-+	skb_index = raw_desc->m0 & USERINFO_MASK;
-+	skb = cp_ring->cp_skb[skb_index];
++	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
++	if (ret)
++		return ret;
 +
-+	dev = ndev_to_dev(cp_ring->ndev);
-+	dma_unmap_single(dev, raw_desc->m1 & DATAADDR_MASK,
-+			 (raw_desc->m1 & BUFDATALEN_MASK) >> BUFDATALEN_POS,
-+			 DMA_TO_DEVICE);
++	/*
++	 * The simplest case is when the value is a single reference.  Just
++	 * return that reference then.
++	 */
++	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
++		if (index)
++			return -EINVAL;
 +
-+	/* Checking for error */
-+	status = (raw_desc->m0 & LERR_MASK) >> LERR_POS;
-+	if (unlikely(status > 2)) {
-+		xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
-+				       status);
-+		ret = -1;
-+	}
++		ret = acpi_bus_get_device(obj->reference.handle, &device);
++		if (ret)
++			return ret;
 +
-+	if (likely(skb)) {
-+		dev_kfree_skb_any(skb);
-+	} else {
-+		netdev_err(cp_ring->ndev, "completion skb is NULL\n");
-+		ret = -1;
++		args->adev = device;
++		args->nargs = 0;
++		return 0;
 +	}
 +
-+	return ret;
-+}
++	/*
++	 * If it is not a single reference, then it is a package of
++	 * references followed by number of ints as follows:
++	 *
++	 *  Package () { REF, INT, REF, INT, INT }
++	 *
++	 * The index argument is then used to determine which reference
++	 * the caller wants (along with the arguments).
++	 */
++	if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
++		return -EPROTO;
 +
-+static u64 xgene_enet_work_msg(struct sk_buff *skb)
-+{
-+	struct iphdr *iph;
-+	u8 l3hlen, l4hlen = 0;
-+	u8 csum_enable = 0;
-+	u8 proto = 0;
-+	u8 ethhdr;
-+	u64 hopinfo;
++	element = obj->package.elements;
++	end = element + obj->package.count;
 +
-+	if (unlikely(skb->protocol != htons(ETH_P_IP)) &&
-+	    unlikely(skb->protocol != htons(ETH_P_8021Q)))
-+		goto out;
++	while (element < end) {
++		u32 nargs, i;
 +
-+	if (unlikely(!(skb->dev->features & NETIF_F_IP_CSUM)))
-+		goto out;
++		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
++			return -EPROTO;
 +
-+	iph = ip_hdr(skb);
-+	if (unlikely(ip_is_fragment(iph)))
-+		goto out;
++		ret = acpi_bus_get_device(element->reference.handle, &device);
++		if (ret)
++			return -ENODEV;
 +
-+	if (likely(iph->protocol == IPPROTO_TCP)) {
-+		l4hlen = tcp_hdrlen(skb) >> 2;
-+		csum_enable = 1;
-+		proto = TSO_IPPROTO_TCP;
-+	} else if (iph->protocol == IPPROTO_UDP) {
-+		l4hlen = UDP_HDR_SIZE;
-+		csum_enable = 1;
-+	}
-+out:
-+	l3hlen = ip_hdrlen(skb) >> 2;
-+	ethhdr = xgene_enet_hdr_len(skb->data);
-+	hopinfo = (l4hlen & TCPHDR_MASK) |
-+		  ((l3hlen << IPHDR_POS) & IPHDR_MASK) |
-+		  (ethhdr << ETHHDR_POS) |
-+		  (csum_enable << EC_POS) |
-+		  (proto << IS_POS) |
-+		  INSERT_CRC |
-+		  TYPE_ETH_WORK_MESSAGE;
-+
-+	return hopinfo;
-+}
-+
-+static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
-+				    struct sk_buff *skb)
-+{
-+	struct device *dev = ndev_to_dev(tx_ring->ndev);
-+	struct xgene_enet_raw_desc *raw_desc;
-+	dma_addr_t dma_addr;
-+	u16 tail = tx_ring->tail;
-+	u64 hopinfo;
-+
-+	raw_desc = &tx_ring->raw_desc[tail];
-+	memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
-+
-+	dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
-+	if (dma_mapping_error(dev, dma_addr)) {
-+		netdev_err(tx_ring->ndev, "DMA mapping error\n");
-+		return -EINVAL;
-+	}
++		element++;
++		nargs = 0;
 +
-+	/* Hardware expects descriptor in little endian format */
-+	raw_desc->m0 = cpu_to_le64(tail);
-+	raw_desc->m1 = cpu_to_le64((dma_addr & DATAADDR_MASK) |
-+		       (((u64)skb->len << BUFDATALEN_POS) & BUFDATALEN_MASK) |
-+		       COHERENT_MASK);
-+	hopinfo = xgene_enet_work_msg(skb);
-+	raw_desc->m3 = cpu_to_le64(
-+		       (((u64)tx_ring->dst_ring_num << HENQNUM_POS) &
-+		       HENQNUM_MASK) | hopinfo);
-+	tx_ring->cp_ring->cp_skb[tail] = skb;
++		/* assume following integer elements are all args */
++		for (i = 0; element + i < end; i++) {
++			int type = element[i].type;
 +
-+	return 0;
-+}
++			if (type == ACPI_TYPE_INTEGER)
++				nargs++;
++			else if (type == ACPI_TYPE_LOCAL_REFERENCE)
++				break;
++			else
++				return -EPROTO;
++		}
 +
-+static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
-+					 struct net_device *ndev)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
-+	struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
-+	u32 tx_level, cq_level;
++		if (idx++ == index) {
++			args->adev = device;
++			args->nargs = nargs;
++			for (i = 0; i < nargs; i++)
++				args->args[i] = element[i].integer.value;
 +
-+	tx_level = xgene_enet_ring_len(tx_ring);
-+	cq_level = xgene_enet_ring_len(cp_ring);
-+	if (unlikely(tx_level > pdata->tx_qcnt_hi ||
-+		     cq_level > pdata->cp_qcnt_hi)) {
-+		netif_stop_queue(ndev);
-+		return NETDEV_TX_BUSY;
-+	}
++			return 0;
++		}
 +
-+	if (xgene_enet_setup_tx_desc(tx_ring, skb)) {
-+		dev_kfree_skb_any(skb);
-+		return NETDEV_TX_OK;
++		element += nargs;
 +	}
 +
-+	iowrite32(1, tx_ring->cmd);
-+	skb_tx_timestamp(skb);
-+	tx_ring->tail = (tx_ring->tail + 1) & (tx_ring->slots - 1);
-+
-+	pdata->stats.tx_packets++;
-+	pdata->stats.tx_bytes += skb->len;
-+
-+	return NETDEV_TX_OK;
++	return -EPROTO;
 +}
++EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
 +
-+static void xgene_enet_skip_csum(struct sk_buff *skb)
++int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
++		      void **valptr)
 +{
-+	struct iphdr *iph = ip_hdr(skb);
-+
-+	if (!ip_is_fragment(iph) ||
-+	    (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)) {
-+		skb->ip_summed = CHECKSUM_UNNECESSARY;
-+	}
++	return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
++				     (const union acpi_object **)valptr);
 +}
 +
-+static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
-+			       struct xgene_enet_raw_desc *raw_desc)
++int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
++			      enum dev_prop_type proptype, void *val)
 +{
-+	struct net_device *ndev;
-+	struct xgene_enet_pdata *pdata;
-+	struct device *dev;
-+	struct xgene_enet_desc_ring *buf_pool;
-+	u32 datalen, skb_index;
-+	struct sk_buff *skb;
-+	u8 status;
-+	int ret = 0;
-+
-+	ndev = rx_ring->ndev;
-+	pdata = netdev_priv(ndev);
-+	dev = ndev_to_dev(rx_ring->ndev);
-+	buf_pool = rx_ring->buf_pool;
-+
-+	dma_unmap_single(dev, raw_desc->m1 & DATAADDR_MASK, XGENE_ENET_MAX_MTU,
-+			 DMA_FROM_DEVICE);
-+	skb_index = raw_desc->m0 & USERINFO_MASK;
-+	skb = buf_pool->rx_skb[skb_index];
-+
-+	/* checking for error */
-+	status = (raw_desc->m0 & LERR_MASK) >> LERR_POS;
-+	if (unlikely(status > 2)) {
-+		dev_kfree_skb_any(skb);
-+		xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
-+				       status);
-+		pdata->stats.rx_dropped++;
-+		ret = -1;
-+		goto out;
-+	}
-+
-+	/* strip off CRC as HW isn't doing this */
-+	datalen = (raw_desc->m1 & BUFDATALEN_MASK) >> BUFDATALEN_POS;
-+	datalen -= 4;
-+	prefetch(skb->data - NET_IP_ALIGN);
-+	skb_put(skb, datalen);
-+
-+	skb_checksum_none_assert(skb);
-+	skb->protocol = eth_type_trans(skb, ndev);
-+	if (likely((ndev->features & NETIF_F_IP_CSUM) &&
-+		   skb->protocol == htons(ETH_P_IP))) {
-+		xgene_enet_skip_csum(skb);
-+	}
-+
-+	pdata->stats.rx_packets++;
-+	pdata->stats.rx_bytes += datalen;
-+	napi_gro_receive(&rx_ring->napi, skb);
-+out:
-+	if (--rx_ring->nbufpool == 0) {
-+		ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
-+		rx_ring->nbufpool = NUM_BUFPOOL;
-+	}
-+
-+	return ret;
-+}
++	const union acpi_object *obj;
++	int ret;
 +
-+static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc)
-+{
-+	/* Hardware stores descriptor in little endian format */
-+	raw_desc->m0 = le64_to_cpu(raw_desc->m0);
-+	raw_desc->m1 = le64_to_cpu(raw_desc->m1);
-+	return ((raw_desc->m0 & FPQNUM_MASK) >> FPQNUM_POS) ? true : false;
-+}
++	if (!val)
++		return -EINVAL;
 +
-+static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
-+				   int budget)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
-+	struct xgene_enet_raw_desc *raw_desc;
-+	u16 head = ring->head;
-+	u16 slots = ring->slots - 1;
-+	int ret, count = 0;
++	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
++		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
++		if (ret)
++			return ret;
 +
-+	do {
-+		raw_desc = &ring->raw_desc[head];
-+		if (unlikely(((u64 *)raw_desc)[EMPTY_SLOT_INDEX] == EMPTY_SLOT))
++		switch (proptype) {
++		case DEV_PROP_U8:
++			if (obj->integer.value > U8_MAX)
++				return -EOVERFLOW;
++			*(u8 *)val = obj->integer.value;
 +			break;
-+
-+		if (is_rx_desc(raw_desc))
-+			ret = xgene_enet_rx_frame(ring, raw_desc);
-+		else
-+			ret = xgene_enet_tx_completion(ring, raw_desc);
-+		((u64 *)raw_desc)[EMPTY_SLOT_INDEX] = EMPTY_SLOT;
-+
-+		head = (head + 1) & slots;
-+		count++;
-+
-+		if (ret)
++		case DEV_PROP_U16:
++			if (obj->integer.value > U16_MAX)
++				return -EOVERFLOW;
++			*(u16 *)val = obj->integer.value;
++			break;
++		case DEV_PROP_U32:
++			if (obj->integer.value > U32_MAX)
++				return -EOVERFLOW;
++			*(u32 *)val = obj->integer.value;
++			break;
++		default:
++			*(u64 *)val = obj->integer.value;
 +			break;
-+	} while (--budget);
-+
-+	if (likely(count)) {
-+		iowrite32(-count, ring->cmd);
-+		ring->head = head;
-+
-+		if (netif_queue_stopped(ring->ndev)) {
-+			if (xgene_enet_ring_len(ring) < pdata->cp_qcnt_low)
-+				netif_wake_queue(ring->ndev);
 +		}
-+	}
++	} else if (proptype == DEV_PROP_STRING) {
++		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
++		if (ret)
++			return ret;
 +
-+	return budget;
++		*(char **)val = obj->string.pointer;
++	} else {
++		ret = -EINVAL;
++	}
++	return ret;
 +}
 +
-+static int xgene_enet_napi(struct napi_struct *napi, const int budget)
++static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
++				       size_t nval)
 +{
-+	struct xgene_enet_desc_ring *ring;
-+	int processed;
++	int i;
 +
-+	ring = container_of(napi, struct xgene_enet_desc_ring, napi);
-+	processed = xgene_enet_process_ring(ring, budget);
++	for (i = 0; i < nval; i++) {
++		if (items[i].type != ACPI_TYPE_INTEGER)
++			return -EPROTO;
++		if (items[i].integer.value > U8_MAX)
++			return -EOVERFLOW;
 +
-+	if (processed != budget) {
-+		napi_complete(napi);
-+		enable_irq(ring->irq);
++		val[i] = items[i].integer.value;
 +	}
-+
-+	return processed;
++	return 0;
 +}
 +
-+static void xgene_enet_timeout(struct net_device *ndev)
++static int acpi_copy_property_array_u16(const union acpi_object *items,
++					u16 *val, size_t nval)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+
-+	xgene_gmac_reset(pdata);
-+}
++	int i;
 +
-+static int xgene_enet_register_irq(struct net_device *ndev)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct device *dev = ndev_to_dev(ndev);
-+	int ret;
++	for (i = 0; i < nval; i++) {
++		if (items[i].type != ACPI_TYPE_INTEGER)
++			return -EPROTO;
++		if (items[i].integer.value > U16_MAX)
++			return -EOVERFLOW;
 +
-+	ret = devm_request_irq(dev, pdata->rx_ring->irq, xgene_enet_rx_irq,
-+			       IRQF_SHARED, ndev->name, pdata->rx_ring);
-+	if (ret) {
-+		netdev_err(ndev, "rx%d interrupt request failed\n",
-+			   pdata->rx_ring->irq);
++		val[i] = items[i].integer.value;
 +	}
-+
-+	return ret;
-+}
-+
-+static void xgene_enet_free_irq(struct net_device *ndev)
-+{
-+	struct xgene_enet_pdata *pdata;
-+	struct device *dev;
-+
-+	pdata = netdev_priv(ndev);
-+	dev = ndev_to_dev(ndev);
-+	devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring);
++	return 0;
 +}
 +
-+static int xgene_enet_open(struct net_device *ndev)
++static int acpi_copy_property_array_u32(const union acpi_object *items,
++					u32 *val, size_t nval)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	int ret;
-+
-+	xgene_gmac_tx_enable(pdata);
-+	xgene_gmac_rx_enable(pdata);
-+
-+	ret = xgene_enet_register_irq(ndev);
-+	if (ret)
-+		return ret;
-+	napi_enable(&pdata->rx_ring->napi);
-+
-+	if (pdata->phy_dev)
-+		phy_start(pdata->phy_dev);
++	int i;
 +
-+	netif_start_queue(ndev);
++	for (i = 0; i < nval; i++) {
++		if (items[i].type != ACPI_TYPE_INTEGER)
++			return -EPROTO;
++		if (items[i].integer.value > U32_MAX)
++			return -EOVERFLOW;
 +
-+	return ret;
++		val[i] = items[i].integer.value;
++	}
++	return 0;
 +}
 +
-+static int xgene_enet_close(struct net_device *ndev)
++static int acpi_copy_property_array_u64(const union acpi_object *items,
++					u64 *val, size_t nval)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+
-+	netif_stop_queue(ndev);
-+
-+	if (pdata->phy_dev)
-+		phy_stop(pdata->phy_dev);
-+
-+	napi_disable(&pdata->rx_ring->napi);
-+	xgene_enet_free_irq(ndev);
-+	xgene_enet_process_ring(pdata->rx_ring, -1);
++	int i;
 +
-+	xgene_gmac_tx_disable(pdata);
-+	xgene_gmac_rx_disable(pdata);
++	for (i = 0; i < nval; i++) {
++		if (items[i].type != ACPI_TYPE_INTEGER)
++			return -EPROTO;
 +
++		val[i] = items[i].integer.value;
++	}
 +	return 0;
 +}
 +
-+static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
++static int acpi_copy_property_array_string(const union acpi_object *items,
++					   char **val, size_t nval)
 +{
-+	struct xgene_enet_pdata *pdata;
-+	struct device *dev;
++	int i;
 +
-+	pdata = netdev_priv(ring->ndev);
-+	dev = ndev_to_dev(ring->ndev);
++	for (i = 0; i < nval; i++) {
++		if (items[i].type != ACPI_TYPE_STRING)
++			return -EPROTO;
 +
-+	xgene_enet_clear_ring(ring);
-+	dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
++		val[i] = items[i].string.pointer;
++	}
++	return 0;
 +}
 +
-+static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
++int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
++		       enum dev_prop_type proptype, void *val, size_t nval)
 +{
-+	struct xgene_enet_desc_ring *buf_pool;
++	const union acpi_object *obj;
++	const union acpi_object *items;
++	int ret;
 +
-+	if (pdata->tx_ring) {
-+		xgene_enet_delete_ring(pdata->tx_ring);
-+		pdata->tx_ring = NULL;
++	if (val && nval == 1) {
++		ret = acpi_dev_prop_read_single(adev, propname, proptype, val);
++		if (!ret)
++			return ret;
 +	}
 +
-+	if (pdata->rx_ring) {
-+		buf_pool = pdata->rx_ring->buf_pool;
-+		xgene_enet_delete_bufpool(buf_pool);
-+		xgene_enet_delete_ring(buf_pool);
-+		xgene_enet_delete_ring(pdata->rx_ring);
-+		pdata->rx_ring = NULL;
-+	}
-+}
++	ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
++	if (ret)
++		return ret;
 +
-+static int xgene_enet_get_ring_size(struct device *dev,
-+				    enum xgene_enet_ring_cfgsize cfgsize)
-+{
-+	int size = -EINVAL;
++	if (!val)
++		return obj->package.count;
++	else if (nval <= 0)
++		return -EINVAL;
++
++	if (nval > obj->package.count)
++		return -EOVERFLOW;
 +
-+	switch (cfgsize) {
-+	case RING_CFGSIZE_512B:
-+		size = 0x200;
++	items = obj->package.elements;
++	switch (proptype) {
++	case DEV_PROP_U8:
++		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
 +		break;
-+	case RING_CFGSIZE_2KB:
-+		size = 0x800;
++	case DEV_PROP_U16:
++		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
 +		break;
-+	case RING_CFGSIZE_16KB:
-+		size = 0x4000;
++	case DEV_PROP_U32:
++		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
 +		break;
-+	case RING_CFGSIZE_64KB:
-+		size = 0x10000;
++	case DEV_PROP_U64:
++		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
 +		break;
-+	case RING_CFGSIZE_512KB:
-+		size = 0x80000;
++	case DEV_PROP_STRING:
++		ret = acpi_copy_property_array_string(items, (char **)val, nval);
 +		break;
 +	default:
-+		dev_err(dev, "Unsupported cfg ring size %d\n", cfgsize);
++		ret = -EINVAL;
 +		break;
 +	}
-+
-+	return size;
++	return ret;
 +}
-+
-+static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 0476e90..9cb5cca 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -124,17 +124,56 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
+ 	if (list_empty(&acpi_dev->pnp.ids))
+ 		return 0;
+ 
+-	len = snprintf(modalias, size, "acpi:");
+-	size -= len;
+-
+-	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+-		count = snprintf(&modalias[len], size, "%s:", id->id);
+-		if (count < 0)
+-			return -EINVAL;
+-		if (count >= size)
+-			return -ENOMEM;
+-		len += count;
+-		size -= count;
++	/*
++	 * If the device has PRP0001 we expose DT compatible modalias
++	 * instead in form of of:NnameTCcompatible.
++	 */
++	if (acpi_dev->data.of_compatible) {
++		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
++		const union acpi_object *of_compatible, *obj;
++		int i, nval;
++		char *c;
++
++		acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
++		/* DT strings are all in lower case */
++		for (c = buf.pointer; *c != '\0'; c++)
++			*c = tolower(*c);
++
++		len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
++		ACPI_FREE(buf.pointer);
++
++		of_compatible = acpi_dev->data.of_compatible;
++		if (of_compatible->type == ACPI_TYPE_PACKAGE) {
++			nval = of_compatible->package.count;
++			obj = of_compatible->package.elements;
++		} else { /* Must be ACPI_TYPE_STRING. */
++			nval = 1;
++			obj = of_compatible;
++		}
++		for (i = 0; i < nval; i++, obj++) {
++			count = snprintf(&modalias[len], size, "C%s",
++					 obj->string.pointer);
++			if (count < 0)
++				return -EINVAL;
++			if (count >= size)
++				return -ENOMEM;
++
++			len += count;
++			size -= count;
++		}
++	} else {
++		len = snprintf(modalias, size, "acpi:");
++		size -= len;
++
++		list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
++			count = snprintf(&modalias[len], size, "%s:", id->id);
++			if (count < 0)
++				return -EINVAL;
++			if (count >= size)
++				return -ENOMEM;
++			len += count;
++			size -= count;
++		}
+ 	}
+ 
+ 	modalias[len] = '\0';
+@@ -902,6 +941,51 @@ int acpi_match_device_ids(struct acpi_device *device,
+ }
+ EXPORT_SYMBOL(acpi_match_device_ids);
+ 
++/* Performs match against special "PRP0001" shoehorn ACPI ID */
++static bool acpi_of_driver_match_device(struct device *dev,
++					const struct device_driver *drv)
 +{
-+	struct device *dev;
++	const union acpi_object *of_compatible, *obj;
++	struct acpi_device *adev;
++	int i, nval;
 +
-+	if (!ring)
-+		return;
++	adev = ACPI_COMPANION(dev);
++	if (!adev)
++		return false;
++
++	of_compatible = adev->data.of_compatible;
++	if (!drv->of_match_table || !of_compatible)
++		return false;
 +
-+	dev = ndev_to_dev(ring->ndev);
++	if (of_compatible->type == ACPI_TYPE_PACKAGE) {
++		nval = of_compatible->package.count;
++		obj = of_compatible->package.elements;
++	} else { /* Must be ACPI_TYPE_STRING. */
++		nval = 1;
++		obj = of_compatible;
++	}
++	/* Now we can look for the driver DT compatible strings */
++	for (i = 0; i < nval; i++, obj++) {
++		const struct of_device_id *id;
 +
-+	if (ring->desc_addr) {
-+		xgene_enet_clear_ring(ring);
-+		dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
++		for (id = drv->of_match_table; id->compatible[0]; id++)
++			if (!strcasecmp(obj->string.pointer, id->compatible))
++				return true;
 +	}
-+	devm_kfree(dev, ring);
++
++	return false;
 +}
 +
-+static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
++bool acpi_driver_match_device(struct device *dev,
++			      const struct device_driver *drv)
 +{
-+	struct device *dev = &pdata->pdev->dev;
-+	struct xgene_enet_desc_ring *ring;
-+
-+	ring = pdata->tx_ring;
-+	if (ring && ring->cp_ring && ring->cp_ring->cp_skb)
-+		devm_kfree(dev, ring->cp_ring->cp_skb);
-+	xgene_enet_free_desc_ring(ring);
++	if (!drv->acpi_match_table)
++		return acpi_of_driver_match_device(dev, drv);
 +
-+	ring = pdata->rx_ring;
-+	if (ring && ring->buf_pool && ring->buf_pool->rx_skb)
-+		devm_kfree(dev, ring->buf_pool->rx_skb);
-+	xgene_enet_free_desc_ring(ring->buf_pool);
-+	xgene_enet_free_desc_ring(ring);
++	return !!acpi_match_device(drv->acpi_match_table, dev);
 +}
++EXPORT_SYMBOL_GPL(acpi_driver_match_device);
 +
-+static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
-+			struct net_device *ndev, u32 ring_num,
-+			enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id)
+ static void acpi_free_power_resources_lists(struct acpi_device *device)
+ {
+ 	int i;
+@@ -922,6 +1006,7 @@ static void acpi_device_release(struct device *dev)
+ {
+ 	struct acpi_device *acpi_dev = to_acpi_device(dev);
+ 
++	acpi_free_properties(acpi_dev);
+ 	acpi_free_pnp_ids(&acpi_dev->pnp);
+ 	acpi_free_power_resources_lists(acpi_dev);
+ 	kfree(acpi_dev);
+@@ -1304,6 +1389,26 @@ int acpi_device_add(struct acpi_device *device,
+ 	return result;
+ }
+ 
++struct acpi_device *acpi_get_next_child(struct device *dev,
++					struct acpi_device *child)
 +{
-+	struct xgene_enet_desc_ring *ring;
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct device *dev = ndev_to_dev(ndev);
-+	u32 size;
++	struct acpi_device *adev = ACPI_COMPANION(dev);
++	struct list_head *head, *next;
 +
-+	ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring),
-+			    GFP_KERNEL);
-+	if (!ring)
++	if (!adev)
 +		return NULL;
 +
-+	ring->ndev = ndev;
-+	ring->num = ring_num;
-+	ring->cfgsize = cfgsize;
-+	ring->id = ring_id;
-+
-+	size = xgene_enet_get_ring_size(dev, cfgsize);
-+	ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
-+					      GFP_KERNEL);
-+	if (!ring->desc_addr) {
-+		devm_kfree(dev, ring);
++	head = &adev->children;
++	if (list_empty(head))
 +		return NULL;
-+	}
-+	ring->size = size;
 +
-+	ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
-+	ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
-+	pdata->rm = RM3;
-+	ring = xgene_enet_setup_ring(ring);
-+	netdev_dbg(ndev, "ring info: num=%d  size=%d  id=%d  slots=%d\n",
-+		   ring->num, ring->size, ring->id, ring->slots);
++	if (!child)
++		return list_first_entry(head, struct acpi_device, node);
++
++	next = child->node.next;
++	return next == head ? NULL : list_entry(next, struct acpi_device, node);
++}
++
+ /* --------------------------------------------------------------------------
+                                  Driver Management
+    -------------------------------------------------------------------------- */
+@@ -1923,9 +2028,11 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
+ 	device->device_type = type;
+ 	device->handle = handle;
+ 	device->parent = acpi_bus_get_parent(handle);
++	device->fwnode.type = FWNODE_ACPI;
+ 	acpi_set_device_status(device, sta);
+ 	acpi_device_get_busid(device);
+ 	acpi_set_pnp_ids(handle, &device->pnp, type);
++	acpi_init_properties(device);
+ 	acpi_bus_get_flags(device);
+ 	device->flags.match_driver = false;
+ 	device->flags.initialized = true;
+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.
++ */
 +
-+	return ring;
-+}
++#include <linux/acpi.h>
 +
-+static u16 xgene_enet_get_ring_id(enum xgene_ring_owner owner, u8 bufnum)
++/*
++ * 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 (owner << 6) | (bufnum & GENMASK(5, 0));
++	return ACPI_STATE_S0;
 +}
++EXPORT_SYMBOL_GPL(acpi_target_system_state);
 +
-+static int xgene_enet_create_desc_rings(struct net_device *ndev)
++int __init acpi_sleep_init(void)
 +{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct device *dev = ndev_to_dev(ndev);
-+	struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
-+	struct xgene_enet_desc_ring *buf_pool = NULL;
-+	u8 cpu_bufnum = 0, eth_bufnum = 0;
-+	u8 bp_bufnum = 0x20;
-+	u16 ring_id, ring_num = 0;
-+	int ret;
++	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");
 +
-+	/* allocate rx descriptor ring */
-+	ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
-+	rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
-+					      RING_CFGSIZE_16KB, ring_id);
-+	if (!rx_ring) {
-+		ret = -ENOMEM;
-+		goto err;
-+	}
++		}
++		break;
 +
-+	/* allocate buffer pool for receiving packets */
-+	ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, bp_bufnum++);
-+	buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
-+					       RING_CFGSIZE_2KB, ring_id);
-+	if (!buf_pool) {
-+		ret = -ENOMEM;
-+		goto err;
-+	}
++	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;
 +
-+	rx_ring->nbufpool = NUM_BUFPOOL;
-+	rx_ring->buf_pool = buf_pool;
-+	rx_ring->irq = pdata->rx_irq;
-+	buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
-+				     sizeof(struct sk_buff *), GFP_KERNEL);
-+	if (!buf_pool->rx_skb) {
-+		ret = -ENOMEM;
-+		goto err;
-+	}
-+
-+	buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
-+	rx_ring->buf_pool = buf_pool;
-+	pdata->rx_ring = rx_ring;
-+
-+	/* allocate tx descriptor ring */
-+	ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, eth_bufnum++);
-+	tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
-+					      RING_CFGSIZE_16KB, ring_id);
-+	if (!tx_ring) {
-+		ret = -ENOMEM;
-+		goto err;
-+	}
-+	pdata->tx_ring = tx_ring;
-+
-+	cp_ring = pdata->rx_ring;
-+	cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
-+				     sizeof(struct sk_buff *), GFP_KERNEL);
-+	if (!cp_ring->cp_skb) {
-+		ret = -ENOMEM;
-+		goto err;
-+	}
-+	pdata->tx_ring->cp_ring = cp_ring;
-+	pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
++	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;
 +
-+	pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2;
-+	pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2;
-+	pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2;
++	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;
 +
-+	return 0;
+ 	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)
+ 
+ 
+ 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);
+ 	}
 +
-+err:
-+	xgene_enet_free_desc_rings(pdata);
-+	return ret;
+ 	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:
 +}
 +
-+static struct rtnl_link_stats64 *xgene_enet_get_stats64(
-+			struct net_device *ndev,
-+			struct rtnl_link_stats64 *storage)
++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 xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	struct rtnl_link_stats64 *stats = &pdata->stats;
++	struct acpi_table_header *table_header = NULL;
++	acpi_size tbl_size;
++	int count;
 +
-+	spin_lock(&pdata->stats_lock);
-+	stats->rx_errors += stats->rx_length_errors +
-+			    stats->rx_crc_errors +
-+			    stats->rx_frame_errors +
-+			    stats->rx_fifo_errors;
-+	memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
-+	spin_unlock(&pdata->stats_lock);
++	if (acpi_disabled)
++		return -ENODEV;
 +
-+	return storage;
-+}
++	if (!handler)
++		return -EINVAL;
 +
-+static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
-+{
-+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-+	int ret;
++	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);
 +
-+	ret = eth_mac_addr(ndev, addr);
-+	if (ret)
-+		return ret;
-+	xgene_gmac_set_mac_addr(pdata);
++	if (!table_header) {
++		pr_warn("%4.4s not present\n", id);
++		return -ENODEV;
++	}
 +
-+	return ret;
-+}
++	count = acpi_parse_entries(table_size, handler, table_header,
++			entry_id, max_entries);
 +
-+static const struct net_device_ops xgene_ndev_ops = {
-+	.ndo_open = xgene_enet_open,
-+	.ndo_stop = xgene_enet_close,
-+	.ndo_start_xmit = xgene_enet_start_xmit,
-+	.ndo_tx_timeout = xgene_enet_timeout,
-+	.ndo_get_stats64 = xgene_enet_get_stats64,
-+	.ndo_change_mtu = eth_change_mtu,
-+	.ndo_set_mac_address = xgene_enet_set_mac_address,
-+};
+ 	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
+-	return -EINVAL;
++	return count;
+ }
+ 
+ int __init
+diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
+index 371ac12..af325a7 100644
+--- a/drivers/acpi/utils.c
++++ b/drivers/acpi/utils.c
+@@ -723,3 +723,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
+ 	return false;
+ }
+ EXPORT_SYMBOL(acpi_check_dsm);
 +
-+static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
++/**
++ * acpi_check_coherency - check for memory coherency of a device
++ * @handle: ACPI device handle
++ * @val:    Pointer to returned value
++ *
++ * Search a device and its parents for a _CCA method and return
++ * its value.
++ */
++acpi_status acpi_check_coherency(acpi_handle handle, int *val)
 +{
-+	struct platform_device *pdev;
-+	struct net_device *ndev;
-+	struct device *dev;
-+	struct resource *res;
-+	void *base_addr;
-+	const char *mac;
-+	int ret;
-+
-+	pdev = pdata->pdev;
-+	dev = &pdev->dev;
-+	ndev = pdata->ndev;
-+
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr");
-+	if (!res) {
-+		dev_err(dev, "Resource enet_csr not defined\n");
-+		return -ENODEV;
-+	}
-+	pdata->base_addr = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pdata->base_addr)) {
-+		dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
-+		return PTR_ERR(pdata->base_addr);
-+	}
-+
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr");
-+	if (!res) {
-+		dev_err(dev, "Resource ring_csr not defined\n");
-+		return -ENODEV;
-+	}
-+	pdata->ring_csr_addr = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pdata->ring_csr_addr)) {
-+		dev_err(dev, "Unable to retrieve ENET Ring CSR region\n");
-+		return PTR_ERR(pdata->ring_csr_addr);
-+	}
++	unsigned long long data;
++	acpi_status status;
 +
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd");
-+	if (!res) {
-+		dev_err(dev, "Resource ring_cmd not defined\n");
-+		return -ENODEV;
-+	}
-+	pdata->ring_cmd_addr = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pdata->ring_cmd_addr)) {
-+		dev_err(dev, "Unable to retrieve ENET Ring command region\n");
-+		return PTR_ERR(pdata->ring_cmd_addr);
-+	}
++	do {
++		status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
++		if (!ACPI_FAILURE(status)) {
++			*val = data;
++			break;
++		}
++		status = acpi_get_parent(handle, &handle);
++	} while (!ACPI_FAILURE(status));
++
++	return status;
++}
++EXPORT_SYMBOL(acpi_check_coherency);
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index cd4cccb..edb00c6 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 06f1d59..df2ea85 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 = {
+@@ -71,6 +74,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
 +
-+	ret = platform_get_irq(pdev, 0);
-+	if (ret <= 0) {
-+		dev_err(dev, "Unable to get ENET Rx IRQ\n");
-+		ret = ret ? : -ENXIO;
-+		return ret;
-+	}
-+	pdata->rx_irq = ret;
+ static struct platform_driver ahci_driver = {
+ 	.probe = ahci_probe,
+ 	.remove = ata_platform_remove_one,
+@@ -78,6 +88,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 0f8538f..2d8103a 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"
+ 
+ /* 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;
+ }
+ 
+-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
+@@ -501,11 +495,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)
+@@ -518,7 +507,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
+ 
+ 	/* Configure the host controller */
+ 	xgene_ahci_hw_init(hpriv);
+-skip_clk_phy:
 +
-+	mac = of_get_mac_address(dev->of_node);
-+	if (mac)
-+		memcpy(ndev->dev_addr, mac, ndev->addr_len);
-+	else
-+		eth_hw_addr_random(ndev);
-+	memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+ 	hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ;
+ 
+ 	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info);
+@@ -533,6 +522,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
 +
-+	pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
-+	if (pdata->phy_mode < 0) {
-+		dev_err(dev, "Incorrect phy-connection-type in DTS\n");
-+		return -EINVAL;
-+	}
+ static const struct of_device_id xgene_ahci_of_match[] = {
+ 	{.compatible = "apm,xgene-ahci"},
+ 	{},
+@@ -546,6 +545,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/base/Makefile b/drivers/base/Makefile
+index 6922cd6..53c3fe1 100644
+--- a/drivers/base/Makefile
++++ b/drivers/base/Makefile
+@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
+ 			   driver.o class.o platform.o \
+ 			   cpu.o firmware.o init.o map.o devres.o \
+ 			   attribute_container.o transport_class.o \
+-			   topology.o container.o
++			   topology.o container.o property.o
+ obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
+ obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
+ obj-y			+= power/
+diff --git a/drivers/base/property.c b/drivers/base/property.c
+new file mode 100644
+index 0000000..c458458
+--- /dev/null
++++ b/drivers/base/property.c
+@@ -0,0 +1,431 @@
++/*
++ * property.c - Unified device property interface.
++ *
++ * Copyright (C) 2014, Intel Corporation
++ * Authors: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
++ *          Mika Westerberg <mika.westerberg at linux.intel.com>
++ *
++ * 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.
++ */
 +
-+	pdata->clk = devm_clk_get(&pdev->dev, NULL);
-+	ret = IS_ERR(pdata->clk);
-+	if (IS_ERR(pdata->clk)) {
-+		dev_err(&pdev->dev, "can't get clock\n");
-+		ret = PTR_ERR(pdata->clk);
-+		return ret;
-+	}
++#include <linux/property.h>
++#include <linux/export.h>
++#include <linux/acpi.h>
++#include <linux/of.h>
 +
-+	base_addr = pdata->base_addr;
-+	pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
-+	pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
-+	pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
-+	pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
-+	pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET;
-+	pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
-+	pdata->rx_buff_cnt = NUM_PKT_BUF;
++/**
++ * device_property_present - check if a property of a device is present
++ * @dev: Device whose property is being checked
++ * @propname: Name of the property
++ *
++ * Check if property @propname is present in the device firmware description.
++ */
++bool device_property_present(struct device *dev, const char *propname)
++{
++	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
++		return of_property_read_bool(dev->of_node, propname);
 +
-+	return ret;
++	return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL);
 +}
++EXPORT_SYMBOL_GPL(device_property_present);
 +
-+static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
++/**
++ * fwnode_property_present - check if a property of a firmware node is present
++ * @fwnode: Firmware node whose property to check
++ * @propname: Name of the property
++ */
++bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
 +{
-+	struct net_device *ndev = pdata->ndev;
-+	struct xgene_enet_desc_ring *buf_pool;
-+	u16 dst_ring_num;
-+	int ret;
++	if (is_of_node(fwnode))
++		return of_property_read_bool(of_node(fwnode), propname);
++	else if (is_acpi_node(fwnode))
++		return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
 +
-+	xgene_gmac_tx_disable(pdata);
-+	xgene_gmac_rx_disable(pdata);
-+
-+	ret = xgene_enet_create_desc_rings(ndev);
-+	if (ret) {
-+		netdev_err(ndev, "Error in ring configuration\n");
-+		return ret;
-+	}
++	return false;
++}
++EXPORT_SYMBOL_GPL(fwnode_property_present);
 +
-+	/* setup buffer pool */
-+	buf_pool = pdata->rx_ring->buf_pool;
-+	xgene_enet_init_bufpool(buf_pool);
-+	ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
-+	if (ret)
-+		return ret;
++#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
++	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
++	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
 +
-+	dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
-+	xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id);
++#define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \
++	IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \
++		(OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \
++					_val_, _nval_)) : \
++		acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \
++				   _proptype_, _val_, _nval_)
 +
-+	return ret;
++/**
++ * device_property_read_u8_array - return a u8 array property of a device
++ * @dev: Device to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Function reads an array of u8 properties with @propname from the device
++ * firmware description and stores them to @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected.
++ */
++int device_property_read_u8_array(struct device *dev, const char *propname,
++				  u8 *val, size_t nval)
++{
++	return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval);
 +}
++EXPORT_SYMBOL_GPL(device_property_read_u8_array);
 +
-+static int xgene_enet_probe(struct platform_device *pdev)
++/**
++ * device_property_read_u16_array - return a u16 array property of a device
++ * @dev: Device to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Function reads an array of u16 properties with @propname from the device
++ * firmware description and stores them to @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected.
++ */
++int device_property_read_u16_array(struct device *dev, const char *propname,
++				   u16 *val, size_t nval)
 +{
-+	struct net_device *ndev;
-+	struct xgene_enet_pdata *pdata;
-+	struct device *dev = &pdev->dev;
-+	struct napi_struct *napi;
-+	int ret;
++	return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval);
++}
++EXPORT_SYMBOL_GPL(device_property_read_u16_array);
 +
-+	ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
-+	if (!ndev)
-+		return -ENOMEM;
++/**
++ * device_property_read_u32_array - return a u32 array property of a device
++ * @dev: Device to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Function reads an array of u32 properties with @propname from the device
++ * firmware description and stores them to @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected.
++ */
++int device_property_read_u32_array(struct device *dev, const char *propname,
++				   u32 *val, size_t nval)
++{
++	return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval);
++}
++EXPORT_SYMBOL_GPL(device_property_read_u32_array);
 +
-+	pdata = netdev_priv(ndev);
++/**
++ * device_property_read_u64_array - return a u64 array property of a device
++ * @dev: Device to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Function reads an array of u64 properties with @propname from the device
++ * firmware description and stores them to @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected.
++ */
++int device_property_read_u64_array(struct device *dev, const char *propname,
++				   u64 *val, size_t nval)
++{
++	return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval);
++}
++EXPORT_SYMBOL_GPL(device_property_read_u64_array);
 +
-+	pdata->pdev = pdev;
-+	pdata->ndev = ndev;
-+	SET_NETDEV_DEV(ndev, dev);
-+	platform_set_drvdata(pdev, pdata);
-+	ndev->netdev_ops = &xgene_ndev_ops;
-+	xgene_enet_set_ethtool_ops(ndev);
-+	ndev->features |= NETIF_F_IP_CSUM |
-+			  NETIF_F_GSO |
-+			  NETIF_F_GRO;
++/**
++ * device_property_read_string_array - return a string array property of device
++ * @dev: Device to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Function reads an array of string properties with @propname from the device
++ * firmware description and stores them to @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
++ *	   %-EOVERFLOW if the size of the property is not as expected.
++ */
++int device_property_read_string_array(struct device *dev, const char *propname,
++				      const char **val, size_t nval)
++{
++	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
++		of_property_read_string_array(dev->of_node, propname, val, nval) :
++		acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
++				   DEV_PROP_STRING, val, nval);
++}
++EXPORT_SYMBOL_GPL(device_property_read_string_array);
 +
-+	ret = xgene_enet_get_resources(pdata);
-+	if (ret)
-+		goto err;
++/**
++ * device_property_read_string - return a string property of a device
++ * @dev: Device to get the property of
++ * @propname: Name of the property
++ * @val: The value is stored here
++ *
++ * Function reads property @propname from the device firmware description and
++ * stores the value into @val if found. The value is checked to be a string.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO or %-EILSEQ if the property type is not a string.
++ */
++int device_property_read_string(struct device *dev, const char *propname,
++				const char **val)
++{
++	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
++		of_property_read_string(dev->of_node, propname, val) :
++		acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
++				   DEV_PROP_STRING, val, 1);
++}
++EXPORT_SYMBOL_GPL(device_property_read_string);
++
++#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
++({ \
++	int _ret_; \
++	if (is_of_node(_fwnode_)) \
++		_ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \
++					       _type_, _val_, _nval_); \
++	else if (is_acpi_node(_fwnode_)) \
++		_ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \
++					   _proptype_, _val_, _nval_); \
++	else \
++		_ret_ = -ENXIO; \
++	_ret_; \
++})
 +
-+	xgene_enet_reset(pdata);
-+	xgene_gmac_init(pdata, SPEED_1000);
++/**
++ * fwnode_property_read_u8_array - return a u8 array property of firmware node
++ * @fwnode: Firmware node to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Read an array of u8 properties with @propname from @fwnode and stores them to
++ * @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected,
++ *	   %-ENXIO if no suitable firmware interface is present.
++ */
++int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
++				  const char *propname, u8 *val, size_t nval)
++{
++	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
++				      val, nval);
++}
++EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
 +
-+	spin_lock_init(&pdata->stats_lock);
-+	ret = register_netdev(ndev);
-+	if (ret) {
-+		netdev_err(ndev, "Failed to register netdev\n");
-+		goto err;
-+	}
++/**
++ * fwnode_property_read_u16_array - return a u16 array property of firmware node
++ * @fwnode: Firmware node to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Read an array of u16 properties with @propname from @fwnode and store them to
++ * @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected,
++ *	   %-ENXIO if no suitable firmware interface is present.
++ */
++int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
++				   const char *propname, u16 *val, size_t nval)
++{
++	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
++				      val, nval);
++}
++EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
 +
-+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
-+	if (ret) {
-+		netdev_err(ndev, "No usable DMA configuration\n");
-+		goto err;
-+	}
++/**
++ * fwnode_property_read_u32_array - return a u32 array property of firmware node
++ * @fwnode: Firmware node to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Read an array of u32 properties with @propname from @fwnode store them to
++ * @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected,
++ *	   %-ENXIO if no suitable firmware interface is present.
++ */
++int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
++				   const char *propname, u32 *val, size_t nval)
++{
++	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
++				      val, nval);
++}
++EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
 +
-+	ret = xgene_enet_init_hw(pdata);
-+	if (ret)
-+		goto err;
++/**
++ * fwnode_property_read_u64_array - return a u64 array property firmware node
++ * @fwnode: Firmware node to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Read an array of u64 properties with @propname from @fwnode and store them to
++ * @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of numbers,
++ *	   %-EOVERFLOW if the size of the property is not as expected,
++ *	   %-ENXIO if no suitable firmware interface is present.
++ */
++int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
++				   const char *propname, u64 *val, size_t nval)
++{
++	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
++				      val, nval);
++}
++EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
 +
-+	napi = &pdata->rx_ring->napi;
-+	netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
-+	ret = xgene_enet_mdio_config(pdata);
++/**
++ * fwnode_property_read_string_array - return string array property of a node
++ * @fwnode: Firmware node to get the property of
++ * @propname: Name of the property
++ * @val: The values are stored here
++ * @nval: Size of the @val array
++ *
++ * Read an string list property @propname from the given firmware node and store
++ * them to @val if found.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO if the property is not an array of strings,
++ *	   %-EOVERFLOW if the size of the property is not as expected,
++ *	   %-ENXIO if no suitable firmware interface is present.
++ */
++int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
++				      const char *propname, const char **val,
++				      size_t nval)
++{
++	if (is_of_node(fwnode))
++		return of_property_read_string_array(of_node(fwnode), propname,
++						     val, nval);
++	else if (is_acpi_node(fwnode))
++		return acpi_dev_prop_read(acpi_node(fwnode), propname,
++					  DEV_PROP_STRING, val, nval);
 +
-+	return ret;
-+err:
-+	free_netdev(ndev);
-+	return ret;
++	return -ENXIO;
 +}
++EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
 +
-+static int xgene_enet_remove(struct platform_device *pdev)
++/**
++ * fwnode_property_read_string - return a string property of a firmware node
++ * @fwnode: Firmware node to get the property of
++ * @propname: Name of the property
++ * @val: The value is stored here
++ *
++ * Read property @propname from the given firmware node and store the value into
++ * @val if found.  The value is checked to be a string.
++ *
++ * Return: %0 if the property was found (success),
++ *	   %-EINVAL if given arguments are not valid,
++ *	   %-ENODATA if the property does not have a value,
++ *	   %-EPROTO or %-EILSEQ if the property is not a string,
++ *	   %-ENXIO if no suitable firmware interface is present.
++ */
++int fwnode_property_read_string(struct fwnode_handle *fwnode,
++				const char *propname, const char **val)
 +{
-+	struct xgene_enet_pdata *pdata;
-+	struct net_device *ndev;
++	if (is_of_node(fwnode))
++		return of_property_read_string(of_node(fwnode),propname, val);
++	else if (is_acpi_node(fwnode))
++		return acpi_dev_prop_read(acpi_node(fwnode), propname,
++					  DEV_PROP_STRING, val, 1);
 +
-+	pdata = platform_get_drvdata(pdev);
-+	ndev = pdata->ndev;
++	return -ENXIO;
++}
++EXPORT_SYMBOL_GPL(fwnode_property_read_string);
 +
-+	xgene_gmac_rx_disable(pdata);
-+	xgene_gmac_tx_disable(pdata);
++/**
++ * device_get_next_child_node - Return the next child node handle for a device
++ * @dev: Device to find the next child node for.
++ * @child: Handle to one of the device's child nodes or a null handle.
++ */
++struct fwnode_handle *device_get_next_child_node(struct device *dev,
++						 struct fwnode_handle *child)
++{
++	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
++		struct device_node *node;
 +
-+	netif_napi_del(&pdata->rx_ring->napi);
-+	xgene_enet_mdio_remove(pdata);
-+	xgene_enet_delete_desc_rings(pdata);
-+	unregister_netdev(ndev);
-+	xgene_gport_shutdown(pdata);
-+	free_netdev(ndev);
++		node = of_get_next_available_child(dev->of_node, of_node(child));
++		if (node)
++			return &node->fwnode;
++	} else if (IS_ENABLED(CONFIG_ACPI)) {
++		struct acpi_device *node;
 +
-+	return 0;
++		node = acpi_get_next_child(dev, acpi_node(child));
++		if (node)
++			return acpi_fwnode_handle(node);
++	}
++	return NULL;
 +}
++EXPORT_SYMBOL_GPL(device_get_next_child_node);
 +
-+static struct of_device_id xgene_enet_match[] = {
-+	{.compatible = "apm,xgene-enet",},
-+	{},
-+};
-+
-+MODULE_DEVICE_TABLE(of, xgene_enet_match);
++/**
++ * fwnode_handle_put - Drop reference to a device node
++ * @fwnode: Pointer to the device node to drop the reference to.
++ *
++ * This has to be used when terminating device_for_each_child_node() iteration
++ * with break or return to prevent stale device node references from being left
++ * behind.
++ */
++void fwnode_handle_put(struct fwnode_handle *fwnode)
++{
++	if (is_of_node(fwnode))
++		of_node_put(of_node(fwnode));
++}
++EXPORT_SYMBOL_GPL(fwnode_handle_put);
 +
-+static struct platform_driver xgene_enet_driver = {
-+	.driver = {
-+		   .name = "xgene-enet",
-+		   .owner = THIS_MODULE,
-+		   .of_match_table = xgene_enet_match,
-+		   },
-+	.probe = xgene_enet_probe,
-+	.remove = xgene_enet_remove,
-+};
++/**
++ * device_get_child_node_count - return the number of child nodes for device
++ * @dev: Device to cound the child nodes for
++ */
++unsigned int device_get_child_node_count(struct device *dev)
++{
++	struct fwnode_handle *child;
++	unsigned int count = 0;
 +
-+module_platform_driver(xgene_enet_driver);
++	device_for_each_child_node(dev, child)
++		count++;
 +
-+MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver");
-+MODULE_VERSION(XGENE_DRV_VERSION);
-+MODULE_AUTHOR("Keyur Chudgar <kchudgar at apm.com>");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
-new file mode 100644
-index 0000000..f4f7e4a
---- /dev/null
-+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
-@@ -0,0 +1,107 @@
-+/* Applied Micro X-Gene SoC Ethernet Driver
-+ *
-+ * Copyright (c) 2014, Applied Micro Circuits Corporation
-+ * Authors: Iyappan Subramanian <isubramanian at apm.com>
-+ *	    Ravi Patel <rapatel at apm.com>
-+ *	    Keyur Chudgar <kchudgar 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.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+ */
++	return count;
++}
++EXPORT_SYMBOL_GPL(device_get_child_node_count);
+diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
+index 43005d4..c9411e6 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;
+ 
+@@ -370,8 +372,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
+@@ -687,20 +693,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
+@@ -719,13 +713,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);
 +
-+#ifndef __XGENE_ENET_MAIN_H__
-+#define __XGENE_ENET_MAIN_H__
++static void __init arch_timer_of_init(struct device_node *np)
++{
++	int i;
 +
-+#include <linux/clk.h>
-+#include <linux/of_platform.h>
-+#include <linux/of_net.h>
-+#include <linux/of_mdio.h>
-+#include <linux/module.h>
-+#include <net/ip.h>
-+#include <linux/prefetch.h>
-+#include <linux/if_vlan.h>
-+#include <linux/phy.h>
-+#include "xgene_enet_hw.h"
-+
-+#define XGENE_DRV_VERSION	"v1.0"
-+#define XGENE_ENET_MAX_MTU	1536
-+#define SKB_BUFFER_SIZE		(XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
-+#define NUM_PKT_BUF	64
-+#define NUM_BUFPOOL	32
-+
-+/* software context of a descriptor ring */
-+struct xgene_enet_desc_ring {
-+	struct net_device *ndev;
-+	u16 id;
-+	u16 num;
-+	u16 head;
-+	u16 tail;
-+	u16 slots;
-+	u16 irq;
-+	u32 size;
-+	u32 state[NUM_RING_CONFIG];
-+	void __iomem *cmd_base;
-+	void __iomem *cmd;
-+	dma_addr_t dma;
-+	u16 dst_ring_num;
-+	u8 nbufpool;
-+	struct sk_buff *(*rx_skb);
-+	struct sk_buff *(*cp_skb);
-+	enum xgene_enet_ring_cfgsize cfgsize;
-+	struct xgene_enet_desc_ring *cp_ring;
-+	struct xgene_enet_desc_ring *buf_pool;
-+	struct napi_struct napi;
-+	union {
-+		void *desc_addr;
-+		struct xgene_enet_raw_desc *raw_desc;
-+		struct xgene_enet_raw_desc16 *raw_desc16;
-+	};
-+};
++	if (arch_timers_present & ARCH_CP15_TIMER) {
++		pr_warn("arch_timer: multiple nodes in dt, skipping\n");
++		return;
++	}
 +
-+/* ethernet private data */
-+struct xgene_enet_pdata {
-+	struct net_device *ndev;
-+	struct mii_bus *mdio_bus;
-+	struct phy_device *phy_dev;
-+	int phy_speed;
-+	struct clk *clk;
-+	struct platform_device *pdev;
-+	struct xgene_enet_desc_ring *tx_ring;
-+	struct xgene_enet_desc_ring *rx_ring;
-+	char *dev_name;
-+	u32 rx_buff_cnt;
-+	u32 tx_qcnt_hi;
-+	u32 cp_qcnt_hi;
-+	u32 cp_qcnt_low;
-+	u32 rx_irq;
-+	void __iomem *eth_csr_addr;
-+	void __iomem *eth_ring_if_addr;
-+	void __iomem *eth_diag_csr_addr;
-+	void __iomem *mcx_mac_addr;
-+	void __iomem *mcx_stats_addr;
-+	void __iomem *mcx_mac_csr_addr;
-+	void __iomem *base_addr;
-+	void __iomem *ring_csr_addr;
-+	void __iomem *ring_cmd_addr;
-+	u32 phy_addr;
-+	int phy_mode;
-+	u32 speed;
-+	u16 rm;
-+	struct rtnl_link_stats64 stats;
-+	/* statistics lock */
-+	spinlock_t stats_lock;
-+};
++	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);
 +
-+void xgene_enet_set_ethtool_ops(struct net_device *netdev);
++	arch_timer_detect_rate(NULL, np);
 +
-+#endif /* __XGENE_ENET_MAIN_H__ */
-diff --git a/drivers/of/address.c b/drivers/of/address.c
-index 5edfcb0..cbbaed2 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>
++	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
++
++	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);
  
- /* 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 __init arch_timer_mem_init(struct device_node *np)
+ {
+@@ -792,3 +804,71 @@ static void __init arch_timer_mem_init(struct device_node *np)
  }
- EXPORT_SYMBOL(of_get_address);
- 
-+struct io_range {
-+	struct list_head list;
-+	phys_addr_t start;
-+	resource_size_t size;
-+};
+ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
+ 		       arch_timer_mem_init);
++
++#ifdef CONFIG_ACPI
++static int __init
++map_generic_timer_interrupt(u32 interrupt, u32 flags)
++{
++	int trigger, polarity;
 +
-+static LIST_HEAD(io_range_list);
++	if (!interrupt)
++		return 0;
 +
-+/*
-+ * 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)
++	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
++			: ACPI_LEVEL_SENSITIVE;
++
++	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
++			: ACPI_ACTIVE_HIGH;
++
++	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
++}
++
++/* Initialize per-processor generic timer */
++static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 +{
-+#ifdef PCI_IOBASE
-+	struct io_range *res;
-+	resource_size_t allocated_size = 0;
++	struct acpi_table_gtdt *gtdt;
 +
-+	/* 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;
++	if (arch_timers_present & ARCH_CP15_TIMER) {
++		pr_warn("arch_timer: already initialized, skipping\n");
++		return -EINVAL;
 +	}
 +
-+	/* range not registed yet, check for available space */
-+	if (allocated_size + size - 1 > IO_SPACE_LIMIT)
-+		return -E2BIG;
++	gtdt = container_of(table, struct acpi_table_gtdt, header);
 +
-+	/* add the range to the list */
-+	res = kzalloc(sizeof(*res), GFP_KERNEL);
-+	if (!res)
-+		return -ENOMEM;
++	arch_timers_present |= ARCH_CP15_TIMER;
 +
-+	res->start = addr;
-+	res->size = size;
++	arch_timer_ppi[PHYS_SECURE_PPI] =
++		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
++		gtdt->secure_el1_flags);
 +
-+	list_add_tail(&res->list, &io_range_list);
++	arch_timer_ppi[PHYS_NONSECURE_PPI] =
++		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
++		gtdt->non_secure_el1_flags);
 +
++	arch_timer_ppi[VIRT_PPI] =
++		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
++		gtdt->virtual_timer_flags);
++
++	arch_timer_ppi[HYP_PPI] =
++		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
++		gtdt->non_secure_el2_flags);
++
++	/* 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;
-+#else
-+	return -EINVAL;
-+#endif
 +}
 +
- unsigned long __weak pci_address_to_pio(phys_addr_t address)
- {
-+#ifdef PCI_IOBASE
-+	struct io_range *res;
-+	resource_size_t offset = 0;
-+
-+	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;
-+	}
++/* Initialize all the generic timers presented in GTDT */
++void __init acpi_generic_timer_init(void)
++{
++	if (acpi_disabled)
++		return;
 +
-+	return (unsigned long)-1;
-+#else
- 	if (address > IO_SPACE_LIMIT)
- 		return (unsigned long)-1;
- 
- 	return (unsigned long) address;
++	acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
++}
 +#endif
+diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
+index 17afc51..c5f7b4e 100644
+--- a/drivers/firmware/dmi_scan.c
++++ b/drivers/firmware/dmi_scan.c
+@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num,
+ 		const struct dmi_header *dm = (const struct dmi_header *)data;
+ 
+ 		/*
++		 * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
++		 */
++		if (dm->type == DMI_ENTRY_END_OF_TABLE)
++			break;
++
++		/*
+ 		 *  We want to know the total length (formatted area and
+ 		 *  strings) before decoding to make sure we won't run off the
+ 		 *  table in dmi_decode or dmi_string
+@@ -107,7 +113,7 @@ static void dmi_table(u8 *buf, int len, int num,
+ 	}
  }
  
- static int __of_address_to_resource(struct device_node *dev,
-@@ -811,3 +872,50 @@ bool of_dma_is_coherent(struct device_node *np)
- 	return false;
+-static u32 dmi_base;
++static phys_addr_t dmi_base;
+ static u16 dmi_len;
+ static u16 dmi_num;
+ 
+@@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf)
+ 
+ 	if (memcmp(buf, "_SM_", 4) == 0 &&
+ 	    buf[5] < 32 && dmi_checksum(buf, buf[5])) {
+-		smbios_ver = (buf[6] << 8) + buf[7];
++		smbios_ver = get_unaligned_be16(buf + 6);
+ 
+ 		/* Some BIOS report weird SMBIOS version, fix that up */
+ 		switch (smbios_ver) {
+@@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf)
+ 	buf += 16;
+ 
+ 	if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
+-		dmi_num = (buf[13] << 8) | buf[12];
+-		dmi_len = (buf[7] << 8) | buf[6];
+-		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
+-			(buf[9] << 8) | buf[8];
++		dmi_num = get_unaligned_le16(buf + 12);
++		dmi_len = get_unaligned_le16(buf + 6);
++		dmi_base = get_unaligned_le32(buf + 8);
+ 
+ 		if (dmi_walk_early(dmi_decode) == 0) {
+ 			if (smbios_ver) {
+@@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf)
+ 	return 1;
  }
- EXPORT_SYMBOL_GPL(of_dma_is_coherent);
-+
+ 
 +/*
-+ * 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.
++ * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy
++ * 32-bit entry point, there is no embedded DMI header (_DMI_) in here.
 + */
-+int of_pci_range_to_resource(struct of_pci_range *range,
-+	struct device_node *np, struct resource *res)
++static int __init dmi_smbios3_present(const u8 *buf)
 +{
-+	int err;
-+	res->flags = range->flags;
-+	res->parent = res->child = res->sibling = NULL;
-+	res->name = np->full_name;
++	if (memcmp(buf, "_SM3_", 5) == 0 &&
++	    buf[6] < 32 && dmi_checksum(buf, buf[6])) {
++		dmi_ver = get_unaligned_be16(buf + 7);
++		dmi_len = get_unaligned_le32(buf + 12);
++		dmi_base = get_unaligned_le64(buf + 16);
 +
-+	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;
++		/*
++		 * The 64-bit SMBIOS 3.0 entry point no longer has a field
++		 * containing the number of structures present in the table.
++		 * Instead, it defines the table size as a maximum size, and
++		 * relies on the end-of-table structure type (#127) to be used
++		 * to signal the end of the table.
++		 * So let's define dmi_num as an upper bound as well: each
++		 * structure has a 4 byte header, so dmi_len / 4 is an upper
++		 * bound for the number of structures in the table.
++		 */
++		dmi_num = dmi_len / 4;
++
++		if (dmi_walk_early(dmi_decode) == 0) {
++			pr_info("SMBIOS %d.%d present.\n",
++				dmi_ver >> 8, dmi_ver & 0xFF);
++			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
++			pr_debug("DMI: %s\n", dmi_ids_string);
++			return 0;
 +		}
-+		res->start = port;
-+	} else {
-+		res->start = range->cpu_addr;
 +	}
-+	res->end = res->start + range->size - 1;
-+	return 0;
-+
-+invalid_range:
-+	res->start = (resource_size_t)OF_BAD_ADDR;
-+	res->end = (resource_size_t)OF_BAD_ADDR;
-+	return err;
++	return 1;
 +}
 +
-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 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)
- }
- EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+ void __init dmi_scan_machine(void)
+ {
+ 	char __iomem *p, *q;
+ 	char buf[32];
  
-+/**
-+ * 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)
-+{
-+	struct resource *res;
-+	struct of_pci_range range;
-+	struct of_pci_range_parser parser;
-+	int err;
-+
-+	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
-+
-+	/* Check for ranges property */
-+	err = of_pci_range_parser_init(&parser, dev);
-+	if (err)
-+		return err;
-+
-+	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);
-+
+ 	if (efi_enabled(EFI_CONFIG_TABLES)) {
 +		/*
-+		 * If we failed translation or got a zero-sized region
-+		 * then skip this range
++		 * According to the DMTF SMBIOS reference spec v3.0.0, it is
++		 * allowed to define both the 64-bit entry point (smbios3) and
++		 * the 32-bit entry point (smbios), in which case they should
++		 * either both point to the same SMBIOS structure table, or the
++		 * table pointed to by the 64-bit entry point should contain a
++		 * superset of the table contents pointed to by the 32-bit entry
++		 * point (section 5.2)
++		 * This implies that the 64-bit entry point should have
++		 * precedence if it is defined and supported by the OS. If we
++		 * have the 64-bit entry point, but fail to decode it, fall
++		 * back to the legacy one (if available)
 +		 */
-+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
-+			continue;
-+
-+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
-+		if (!res)
-+			return -ENOMEM;
-+
-+		err = of_pci_range_to_resource(&range, dev, res);
-+		if (err)
-+			return err;
-+
-+		if (resource_type(res) == IORESOURCE_IO)
-+			*io_base = range.cpu_addr;
++		if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) {
++			p = dmi_early_remap(efi.smbios3, 32);
++			if (p == NULL)
++				goto error;
++			memcpy_fromio(buf, p, 32);
++			dmi_early_unmap(p, 32);
++
++			if (!dmi_smbios3_present(buf)) {
++				dmi_available = 1;
++				goto out;
++			}
++		}
+ 		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
+ 			goto error;
+ 
+@@ -552,7 +617,7 @@ void __init dmi_scan_machine(void)
+ 		memset(buf, 0, 16);
+ 		for (q = p; q < p + 0x10000; q += 16) {
+ 			memcpy_fromio(buf + 16, q, 16);
+-			if (!dmi_present(buf)) {
++			if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
+ 				dmi_available = 1;
+ 				dmi_early_unmap(p, 0x10000);
+ 				goto out;
+diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
+index 8590099..9035c1b 100644
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -30,6 +30,7 @@ struct efi __read_mostly efi = {
+ 	.acpi       = EFI_INVALID_TABLE_ADDR,
+ 	.acpi20     = EFI_INVALID_TABLE_ADDR,
+ 	.smbios     = EFI_INVALID_TABLE_ADDR,
++	.smbios3    = EFI_INVALID_TABLE_ADDR,
+ 	.sal_systab = EFI_INVALID_TABLE_ADDR,
+ 	.boot_info  = EFI_INVALID_TABLE_ADDR,
+ 	.hcdp       = EFI_INVALID_TABLE_ADDR,
+@@ -86,6 +87,8 @@ static ssize_t systab_show(struct kobject *kobj,
+ 		str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
+ 	if (efi.smbios != EFI_INVALID_TABLE_ADDR)
+ 		str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
++	if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
++		str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
+ 	if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
+ 		str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
+ 	if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
+@@ -260,6 +263,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
+ 	{MPS_TABLE_GUID, "MPS", &efi.mps},
+ 	{SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
+ 	{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
++	{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
+ 	{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
+ 	{NULL_GUID, NULL, NULL},
+ };
+diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
+index 75ee059..eb48a1a 100644
+--- a/drivers/firmware/efi/libstub/arm-stub.c
++++ b/drivers/firmware/efi/libstub/arm-stub.c
+@@ -247,9 +247,18 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
+ 			goto fail_free_cmdline;
+ 		}
+ 	}
+-	if (!fdt_addr)
 +
-+		pci_add_resource_offset(resources, res,
-+				res->start - range.pci_addr);
++	if (fdt_addr) {
++		pr_efi(sys_table, "Using DTB from command line\n");
++	} else {
+ 		/* Look for a device tree configuration table entry. */
+ 		fdt_addr = (uintptr_t)get_fdt(sys_table);
++		if (fdt_addr)
++			pr_efi(sys_table, "Using DTB from configuration table\n");
 +	}
 +
-+	/* Apply architecture specific fixups for the ranges */
-+	return pcibios_fixup_bridge_ranges(resources);
-+}
-+
-+static atomic_t domain_nr = ATOMIC_INIT(-1);
-+
-+/**
-+ * 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.
++	if (!fdt_addr)
++		pr_efi(sys_table, "Generating empty DTB\n");
+ 
+ 	status = handle_cmdline_files(sys_table, image, cmdline_ptr,
+ 				      "initrd=", dram_base + SZ_512M,
+diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
+index 954b9f6..13dbd3d 100644
+--- a/drivers/gpio/devres.c
++++ b/drivers/gpio/devres.c
+@@ -109,6 +109,38 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
+ EXPORT_SYMBOL(__devm_gpiod_get_index);
+ 
+ /**
++ * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
++ * @dev:	GPIO consumer
++ * @child:	firmware node (child of @dev)
 + *
-+ * 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.
++ * GPIO descriptors returned from this function are automatically disposed on
++ * driver detach.
 + */
-+struct pci_host_bridge *
-+of_create_pci_host_bridge(struct device *parent, struct pci_ops *ops, void *host_data)
++struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
++					    struct fwnode_handle *child)
 +{
-+	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 gpio_desc **dr;
++	struct gpio_desc *desc;
 +
-+	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
-+	if (!bus_range)
++	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
++			  GFP_KERNEL);
++	if (!dr)
 +		return ERR_PTR(-ENOMEM);
 +
-+	domain = of_alias_get_id(parent->of_node, "pci-domain");
-+	if (domain == -ENODEV)
-+		domain = atomic_inc_return(&domain_nr);
-+
-+	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);
-+
-+	/* 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;
-+
-+	/* 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;
++	desc = fwnode_get_named_gpiod(child, "gpios");
++	if (IS_ERR(desc)) {
++		devres_free(dr);
++		return desc;
 +	}
 +
-+	bridge = to_pci_host_bridge(root_bus->bridge);
-+	bridge->io_base = io_base;
-+
-+	return bridge;
++	*dr = desc;
++	devres_add(dev, dr);
 +
-+err_create:
-+	pci_free_resource_list(&res);
-+	return ERR_PTR(err);
++	return desc;
 +}
-+EXPORT_SYMBOL_GPL(of_create_pci_host_bridge);
++EXPORT_SYMBOL(devm_get_gpiod_from_child);
 +
- #ifdef CONFIG_PCI_MSI
++/**
+  * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
+  * @dev: GPIO consumer
+  * @con_id: function within the GPIO consumer
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 41e91d7..99720c8 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -29,290 +29,221 @@
+ 
+ #include <linux/gpio.h>
+ 
+-static DEFINE_SPINLOCK(gpio_lock);
+-
+-#define CGEN	(0x00)
+-#define CGIO	(0x04)
+-#define CGLV	(0x08)
+-
+-#define RGEN	(0x20)
+-#define RGIO	(0x24)
+-#define RGLV	(0x28)
+-
+-static unsigned short gpio_ba;
+-
+-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+-{
+-	u8 curr_dirs;
+-	unsigned short offset, bit;
+-
+-	spin_lock(&gpio_lock);
+-
+-	offset = CGIO + gpio_num / 8;
+-	bit = gpio_num % 8;
+-
+-	curr_dirs = inb(gpio_ba + offset);
+-
+-	if (!(curr_dirs & (1 << bit)))
+-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
++#define GEN	0x00
++#define GIO	0x04
++#define GLV	0x08
++
++struct sch_gpio {
++	struct gpio_chip chip;
++	spinlock_t lock;
++	unsigned short iobase;
++	unsigned short core_base;
++	unsigned short resume_base;
++};
+ 
+-	spin_unlock(&gpio_lock);
+-	return 0;
+-}
++#define to_sch_gpio(c)	container_of(c, struct sch_gpio, chip)
  
- 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;
+-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
++static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
++				unsigned reg)
+ {
+-	int res;
+-	unsigned short offset, bit;
++	unsigned base = 0;
+ 
+-	offset = CGLV + gpio_num / 8;
+-	bit = gpio_num % 8;
++	if (gpio >= sch->resume_base) {
++		gpio -= sch->resume_base;
++		base += 0x20;
++	}
+ 
+-	res = !!(inb(gpio_ba + offset) & (1 << bit));
+-	return res;
++	return base + reg + gpio / 8;
+ }
+ 
+-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
++static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
+ {
+-	u8 curr_vals;
+-	unsigned short offset, bit;
+-
+-	spin_lock(&gpio_lock);
+-
+-	offset = CGLV + gpio_num / 8;
+-	bit = gpio_num % 8;
+-
+-	curr_vals = inb(gpio_ba + offset);
+-
+-	if (val)
+-		outb(curr_vals | (1 << bit), gpio_ba + offset);
+-	else
+-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+-	spin_unlock(&gpio_lock);
++	if (gpio >= sch->resume_base)
++		gpio -= sch->resume_base;
++	return gpio % 8;
  }
  
--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)
+-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
+-					unsigned gpio_num, int val)
++static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
  {
- 	struct pci_bus *root_bus = find_pci_root_bus(bus);
+-	u8 curr_dirs;
+ 	unsigned short offset, bit;
++	u8 enable;
+ 
+-	spin_lock(&gpio_lock);
++	spin_lock(&sch->lock);
+ 
+-	offset = CGIO + gpio_num / 8;
+-	bit = gpio_num % 8;
+-
+-	curr_dirs = inb(gpio_ba + offset);
+-	if (curr_dirs & (1 << bit))
+-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
++	offset = sch_gpio_offset(sch, gpio, GEN);
++	bit = sch_gpio_bit(sch, gpio);
+ 
+-	spin_unlock(&gpio_lock);
++	enable = inb(sch->iobase + offset);
++	if (!(enable & (1 << bit)))
++		outb(enable | (1 << bit), sch->iobase + offset);
  
- 	return to_pci_host_bridge(root_bus->bridge);
+-	/*
+-	 * according to the datasheet, writing to the level register has no
+-	 * effect when GPIO is programmed as input.
+-	 * Actually the the level register is read-only when configured as input.
+-	 * Thus presetting the output level before switching to output is _NOT_ possible.
+-	 * Hence we set the level after configuring the GPIO as output.
+-	 * But we cannot prevent a short low pulse if direction is set to high
+-	 * and an external pull-up is connected.
+-	 */
+-	sch_gpio_core_set(gc, gpio_num, val);
+-	return 0;
++	spin_unlock(&sch->lock);
  }
-+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;
+-static struct gpio_chip sch_gpio_core = {
+-	.label			= "sch_gpio_core",
+-	.owner			= THIS_MODULE,
+-	.direction_input	= sch_gpio_core_direction_in,
+-	.get			= sch_gpio_core_get,
+-	.direction_output	= sch_gpio_core_direction_out,
+-	.set			= sch_gpio_core_set,
+-};
+-
+-static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
+-					unsigned gpio_num)
++static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+ {
++	struct sch_gpio *sch = to_sch_gpio(gc);
+ 	u8 curr_dirs;
+ 	unsigned short offset, bit;
+ 
+-	spin_lock(&gpio_lock);
++	spin_lock(&sch->lock);
+ 
+-	offset = RGIO + gpio_num / 8;
+-	bit = gpio_num % 8;
++	offset = sch_gpio_offset(sch, gpio_num, GIO);
++	bit = sch_gpio_bit(sch, gpio_num);
+ 
+-	curr_dirs = inb(gpio_ba + offset);
++	curr_dirs = inb(sch->iobase + offset);
+ 
+ 	if (!(curr_dirs & (1 << bit)))
+-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
++		outb(curr_dirs | (1 << bit), sch->iobase + offset);
+ 
+-	spin_unlock(&gpio_lock);
++	spin_unlock(&sch->lock);
+ 	return 0;
  }
- 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)
-+{
-+	return 0;
-+}
-diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
-index 21df477..3b988a2 100644
---- a/drivers/pci/host/Kconfig
-+++ b/drivers/pci/host/Kconfig
-@@ -46,4 +46,14 @@ config PCI_HOST_GENERIC
- 	  Say Y here if you want to support a simple generic PCI host
- 	  controller, such as the one emulated by kvmtool.
- 
-+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 611ba4b..0801606 100644
---- a/drivers/pci/host/Makefile
-+++ b/drivers/pci/host/Makefile
-@@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
- 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_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>
+ 
+-static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
++static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ {
++	struct sch_gpio *sch = to_sch_gpio(gc);
++	int res;
+ 	unsigned short offset, bit;
+ 
+-	offset = RGLV + gpio_num / 8;
+-	bit = gpio_num % 8;
++	offset = sch_gpio_offset(sch, gpio_num, GLV);
++	bit = sch_gpio_bit(sch, gpio_num);
 +
-+#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
-+
-+#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)
-+
-+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;
-+};
++	res = !!(inb(sch->iobase + offset) & (1 << bit));
+ 
+-	return !!(inb(gpio_ba + offset) & (1 << bit));
++	return res;
+ }
+ 
+-static void sch_gpio_resume_set(struct gpio_chip *gc,
+-				unsigned gpio_num, int val)
++static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ {
++	struct sch_gpio *sch = to_sch_gpio(gc);
+ 	u8 curr_vals;
+ 	unsigned short offset, bit;
+ 
+-	spin_lock(&gpio_lock);
++	spin_lock(&sch->lock);
+ 
+-	offset = RGLV + gpio_num / 8;
+-	bit = gpio_num % 8;
++	offset = sch_gpio_offset(sch, gpio_num, GLV);
++	bit = sch_gpio_bit(sch, gpio_num);
+ 
+-	curr_vals = inb(gpio_ba + offset);
++	curr_vals = inb(sch->iobase + offset);
+ 
+ 	if (val)
+-		outb(curr_vals | (1 << bit), gpio_ba + offset);
++		outb(curr_vals | (1 << bit), sch->iobase + offset);
+ 	else
+-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
++		outb((curr_vals & ~(1 << bit)), sch->iobase + offset);
+ 
+-	spin_unlock(&gpio_lock);
++	spin_unlock(&sch->lock);
+ }
+ 
+-static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
+-					unsigned gpio_num, int val)
++static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
++				  int val)
+ {
++	struct sch_gpio *sch = to_sch_gpio(gc);
+ 	u8 curr_dirs;
+ 	unsigned short offset, bit;
+ 
+-	offset = RGIO + gpio_num / 8;
+-	bit = gpio_num % 8;
++	spin_lock(&sch->lock);
+ 
+-	spin_lock(&gpio_lock);
++	offset = sch_gpio_offset(sch, gpio_num, GIO);
++	bit = sch_gpio_bit(sch, gpio_num);
+ 
+-	curr_dirs = inb(gpio_ba + offset);
++	curr_dirs = inb(sch->iobase + offset);
+ 	if (curr_dirs & (1 << bit))
+-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
++		outb(curr_dirs & ~(1 << bit), sch->iobase + offset);
+ 
+-	spin_unlock(&gpio_lock);
++	spin_unlock(&sch->lock);
+ 
+ 	/*
+-	* according to the datasheet, writing to the level register has no
+-	* effect when GPIO is programmed as input.
+-	* Actually the the level register is read-only when configured as input.
+-	* Thus presetting the output level before switching to output is _NOT_ possible.
+-	* Hence we set the level after configuring the GPIO as output.
+-	* But we cannot prevent a short low pulse if direction is set to high
+-	* and an external pull-up is connected.
+-	*/
+-	sch_gpio_resume_set(gc, gpio_num, val);
++	 * according to the datasheet, writing to the level register has no
++	 * effect when GPIO is programmed as input.
++	 * Actually the the level register is read-only when configured as input.
++	 * Thus presetting the output level before switching to output is _NOT_ possible.
++	 * Hence we set the level after configuring the GPIO as output.
++	 * But we cannot prevent a short low pulse if direction is set to high
++	 * and an external pull-up is connected.
++	 */
++	sch_gpio_set(gc, gpio_num, val);
+ 	return 0;
+ }
+ 
+-static struct gpio_chip sch_gpio_resume = {
+-	.label			= "sch_gpio_resume",
++static struct gpio_chip sch_gpio_chip = {
++	.label			= "sch_gpio",
+ 	.owner			= THIS_MODULE,
+-	.direction_input	= sch_gpio_resume_direction_in,
+-	.get			= sch_gpio_resume_get,
+-	.direction_output	= sch_gpio_resume_direction_out,
+-	.set			= sch_gpio_resume_set,
++	.direction_input	= sch_gpio_direction_in,
++	.get			= sch_gpio_get,
++	.direction_output	= sch_gpio_direction_out,
++	.set			= sch_gpio_set,
+ };
+ 
+ static int sch_gpio_probe(struct platform_device *pdev)
+ {
++	struct sch_gpio *sch;
+ 	struct resource *res;
+-	int err, id;
+ 
+-	id = pdev->id;
+-	if (!id)
+-		return -ENODEV;
++	sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
++	if (!sch)
++		return -ENOMEM;
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ 	if (!res)
+ 		return -EBUSY;
+ 
+-	if (!request_region(res->start, resource_size(res), pdev->name))
++	if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
++				 pdev->name))
+ 		return -EBUSY;
+ 
+-	gpio_ba = res->start;
++	spin_lock_init(&sch->lock);
++	sch->iobase = res->start;
++	sch->chip = sch_gpio_chip;
++	sch->chip.label = dev_name(&pdev->dev);
++	sch->chip.dev = &pdev->dev;
+ 
+-	switch (id) {
++	switch (pdev->id) {
+ 	case PCI_DEVICE_ID_INTEL_SCH_LPC:
+-		sch_gpio_core.base = 0;
+-		sch_gpio_core.ngpio = 10;
+-		sch_gpio_resume.base = 10;
+-		sch_gpio_resume.ngpio = 4;
++		sch->core_base = 0;
++		sch->resume_base = 10;
++		sch->chip.ngpio = 14;
 +
-+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)
+ 		/*
+ 		 * GPIO[6:0] enabled by default
+ 		 * GPIO7 is configured by the CMC as SLPIOVR
+ 		 * Enable GPIO[9:8] core powered gpios explicitly
+ 		 */
+-		outb(0x3, gpio_ba + CGEN + 1);
++		sch_gpio_enable(sch, 8);
++		sch_gpio_enable(sch, 9);
+ 		/*
+ 		 * SUS_GPIO[2:0] enabled by default
+ 		 * Enable SUS_GPIO3 resume powered gpio explicitly
+ 		 */
+-		outb(0x8, gpio_ba + RGEN);
++		sch_gpio_enable(sch, 13);
+ 		break;
+ 
+ 	case PCI_DEVICE_ID_INTEL_ITC_LPC:
+-		sch_gpio_core.base = 0;
+-		sch_gpio_core.ngpio = 5;
+-		sch_gpio_resume.base = 5;
+-		sch_gpio_resume.ngpio = 9;
++		sch->core_base = 0;
++		sch->resume_base = 5;
++		sch->chip.ngpio = 14;
+ 		break;
+ 
+ 	case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
+-		sch_gpio_core.base = 0;
+-		sch_gpio_core.ngpio = 21;
+-		sch_gpio_resume.base = 21;
+-		sch_gpio_resume.ngpio = 9;
++		sch->core_base = 0;
++		sch->resume_base = 21;
++		sch->chip.ngpio = 30;
+ 		break;
+ 
+ 	default:
+-		err = -ENODEV;
+-		goto err_sch_gpio_core;
++		return -ENODEV;
+ 	}
+ 
+-	sch_gpio_core.dev = &pdev->dev;
+-	sch_gpio_resume.dev = &pdev->dev;
+-
+-	err = gpiochip_add(&sch_gpio_core);
+-	if (err < 0)
+-		goto err_sch_gpio_core;
++	platform_set_drvdata(pdev, sch);
+ 
+-	err = gpiochip_add(&sch_gpio_resume);
+-	if (err < 0)
+-		goto err_sch_gpio_resume;
+-
+-	return 0;
+-
+-err_sch_gpio_resume:
+-	gpiochip_remove(&sch_gpio_core);
+-
+-err_sch_gpio_core:
+-	release_region(res->start, resource_size(res));
+-	gpio_ba = 0;
+-
+-	return err;
++	return gpiochip_add(&sch->chip);
+ }
+ 
+ static int sch_gpio_remove(struct platform_device *pdev)
+ {
+-	struct resource *res;
+-	if (gpio_ba) {
+-
+-		gpiochip_remove(&sch_gpio_core);
+-		gpiochip_remove(&sch_gpio_resume);
+-
+-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+-
+-		release_region(res->start, resource_size(res));
+-		gpio_ba = 0;
+-	}
++	struct sch_gpio *sch = platform_get_drvdata(pdev);
+ 
++	gpiochip_remove(&sch->chip);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 05c6275..ba98bb5 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -287,9 +287,45 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
+ 	}
+ }
+ 
++int acpi_dev_add_driver_gpios(struct acpi_device *adev,
++			      const struct acpi_gpio_mapping *gpios)
 +{
-+	writel(val, addr + offset);
++	if (adev && gpios) {
++		adev->driver_gpios = gpios;
++		return 0;
++	}
++	return -EINVAL;
 +}
++EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
 +
-+static inline void xgene_pcie_cfg_out16(void __iomem *addr, int offset, u16 val)
++static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
++				      const char *name, int index,
++				      struct acpi_reference_args *args)
 +{
-+	u32 val32 = readl(addr + (offset & ~0x3));
++	const struct acpi_gpio_mapping *gm;
 +
-+	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));
-+}
++	if (!adev->driver_gpios)
++		return false;
 +
-+static inline void xgene_pcie_cfg_out8(void __iomem *addr, int offset, u8 val)
-+{
-+	u32 val32 = readl(addr + (offset & ~0x3));
++	for (gm = adev->driver_gpios; gm->name; gm++)
++		if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
++			const struct acpi_gpio_params *par = gm->data + index;
 +
-+	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));
-+}
++			args->adev = adev;
++			args->args[0] = par->crs_entry_index;
++			args->args[1] = par->line_index;
++			args->args[2] = par->active_low;
++			args->nargs = 3;
++			return true;
++		}
 +
-+static inline void xgene_pcie_cfg_in32(void __iomem *addr, int offset, u32 *val)
-+{
-+	*val = readl(addr + offset);
++	return false;
 +}
 +
-+static inline void
-+xgene_pcie_cfg_in16(void __iomem *addr, int offset, u32 *val)
-+{
-+	*val = readl(addr + (offset & ~0x3));
+ struct acpi_gpio_lookup {
+ 	struct acpi_gpio_info info;
+ 	int index;
++	int pin_index;
+ 	struct gpio_desc *desc;
+ 	int n;
+ };
+@@ -303,13 +339,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
+ 
+ 	if (lookup->n++ == lookup->index && !lookup->desc) {
+ 		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
++		int pin_index = lookup->pin_index;
 +
-+	switch (offset & 0x3) {
-+	case 2:
-+		*val >>= 16;
-+		break;
-+	}
++		if (pin_index >= agpio->pin_table_length)
++			return 1;
+ 
+ 		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
+-					      agpio->pin_table[0]);
++					      agpio->pin_table[pin_index]);
+ 		lookup->info.gpioint =
+ 			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
+-		lookup->info.active_low =
+-			agpio->polarity == ACPI_ACTIVE_LOW;
 +
-+	*val &= 0xFFFF;
-+}
++		/*
++		 * ActiveLow is only specified for GpioInt resource. If
++		 * GpioIo is used then the only way to set the flag is
++		 * to use _DSD "gpios" property.
++		 */
++		if (lookup->info.gpioint)
++			lookup->info.active_low =
++				agpio->polarity == ACPI_ACTIVE_LOW;
+ 	}
+ 
+ 	return 1;
+@@ -317,40 +364,79 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
+ 
+ /**
+  * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
+- * @dev: pointer to a device to get GPIO from
++ * @adev: pointer to a ACPI device to get GPIO from
++ * @propname: Property name of the GPIO (optional)
+  * @index: index of GpioIo/GpioInt resource (starting from %0)
+  * @info: info pointer to fill in (optional)
+  *
+- * Function goes through ACPI resources for @dev and based on @index looks
++ * Function goes through ACPI resources for @adev and based on @index looks
+  * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
+  * and returns it. @index matches GpioIo/GpioInt resources only so if there
+  * are total %3 GPIO resources, the index goes from %0 to %2.
+  *
++ * If @propname is specified the GPIO is looked using device property. In
++ * that case @index is used to select the GPIO entry in the property value
++ * (in case of multiple).
++ *
+  * If the GPIO cannot be translated or there is an error an ERR_PTR is
+  * returned.
+  *
+  * Note: if the GPIO resource has multiple entries in the pin list, this
+  * function only returns the first.
+  */
+-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
++struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
++					  const char *propname, int index,
+ 					  struct acpi_gpio_info *info)
+ {
+ 	struct acpi_gpio_lookup lookup;
+ 	struct list_head resource_list;
+-	struct acpi_device *adev;
+-	acpi_handle handle;
++	bool active_low = false;
+ 	int ret;
+ 
+-	if (!dev)
+-		return ERR_PTR(-EINVAL);
+-
+-	handle = ACPI_HANDLE(dev);
+-	if (!handle || acpi_bus_get_device(handle, &adev))
++	if (!adev)
+ 		return ERR_PTR(-ENODEV);
+ 
+ 	memset(&lookup, 0, sizeof(lookup));
+ 	lookup.index = index;
+ 
++	if (propname) {
++		struct acpi_reference_args args;
++
++		dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
++
++		memset(&args, 0, sizeof(args));
++		ret = acpi_dev_get_property_reference(adev, propname,
++						      index, &args);
++		if (ret) {
++			bool found = acpi_get_driver_gpio_data(adev, propname,
++							       index, &args);
++			if (!found)
++				return ERR_PTR(ret);
++		}
 +
-+static inline void
-+xgene_pcie_cfg_in8(void __iomem *addr, int offset, u32 *val)
-+{
-+	*val = readl(addr + (offset & ~0x3));
++		/*
++		 * The property was found and resolved so need to
++		 * lookup the GPIO based on returned args instead.
++		 */
++		adev = args.adev;
++		if (args.nargs >= 2) {
++			lookup.index = args.args[0];
++			lookup.pin_index = args.args[1];
++			/*
++			 * 3rd argument, if present is used to
++			 * specify active_low.
++			 */
++			if (args.nargs >= 3)
++				active_low = !!args.args[2];
++		}
 +
-+	switch (offset & 0x3) {
-+	case 3:
-+		*val = *val >> 24;
-+		break;
-+	case 2:
-+		*val = *val >> 16;
-+		break;
-+	case 1:
-+		*val = *val >> 8;
-+		break;
++		dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n",
++			dev_name(&adev->dev), args.nargs,
++			args.args[0], args.args[1], args.args[2]);
++	} else {
++		dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
 +	}
-+	*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;
+ 	INIT_LIST_HEAD(&resource_list);
+ 	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
+ 				     &lookup);
+@@ -359,8 +445,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+ 
+ 	acpi_dev_free_resource_list(&resource_list);
+ 
+-	if (lookup.desc && info)
++	if (lookup.desc && info) {
+ 		*info = lookup.info;
++		if (active_low)
++			info->active_low = active_low;
++	}
+ 
+ 	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
+ }
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index e8e98ca..58659db 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
+ 					unsigned int idx,
+ 					enum gpio_lookup_flags *flags)
+ {
++	static const char * const suffixes[] = { "gpios", "gpio" };
++	struct acpi_device *adev = ACPI_COMPANION(dev);
+ 	struct acpi_gpio_info info;
+ 	struct gpio_desc *desc;
++	char propname[32];
++	int i;
+ 
+-	desc = acpi_get_gpiod_by_index(dev, idx, &info);
+-	if (IS_ERR(desc))
+-		return desc;
++	/* Try first from _DSD */
++	for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
++		if (con_id && strcmp(con_id, "gpios")) {
++			snprintf(propname, sizeof(propname), "%s-%s",
++				 con_id, suffixes[i]);
++		} else {
++			snprintf(propname, sizeof(propname), "%s",
++				 suffixes[i]);
++		}
 +
-+	return port->cfg_base;
-+}
++		desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
++		if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
++			break;
++	}
+ 
+-	if (info.gpioint && info.active_low)
++	/* Then from plain _CRS GPIOs */
++	if (IS_ERR(desc)) {
++		desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
++		if (IS_ERR(desc))
++			return desc;
++	}
 +
-+/* For Configuration request, RTDID register is used as Bus Number,
-+ * Device Number and Function number of the header fields.
++	if (info.active_low)
+ 		*flags |= GPIO_ACTIVE_LOW;
+ 
+ 	return desc;
+@@ -1713,6 +1735,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
+ EXPORT_SYMBOL_GPL(__gpiod_get_index);
+ 
+ /**
++ * fwnode_get_named_gpiod - obtain a GPIO from firmware node
++ * @fwnode:	handle of the firmware node
++ * @propname:	name of the firmware property representing the GPIO
++ *
++ * This function can be used for drivers that get their configuration
++ * from firmware.
++ *
++ * Function properly finds the corresponding GPIO using whatever is the
++ * underlying firmware interface and then makes sure that the GPIO
++ * descriptor is requested before it is returned to the caller.
++ *
++ * In case of error an ERR_PTR() is returned.
 + */
-+static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
++struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
++					 const char *propname)
 +{
-+	struct xgene_pcie_port *port = bus->sysdata;
-+	unsigned int b, d, f;
-+	u32 rtdid_val = 0;
++	struct gpio_desc *desc = ERR_PTR(-ENODEV);
++	bool active_low = false;
++	int ret;
 +
-+	b = bus->number;
-+	d = PCI_SLOT(devfn);
-+	f = PCI_FUNC(devfn);
++	if (!fwnode)
++		return ERR_PTR(-EINVAL);
 +
-+	if (!pci_is_root_bus(bus))
-+		rtdid_val = (b << 8) | (d << 3) | f;
++	if (is_of_node(fwnode)) {
++		enum of_gpio_flags flags;
 +
-+	writel(rtdid_val, port->csr_base + RTDID);
-+	/* read the register back to ensure flush */
-+	readl(port->csr_base + RTDID);
-+}
++		desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0,
++						&flags);
++		if (!IS_ERR(desc))
++			active_low = flags & OF_GPIO_ACTIVE_LOW;
++	} else if (is_acpi_node(fwnode)) {
++		struct acpi_gpio_info info;
 +
-+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;
++		desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0,
++					       &info);
++		if (!IS_ERR(desc))
++			active_low = info.active_low;
++	}
 +
-+	if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
-+		return PCIBIOS_DEVICE_NOT_FOUND;
++	if (IS_ERR(desc))
++		return desc;
 +
-+	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;
++	ret = gpiod_request(desc, NULL);
++	if (ret)
++		return ERR_PTR(ret);
++
++	/* Only value flag can be set from both DT and ACPI is active_low */
++	if (active_low)
++		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
++
++	return desc;
 +}
++EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
 +
-+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;
++/**
+  * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
+  *                            function
+  * @dev: GPIO consumer, can be NULL for system-global GPIOs
+diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
+index 9db2b6a..e3a5211 100644
+--- a/drivers/gpio/gpiolib.h
++++ b/drivers/gpio/gpiolib.h
+@@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
+ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
+ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
+ 
+-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
++struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
++					  const char *propname, int index,
+ 					  struct acpi_gpio_info *info);
+ #else
+ static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
+@@ -47,8 +48,8 @@ static inline void
+ acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
+ 
+ static inline struct gpio_desc *
+-acpi_get_gpiod_by_index(struct device *dev, int index,
+-			struct acpi_gpio_info *info)
++acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
++			int index, struct acpi_gpio_info *info)
+ {
+ 	return ERR_PTR(-ENOSYS);
+ }
+diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
+index 432d363..c9c1c8c 100644
+--- a/drivers/input/keyboard/gpio_keys_polled.c
++++ b/drivers/input/keyboard/gpio_keys_polled.c
+@@ -23,10 +23,9 @@
+ #include <linux/ioport.h>
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/gpio_keys.h>
+-#include <linux/of.h>
+-#include <linux/of_platform.h>
+-#include <linux/of_gpio.h>
++#include <linux/property.h>
+ 
+ #define DRV_NAME	"gpio-keys-polled"
+ 
+@@ -51,15 +50,14 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
+ 	int state;
+ 
+ 	if (bdata->can_sleep)
+-		state = !!gpio_get_value_cansleep(button->gpio);
++		state = !!gpiod_get_value_cansleep(button->gpiod);
+ 	else
+-		state = !!gpio_get_value(button->gpio);
++		state = !!gpiod_get_value(button->gpiod);
+ 
+ 	if (state != bdata->last_state) {
+ 		unsigned int type = button->type ?: EV_KEY;
+ 
+-		input_event(input, type, button->code,
+-			    !!(state ^ button->active_low));
++		input_event(input, type, button->code, state);
+ 		input_sync(input);
+ 		bdata->count = 0;
+ 		bdata->last_state = state;
+@@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
+ 		pdata->disable(bdev->dev);
+ }
+ 
+-#ifdef CONFIG_OF
+ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
+ {
+-	struct device_node *node, *pp;
+ 	struct gpio_keys_platform_data *pdata;
+ 	struct gpio_keys_button *button;
++	struct fwnode_handle *child;
+ 	int error;
+ 	int nbuttons;
+-	int i;
+-
+-	node = dev->of_node;
+-	if (!node)
+-		return NULL;
+ 
+-	nbuttons = of_get_child_count(node);
++	nbuttons = device_get_child_node_count(dev);
+ 	if (nbuttons == 0)
+ 		return NULL;
+ 
+@@ -126,52 +118,44 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
+ 		return ERR_PTR(-ENOMEM);
+ 
+ 	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
+-	pdata->nbuttons = nbuttons;
+ 
+-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
+-	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
++	pdata->rep = device_property_present(dev, "autorepeat");
++	device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
+ 
+-	i = 0;
+-	for_each_child_of_node(node, pp) {
+-		int gpio;
+-		enum of_gpio_flags flags;
++	device_for_each_child_node(dev, child) {
++		struct gpio_desc *desc;
+ 
+-		if (!of_find_property(pp, "gpios", NULL)) {
+-			pdata->nbuttons--;
+-			dev_warn(dev, "Found button without gpios\n");
+-			continue;
+-		}
+-
+-		gpio = of_get_gpio_flags(pp, 0, &flags);
+-		if (gpio < 0) {
+-			error = gpio;
++		desc = devm_get_gpiod_from_child(dev, child);
++		if (IS_ERR(desc)) {
++			error = PTR_ERR(desc);
+ 			if (error != -EPROBE_DEFER)
+ 				dev_err(dev,
+ 					"Failed to get gpio flags, error: %d\n",
+ 					error);
++			fwnode_handle_put(child);
+ 			return ERR_PTR(error);
+ 		}
+ 
+-		button = &pdata->buttons[i++];
+-
+-		button->gpio = gpio;
+-		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
++		button = &pdata->buttons[pdata->nbuttons++];
++		button->gpiod = desc;
+ 
+-		if (of_property_read_u32(pp, "linux,code", &button->code)) {
+-			dev_err(dev, "Button without keycode: 0x%x\n",
+-				button->gpio);
++		if (fwnode_property_read_u32(child, "linux,code", &button->code)) {
++			dev_err(dev, "Button without keycode: %d\n",
++				pdata->nbuttons - 1);
++			fwnode_handle_put(child);
+ 			return ERR_PTR(-EINVAL);
+ 		}
+ 
+-		button->desc = of_get_property(pp, "label", NULL);
++		fwnode_property_read_string(child, "label", &button->desc);
+ 
+-		if (of_property_read_u32(pp, "linux,input-type", &button->type))
++		if (fwnode_property_read_u32(child, "linux,input-type",
++					     &button->type))
+ 			button->type = EV_KEY;
+ 
+-		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
++		button->wakeup = fwnode_property_present(child, "gpio-key,wakeup");
+ 
+-		if (of_property_read_u32(pp, "debounce-interval",
+-					 &button->debounce_interval))
++		if (fwnode_property_read_u32(child, "debounce-interval",
++					     &button->debounce_interval))
+ 			button->debounce_interval = 5;
+ 	}
+ 
+@@ -187,15 +171,6 @@ static const struct of_device_id gpio_keys_polled_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
+ 
+-#else
+-
+-static inline struct gpio_keys_platform_data *
+-gpio_keys_polled_get_devtree_pdata(struct device *dev)
+-{
+-	return NULL;
+-}
+-#endif
+-
+ static int gpio_keys_polled_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+@@ -259,7 +234,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
+ 	for (i = 0; i < pdata->nbuttons; i++) {
+ 		struct gpio_keys_button *button = &pdata->buttons[i];
+ 		struct gpio_keys_button_data *bdata = &bdev->data[i];
+-		unsigned int gpio = button->gpio;
+ 		unsigned int type = button->type ?: EV_KEY;
+ 
+ 		if (button->wakeup) {
+@@ -267,15 +241,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
+ 			return -EINVAL;
+ 		}
+ 
+-		error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
+-					      button->desc ? : DRV_NAME);
+-		if (error) {
+-			dev_err(dev, "unable to claim gpio %u, err=%d\n",
+-				gpio, error);
+-			return error;
++		/*
++		 * Legacy GPIO number so request the GPIO here and
++		 * convert it to descriptor.
++		 */
++		if (!button->gpiod && gpio_is_valid(button->gpio)) {
++			unsigned flags = 0;
++
++			if (button->active_low)
++				flags |= GPIOF_ACTIVE_LOW;
++
++			error = devm_gpio_request_one(&pdev->dev, button->gpio,
++					flags, button->desc ? : DRV_NAME);
++			if (error) {
++				dev_err(dev, "unable to claim gpio %u, err=%d\n",
++					button->gpio, error);
++				return error;
++			}
 +
-+	if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up)
-+		return PCIBIOS_DEVICE_NOT_FOUND;
++			button->gpiod = gpio_to_desc(button->gpio);
+ 		}
+ 
+-		bdata->can_sleep = gpio_cansleep(gpio);
++		if (IS_ERR(button->gpiod))
++			return PTR_ERR(button->gpiod);
++
++		bdata->can_sleep = gpiod_cansleep(button->gpiod);
+ 		bdata->last_state = -1;
+ 		bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
+ 						pdata->poll_interval);
+@@ -308,7 +298,7 @@ static struct platform_driver gpio_keys_polled_driver = {
+ 	.driver	= {
+ 		.name	= DRV_NAME,
+ 		.owner	= THIS_MODULE,
+-		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
++		.of_match_table = gpio_keys_polled_of_match,
+ 	},
+ };
+ module_platform_driver(gpio_keys_polled_driver);
+diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
+index 60558f7..3b92862 100644
+--- a/drivers/iommu/arm-smmu.c
++++ b/drivers/iommu/arm-smmu.c
+@@ -444,7 +444,10 @@ static struct device_node *dev_get_dev_node(struct device *dev)
+ 
+ 		while (!pci_is_root_bus(bus))
+ 			bus = bus->parent;
+-		return bus->bridge->parent->of_node;
++		if (bus->bridge->parent)
++			return bus->bridge->parent->of_node;
++		else
++			return NULL;
+ 	}
+ 
+ 	return dev->of_node;
+@@ -560,6 +563,9 @@ static struct arm_smmu_device *find_smmu_for_device(struct device *dev)
+ 	struct arm_smmu_master *master = NULL;
+ 	struct device_node *dev_node = dev_get_dev_node(dev);
+ 
++	if (!dev_node)
++		return NULL;
 +
-+	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;
+ 	spin_lock(&arm_smmu_devices_lock);
+ 	list_for_each_entry(smmu, &arm_smmu_devices, list) {
+ 		master = find_smmu_master(smmu, dev_node);
+diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
+index aa17ae8..d330dab 100644
+--- a/drivers/irqchip/irq-gic-v3.c
++++ b/drivers/irqchip/irq-gic-v3.c
+@@ -506,9 +506,19 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+ 	isb();
+ }
+ 
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++static void gic_wakeup_parked_cpu(int cpu)
++{
++	gic_raise_softirq(cpumask_of(cpu), 0);
 +}
++#endif
 +
-+static struct pci_ops xgene_pcie_ops = {
-+	.read = xgene_pcie_read_config,
-+	.write = xgene_pcie_write_config
-+};
+ static void gic_smp_init(void)
+ {
+ 	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);
+ }
+ 
+diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
+index 38493ff..26e6773 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>
+@@ -641,6 +643,13 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+ 
+ 	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
+ }
 +
-+static void xgene_pcie_program_core(void __iomem *csr_base)
++#ifdef CONFIG_ARM_PARKING_PROTOCOL
++static void gic_wakeup_parked_cpu(int cpu)
 +{
-+	u32 val;
-+
-+	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);
++	gic_raise_softirq(cpumask_of(cpu), GIC_DIST_SOFTINT_NSATT);
 +}
++#endif
+ #endif
+ 
+ #ifdef CONFIG_BL_SWITCHER
+@@ -996,6 +1005,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);
+ 	}
+@@ -1048,3 +1060,107 @@ IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
+ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
+ 
+ #endif
 +
-+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;
++#ifdef CONFIG_ACPI
++static phys_addr_t dist_phy_base, cpu_phy_base;
++static int cpu_base_assigned;
 +
-+	val32 = readl(csr_base + addr);
-+	val = (val32 & 0x0000ffff) | (lower_32_bits(mask) << 16);
-+	writel(val, csr_base + addr);
++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;
 +
-+	val32 = readl(csr_base + addr + 0x04);
-+	val = (val32 & 0xffff0000) | (lower_32_bits(mask) >> 16);
-+	writel(val, csr_base + addr + 0x04);
++	processor = (struct acpi_madt_generic_interrupt *)header;
 +
-+	val32 = readl(csr_base + addr + 0x04);
-+	val = (val32 & 0x0000ffff) | (upper_32_bits(mask) << 16);
-+	writel(val, csr_base + addr + 0x04);
++	if (BAD_MADT_ENTRY(processor, end))
++		return -EINVAL;
 +
-+	val32 = readl(csr_base + addr + 0x08);
-+	val = (val32 & 0xffff0000) | (upper_32_bits(mask) >> 16);
-+	writel(val, csr_base + addr + 0x08);
++	/*
++	 * 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;
 +
-+	return mask;
++	cpu_phy_base = gic_cpu_base;
++	cpu_base_assigned = 1;
++	return 0;
 +}
 +
-+static void xgene_pcie_poll_linkup(struct xgene_pcie_port *port,
-+				   u32 *lanes, u32 *speed)
++static int __init
++gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
++				const unsigned long end)
 +{
-+	void __iomem *csr_base = port->csr_base;
-+	ulong timeout;
-+	u32 val32;
++	struct acpi_madt_generic_distributor *dist;
 +
-+	/*
-+	 * 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;
-+			break;
-+		}
-+		msleep(1);
-+	}
-+}
++	dist = (struct acpi_madt_generic_distributor *)header;
 +
-+static void xgene_pcie_setup_root_complex(struct xgene_pcie_port *port)
-+{
-+	void __iomem *csr_base = port->csr_base;
-+	u32 val;
++	if (BAD_MADT_ENTRY(dist, end))
++		return -EINVAL;
 +
-+	val = (XGENE_PCIE_DEVICEID << 16) | XGENE_PCIE_VENDORID;
-+	writel(val, csr_base + BRIDGE_CFG_0);
++	dist_phy_base = dist->base_address;
++	return 0;
++}
++
++int __init
++gic_v2_acpi_init(struct acpi_table_header *table)
++{
++	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;
++	}
++
++	/*
++	 * 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;
++	}
++
++	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;
++	}
++
++	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;
++	}
++
++	/*
++	 * 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);
++
++	acpi_gic_init();
+ }
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index b4518c8..b3c5d9d 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -12,25 +12,23 @@
+  */
+ #include <linux/err.h>
+ #include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/kernel.h>
+ #include <linux/leds.h>
+ #include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_gpio.h>
+-#include <linux/of_platform.h>
+ #include <linux/platform_device.h>
++#include <linux/property.h>
+ #include <linux/slab.h>
+ #include <linux/workqueue.h>
+ 
+ struct gpio_led_data {
+ 	struct led_classdev cdev;
+-	unsigned gpio;
++	struct gpio_desc *gpiod;
+ 	struct work_struct work;
+ 	u8 new_level;
+ 	u8 can_sleep;
+-	u8 active_low;
+ 	u8 blinking;
+-	int (*platform_gpio_blink_set)(unsigned gpio, int state,
++	int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state,
+ 			unsigned long *delay_on, unsigned long *delay_off);
+ };
+ 
+@@ -40,12 +38,11 @@ static void gpio_led_work(struct work_struct *work)
+ 		container_of(work, struct gpio_led_data, work);
+ 
+ 	if (led_dat->blinking) {
+-		led_dat->platform_gpio_blink_set(led_dat->gpio,
+-						 led_dat->new_level,
+-						 NULL, NULL);
++		led_dat->platform_gpio_blink_set(led_dat->gpiod,
++					led_dat->new_level, NULL, NULL);
+ 		led_dat->blinking = 0;
+ 	} else
+-		gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
++		gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
+ }
+ 
+ static void gpio_led_set(struct led_classdev *led_cdev,
+@@ -60,9 +57,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,
+ 	else
+ 		level = 1;
+ 
+-	if (led_dat->active_low)
+-		level = !level;
+-
+ 	/* Setting GPIOs with I2C/etc requires a task context, and we don't
+ 	 * seem to have a reliable way to know if we're already in one; so
+ 	 * let's just assume the worst.
+@@ -72,11 +66,11 @@ static void gpio_led_set(struct led_classdev *led_cdev,
+ 		schedule_work(&led_dat->work);
+ 	} else {
+ 		if (led_dat->blinking) {
+-			led_dat->platform_gpio_blink_set(led_dat->gpio, level,
++			led_dat->platform_gpio_blink_set(led_dat->gpiod, level,
+ 							 NULL, NULL);
+ 			led_dat->blinking = 0;
+ 		} else
+-			gpio_set_value(led_dat->gpio, level);
++			gpiod_set_value(led_dat->gpiod, level);
+ 	}
+ }
+ 
+@@ -87,34 +81,49 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
+ 		container_of(led_cdev, struct gpio_led_data, cdev);
+ 
+ 	led_dat->blinking = 1;
+-	return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
++	return led_dat->platform_gpio_blink_set(led_dat->gpiod, GPIO_LED_BLINK,
+ 						delay_on, delay_off);
+ }
+ 
+ static int create_gpio_led(const struct gpio_led *template,
+ 	struct gpio_led_data *led_dat, struct device *parent,
+-	int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
++	int (*blink_set)(struct gpio_desc *, int, unsigned long *,
++			 unsigned long *))
+ {
+ 	int ret, state;
+ 
+-	led_dat->gpio = -1;
++	led_dat->gpiod = template->gpiod;
++	if (!led_dat->gpiod) {
++		/*
++		 * This is the legacy code path for platform code that
++		 * still uses GPIO numbers. Ultimately we would like to get
++		 * rid of this block completely.
++		 */
++		unsigned long flags = 0;
++
++		/* skip leds that aren't available */
++		if (!gpio_is_valid(template->gpio)) {
++			dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
++					template->gpio, template->name);
++			return 0;
++		}
+ 
+-	/* skip leds that aren't available */
+-	if (!gpio_is_valid(template->gpio)) {
+-		dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
+-				template->gpio, template->name);
+-		return 0;
+-	}
++		if (template->active_low)
++			flags |= GPIOF_ACTIVE_LOW;
+ 
+-	ret = devm_gpio_request(parent, template->gpio, template->name);
+-	if (ret < 0)
+-		return ret;
++		ret = devm_gpio_request_one(parent, template->gpio, flags,
++					    template->name);
++		if (ret < 0)
++			return ret;
++
++		led_dat->gpiod = gpio_to_desc(template->gpio);
++		if (IS_ERR(led_dat->gpiod))
++			return PTR_ERR(led_dat->gpiod);
++	}
+ 
+ 	led_dat->cdev.name = template->name;
+ 	led_dat->cdev.default_trigger = template->default_trigger;
+-	led_dat->gpio = template->gpio;
+-	led_dat->can_sleep = gpio_cansleep(template->gpio);
+-	led_dat->active_low = template->active_low;
++	led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
+ 	led_dat->blinking = 0;
+ 	if (blink_set) {
+ 		led_dat->platform_gpio_blink_set = blink_set;
+@@ -122,30 +131,24 @@ static int create_gpio_led(const struct gpio_led *template,
+ 	}
+ 	led_dat->cdev.brightness_set = gpio_led_set;
+ 	if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
+-		state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
++		state = !!gpiod_get_value_cansleep(led_dat->gpiod);
+ 	else
+ 		state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
+ 	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
+ 	if (!template->retain_state_suspended)
+ 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ 
+-	ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
++	ret = gpiod_direction_output(led_dat->gpiod, state);
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	INIT_WORK(&led_dat->work, gpio_led_work);
+ 
+-	ret = led_classdev_register(parent, &led_dat->cdev);
+-	if (ret < 0)
+-		return ret;
+-
+-	return 0;
++	return led_classdev_register(parent, &led_dat->cdev);
+ }
+ 
+ static void delete_gpio_led(struct gpio_led_data *led)
+ {
+-	if (!gpio_is_valid(led->gpio))
+-		return;
+ 	led_classdev_unregister(&led->cdev);
+ 	cancel_work_sync(&led->work);
+ }
+@@ -161,40 +164,37 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
+ 		(sizeof(struct gpio_led_data) * num_leds);
+ }
+ 
+-/* Code to create from OpenFirmware platform devices */
+-#ifdef CONFIG_OF_GPIO
+-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
++static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
+ {
+-	struct device_node *np = pdev->dev.of_node, *child;
++	struct device *dev = &pdev->dev;
++	struct fwnode_handle *child;
+ 	struct gpio_leds_priv *priv;
+ 	int count, ret;
+ 
+-	/* count LEDs in this device, so we know how much to allocate */
+-	count = of_get_available_child_count(np);
++	count = device_get_child_node_count(dev);
+ 	if (!count)
+ 		return ERR_PTR(-ENODEV);
+ 
+-	for_each_available_child_of_node(np, child)
+-		if (of_get_gpio(child, 0) == -EPROBE_DEFER)
+-			return ERR_PTR(-EPROBE_DEFER);
+-
+-	priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
+-			GFP_KERNEL);
++	priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
+ 	if (!priv)
+ 		return ERR_PTR(-ENOMEM);
+ 
+-	for_each_available_child_of_node(np, child) {
++	device_for_each_child_node(dev, child) {
+ 		struct gpio_led led = {};
+-		enum of_gpio_flags flags;
+-		const char *state;
+-
+-		led.gpio = of_get_gpio_flags(child, 0, &flags);
+-		led.active_low = flags & OF_GPIO_ACTIVE_LOW;
+-		led.name = of_get_property(child, "label", NULL) ? : child->name;
+-		led.default_trigger =
+-			of_get_property(child, "linux,default-trigger", NULL);
+-		state = of_get_property(child, "default-state", NULL);
+-		if (state) {
++		const char *state = NULL;
++
++		led.gpiod = devm_get_gpiod_from_child(dev, child);
++		if (IS_ERR(led.gpiod)) {
++			fwnode_handle_put(child);
++			goto err;
++		}
++
++		fwnode_property_read_string(child, "label", &led.name);
++		fwnode_property_read_string(child, "linux,default-trigger",
++					    &led.default_trigger);
++
++		if (!fwnode_property_read_string(child, "linux,default_state",
++						 &state)) {
+ 			if (!strcmp(state, "keep"))
+ 				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
+ 			else if (!strcmp(state, "on"))
+@@ -203,13 +203,13 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+ 				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
+ 		}
+ 
+-		if (of_get_property(child, "retain-state-suspended", NULL))
++		if (fwnode_property_present(child, "retain-state-suspended"))
+ 			led.retain_state_suspended = 1;
+ 
+ 		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
+-				      &pdev->dev, NULL);
++				      dev, NULL);
+ 		if (ret < 0) {
+-			of_node_put(child);
++			fwnode_handle_put(child);
+ 			goto err;
+ 		}
+ 	}
+@@ -228,12 +228,6 @@ static const struct of_device_id of_gpio_leds_match[] = {
+ };
+ 
+ MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
+-#else /* CONFIG_OF_GPIO */
+-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+-{
+-	return ERR_PTR(-ENODEV);
+-}
+-#endif /* CONFIG_OF_GPIO */
+ 
+ static int gpio_led_probe(struct platform_device *pdev)
+ {
+@@ -261,7 +255,7 @@ static int gpio_led_probe(struct platform_device *pdev)
+ 			}
+ 		}
+ 	} else {
+-		priv = gpio_leds_create_of(pdev);
++		priv = gpio_leds_create(pdev);
+ 		if (IS_ERR(priv))
+ 			return PTR_ERR(priv);
+ 	}
+@@ -288,7 +282,7 @@ static struct platform_driver gpio_led_driver = {
+ 	.driver		= {
+ 		.name	= "leds-gpio",
+ 		.owner	= THIS_MODULE,
+-		.of_match_table = of_match_ptr(of_gpio_leds_match),
++		.of_match_table = of_gpio_leds_match,
+ 	},
+ };
+ 
+diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
+index 634f729..0a1af93 100644
+--- a/drivers/misc/eeprom/at25.c
++++ b/drivers/misc/eeprom/at25.c
+@@ -18,7 +18,7 @@
+ 
+ #include <linux/spi/spi.h>
+ #include <linux/spi/eeprom.h>
+-#include <linux/of.h>
++#include <linux/property.h>
+ 
+ /*
+  * NOTE: this is an *EEPROM* driver.  The vagaries of product naming
+@@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-static int at25_np_to_chip(struct device *dev,
+-			   struct device_node *np,
+-			   struct spi_eeprom *chip)
++static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
+ {
+ 	u32 val;
+ 
+ 	memset(chip, 0, sizeof(*chip));
+-	strncpy(chip->name, np->name, sizeof(chip->name));
++	strncpy(chip->name, "at25", sizeof(chip->name));
+ 
+-	if (of_property_read_u32(np, "size", &val) == 0 ||
+-	    of_property_read_u32(np, "at25,byte-len", &val) == 0) {
++	if (device_property_read_u32(dev, "size", &val) == 0 ||
++	    device_property_read_u32(dev, "at25,byte-len", &val) == 0) {
+ 		chip->byte_len = val;
+ 	} else {
+ 		dev_err(dev, "Error: missing \"size\" property\n");
+ 		return -ENODEV;
+ 	}
+ 
+-	if (of_property_read_u32(np, "pagesize", &val) == 0 ||
+-	    of_property_read_u32(np, "at25,page-size", &val) == 0) {
++	if (device_property_read_u32(dev, "pagesize", &val) == 0 ||
++	    device_property_read_u32(dev, "at25,page-size", &val) == 0) {
+ 		chip->page_size = (u16)val;
+ 	} else {
+ 		dev_err(dev, "Error: missing \"pagesize\" property\n");
+ 		return -ENODEV;
+ 	}
+ 
+-	if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) {
++	if (device_property_read_u32(dev, "at25,addr-mode", &val) == 0) {
+ 		chip->flags = (u16)val;
+ 	} else {
+-		if (of_property_read_u32(np, "address-width", &val)) {
++		if (device_property_read_u32(dev, "address-width", &val)) {
+ 			dev_err(dev,
+ 				"Error: missing \"address-width\" property\n");
+ 			return -ENODEV;
+@@ -350,7 +348,7 @@ static int at25_np_to_chip(struct device *dev,
+ 				val);
+ 			return -ENODEV;
+ 		}
+-		if (of_find_property(np, "read-only", NULL))
++		if (device_property_present(dev, "read-only"))
+ 			chip->flags |= EE_READONLY;
+ 	}
+ 	return 0;
+@@ -360,21 +358,15 @@ static int at25_probe(struct spi_device *spi)
+ {
+ 	struct at25_data	*at25 = NULL;
+ 	struct spi_eeprom	chip;
+-	struct device_node	*np = spi->dev.of_node;
+ 	int			err;
+ 	int			sr;
+ 	int			addrlen;
+ 
+ 	/* Chip description */
+ 	if (!spi->dev.platform_data) {
+-		if (np) {
+-			err = at25_np_to_chip(&spi->dev, np, &chip);
+-			if (err)
+-				return err;
+-		} else {
+-			dev_err(&spi->dev, "Error: no chip description\n");
+-			return -ENODEV;
+-		}
++		err = at25_fw_to_chip(&spi->dev, &chip);
++		if (err)
++			return err;
+ 	} else
+ 		chip = *(struct spi_eeprom *)spi->dev.platform_data;
+ 
+diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
+index 8319c99..6feb6ef3 100644
+--- a/drivers/net/ethernet/amd/Kconfig
++++ b/drivers/net/ethernet/amd/Kconfig
+@@ -179,7 +179,7 @@ config SUNLANCE
+ 
+ config AMD_XGBE
+ 	tristate "AMD 10GbE Ethernet driver"
+-	depends on OF_NET
++	depends on OF_NET || ACPI
+ 	select PHYLIB
+ 	select AMD_XGBE_PHY
+ 	select BITREVERSE
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index 9da3a03..a34cad2 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -130,7 +130,7 @@ static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata,
+ 
+ 	DBGPR("-->xgbe_usec_to_riwt\n");
+ 
+-	rate = clk_get_rate(pdata->sysclk);
++	rate = pdata->sysclk_rate;
+ 
+ 	/*
+ 	 * Convert the input usec value to the watchdog timer value. Each
+@@ -153,7 +153,7 @@ static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata,
+ 
+ 	DBGPR("-->xgbe_riwt_to_usec\n");
+ 
+-	rate = clk_get_rate(pdata->sysclk);
++	rate = pdata->sysclk_rate;
+ 
+ 	/*
+ 	 * Convert the input watchdog timer value to the usec value. Each
+@@ -695,6 +695,18 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ 	else
+ 		mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
+ 
++	if (XGBE_SEATTLE_A0) {
++		/* The PCS implementation has reversed the devices in
++		 * package registers so we need to change 05 to 06 and
++		 * 06 to 05 if being read (these registers are readonly
++		 * so no need to do this in the write function)
++		 */
++		if ((mmd_address & 0xffff) == 0x05)
++			mmd_address = (mmd_address & ~0xffff) | 0x06;
++		else if ((mmd_address & 0xffff) == 0x06)
++			mmd_address = (mmd_address & ~0xffff) | 0x05;
++	}
++
+ 	/* The PCS registers are accessed using mmio. The underlying APB3
+ 	 * management interface uses indirect addressing to access the MMD
+ 	 * register sets. This requires accessing of the PCS register in two
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+index 2349ea9..a04b18b 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+@@ -425,6 +425,9 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
+ 	hw_feat->rx_ch_cnt++;
+ 	hw_feat->tx_ch_cnt++;
+ 
++	/* A0 does not support NUMTC, hardcode it for now */
++	hw_feat->tc_cnt = XGBE_TC_CNT;
++
+ 	DBGPR("<--xgbe_get_all_hw_features\n");
+ }
+ 
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+index f5a8fa0..338c0ed 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+@@ -124,6 +124,7 @@
+ #include <linux/of.h>
+ #include <linux/of_net.h>
+ #include <linux/clk.h>
++#include <linux/acpi.h>
+ 
+ #include "xgbe.h"
+ #include "xgbe-common.h"
+@@ -215,6 +216,205 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata)
+ 	xgbe_init_function_ptrs_desc(&pdata->desc_if);
+ }
+ 
++static int xgbe_map_resources(struct xgbe_prv_data *pdata)
++{
++	struct platform_device *pdev = pdata->pdev;
++	struct device *dev = pdata->dev;
++	struct resource *res;
++
++	/* Obtain the mmio areas for the device */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	pdata->xgmac_regs = devm_ioremap_resource(dev, res);
++	if (IS_ERR(pdata->xgmac_regs)) {
++		dev_err(dev, "xgmac ioremap failed\n");
++		return PTR_ERR(pdata->xgmac_regs);
++	}
++	DBGPR("  xgmac_regs = %p\n", pdata->xgmac_regs);
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++	pdata->xpcs_regs = devm_ioremap_resource(dev, res);
++	if (IS_ERR(pdata->xpcs_regs)) {
++		dev_err(dev, "xpcs ioremap failed\n");
++		return PTR_ERR(pdata->xpcs_regs);
++	}
++	DBGPR("  xpcs_regs  = %p\n", pdata->xpcs_regs);
++
++	return 0;
++}
++
++#ifdef CONFIG_ACPI
++static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
++{
++	struct acpi_device *adev = pdata->adev;
++	struct device *dev = pdata->dev;
++	const union acpi_object *property;
++	acpi_status status;
++	u64 cca;
++	unsigned int i;
++	int ret;
++
++	/* Map the memory resources */
++	ret = xgbe_map_resources(pdata);
++	if (ret)
++		return ret;
++
++	/* Obtain the system clock setting */
++	ret = acpi_dev_get_property(adev, XGBE_ACPI_DMA_FREQ, ACPI_TYPE_INTEGER,
++				    &property);
++	if (ret) {
++		dev_err(dev, "unable to obtain %s acpi property\n",
++			XGBE_ACPI_DMA_FREQ);
++		return ret;
++	}
++	pdata->sysclk_rate = property->integer.value;
++
++	/* Obtain the PTP clock setting */
++	ret = acpi_dev_get_property(adev, XGBE_ACPI_PTP_FREQ, ACPI_TYPE_INTEGER,
++				    &property);
++	if (ret) {
++		dev_err(dev, "unable to obtain %s acpi property\n",
++			XGBE_ACPI_PTP_FREQ);
++		return ret;
++	}
++	pdata->ptpclk_rate = property->integer.value;
++
++	/* Retrieve the MAC address */
++	ret = acpi_dev_get_property_array(adev, XGBE_ACPI_MAC_ADDR,
++					  ACPI_TYPE_INTEGER, &property);
++	if (ret) {
++		dev_err(dev, "unable to obtain %s acpi property\n",
++			XGBE_ACPI_MAC_ADDR);
++		return ret;
++	}
++	if (property->package.count != 6) {
++		dev_err(dev, "invalid %s acpi property\n",
++			XGBE_ACPI_MAC_ADDR);
++		return -EINVAL;
++	}
++	for (i = 0; i < property->package.count; i++) {
++		union acpi_object *obj = &property->package.elements[i];
++
++		pdata->mac_addr[i] = (u8)obj->integer.value;
++	}
++	if (!is_valid_ether_addr(pdata->mac_addr)) {
++		dev_err(dev, "invalid %s acpi property\n",
++			XGBE_ACPI_MAC_ADDR);
++		return -EINVAL;
++	}
++
++	/* Retrieve the PHY mode - it must be "xgmii" */
++	ret = acpi_dev_get_property(adev, XGBE_ACPI_PHY_MODE, ACPI_TYPE_STRING,
++				    &property);
++	if (ret) {
++		dev_err(dev, "unable to obtain %s acpi property\n",
++			XGBE_ACPI_PHY_MODE);
++		return ret;
++	}
++	if (strcmp(property->string.pointer,
++		   phy_modes(PHY_INTERFACE_MODE_XGMII))) {
++		dev_err(dev, "invalid %s acpi property\n",
++			XGBE_ACPI_PHY_MODE);
++		return -EINVAL;
++	}
++	pdata->phy_mode = PHY_INTERFACE_MODE_XGMII;
++
++#ifndef METHOD_NAME__CCA
++#define METHOD_NAME__CCA "_CCA"
++#endif
++	/* Set the device cache coherency values */
++	if (acpi_has_method(adev->handle, METHOD_NAME__CCA)) {
++		status = acpi_evaluate_integer(adev->handle, METHOD_NAME__CCA,
++					       NULL, &cca);
++		if (ACPI_FAILURE(status)) {
++			dev_err(dev, "error obtaining acpi _CCA method\n");
++			return -EINVAL;
++		}
++	} else {
++		cca = 0;
++	}
++
++	if (cca) {
++		pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
++		pdata->arcache = XGBE_DMA_OS_ARCACHE;
++		pdata->awcache = XGBE_DMA_OS_AWCACHE;
++	} else {
++		pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
++		pdata->arcache = XGBE_DMA_SYS_ARCACHE;
++		pdata->awcache = XGBE_DMA_SYS_AWCACHE;
++	}
++
++	return 0;
++}
++#else   /* CONFIG_ACPI */
++static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
++{
++	return -EINVAL;
++}
++#endif  /* CONFIG_ACPI */
++
++#ifdef CONFIG_OF
++static int xgbe_of_support(struct xgbe_prv_data *pdata)
++{
++	struct device *dev = pdata->dev;
++	const u8 *mac_addr;
++	int ret;
++
++	/* Map the memory resources */
++	ret = xgbe_map_resources(pdata);
++	if (ret)
++		return ret;
++
++	/* Obtain the system clock setting */
++	pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
++	if (IS_ERR(pdata->sysclk)) {
++		dev_err(dev, "dma devm_clk_get failed\n");
++		return PTR_ERR(pdata->sysclk);
++	}
++	pdata->sysclk_rate = clk_get_rate(pdata->sysclk);
++
++	/* Obtain the PTP clock setting */
++	pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
++	if (IS_ERR(pdata->ptpclk)) {
++		dev_err(dev, "ptp devm_clk_get failed\n");
++		return PTR_ERR(pdata->ptpclk);
++	}
++	pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
++
++	/* Retrieve the MAC address */
++	mac_addr = of_get_mac_address(dev->of_node);
++	if (!mac_addr) {
++		dev_err(dev, "invalid mac address for this device\n");
++		return -EINVAL;
++	}
++	memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
++
++	/* Retrieve the PHY mode - it must be "xgmii" */
++	pdata->phy_mode = of_get_phy_mode(dev->of_node);
++	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
++		dev_err(dev, "invalid phy-mode specified for this device\n");
++		return -EINVAL;
++	}
++
++	/* Set the device cache coherency values */
++	if (of_property_read_bool(dev->of_node, "dma-coherent")) {
++		pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
++		pdata->arcache = XGBE_DMA_OS_ARCACHE;
++		pdata->awcache = XGBE_DMA_OS_AWCACHE;
++	} else {
++		pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
++		pdata->arcache = XGBE_DMA_SYS_ARCACHE;
++		pdata->awcache = XGBE_DMA_SYS_AWCACHE;
++	}
++
++	return 0;
++}
++#else   /* CONFIG_OF */
++static int xgbe_of_support(struct xgbe_prv_data *pdata)
++{
++	return -EINVAL;
++}
++#endif  /*CONFIG_OF */
++
+ static int xgbe_probe(struct platform_device *pdev)
+ {
+ 	struct xgbe_prv_data *pdata;
+@@ -222,8 +422,6 @@ static int xgbe_probe(struct platform_device *pdev)
+ 	struct xgbe_desc_if *desc_if;
+ 	struct net_device *netdev;
+ 	struct device *dev = &pdev->dev;
+-	struct resource *res;
+-	const u8 *mac_addr;
+ 	int ret;
+ 
+ 	DBGPR("--> xgbe_probe\n");
+@@ -239,6 +437,7 @@ static int xgbe_probe(struct platform_device *pdev)
+ 	pdata = netdev_priv(netdev);
+ 	pdata->netdev = netdev;
+ 	pdata->pdev = pdev;
++	pdata->adev = ACPI_COMPANION(dev);
+ 	pdata->dev = dev;
+ 	platform_set_drvdata(pdev, netdev);
+ 
+@@ -264,40 +463,13 @@ static int xgbe_probe(struct platform_device *pdev)
+ 		goto err_io;
+ 	}
+ 
+-	/* Obtain the system clock setting */
+-	pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
+-	if (IS_ERR(pdata->sysclk)) {
+-		dev_err(dev, "dma devm_clk_get failed\n");
+-		ret = PTR_ERR(pdata->sysclk);
+-		goto err_io;
+-	}
+-
+-	/* Obtain the PTP clock setting */
+-	pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
+-	if (IS_ERR(pdata->ptpclk)) {
+-		dev_err(dev, "ptp devm_clk_get failed\n");
+-		ret = PTR_ERR(pdata->ptpclk);
+-		goto err_io;
+-	}
+-
+-	/* Obtain the mmio areas for the device */
+-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	pdata->xgmac_regs = devm_ioremap_resource(dev, res);
+-	if (IS_ERR(pdata->xgmac_regs)) {
+-		dev_err(dev, "xgmac ioremap failed\n");
+-		ret = PTR_ERR(pdata->xgmac_regs);
+-		goto err_io;
+-	}
+-	DBGPR("  xgmac_regs = %p\n", pdata->xgmac_regs);
+-
+-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-	pdata->xpcs_regs = devm_ioremap_resource(dev, res);
+-	if (IS_ERR(pdata->xpcs_regs)) {
+-		dev_err(dev, "xpcs ioremap failed\n");
+-		ret = PTR_ERR(pdata->xpcs_regs);
++	/* Obtain device settings */
++	if (pdata->adev && !acpi_disabled)
++		ret = xgbe_acpi_support(pdata);
++	else
++		ret = xgbe_of_support(pdata);
++	if (ret)
+ 		goto err_io;
+-	}
+-	DBGPR("  xpcs_regs  = %p\n", pdata->xpcs_regs);
+ 
+ 	/* Set the DMA mask */
+ 	if (!dev->dma_mask)
+@@ -308,23 +480,16 @@ static int xgbe_probe(struct platform_device *pdev)
+ 		goto err_io;
+ 	}
+ 
+-	if (of_property_read_bool(dev->of_node, "dma-coherent")) {
+-		pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+-		pdata->arcache = XGBE_DMA_OS_ARCACHE;
+-		pdata->awcache = XGBE_DMA_OS_AWCACHE;
+-	} else {
+-		pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
+-		pdata->arcache = XGBE_DMA_SYS_ARCACHE;
+-		pdata->awcache = XGBE_DMA_SYS_AWCACHE;
+-	}
+-
++	/* Get the device interrupt */
+ 	ret = platform_get_irq(pdev, 0);
+ 	if (ret < 0) {
+ 		dev_err(dev, "platform_get_irq failed\n");
+ 		goto err_io;
+ 	}
++
+ 	netdev->irq = ret;
+ 	netdev->base_addr = (unsigned long)pdata->xgmac_regs;
++	memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len);
+ 
+ 	/* Set all the function pointers */
+ 	xgbe_init_all_fptrs(pdata);
+@@ -337,23 +502,6 @@ static int xgbe_probe(struct platform_device *pdev)
+ 	/* Populate the hardware features */
+ 	xgbe_get_all_hw_features(pdata);
+ 
+-	/* Retrieve the MAC address */
+-	mac_addr = of_get_mac_address(dev->of_node);
+-	if (!mac_addr) {
+-		dev_err(dev, "invalid mac address for this device\n");
+-		ret = -EINVAL;
+-		goto err_io;
+-	}
+-	memcpy(netdev->dev_addr, mac_addr, netdev->addr_len);
+-
+-	/* Retrieve the PHY mode - it must be "xgmii" */
+-	pdata->phy_mode = of_get_phy_mode(dev->of_node);
+-	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
+-		dev_err(dev, "invalid phy-mode specified for this device\n");
+-		ret = -EINVAL;
+-		goto err_io;
+-	}
+-
+ 	/* Set default configuration data */
+ 	xgbe_default_config(pdata);
+ 
+@@ -531,10 +679,22 @@ static int xgbe_resume(struct device *dev)
+ }
+ #endif /* CONFIG_PM */
+ 
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id xgbe_acpi_match[] = {
++	{ "AMDI8000", 0 },
++	{},
++};
++
++MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
++#endif
++
++#ifdef CONFIG_OF
+ static const struct of_device_id xgbe_of_match[] = {
++	{ .compatible = "amd,xgbe-seattle-v0a", },
+ 	{ .compatible = "amd,xgbe-seattle-v1a", },
+ 	{},
+ };
++#endif
+ 
+ MODULE_DEVICE_TABLE(of, xgbe_of_match);
+ static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume);
+@@ -542,7 +702,12 @@ static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume);
+ static struct platform_driver xgbe_driver = {
+ 	.driver = {
+ 		.name = "amd-xgbe",
++#ifdef CONFIG_ACPI
++		.acpi_match_table = xgbe_acpi_match,
++#endif
++#ifdef CONFIG_OF
+ 		.of_match_table = xgbe_of_match,
++#endif
+ 		.pm = &xgbe_pm_ops,
+ 	},
+ 	.probe = xgbe_probe,
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+index 363b210..5d2c89b 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+@@ -119,6 +119,7 @@
+ #include <linux/mdio.h>
+ #include <linux/phy.h>
+ #include <linux/of.h>
++#include <linux/acpi.h>
+ 
+ #include "xgbe.h"
+ #include "xgbe-common.h"
+@@ -205,25 +206,16 @@ void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
+ 
+ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
+ {
+-	struct device_node *phy_node;
+ 	struct mii_bus *mii;
+ 	struct phy_device *phydev;
+ 	int ret = 0;
+ 
+ 	DBGPR("-->xgbe_mdio_register\n");
+ 
+-	/* Retrieve the phy-handle */
+-	phy_node = of_parse_phandle(pdata->dev->of_node, "phy-handle", 0);
+-	if (!phy_node) {
+-		dev_err(pdata->dev, "unable to parse phy-handle\n");
+-		return -EINVAL;
+-	}
+-
+ 	mii = mdiobus_alloc();
+ 	if (mii == NULL) {
+ 		dev_err(pdata->dev, "mdiobus_alloc failed\n");
+-		ret = -ENOMEM;
+-		goto err_node_get;
++		return -ENOMEM;
+ 	}
+ 
+ 	/* Register on the MDIO bus (don't probe any PHYs) */
+@@ -252,12 +244,9 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
+ 	request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
+ 		       MDIO_ID_ARGS(phydev->c45_ids.device_ids[MDIO_MMD_PCS]));
+ 
+-	of_node_get(phy_node);
+-	phydev->dev.of_node = phy_node;
+ 	ret = phy_device_register(phydev);
+ 	if (ret) {
+ 		dev_err(pdata->dev, "phy_device_register failed\n");
+-		of_node_put(phy_node);
+ 		goto err_phy_device;
+ 	}
+ 
+@@ -283,8 +272,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
+ 
+ 	pdata->phydev = phydev;
+ 
+-	of_node_put(phy_node);
+-
+ 	DBGPHY_REGS(pdata);
+ 
+ 	DBGPR("<--xgbe_mdio_register\n");
+@@ -300,9 +287,6 @@ err_mdiobus_register:
+ err_mdiobus_alloc:
+ 	mdiobus_free(mii);
+ 
+-err_node_get:
+-	of_node_put(phy_node);
+-
+ 	return ret;
+ }
+ 
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+index a1bf9d1c..fa67203 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+@@ -239,7 +239,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
+ 	snprintf(info->name, sizeof(info->name), "%s",
+ 		 netdev_name(pdata->netdev));
+ 	info->owner = THIS_MODULE;
+-	info->max_adj = clk_get_rate(pdata->ptpclk);
++	info->max_adj = pdata->ptpclk_rate;
+ 	info->adjfreq = xgbe_adjfreq;
+ 	info->adjtime = xgbe_adjtime;
+ 	info->gettime = xgbe_gettime;
+@@ -260,7 +260,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
+ 	 */
+ 	dividend = 50000000;
+ 	dividend <<= 32;
+-	pdata->tstamp_addend = div_u64(dividend, clk_get_rate(pdata->ptpclk));
++	pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
+ 
+ 	/* Setup the timecounter */
+ 	cc->read = xgbe_cc_read;
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
+index 789957d..59498eb 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
+@@ -172,6 +172,12 @@
+ #define XGBE_DMA_CLOCK		"dma_clk"
+ #define XGBE_PTP_CLOCK		"ptp_clk"
+ 
++/* ACPI property names */
++#define XGBE_ACPI_MAC_ADDR	"mac-address"
++#define XGBE_ACPI_PHY_MODE	"phy-mode"
++#define XGBE_ACPI_DMA_FREQ	"amd,dma-freq"
++#define XGBE_ACPI_PTP_FREQ	"amd,ptp-freq"
++
+ /* Timestamp support - values based on 50MHz PTP clock
+  *   50MHz => 20 nsec
+  */
+@@ -186,8 +192,11 @@
+ #define XGBE_FIFO_SIZE_B(x)	(x)
+ #define XGBE_FIFO_SIZE_KB(x)	(x * 1024)
+ 
++#define XGBE_TC_CNT		2
+ #define XGBE_TC_MIN_QUANTUM	10
+ 
++#define XGBE_SEATTLE_A0		((read_cpuid_id() & 0x00f0000f) == 0)
++
+ /* Helper macro for descriptor handling
+  *  Always use XGBE_GET_DESC_DATA to access the descriptor data
+  *  since the index is free-running and needs to be and-ed
+@@ -569,6 +578,7 @@ struct xgbe_hw_features {
+ struct xgbe_prv_data {
+ 	struct net_device *netdev;
+ 	struct platform_device *pdev;
++	struct acpi_device *adev;
+ 	struct device *dev;
+ 
+ 	/* XGMAC/XPCS related mmio registers */
+@@ -649,6 +659,7 @@ struct xgbe_prv_data {
+ 	unsigned int phy_rx_pause;
+ 
+ 	/* Netdev related settings */
++	unsigned char mac_addr[MAX_ADDR_LEN];
+ 	netdev_features_t netdev_features;
+ 	struct napi_struct napi;
+ 	struct xgbe_mmc_stats mmc_stats;
+@@ -658,7 +669,9 @@ struct xgbe_prv_data {
+ 
+ 	/* Device clocks */
+ 	struct clk *sysclk;
++	unsigned long sysclk_rate;
+ 	struct clk *ptpclk;
++	unsigned long ptpclk_rate;
+ 
+ 	/* Timestamp support */
+ 	spinlock_t tstamp_lock;
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+index 7ba83ff..29aad5e 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+@@ -663,15 +663,20 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
+ 	struct phy_device *phy_dev;
+ 	struct device *dev = &pdata->pdev->dev;
+ 
+-	phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
+-	if (!phy_np) {
+-		netdev_dbg(ndev, "No phy-handle found\n");
+-		return -ENODEV;
++	if (dev->of_node) {
++		phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
++		if (!phy_np) {
++			netdev_dbg(ndev, "No phy-handle found in DT\n");
++			return -ENODEV;
++		}
++		pdata->phy_dev = of_phy_find_device(phy_np);
+ 	}
+ 
+-	phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
+-				 0, pdata->phy_mode);
+-	if (!phy_dev) {
++	phy_dev = pdata->phy_dev;
++
++	if (phy_dev == NULL ||
++	    phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
++			       pdata->phy_mode)) {
+ 		netdev_err(ndev, "Could not connect to PHY\n");
+ 		return  -ENODEV;
+ 	}
+@@ -681,11 +686,52 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
+ 			      ~SUPPORTED_100baseT_Half &
+ 			      ~SUPPORTED_1000baseT_Half;
+ 	phy_dev->advertising = phy_dev->supported;
+-	pdata->phy_dev = phy_dev;
+ 
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_ACPI
++static int xgene_acpi_mdiobus_register(struct xgene_enet_pdata *pdata,
++	struct mii_bus *mdio)
++{
++	struct device *dev = &pdata->pdev->dev;
++	struct phy_device *phy;
++	int i, ret;
++	u32 phy_id;
++
++	/* Mask out all PHYs from auto probing. */
++	mdio->phy_mask = ~0;
++
++	/* Clear all the IRQ properties */
++	if (mdio->irq)
++		for (i = 0; i < PHY_MAX_ADDR; i++)
++			mdio->irq[i] = PHY_POLL;
++
++	/* Register the MDIO bus */
++	ret = mdiobus_register(mdio);
++	if (ret)
++		return ret;
++
++	ret = device_property_read_u32(dev, "phy-channel", &phy_id);
++	if (ret)
++		return -EINVAL;
++
++	phy = get_phy_device(mdio, phy_id, true);
++	if (!phy || IS_ERR(phy))
++		return -EIO;
++
++	ret = phy_device_register(phy);
++	if (ret)
++		phy_device_free(phy);
++	else
++		pdata->phy_dev = phy;
++
++	return ret;
++}
++#else
++#define xgene_acpi_mdiobus_register(a, b) -1
++#endif
++
+ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+ {
+ 	struct net_device *ndev = pdata->ndev;
+@@ -702,7 +748,7 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+ 		}
+ 	}
+ 
+-	if (!mdio_np) {
++	if (dev->of_node && !mdio_np) {
+ 		netdev_dbg(ndev, "No mdio node in the dts\n");
+ 		return -ENXIO;
+ 	}
+@@ -720,7 +766,10 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+ 	mdio_bus->priv = pdata;
+ 	mdio_bus->parent = &ndev->dev;
+ 
+-	ret = of_mdiobus_register(mdio_bus, mdio_np);
++	if (dev->of_node)
++		ret = of_mdiobus_register(mdio_bus, mdio_np);
++	else
++		ret = xgene_acpi_mdiobus_register(pdata, mdio_bus);
+ 	if (ret) {
+ 		netdev_err(ndev, "Failed to register MDIO bus\n");
+ 		mdiobus_free(mdio_bus);
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 1236696..f66598a 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -746,6 +746,42 @@ static const struct net_device_ops xgene_ndev_ops = {
+ 	.ndo_set_mac_address = xgene_enet_set_mac_address,
+ };
+ 
++#ifdef CONFIG_ACPI
++static int acpi_get_mac_address(struct device *dev,
++				unsigned char *addr)
++{
++	int ret;
++
++	ret = device_property_read_u8_array(dev, "mac-address", addr, 6);
++	if (ret)
++		return 0;
++
++	return 6;
++}
++
++static int acpi_get_phy_mode(struct device *dev)
++{
++	int i, ret, phy_mode;
++	char *modestr;
++
++	ret = device_property_read_string(dev, "phy-mode", &modestr);
++	if (ret)
++		return -1;
++
++	phy_mode = -1;
++	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
++		if (!strcasecmp(modestr, phy_modes(i))) {
++			phy_mode = i;
++			break;
++		}
++	}
++	return phy_mode;
++}
++#else
++#define acpi_get_mac_address(a, b, c) 0
++#define acpi_get_phy_mode(a) -1
++#endif
++
+ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ {
+ 	struct platform_device *pdev;
+@@ -761,6 +797,8 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ 	ndev = pdata->ndev;
+ 
+ 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr");
++	if (!res)
++		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	if (!res) {
+ 		dev_err(dev, "Resource enet_csr not defined\n");
+ 		return -ENODEV;
+@@ -772,6 +810,8 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ 	}
+ 
+ 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr");
++	if (!res)
++		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ 	if (!res) {
+ 		dev_err(dev, "Resource ring_csr not defined\n");
+ 		return -ENODEV;
+@@ -783,6 +823,8 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ 	}
+ 
+ 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd");
++	if (!res)
++		res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ 	if (!res) {
+ 		dev_err(dev, "Resource ring_cmd not defined\n");
+ 		return -ENODEV;
+@@ -804,11 +846,13 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ 	mac = of_get_mac_address(dev->of_node);
+ 	if (mac)
+ 		memcpy(ndev->dev_addr, mac, ndev->addr_len);
+-	else
++	else if (!acpi_get_mac_address(dev, ndev->dev_addr))
+ 		eth_hw_addr_random(ndev);
+ 	memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+ 
+ 	pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
++	if (pdata->phy_mode < 0)
++		pdata->phy_mode = acpi_get_phy_mode(dev);
+ 	if (pdata->phy_mode < 0) {
+ 		dev_err(dev, "Unable to get phy-connection-type\n");
+ 		return pdata->phy_mode;
+@@ -821,11 +865,12 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ 	}
+ 
+ 	pdata->clk = devm_clk_get(&pdev->dev, NULL);
+-	ret = IS_ERR(pdata->clk);
+ 	if (IS_ERR(pdata->clk)) {
+-		dev_err(&pdev->dev, "can't get clock\n");
+-		ret = PTR_ERR(pdata->clk);
+-		return ret;
++		/*
++		 * Not necessarily an error. Firmware may have
++		 * set up the clock already.
++		 */
++		pdata->clk = NULL;
+ 	}
+ 
+ 	base_addr = pdata->base_addr;
+@@ -875,7 +920,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+ 	pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
+ 	pdata->mac_ops->init(pdata);
+ 
+-	return ret;
++	return 0;
+ }
+ 
+ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
+@@ -936,7 +981,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
+ 		goto err;
+ 	}
+ 
+-	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
++	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ 	if (ret) {
+ 		netdev_err(ndev, "No usable DMA configuration\n");
+ 		goto err;
+@@ -984,6 +1029,14 @@ static int xgene_enet_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id xgene_enet_acpi_match[] = {
++	{ "APMC0D05", },
++	{ }
++};
++MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match);
++#endif
++
+ static struct of_device_id xgene_enet_match[] = {
+ 	{.compatible = "apm,xgene-enet",},
+ 	{},
+@@ -995,6 +1048,7 @@ static struct platform_driver xgene_enet_driver = {
+ 	.driver = {
+ 		   .name = "xgene-enet",
+ 		   .of_match_table = xgene_enet_match,
++		   .acpi_match_table = ACPI_PTR(xgene_enet_acpi_match),
+ 	},
+ 	.probe = xgene_enet_probe,
+ 	.remove = xgene_enet_remove,
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index f9958fa..0e06cad 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -31,6 +31,7 @@
+ #include <linux/prefetch.h>
+ #include <linux/if_vlan.h>
+ #include <linux/phy.h>
++#include <linux/acpi.h>
+ #include "xgene_enet_hw.h"
+ 
+ #define XGENE_DRV_VERSION	"v1.0"
+diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
+index 6cc3cf6..91c36a2 100644
+--- a/drivers/net/ethernet/smsc/smc91x.c
++++ b/drivers/net/ethernet/smsc/smc91x.c
+@@ -82,6 +82,7 @@ static const char version[] =
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/of_gpio.h>
++#include <linux/acpi.h>
+ 
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+@@ -2467,6 +2468,14 @@ static struct dev_pm_ops smc_drv_pm_ops = {
+ 	.resume		= smc_drv_resume,
+ };
+ 
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id smc91x_acpi_match[] = {
++	{ "LNRO0003", },
++	{ }
++};
++MODULE_DEVICE_TABLE(acpi, smc91x_acpi_match);
++#endif
++
+ static struct platform_driver smc_driver = {
+ 	.probe		= smc_drv_probe,
+ 	.remove		= smc_drv_remove,
+@@ -2475,6 +2484,7 @@ static struct platform_driver smc_driver = {
+ 		.owner	= THIS_MODULE,
+ 		.pm	= &smc_drv_pm_ops,
+ 		.of_match_table = of_match_ptr(smc91x_match),
++		.acpi_match_table = ACPI_PTR(smc91x_acpi_match),
+ 	},
+ };
+ 
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 75472cf7..bacafe2 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -26,7 +26,7 @@ config AMD_PHY
+ 
+ config AMD_XGBE_PHY
+ 	tristate "Driver for the AMD 10GbE (amd-xgbe) PHYs"
+-	depends on OF
++	depends on OF || ACPI
+ 	---help---
+ 	  Currently supports the AMD 10GbE PHY
+ 
+diff --git a/drivers/net/phy/amd-xgbe-phy.c b/drivers/net/phy/amd-xgbe-phy.c
+index c456559..d852c6e 100644
+--- a/drivers/net/phy/amd-xgbe-phy.c
++++ b/drivers/net/phy/amd-xgbe-phy.c
+@@ -74,15 +74,19 @@
+ #include <linux/of_platform.h>
+ #include <linux/of_device.h>
+ #include <linux/uaccess.h>
++#include <linux/acpi.h>
++
+ 
+ MODULE_AUTHOR("Tom Lendacky <thomas.lendacky at amd.com>");
+ MODULE_LICENSE("Dual BSD/GPL");
+-MODULE_VERSION("1.0.0-a");
++MODULE_VERSION("0.0.0-a");
+ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
+ 
+-#define XGBE_PHY_ID	0x000162d0
++#define XGBE_PHY_ID	0x7996ced0
+ #define XGBE_PHY_MASK	0xfffffff0
+ 
++#define XGBE_PHY_SERDES_RETRY		32
++#define XGBE_PHY_CHANNEL_PROPERTY	"amd,serdes-channel"
+ #define XGBE_PHY_SPEEDSET_PROPERTY	"amd,speed-set"
+ 
+ #define XGBE_AN_INT_CMPLT		0x01
+@@ -99,11 +103,9 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
+ #ifndef MDIO_PMA_10GBR_PMD_CTRL
+ #define MDIO_PMA_10GBR_PMD_CTRL		0x0096
+ #endif
+-
+ #ifndef MDIO_PMA_10GBR_FEC_CTRL
+ #define MDIO_PMA_10GBR_FEC_CTRL		0x00ab
+ #endif
+-
+ #ifndef MDIO_AN_XNP
+ #define MDIO_AN_XNP			0x0016
+ #endif
+@@ -111,93 +113,14 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
+ #ifndef MDIO_AN_INTMASK
+ #define MDIO_AN_INTMASK			0x8001
+ #endif
+-
+ #ifndef MDIO_AN_INT
+ #define MDIO_AN_INT			0x8002
+ #endif
+ 
+-#ifndef MDIO_AN_KR_CTRL
+-#define MDIO_AN_KR_CTRL			0x8003
+-#endif
+-
+ #ifndef MDIO_CTRL1_SPEED1G
+ #define MDIO_CTRL1_SPEED1G		(MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
+ #endif
+ 
+-#ifndef MDIO_KR_CTRL_PDETECT
+-#define MDIO_KR_CTRL_PDETECT		0x01
+-#endif
+-
+-/* SerDes integration register offsets */
+-#define SIR0_KR_RT_1			0x002c
+-#define SIR0_STATUS			0x0040
+-#define SIR1_SPEED			0x0000
+-
+-/* SerDes integration register entry bit positions and sizes */
+-#define SIR0_KR_RT_1_RESET_INDEX	11
+-#define SIR0_KR_RT_1_RESET_WIDTH	1
+-#define SIR0_STATUS_RX_READY_INDEX	0
+-#define SIR0_STATUS_RX_READY_WIDTH	1
+-#define SIR0_STATUS_TX_READY_INDEX	8
+-#define SIR0_STATUS_TX_READY_WIDTH	1
+-#define SIR1_SPEED_DATARATE_INDEX	4
+-#define SIR1_SPEED_DATARATE_WIDTH	2
+-#define SIR1_SPEED_PI_SPD_SEL_INDEX	12
+-#define SIR1_SPEED_PI_SPD_SEL_WIDTH	4
+-#define SIR1_SPEED_PLLSEL_INDEX		3
+-#define SIR1_SPEED_PLLSEL_WIDTH		1
+-#define SIR1_SPEED_RATECHANGE_INDEX	6
+-#define SIR1_SPEED_RATECHANGE_WIDTH	1
+-#define SIR1_SPEED_TXAMP_INDEX		8
+-#define SIR1_SPEED_TXAMP_WIDTH		4
+-#define SIR1_SPEED_WORDMODE_INDEX	0
+-#define SIR1_SPEED_WORDMODE_WIDTH	3
+-
+-#define SPEED_10000_CDR			0x7
+-#define SPEED_10000_PLL			0x1
+-#define SPEED_10000_RATE		0x0
+-#define SPEED_10000_TXAMP		0xa
+-#define SPEED_10000_WORD		0x7
+-
+-#define SPEED_2500_CDR			0x2
+-#define SPEED_2500_PLL			0x0
+-#define SPEED_2500_RATE			0x1
+-#define SPEED_2500_TXAMP		0xf
+-#define SPEED_2500_WORD			0x1
+-
+-#define SPEED_1000_CDR			0x2
+-#define SPEED_1000_PLL			0x0
+-#define SPEED_1000_RATE			0x3
+-#define SPEED_1000_TXAMP		0xf
+-#define SPEED_1000_WORD			0x1
+-
+-/* SerDes RxTx register offsets */
+-#define RXTX_REG20			0x0050
+-#define RXTX_REG114			0x01c8
+-
+-/* SerDes RxTx register entry bit positions and sizes */
+-#define RXTX_REG20_BLWC_ENA_INDEX	2
+-#define RXTX_REG20_BLWC_ENA_WIDTH	1
+-#define RXTX_REG114_PQ_REG_INDEX	9
+-#define RXTX_REG114_PQ_REG_WIDTH	7
+-
+-#define RXTX_10000_BLWC			0
+-#define RXTX_10000_PQ			0x1e
+-
+-#define RXTX_2500_BLWC			1
+-#define RXTX_2500_PQ			0xa
+-
+-#define RXTX_1000_BLWC			1
+-#define RXTX_1000_PQ			0xa
+-
+-/* Bit setting and getting macros
+- *  The get macro will extract the current bit field value from within
+- *  the variable
+- *
+- *  The set macro will clear the current bit field value within the
+- *  variable and then set the bit field of the variable to the
+- *  specified value
+- */
+ #define GET_BITS(_var, _index, _width)					\
+ 	(((_var) >> (_index)) & ((0x1 << (_width)) - 1))
+ 
+@@ -207,70 +130,12 @@ do {									\
+ 	(_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index));	\
+ } while (0)
+ 
+-#define XSIR_GET_BITS(_var, _prefix, _field)				\
+-	GET_BITS((_var),						\
+-		 _prefix##_##_field##_INDEX,				\
+-		 _prefix##_##_field##_WIDTH)
+-
+-#define XSIR_SET_BITS(_var, _prefix, _field, _val)			\
+-	SET_BITS((_var),						\
+-		 _prefix##_##_field##_INDEX,				\
+-		 _prefix##_##_field##_WIDTH, (_val))
+-
+-/* Macros for reading or writing SerDes integration registers
+- *  The ioread macros will get bit fields or full values using the
+- *  register definitions formed using the input names
+- *
+- *  The iowrite macros will set bit fields or full values using the
+- *  register definitions formed using the input names
+- */
+-#define XSIR0_IOREAD(_priv, _reg)					\
+-	ioread16((_priv)->sir0_regs + _reg)
+-
+-#define XSIR0_IOREAD_BITS(_priv, _reg, _field)				\
+-	GET_BITS(XSIR0_IOREAD((_priv), _reg),				\
+-		 _reg##_##_field##_INDEX,				\
+-		 _reg##_##_field##_WIDTH)
+-
+-#define XSIR0_IOWRITE(_priv, _reg, _val)				\
+-	iowrite16((_val), (_priv)->sir0_regs + _reg)
+-
+-#define XSIR0_IOWRITE_BITS(_priv, _reg, _field, _val)			\
+-do {									\
+-	u16 reg_val = XSIR0_IOREAD((_priv), _reg);			\
+-	SET_BITS(reg_val,						\
+-		 _reg##_##_field##_INDEX,				\
+-		 _reg##_##_field##_WIDTH, (_val));			\
+-	XSIR0_IOWRITE((_priv), _reg, reg_val);				\
+-} while (0)
+-
+-#define XSIR1_IOREAD(_priv, _reg)					\
+-	ioread16((_priv)->sir1_regs + _reg)
+-
+-#define XSIR1_IOREAD_BITS(_priv, _reg, _field)				\
+-	GET_BITS(XSIR1_IOREAD((_priv), _reg),				\
+-		 _reg##_##_field##_INDEX,				\
+-		 _reg##_##_field##_WIDTH)
++#define XCMU_IOREAD(_priv, _reg)					\
++	ioread16((_priv)->cmu_regs + _reg)
+ 
+-#define XSIR1_IOWRITE(_priv, _reg, _val)				\
+-	iowrite16((_val), (_priv)->sir1_regs + _reg)
++#define XCMU_IOWRITE(_priv, _reg, _val)					\
++	iowrite16((_val), (_priv)->cmu_regs + _reg)
+ 
+-#define XSIR1_IOWRITE_BITS(_priv, _reg, _field, _val)			\
+-do {									\
+-	u16 reg_val = XSIR1_IOREAD((_priv), _reg);			\
+-	SET_BITS(reg_val,						\
+-		 _reg##_##_field##_INDEX,				\
+-		 _reg##_##_field##_WIDTH, (_val));			\
+-	XSIR1_IOWRITE((_priv), _reg, reg_val);				\
+-} while (0)
+-
+-/* Macros for reading or writing SerDes RxTx registers
+- *  The ioread macros will get bit fields or full values using the
+- *  register definitions formed using the input names
+- *
+- *  The iowrite macros will set bit fields or full values using the
+- *  register definitions formed using the input names
+- */
+ #define XRXTX_IOREAD(_priv, _reg)					\
+ 	ioread16((_priv)->rxtx_regs + _reg)
+ 
+@@ -291,6 +156,78 @@ do {									\
+ 	XRXTX_IOWRITE((_priv), _reg, reg_val);				\
+ } while (0)
+ 
++/* SerDes CMU register offsets */
++#define CMU_REG15			0x003c
++#define CMU_REG16			0x0040
++
++/* SerDes CMU register entry bit positions and sizes */
++#define CMU_REG16_TX_RATE_CHANGE_BASE	15
++#define CMU_REG16_RX_RATE_CHANGE_BASE	14
++#define CMU_REG16_RATE_CHANGE_DECR	2
++
++
++/* SerDes RxTx register offsets */
++#define RXTX_REG2			0x0008
++#define RXTX_REG3			0x000c
++#define RXTX_REG5			0x0014
++#define RXTX_REG6			0x0018
++#define RXTX_REG20			0x0050
++#define RXTX_REG53			0x00d4
++#define RXTX_REG114			0x01c8
++#define RXTX_REG115			0x01cc
++#define RXTX_REG142			0x0238
++
++/* SerDes RxTx register entry bit positions and sizes */
++#define RXTX_REG2_RESETB_INDEX			15
++#define RXTX_REG2_RESETB_WIDTH			1
++#define RXTX_REG3_TX_DATA_RATE_INDEX		14
++#define RXTX_REG3_TX_DATA_RATE_WIDTH		2
++#define RXTX_REG3_TX_WORD_MODE_INDEX		11
++#define RXTX_REG3_TX_WORD_MODE_WIDTH		3
++#define RXTX_REG5_TXAMP_CNTL_INDEX		7
++#define RXTX_REG5_TXAMP_CNTL_WIDTH		4
++#define RXTX_REG6_RX_DATA_RATE_INDEX		9
++#define RXTX_REG6_RX_DATA_RATE_WIDTH		2
++#define RXTX_REG6_RX_WORD_MODE_INDEX		11
++#define RXTX_REG6_RX_WORD_MODE_WIDTH		3
++#define RXTX_REG20_BLWC_ENA_INDEX		2
++#define RXTX_REG20_BLWC_ENA_WIDTH		1
++#define RXTX_REG53_RX_PLLSELECT_INDEX		15
++#define RXTX_REG53_RX_PLLSELECT_WIDTH		1
++#define RXTX_REG53_TX_PLLSELECT_INDEX		14
++#define RXTX_REG53_TX_PLLSELECT_WIDTH		1
++#define RXTX_REG53_PI_SPD_SEL_CDR_INDEX		10
++#define RXTX_REG53_PI_SPD_SEL_CDR_WIDTH		4
++#define RXTX_REG114_PQ_REG_INDEX		9
++#define RXTX_REG114_PQ_REG_WIDTH		7
++#define RXTX_REG115_FORCE_LAT_CAL_START_INDEX	2
++#define RXTX_REG115_FORCE_LAT_CAL_START_WIDTH	1
++#define RXTX_REG115_FORCE_SUM_CAL_START_INDEX	1
++#define RXTX_REG115_FORCE_SUM_CAL_START_WIDTH	1
++#define RXTX_REG142_SUM_CALIB_DONE_INDEX	15
++#define RXTX_REG142_SUM_CALIB_DONE_WIDTH	1
++#define RXTX_REG142_SUM_CALIB_ERR_INDEX		14
++#define RXTX_REG142_SUM_CALIB_ERR_WIDTH		1
++#define RXTX_REG142_LAT_CALIB_DONE_INDEX	11
++#define RXTX_REG142_LAT_CALIB_DONE_WIDTH	1
++
++#define RXTX_FULL_RATE				0x0
++#define RXTX_HALF_RATE				0x1
++#define RXTX_FIFTH_RATE				0x3
++#define RXTX_66BIT_WORD				0x7
++#define RXTX_10BIT_WORD				0x1
++#define RXTX_10G_TX_AMP				0xa
++#define RXTX_1G_TX_AMP				0xf
++#define RXTX_10G_CDR				0x7
++#define RXTX_1G_CDR				0x2
++#define RXTX_10G_PLL				0x1
++#define RXTX_1G_PLL				0x0
++#define RXTX_10G_PQ				0x1e
++#define RXTX_1G_PQ				0xa
++
++
++DEFINE_SPINLOCK(cmu_lock);
++
+ enum amd_xgbe_phy_an {
+ 	AMD_XGBE_AN_READY = 0,
+ 	AMD_XGBE_AN_START,
+@@ -316,29 +253,31 @@ enum amd_xgbe_phy_mode {
+ };
+ 
+ enum amd_xgbe_phy_speedset {
+-	AMD_XGBE_PHY_SPEEDSET_1000_10000,
++	AMD_XGBE_PHY_SPEEDSET_1000_10000 = 0,
+ 	AMD_XGBE_PHY_SPEEDSET_2500_10000,
+ };
+ 
+ struct amd_xgbe_phy_priv {
+ 	struct platform_device *pdev;
++	struct acpi_device *adev;
+ 	struct device *dev;
+ 
+ 	struct phy_device *phydev;
+ 
+ 	/* SerDes related mmio resources */
+ 	struct resource *rxtx_res;
+-	struct resource *sir0_res;
+-	struct resource *sir1_res;
++	struct resource *cmu_res;
+ 
+ 	/* SerDes related mmio registers */
+ 	void __iomem *rxtx_regs;	/* SerDes Rx/Tx CSRs */
+-	void __iomem *sir0_regs;	/* SerDes integration registers (1/2) */
+-	void __iomem *sir1_regs;	/* SerDes integration registers (2/2) */
++	void __iomem *cmu_regs;		/* SerDes CMU CSRs */
++
++	unsigned int serdes_channel;
++	unsigned int speed_set;
+ 
+ 	/* Maintain link status for re-starting auto-negotiation */
+ 	unsigned int link;
+-	unsigned int speed_set;
++	enum amd_xgbe_phy_mode mode;
+ 
+ 	/* Auto-negotiation state machine support */
+ 	struct mutex an_mutex;
+@@ -348,7 +287,6 @@ struct amd_xgbe_phy_priv {
+ 	enum amd_xgbe_phy_rx kx_state;
+ 	struct work_struct an_work;
+ 	struct workqueue_struct *an_workqueue;
+-	unsigned int parallel_detect;
+ };
+ 
+ static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev)
+@@ -401,33 +339,51 @@ static int amd_xgbe_phy_pcs_power_cycle(struct phy_device *phydev)
+ static void amd_xgbe_phy_serdes_start_ratechange(struct phy_device *phydev)
+ {
+ 	struct amd_xgbe_phy_priv *priv = phydev->priv;
++	u16 val, mask;
++
++	/* Assert Rx and Tx ratechange in CMU_reg16 */
++	val = XCMU_IOREAD(priv, CMU_REG16);
+ 
+-	/* Assert Rx and Tx ratechange */
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, RATECHANGE, 1);
++	mask = (1 << (CMU_REG16_TX_RATE_CHANGE_BASE -
++		      (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR))) |
++	       (1 << (CMU_REG16_RX_RATE_CHANGE_BASE -
++		      (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR)));
++	val |= mask;
++
++	XCMU_IOWRITE(priv, CMU_REG16, val);
+ }
+ 
+ static void amd_xgbe_phy_serdes_complete_ratechange(struct phy_device *phydev)
+ {
+ 	struct amd_xgbe_phy_priv *priv = phydev->priv;
++	u16 val, mask;
+ 	unsigned int wait;
+-	u16 status;
+ 
+-	/* Release Rx and Tx ratechange */
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, RATECHANGE, 0);
++	/* Release Rx and Tx ratechange for proper channel in CMU_reg16 */
++	val = XCMU_IOREAD(priv, CMU_REG16);
++
++	mask = (1 << (CMU_REG16_TX_RATE_CHANGE_BASE -
++		      (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR))) |
++	       (1 << (CMU_REG16_RX_RATE_CHANGE_BASE -
++		      (priv->serdes_channel * CMU_REG16_RATE_CHANGE_DECR)));
++	val &= ~mask;
+ 
+-	/* Wait for Rx and Tx ready */
++	XCMU_IOWRITE(priv, CMU_REG16, val);
++
++	/* Wait for Rx and Tx ready in CMU_reg15 */
++	mask = (1 << priv->serdes_channel) |
++	       (1 << (priv->serdes_channel + 8));
+ 	wait = XGBE_PHY_RATECHANGE_COUNT;
+ 	while (wait--) {
+-		usleep_range(50, 75);
++		udelay(50);
+ 
+-		status = XSIR0_IOREAD(priv, SIR0_STATUS);
+-		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
+-		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
++		val = XCMU_IOREAD(priv, CMU_REG15);
++		if ((val & mask) == mask)
+ 			return;
+ 	}
+ 
+ 	netdev_dbg(phydev->attached_dev, "SerDes rx/tx not ready (%#hx)\n",
+-		   status);
++		   val);
+ }
+ 
+ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
+@@ -435,8 +391,8 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
+ 	struct amd_xgbe_phy_priv *priv = phydev->priv;
+ 	int ret;
+ 
+-	/* Enable KR training */
+-	ret = amd_xgbe_an_enable_kr_training(phydev);
++	/* Disable KR training */
++	ret = amd_xgbe_an_disable_kr_training(phydev);
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -462,19 +418,32 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
+ 		return ret;
+ 
+ 	/* Set SerDes to 10G speed */
++	spin_lock(&cmu_lock);
++
+ 	amd_xgbe_phy_serdes_start_ratechange(phydev);
+ 
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, DATARATE, SPEED_10000_RATE);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, WORDMODE, SPEED_10000_WORD);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, SPEED_10000_TXAMP);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PLLSEL, SPEED_10000_PLL);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PI_SPD_SEL, SPEED_10000_CDR);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_DATA_RATE, RXTX_FULL_RATE);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_66BIT_WORD);
+ 
+-	XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, RXTX_10000_BLWC);
+-	XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_10000_PQ);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, RXTX_10G_TX_AMP);
++
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_DATA_RATE, RXTX_FULL_RATE);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_WORD_MODE, RXTX_66BIT_WORD);
++
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, 0);
++
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_10G_PLL);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, TX_PLLSELECT, RXTX_10G_PLL);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, PI_SPD_SEL_CDR, RXTX_10G_CDR);
++
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_10G_PQ);
+ 
+ 	amd_xgbe_phy_serdes_complete_ratechange(phydev);
+ 
++	spin_unlock(&cmu_lock);
++
++	priv->mode = AMD_XGBE_MODE_KR;
++
+ 	return 0;
+ }
+ 
+@@ -510,19 +479,32 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev)
+ 		return ret;
+ 
+ 	/* Set SerDes to 2.5G speed */
++	spin_lock(&cmu_lock);
 +
-+	val = readl(csr_base + BRIDGE_CFG_1);
-+	val &= ~CLASS_CODE_MASK;
-+	val |= PCI_CLASS_BRIDGE_PCI << 16;
-+	writel(val, csr_base + BRIDGE_CFG_1);
+ 	amd_xgbe_phy_serdes_start_ratechange(phydev);
+ 
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, DATARATE, SPEED_2500_RATE);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, WORDMODE, SPEED_2500_WORD);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, SPEED_2500_TXAMP);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PLLSEL, SPEED_2500_PLL);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PI_SPD_SEL, SPEED_2500_CDR);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_DATA_RATE, RXTX_HALF_RATE);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_10BIT_WORD);
 +
-+	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);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, RXTX_1G_TX_AMP);
 +
-+	val = readl(csr_base + BRIDGE_CTRL_5);
-+	val &= ~DEVICE_PORT_TYPE_MASK;
-+	val |= XGENE_PORT_TYPE_RC;
-+	writel(val, csr_base + BRIDGE_CTRL_5);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_DATA_RATE, RXTX_HALF_RATE);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_WORD_MODE, RXTX_10BIT_WORD);
+ 
+-	XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, RXTX_2500_BLWC);
+-	XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_2500_PQ);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, 1);
 +
-+	val = readl(csr_base + BRIDGE_CTRL_2);
-+	val |= ENABLE_ASPM;
-+	writel(val, csr_base + BRIDGE_CTRL_2);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_1G_PLL);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, TX_PLLSELECT, RXTX_1G_PLL);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, PI_SPD_SEL_CDR, RXTX_1G_CDR);
 +
-+	val = readl(csr_base + BRIDGE_CFG_32);
-+	writel(val | (1 << 19), csr_base + BRIDGE_CFG_32);
-+}
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_1G_PQ);
+ 
+ 	amd_xgbe_phy_serdes_complete_ratechange(phydev);
+ 
++	spin_unlock(&cmu_lock);
 +
-+/* Return 0 on success */
-+static int xgene_pcie_init_ecc(struct xgene_pcie_port *port)
-+{
-+	void __iomem *csr_base = port->csr_base;
-+	ulong timeout;
-+	u32 val;
++	priv->mode = AMD_XGBE_MODE_KX;
 +
-+	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);
-+	}
+ 	return 0;
+ }
+ 
+@@ -558,47 +540,33 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev)
+ 		return ret;
+ 
+ 	/* Set SerDes to 1G speed */
++	spin_lock(&cmu_lock);
 +
-+	return 1;
-+}
+ 	amd_xgbe_phy_serdes_start_ratechange(phydev);
+ 
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, DATARATE, SPEED_1000_RATE);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, WORDMODE, SPEED_1000_WORD);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, SPEED_1000_TXAMP);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PLLSEL, SPEED_1000_PLL);
+-	XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PI_SPD_SEL, SPEED_1000_CDR);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_DATA_RATE, RXTX_FIFTH_RATE);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_10BIT_WORD);
+ 
+-	XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, RXTX_1000_BLWC);
+-	XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_1000_PQ);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, RXTX_1G_TX_AMP);
+ 
+-	amd_xgbe_phy_serdes_complete_ratechange(phydev);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_DATA_RATE, RXTX_FIFTH_RATE);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RX_WORD_MODE, RXTX_10BIT_WORD);
+ 
+-	return 0;
+-}
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, 1);
+ 
+-static int amd_xgbe_phy_cur_mode(struct phy_device *phydev,
+-				 enum amd_xgbe_phy_mode *mode)
+-{
+-	int ret;
+-
+-	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
+-	if (ret < 0)
+-		return ret;
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_1G_PLL);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, TX_PLLSELECT, RXTX_1G_PLL);
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG53, PI_SPD_SEL_CDR, RXTX_1G_CDR);
+ 
+-	if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
+-		*mode = AMD_XGBE_MODE_KR;
+-	else
+-		*mode = AMD_XGBE_MODE_KX;
++	XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_1G_PQ);
+ 
+-	return 0;
+-}
++	amd_xgbe_phy_serdes_complete_ratechange(phydev);
+ 
+-static bool amd_xgbe_phy_in_kr_mode(struct phy_device *phydev)
+-{
+-	enum amd_xgbe_phy_mode mode;
++	spin_unlock(&cmu_lock);
+ 
+-	if (amd_xgbe_phy_cur_mode(phydev, &mode))
+-		return false;
++	priv->mode = AMD_XGBE_MODE_KX;
+ 
+-	return (mode == AMD_XGBE_MODE_KR);
++	return 0;
+ }
+ 
+ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
+@@ -607,7 +575,7 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
+ 	int ret;
+ 
+ 	/* If we are in KR switch to KX, and vice-versa */
+-	if (amd_xgbe_phy_in_kr_mode(phydev)) {
++	if (priv->mode == AMD_XGBE_MODE_KR) {
+ 		if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000)
+ 			ret = amd_xgbe_phy_gmii_mode(phydev);
+ 		else
+@@ -619,20 +587,15 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
+ 	return ret;
+ }
+ 
+-static int amd_xgbe_phy_set_mode(struct phy_device *phydev,
+-				 enum amd_xgbe_phy_mode mode)
++static enum amd_xgbe_phy_an amd_xgbe_an_switch_mode(struct phy_device *phydev)
+ {
+-	enum amd_xgbe_phy_mode cur_mode;
+ 	int ret;
+ 
+-	ret = amd_xgbe_phy_cur_mode(phydev, &cur_mode);
+-	if (ret)
+-		return ret;
+-
+-	if (mode != cur_mode)
+-		ret = amd_xgbe_phy_switch_mode(phydev);
++	ret = amd_xgbe_phy_switch_mode(phydev);
++	if (ret < 0)
++		return AMD_XGBE_AN_ERROR;
+ 
+-	return ret;
++	return AMD_XGBE_AN_START;
+ }
+ 
+ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev,
+@@ -643,8 +606,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev,
+ 
+ 	*state = AMD_XGBE_RX_COMPLETE;
+ 
+-	/* If we're not in KR mode then we're done */
+-	if (!amd_xgbe_phy_in_kr_mode(phydev))
++	/* If we're in KX mode then we're done */
++	if (priv->mode == AMD_XGBE_MODE_KX)
+ 		return AMD_XGBE_AN_EVENT;
+ 
+ 	/* Enable/Disable FEC */
+@@ -672,13 +635,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev,
+ 	if (ret < 0)
+ 		return AMD_XGBE_AN_ERROR;
+ 
+-	XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 1);
+-
+ 	ret |= 0x01;
+ 	phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret);
+ 
+-	XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 0);
+-
+ 	return AMD_XGBE_AN_EVENT;
+ }
+ 
+@@ -702,6 +661,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev,
+ static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev,
+ 					       enum amd_xgbe_phy_rx *state)
+ {
++	struct amd_xgbe_phy_priv *priv = phydev->priv;
+ 	unsigned int link_support;
+ 	int ret, ad_reg, lp_reg;
+ 
+@@ -711,9 +671,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev,
+ 		return AMD_XGBE_AN_ERROR;
+ 
+ 	/* Check for a supported mode, otherwise restart in a different one */
+-	link_support = amd_xgbe_phy_in_kr_mode(phydev) ? 0x80 : 0x20;
++	link_support = (priv->mode == AMD_XGBE_MODE_KR) ? 0x80 : 0x20;
+ 	if (!(ret & link_support))
+-		return AMD_XGBE_AN_INCOMPAT_LINK;
++		return amd_xgbe_an_switch_mode(phydev);
+ 
+ 	/* Check Extended Next Page support */
+ 	ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
+@@ -754,7 +714,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
+ 	int ret;
+ 
+ 	/* Be sure we aren't looping trying to negotiate */
+-	if (amd_xgbe_phy_in_kr_mode(phydev)) {
++	if (priv->mode == AMD_XGBE_MODE_KR) {
+ 		if (priv->kr_state != AMD_XGBE_RX_READY)
+ 			return AMD_XGBE_AN_NO_LINK;
+ 		priv->kr_state = AMD_XGBE_RX_BPA;
+@@ -817,13 +777,6 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
+ 	/* Enable and start auto-negotiation */
+ 	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ 
+-	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL);
+-	if (ret < 0)
+-		return AMD_XGBE_AN_ERROR;
+-
+-	ret |= MDIO_KR_CTRL_PDETECT;
+-	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL, ret);
+-
+ 	ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+ 	if (ret < 0)
+ 		return AMD_XGBE_AN_ERROR;
+@@ -864,8 +817,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
+ 	enum amd_xgbe_phy_rx *state;
+ 	int ret;
+ 
+-	state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state
+-						: &priv->kx_state;
++	state = (priv->mode == AMD_XGBE_MODE_KR) ? &priv->kr_state
++						 : &priv->kx_state;
+ 
+ 	switch (*state) {
+ 	case AMD_XGBE_RX_BPA:
+@@ -885,13 +838,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
+ 
+ static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev)
+ {
+-	int ret;
+-
+-	ret = amd_xgbe_phy_switch_mode(phydev);
+-	if (ret)
+-		return AMD_XGBE_AN_ERROR;
+-
+-	return AMD_XGBE_AN_START;
++	return amd_xgbe_an_switch_mode(phydev);
+ }
+ 
+ static void amd_xgbe_an_state_machine(struct work_struct *work)
+@@ -904,10 +851,6 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
+ 	int sleep;
+ 	unsigned int an_supported = 0;
+ 
+-	/* Start in KX mode */
+-	if (amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX))
+-		priv->an_state = AMD_XGBE_AN_ERROR;
+-
+ 	while (1) {
+ 		mutex_lock(&priv->an_mutex);
+ 
+@@ -915,9 +858,8 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
+ 
+ 		switch (priv->an_state) {
+ 		case AMD_XGBE_AN_START:
+-			an_supported = 0;
+-			priv->parallel_detect = 0;
+ 			priv->an_state = amd_xgbe_an_start(phydev);
++			an_supported = 0;
+ 			break;
+ 
+ 		case AMD_XGBE_AN_EVENT:
+@@ -934,7 +876,6 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
+ 			break;
+ 
+ 		case AMD_XGBE_AN_COMPLETE:
+-			priv->parallel_detect = an_supported ? 0 : 1;
+ 			netdev_info(phydev->attached_dev, "%s successful\n",
+ 				    an_supported ? "Auto negotiation"
+ 						 : "Parallel detection");
+@@ -1069,6 +1010,7 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev)
+ {
+ 	struct amd_xgbe_phy_priv *priv = phydev->priv;
+ 	u32 mmd_mask = phydev->c45_ids.devices_in_package;
++	int ret;
+ 
+ 	if (phydev->autoneg != AUTONEG_ENABLE)
+ 		return amd_xgbe_phy_setup_forced(phydev);
+@@ -1077,6 +1019,11 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev)
+ 	if (!(mmd_mask & MDIO_DEVS_AN))
+ 		return -EINVAL;
+ 
++	/* Get the current speed mode */
++	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
++	if (ret < 0)
++		return ret;
 +
-+static int xgene_pcie_init_port(struct xgene_pcie_port *port)
+ 	/* Start/Restart the auto-negotiation state machine */
+ 	mutex_lock(&priv->an_mutex);
+ 	priv->an_result = AMD_XGBE_AN_READY;
+@@ -1166,14 +1113,18 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
+ {
+ 	struct amd_xgbe_phy_priv *priv = phydev->priv;
+ 	u32 mmd_mask = phydev->c45_ids.devices_in_package;
+-	int ret, ad_ret, lp_ret;
++	int ret, mode, ad_ret, lp_ret;
+ 
+ 	ret = amd_xgbe_phy_update_link(phydev);
+ 	if (ret)
+ 		return ret;
+ 
+-	if ((phydev->autoneg == AUTONEG_ENABLE) &&
+-	    !priv->parallel_detect) {
++	mode = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
++	if (mode < 0)
++		return mode;
++	mode &= MDIO_PCS_CTRL2_TYPE;
++
++	if (phydev->autoneg == AUTONEG_ENABLE) {
+ 		if (!(mmd_mask & MDIO_DEVS_AN))
+ 			return -EINVAL;
+ 
+@@ -1204,39 +1155,40 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
+ 		ad_ret &= lp_ret;
+ 		if (ad_ret & 0x80) {
+ 			phydev->speed = SPEED_10000;
+-			ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR);
+-			if (ret)
+-				return ret;
++			if (mode != MDIO_PCS_CTRL2_10GBR) {
++				ret = amd_xgbe_phy_xgmii_mode(phydev);
++				if (ret < 0)
++					return ret;
++			}
+ 		} else {
+-			switch (priv->speed_set) {
+-			case AMD_XGBE_PHY_SPEEDSET_1000_10000:
+-				phydev->speed = SPEED_1000;
+-				break;
++			int (*mode_fcn)(struct phy_device *);
+ 
+-			case AMD_XGBE_PHY_SPEEDSET_2500_10000:
++			if (priv->speed_set ==
++			    AMD_XGBE_PHY_SPEEDSET_1000_10000) {
++				phydev->speed = SPEED_1000;
++				mode_fcn = amd_xgbe_phy_gmii_mode;
++			} else {
+ 				phydev->speed = SPEED_2500;
+-				break;
++				mode_fcn = amd_xgbe_phy_gmii_2500_mode;
+ 			}
+ 
+-			ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX);
+-			if (ret)
+-				return ret;
++			if (mode == MDIO_PCS_CTRL2_10GBR) {
++				ret = mode_fcn(phydev);
++				if (ret < 0)
++					return ret;
++			}
+ 		}
+ 
+ 		phydev->duplex = DUPLEX_FULL;
+ 	} else {
+-		if (amd_xgbe_phy_in_kr_mode(phydev)) {
++		if (mode == MDIO_PCS_CTRL2_10GBR) {
+ 			phydev->speed = SPEED_10000;
+ 		} else {
+-			switch (priv->speed_set) {
+-			case AMD_XGBE_PHY_SPEEDSET_1000_10000:
++			if (priv->speed_set ==
++			    AMD_XGBE_PHY_SPEEDSET_1000_10000)
+ 				phydev->speed = SPEED_1000;
+-				break;
+-
+-			case AMD_XGBE_PHY_SPEEDSET_2500_10000:
++			else
+ 				phydev->speed = SPEED_2500;
+-				break;
+-			}
+ 		}
+ 		phydev->duplex = DUPLEX_FULL;
+ 		phydev->pause = 0;
+@@ -1288,29 +1240,188 @@ unlock:
+ 	return ret;
+ }
+ 
++static int amd_xgbe_phy_map_resources(struct amd_xgbe_phy_priv *priv,
++				      struct platform_device *phy_pdev,
++				      unsigned int phy_resnum)
 +{
-+	int rc;
++	struct device *dev = priv->dev;
++	int ret;
 +
-+	port->clk = clk_get(port->dev, NULL);
-+	if (IS_ERR(port->clk)) {
-+		dev_err(port->dev, "clock not available\n");
-+		return -ENODEV;
++	/* Get the device mmio areas */
++	priv->rxtx_res = platform_get_resource(phy_pdev, IORESOURCE_MEM,
++					       phy_resnum++);
++	priv->rxtx_regs = devm_ioremap_resource(dev, priv->rxtx_res);
++	if (IS_ERR(priv->rxtx_regs)) {
++		dev_err(dev, "rxtx ioremap failed\n");
++		return PTR_ERR(priv->rxtx_regs);
 +	}
 +
-+	rc = clk_prepare_enable(port->clk);
-+	if (rc) {
-+		dev_err(port->dev, "clock enable failed\n");
-+		return rc;
++	/* All xgbe phy devices share the CMU registers so retrieve
++	 * the resource and do the ioremap directly rather than
++	 * the devm_ioremap_resource call
++	 */
++	priv->cmu_res = platform_get_resource(phy_pdev, IORESOURCE_MEM,
++					      phy_resnum++);
++	if (!priv->cmu_res) {
++		dev_err(dev, "cmu invalid resource\n");
++		ret = -EINVAL;
++		goto err_rxtx;
 +	}
-+
-+	rc = xgene_pcie_init_ecc(port);
-+	if (rc) {
-+		dev_err(port->dev, "memory init failed\n");
-+		return rc;
++	priv->cmu_regs = devm_ioremap_nocache(dev, priv->cmu_res->start,
++					      resource_size(priv->cmu_res));
++	if (!priv->cmu_regs) {
++		dev_err(dev, "cmu ioremap failed\n");
++		ret = -ENOMEM;
++		goto err_rxtx;
 +	}
 +
 +	return 0;
-+}
 +
-+static void xgene_pcie_fixup_bridge(struct pci_dev *dev)
-+{
-+	int i;
++err_rxtx:
++	devm_iounmap(dev, priv->rxtx_regs);
++	devm_release_mem_region(dev, priv->rxtx_res->start,
++				resource_size(priv->rxtx_res));
 +
-+	/* Hide the PCI host BARs from the kernel as their content doesn't
-+	 * fit well in the resource management
-+	 */
-+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-+		dev->resource[i].start = dev->resource[i].end = 0;
-+		dev->resource[i].flags = 0;
-+	}
-+	dev_info(&dev->dev, "Hiding X-Gene pci host bridge resources %s\n",
-+		 pci_name(dev));
++	return ret;
 +}
-+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, u64 *cfg_addr)
++static void amd_xgbe_phy_unmap_resources(struct amd_xgbe_phy_priv *priv)
 +{
-+	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);
++	struct device *dev = priv->dev;
 +
-+	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;
++	devm_iounmap(dev, priv->cmu_regs);
 +
-+	return 0;
++	devm_iounmap(dev, priv->rxtx_regs);
++	devm_release_mem_region(dev, priv->rxtx_res->start,
++				resource_size(priv->rxtx_res));
 +}
 +
-+static void xgene_pcie_setup_ob_reg(struct xgene_pcie_port *port,
-+				    struct resource *res, u32 offset, u64 addr)
++#ifdef CONFIG_ACPI
++static int amd_xgbe_phy_acpi_support(struct amd_xgbe_phy_priv *priv)
 +{
-+	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;
-+
-+	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;
-+	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);
-+}
++	struct platform_device *phy_pdev = priv->pdev;
++	struct acpi_device *adev = priv->adev;
++	struct device *dev = priv->dev;
++	const union acpi_object *property;
++	int ret;
 +
-+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);
-+}
++	/* Map the memory resources */
++	ret = amd_xgbe_phy_map_resources(priv, phy_pdev, 2);
++	if (ret)
++		return ret;
 +
-+static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
-+				 struct pci_host_bridge *bridge,
-+				 u64 cfg_addr)
-+{
-+	struct device *dev = port->dev;
-+	struct pci_host_bridge_window *window;
-+	int ret;
++	/* Get the device serdes channel property */
++	ret = acpi_dev_get_property(adev, XGBE_PHY_CHANNEL_PROPERTY,
++				    ACPI_TYPE_INTEGER, &property);
++	if (ret) {
++		dev_err(dev, "unable to obtain %s acpi property\n",
++			XGBE_PHY_CHANNEL_PROPERTY);
++		goto err_resources;
++	}
++	priv->serdes_channel = property->integer.value;
 +
-+	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);
-+
-+		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;
-+		}
++	/* Get the device speed set property */
++	ret = acpi_dev_get_property(adev, XGBE_PHY_SPEEDSET_PROPERTY,
++				    ACPI_TYPE_INTEGER, &property);
++	if (ret) {
++		dev_err(dev, "unable to obtain %s acpi property\n",
++			XGBE_PHY_SPEEDSET_PROPERTY);
++		goto err_resources;
 +	}
-+	xgene_pcie_setup_cfg_reg(port->csr_base, cfg_addr);
++	priv->speed_set = property->integer.value;
++
 +	return 0;
-+}
 +
-+static void xgene_pcie_setup_pims(void *addr, u64 pim, u64 size)
++err_resources:
++	amd_xgbe_phy_unmap_resources(priv);
++
++	return ret;
++}
++#else	/* CONFIG_ACPI */
++static int amd_xgbe_phy_acpi_support(struct amd_xgbe_phy_priv *priv)
 +{
-+	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);
++	return -EINVAL;
 +}
++#endif	/* CONFIG_ACPI */
 +
-+/*
-+ * 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)
++#ifdef CONFIG_OF
++static int amd_xgbe_phy_of_support(struct amd_xgbe_phy_priv *priv)
 +{
-+	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;
-+	}
++	struct platform_device *phy_pdev;
++	struct device_node *bus_node;
++	struct device_node *phy_node;
++	struct device *dev = priv->dev;
++	const __be32 *property;
++	int ret;
 +
-+	if ((size > SZ_1M) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 2))) {
-+		*ib_reg_mask |= (1 << 2);
-+		return 2;
++	bus_node = priv->dev->of_node;
++	phy_node = of_parse_phandle(bus_node, "phy-handle", 0);
++	if (!phy_node) {
++		dev_err(dev, "unable to parse phy-handle\n");
++		return -EINVAL;
 +	}
-+	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 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;
-+
-+	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;
++	phy_pdev = of_find_device_by_node(phy_node);
++	if (!phy_pdev) {
++		dev_err(dev, "unable to obtain phy device\n");
++		ret = -EINVAL;
++		goto err_put;
 +	}
 +
-+	if (restype == PCI_BASE_ADDRESS_MEM_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;
++	/* Map the memory resources */
++	ret = amd_xgbe_phy_map_resources(priv, phy_pdev, 0);
++	if (ret)
++		goto err_put;
++
++	/* Get the device serdes channel property */
++	property = of_get_property(phy_node, XGBE_PHY_CHANNEL_PROPERTY, NULL);
++	if (!property) {
++		dev_err(dev, "unable to obtain %s property\n",
++			XGBE_PHY_CHANNEL_PROPERTY);
++		ret = -EINVAL;
++		goto err_resources;
 +	}
++	priv->serdes_channel = be32_to_cpu(*property);
 +
-+	xgene_pcie_setup_pims(pim_addr, pci_addr, size);
-+}
-+
-+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;
++	/* Get the device speed set property */
++	property = of_get_property(phy_node, XGBE_PHY_SPEEDSET_PROPERTY, NULL);
++	if (property)
++		priv->speed_set = be32_to_cpu(*property);
 +
-+	parser->range = of_get_property(node, "dma-ranges", &rlen);
-+	if (!parser->range)
-+		return -ENOENT;
++	of_node_put(phy_node);
 +
-+	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;
++err_resources:
++	amd_xgbe_phy_unmap_resources(priv);
 +
-+	if (pci_dma_range_parser_init(&parser, np)) {
-+		dev_err(dev, "missing dma-ranges property\n");
-+		return -EINVAL;
-+	}
++err_put:
++	of_node_put(phy_node);
 +
-+	/* 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;
++	return ret;
 +}
-+
-+static int xgene_pcie_probe_bridge(struct platform_device *pdev)
++#else	/* CONFIG_OF */
++static int amd_xgbe_phy_of_support(struct amd_xgbe_phy_priv *priv)
 +{
-+	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;
++	return -EINVAL;
++}
++#endif	/* CONFIG_OF */
 +
-+	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
-+	if (!port)
+ static int amd_xgbe_phy_probe(struct phy_device *phydev)
+ {
+ 	struct amd_xgbe_phy_priv *priv;
+-	struct platform_device *pdev;
+ 	struct device *dev;
+ 	char *wq_name;
+-	const __be32 *property;
+-	unsigned int speed_set;
+ 	int ret;
+ 
+-	if (!phydev->dev.of_node)
++	if (!phydev->bus || !phydev->bus->parent)
+ 		return -EINVAL;
+ 
+-	pdev = of_find_device_by_node(phydev->dev.of_node);
+-	if (!pdev)
+-		return -EINVAL;
+-	dev = &pdev->dev;
++	dev = phydev->bus->parent;
+ 
+ 	wq_name = kasprintf(GFP_KERNEL, "%s-amd-xgbe-phy", phydev->bus->name);
+-	if (!wq_name) {
+-		ret = -ENOMEM;
+-		goto err_pdev;
+-	}
++	if (!wq_name)
 +		return -ENOMEM;
-+	port->node = np;
-+	port->dev = &pdev->dev;
-+
-+	ret = xgene_pcie_map_reg(port, pdev, &cfg_addr);
-+	if (ret)
-+		return ret;
-+
-+	ret = xgene_pcie_init_port(port);
-+	if (ret)
-+		return ret;
-+	xgene_pcie_program_core(port->csr_base);
-+	xgene_pcie_setup_root_complex(port);
-+
-+	bridge = of_create_pci_host_bridge(&pdev->dev, &xgene_pcie_ops, port);
-+	if (IS_ERR_OR_NULL(bridge))
-+		return PTR_ERR(bridge);
-+
-+	ret = xgene_pcie_map_ranges(port, bridge, cfg_addr);
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv) {
+@@ -1318,86 +1429,54 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev)
+ 		goto err_name;
+ 	}
+ 
+-	priv->pdev = pdev;
++	priv->pdev = to_platform_device(dev);
++	priv->adev = ACPI_COMPANION(dev);
+ 	priv->dev = dev;
+ 	priv->phydev = phydev;
+ 
+-	/* Get the device mmio areas */
+-	priv->rxtx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	priv->rxtx_regs = devm_ioremap_resource(dev, priv->rxtx_res);
+-	if (IS_ERR(priv->rxtx_regs)) {
+-		dev_err(dev, "rxtx ioremap failed\n");
+-		ret = PTR_ERR(priv->rxtx_regs);
++	if (priv->adev && !acpi_disabled)
++		ret = amd_xgbe_phy_acpi_support(priv);
++	else
++		ret = amd_xgbe_phy_of_support(priv);
 +	if (ret)
-+		return ret;
+ 		goto err_priv;
+-	}
+-
+-	priv->sir0_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-	priv->sir0_regs = devm_ioremap_resource(dev, priv->sir0_res);
+-	if (IS_ERR(priv->sir0_regs)) {
+-		dev_err(dev, "sir0 ioremap failed\n");
+-		ret = PTR_ERR(priv->sir0_regs);
+-		goto err_rxtx;
+-	}
+-
+-	priv->sir1_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+-	priv->sir1_regs = devm_ioremap_resource(dev, priv->sir1_res);
+-	if (IS_ERR(priv->sir1_regs)) {
+-		dev_err(dev, "sir1 ioremap failed\n");
+-		ret = PTR_ERR(priv->sir1_regs);
+-		goto err_sir0;
+-	}
+ 
+-	/* Get the device speed set property */
+-	speed_set = 0;
+-	property = of_get_property(dev->of_node, XGBE_PHY_SPEEDSET_PROPERTY,
+-				   NULL);
+-	if (property)
+-		speed_set = be32_to_cpu(*property);
+-
+-	switch (speed_set) {
+-	case 0:
+-		priv->speed_set = AMD_XGBE_PHY_SPEEDSET_1000_10000;
+-		break;
+-	case 1:
+-		priv->speed_set = AMD_XGBE_PHY_SPEEDSET_2500_10000;
++	switch (priv->speed_set) {
++	case AMD_XGBE_PHY_SPEEDSET_1000_10000:
++	case AMD_XGBE_PHY_SPEEDSET_2500_10000:
+ 		break;
+ 	default:
+ 		dev_err(dev, "invalid amd,speed-set property\n");
+ 		ret = -EINVAL;
+-		goto err_sir1;
++		goto err_resources;
+ 	}
+ 
+ 	priv->link = 1;
+ 
++	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
++	if (ret < 0)
++		goto err_resources;
++	if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
++		priv->mode = AMD_XGBE_MODE_KR;
++	else
++		priv->mode = AMD_XGBE_MODE_KX;
++
+ 	mutex_init(&priv->an_mutex);
+ 	INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine);
+ 	priv->an_workqueue = create_singlethread_workqueue(wq_name);
+ 	if (!priv->an_workqueue) {
+ 		ret = -ENOMEM;
+-		goto err_sir1;
++		goto err_resources;
+ 	}
+ 
+ 	phydev->priv = priv;
+ 
+ 	kfree(wq_name);
+-	of_dev_put(pdev);
+ 
+ 	return 0;
+ 
+-err_sir1:
+-	devm_iounmap(dev, priv->sir1_regs);
+-	devm_release_mem_region(dev, priv->sir1_res->start,
+-				resource_size(priv->sir1_res));
+-
+-err_sir0:
+-	devm_iounmap(dev, priv->sir0_regs);
+-	devm_release_mem_region(dev, priv->sir0_res->start,
+-				resource_size(priv->sir0_res));
+-
+-err_rxtx:
+-	devm_iounmap(dev, priv->rxtx_regs);
+-	devm_release_mem_region(dev, priv->rxtx_res->start,
+-				resource_size(priv->rxtx_res));
++err_resources:
++	amd_xgbe_phy_unmap_resources(priv);
+ 
+ err_priv:
+ 	devm_kfree(dev, priv);
+@@ -1405,9 +1484,6 @@ err_priv:
+ err_name:
+ 	kfree(wq_name);
+ 
+-err_pdev:
+-	of_dev_put(pdev);
+-
+ 	return ret;
+ }
+ 
+@@ -1424,18 +1500,7 @@ static void amd_xgbe_phy_remove(struct phy_device *phydev)
+ 	flush_workqueue(priv->an_workqueue);
+ 	destroy_workqueue(priv->an_workqueue);
+ 
+-	/* Release resources */
+-	devm_iounmap(dev, priv->sir1_regs);
+-	devm_release_mem_region(dev, priv->sir1_res->start,
+-				resource_size(priv->sir1_res));
+-
+-	devm_iounmap(dev, priv->sir0_regs);
+-	devm_release_mem_region(dev, priv->sir0_res->start,
+-				resource_size(priv->sir0_res));
+-
+-	devm_iounmap(dev, priv->rxtx_regs);
+-	devm_release_mem_region(dev, priv->rxtx_res->start,
+-				resource_size(priv->rxtx_res));
++	amd_xgbe_phy_unmap_resources(priv);
+ 
+ 	devm_kfree(dev, priv);
+ }
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 3823edf..4c2ccde 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1250,6 +1250,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
+ EXPORT_SYMBOL_GPL(of_property_read_u64);
+ 
+ /**
++ * of_property_read_u64_array - Find and read an array of 64 bit integers
++ * from a property.
++ *
++ * @np:		device node from which the property value is to be read.
++ * @propname:	name of the property to be searched.
++ * @out_values:	pointer to return value, modified only if return value is 0.
++ * @sz:		number of array elements to read
++ *
++ * Search for a property in a device node and read 64-bit value(s) from
++ * it. Returns 0 on success, -EINVAL if the property does not exist,
++ * -ENODATA if property does not have a value, and -EOVERFLOW if the
++ * property data isn't large enough.
++ *
++ * The out_values is modified only if a valid u64 value can be decoded.
++ */
++int of_property_read_u64_array(const struct device_node *np,
++			       const char *propname, u64 *out_values,
++			       size_t sz)
++{
++	const __be32 *val = of_find_property_value_of_size(np, propname,
++						(sz * sizeof(*out_values)));
 +
-+	ret = xgene_pcie_parse_map_dma_ranges(port);
-+	if (ret)
-+		return ret;
++	if (IS_ERR(val))
++		return PTR_ERR(val);
 +
-+	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);
++	while (sz--) {
++		*out_values++ = of_read_number(val, 2);
++		val += 2;
++	}
 +	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/pci.c b/drivers/pci/pci.c
-index 1c8592b..b81dc68 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
++/**
+  * of_property_read_string - Find and read a string from a property
+  * @np:		device node from which the property value is to be read.
+  * @propname:	name of the property to be searched.
+diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
+index 2988fe1..9029d59c 100644
+--- a/drivers/pci/host/pci-xgene.c
++++ b/drivers/pci/host/pci-xgene.c
+@@ -29,6 +29,7 @@
+ #include <linux/pci.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
++#include <linux/acpi.h>
+ 
+ #define PCIECORE_CTLANDSTATUS		0x50
+ #define PIM1_1L				0x80
+@@ -235,6 +236,13 @@ static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+ 		break;
+ 	case 2:
+ 		xgene_pcie_cfg_in16(addr, offset, val);
++		/* FIXME.
++		 * Something wrong with Configuration Request Retry Status
++		 * on this hw. Pretend it isn't supported until the problem
++		 * gets sorted out properly.
++		 */
++		if (pci_is_root_bus(bus) && offset == (0x40 + PCI_EXP_RTCAP))
++			*val &= ~PCI_EXP_RTCAP_CRSVIS;
+ 		break;
+ 	default:
+ 		xgene_pcie_cfg_in32(addr, offset, val);
+@@ -600,6 +608,165 @@ static int xgene_pcie_setup(struct xgene_pcie_port *port,
  	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.
++#ifdef CONFIG_ACPI
++struct xgene_mcfg_info {
++	void __iomem *csr_base;
++};
++
++/*
++ * 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.
 + */
-+int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
++static void __iomem *__get_cfg_base(struct pci_mmcfg_region *cfg,
++				    unsigned int bus)
 +{
-+	int err = -ENODEV;
++	if (bus > cfg->start_bus)
++		return cfg->virt + AXI_EP_CFG_ACCESS;
 +
-+#ifdef PCI_IOBASE
-+	if (!(res->flags & IORESOURCE_IO))
-+		return -EINVAL;
++	return cfg->virt;
++}
 +
-+	if (res->end > IO_SPACE_LIMIT)
-+		return -EINVAL;
++/*
++ * For Configuration request, RTDID register is used as Bus Number,
++ * Device Number and Function number of the header fields.
++ */
++static void __set_rtdid_reg(struct pci_mmcfg_region *cfg,
++			    unsigned int bus, unsigned int devfn)
++{
++	struct xgene_mcfg_info *info = cfg->data;
++	unsigned int b, d, f;
++	u32 rtdid_val = 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
++	b = bus;
++	d = PCI_SLOT(devfn);
++	f = PCI_FUNC(devfn);
 +
-+	return err;
-+}
++	if (bus != cfg->start_bus)
++		rtdid_val = (b << 8) | (d << 3) | f;
 +
- static void __pci_set_master(struct pci_dev *dev, bool enable)
- {
- 	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);
- }
- 
--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 +524,6 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
- 		return NULL;
- 
- 	INIT_LIST_HEAD(&bridge->windows);
--	bridge->bus = b;
- 	return bridge;
- }
- 
-@@ -1749,8 +1748,9 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
- {
- }
- 
--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;
- 
-+	bridge = pci_alloc_host_bridge();
-+	if (!bridge)
-+		return ERR_PTR(-ENOMEM);
++	writel(rtdid_val, info->csr_base + RTDID);
++	/* read the register back to ensure flush */
++	readl(info->csr_base + RTDID);
++}
 +
-+	bridge->dev.parent = parent;
-+	bridge->dev.release = pci_release_host_bridge_dev;
-+	bridge->domain_nr = domain;
++static int xgene_raw_pci_read(struct pci_mmcfg_region *cfg, unsigned int bus,
++			      unsigned int devfn, int offset, int len, u32 *val)
++{
++	void __iomem *addr;
 +
- 	b = pci_alloc_bus();
--	if (!b)
--		return NULL;
-+	if (!b) {
-+		error = -ENOMEM;
-+		goto err_out;
-+	}
- 
- 	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;
- 	}
- 
--	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;
--	}
- 
- 	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);
-+}
-+
-+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;
++	if (bus == cfg->start_bus) {
++		if (devfn != 0) {
++			*val = 0xffffffff;
++			return PCIBIOS_DEVICE_NOT_FOUND;
++		}
 +
-+	b->sysdata = sysdata;
-+	domain_nr = pci_domain_nr(b);
- 	kfree(b);
--	return NULL;
++		/* see xgene_pcie_hide_rc_bars() above */
++		if (offset == PCI_BASE_ADDRESS_0 ||
++		    offset == PCI_BASE_ADDRESS_1) {
++			*val = 0;
++			return PCIBIOS_SUCCESSFUL;
++		}
++	}
 +
-+	b = pci_create_root_bus_in_domain(parent, domain_nr, bus,
-+				ops, sysdata, resources);
-+	if (IS_ERR(b))
-+		return NULL;
++	__set_rtdid_reg(cfg, bus, devfn);
++	addr = __get_cfg_base(cfg, bus);
++	switch (len) {
++	case 1:
++		xgene_pcie_cfg_in8(addr, offset, val);
++		break;
++	case 2:
++		xgene_pcie_cfg_in16(addr, offset, val);
++		/* FIXME.
++		 * Something wrong with Configuration Request Retry Status
++		 * on this hw. Pretend it isn't supported until the problem
++		 * gets sorted out properly.
++		 */
++		if (bus == cfg->start_bus && offset == (0x40 + PCI_EXP_RTCAP))
++			*val &= ~PCI_EXP_RTCAP_CRSVIS;
++		break;
++	default:
++		xgene_pcie_cfg_in32(addr, offset, val);
++		break;
++	}
++	return PCIBIOS_SUCCESSFUL;
++}
 +
-+	return b;
- }
- 
- int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
-diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
-index 0754f5c..4478a59 100644
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -789,7 +789,7 @@ config RTC_DRV_DA9063
- 
- config RTC_DRV_EFI
- 	tristate "EFI RTC"
--	depends on IA64
-+	depends on EFI
- 	help
- 	  If you say yes here you will get support for the EFI
- 	  Real Time Clock.
-diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
-index 70347d0..f1dfc36 100644
---- a/drivers/rtc/Makefile
-+++ b/drivers/rtc/Makefile
-@@ -10,6 +10,10 @@ obj-$(CONFIG_RTC_SYSTOHC)	+= systohc.o
- obj-$(CONFIG_RTC_CLASS)		+= rtc-core.o
- rtc-core-y			:= class.o interface.o
- 
-+ifdef CONFIG_RTC_DRV_EFI
-+rtc-core-y			+= rtc-efi-platform.o
-+endif
++static int xgene_raw_pci_write(struct pci_mmcfg_region *cfg, unsigned int bus,
++			       unsigned int devfn, int offset, int len, u32 val)
++{
++	void __iomem *addr;
 +
- rtc-core-$(CONFIG_RTC_INTF_DEV)	+= rtc-dev.o
- rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
- rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
-diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c
-new file mode 100644
-index 0000000..b40fbe3
---- /dev/null
-+++ b/drivers/rtc/rtc-efi-platform.c
-@@ -0,0 +1,31 @@
-+/*
-+ * Moved from arch/ia64/kernel/time.c
-+ *
-+ * Copyright (C) 1998-2003 Hewlett-Packard Co
-+ *	Stephane Eranian <eranian at hpl.hp.com>
-+ *	David Mosberger <davidm at hpl.hp.com>
-+ * Copyright (C) 1999 Don Dugger <don.dugger at intel.com>
-+ * Copyright (C) 1999-2000 VA Linux Systems
-+ * Copyright (C) 1999-2000 Walt Drummond <drummond at valinux.com>
-+ */
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/efi.h>
-+#include <linux/platform_device.h>
++	if (bus == cfg->start_bus && devfn != 0)
++		return PCIBIOS_DEVICE_NOT_FOUND;
 +
-+static struct platform_device rtc_efi_dev = {
-+	.name = "rtc-efi",
-+	.id = -1,
-+};
++	__set_rtdid_reg(cfg, bus, devfn);
++	addr = __get_cfg_base(cfg, 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 int __init rtc_init(void)
++static acpi_status find_csr_base(struct acpi_resource *acpi_res, void *data)
 +{
-+	if (efi_enabled(EFI_RUNTIME_SERVICES))
-+		if (platform_device_register(&rtc_efi_dev) < 0)
-+			pr_err("unable to register rtc device...\n");
++	struct pci_mmcfg_region *cfg = data;
++	struct xgene_mcfg_info *info = cfg->data;
++	struct acpi_resource_fixed_memory32 *fixed32;
 +
-+	/* not necessarily an error */
-+	return 0;
++	if (acpi_res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
++		fixed32 = &acpi_res->data.fixed_memory32;
++		info->csr_base = ioremap(fixed32->address,
++					 fixed32->address_length);
++		return AE_CTRL_TERMINATE;
++	}
++	return AE_OK;
 +}
-+module_init(rtc_init);
-diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
-index 975e1cc..2e2161b 100644
---- a/include/asm-generic/io.h
-+++ b/include/asm-generic/io.h
-@@ -331,7 +331,7 @@ static inline void iounmap(void __iomem *addr)
- #ifndef CONFIG_GENERIC_IOMAP
- static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
- {
--	return (void __iomem *) port;
-+	return (void __iomem *)(PCI_IOBASE + (port & IO_SPACE_LIMIT));
- }
- 
- static inline void ioport_unmap(void __iomem *p)
-diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
-index f27000f..35b0c12 100644
---- a/include/kvm/arm_vgic.h
-+++ b/include/kvm/arm_vgic.h
-@@ -24,7 +24,6 @@
- #include <linux/irqreturn.h>
- #include <linux/spinlock.h>
- #include <linux/types.h>
--#include <linux/irqchip/arm-gic.h>
- 
- #define VGIC_NR_IRQS		256
- #define VGIC_NR_SGIS		16
-@@ -32,7 +31,9 @@
- #define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
- #define VGIC_NR_SHARED_IRQS	(VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)
- #define VGIC_MAX_CPUS		KVM_MAX_VCPUS
--#define VGIC_MAX_LRS		(1 << 6)
-+
-+#define VGIC_V2_MAX_LRS		(1 << 6)
-+#define VGIC_V3_MAX_LRS		16
- 
- /* Sanity checks... */
- #if (VGIC_MAX_CPUS > 8)
-@@ -68,9 +69,62 @@ struct vgic_bytemap {
- 	u32 shared[VGIC_NR_SHARED_IRQS  / 4];
- };
- 
-+struct kvm_vcpu;
-+
-+enum vgic_type {
-+	VGIC_V2,		/* Good ol' GICv2 */
-+	VGIC_V3,		/* New fancy GICv3 */
-+};
 +
-+#define LR_STATE_PENDING	(1 << 0)
-+#define LR_STATE_ACTIVE		(1 << 1)
-+#define LR_STATE_MASK		(3 << 0)
-+#define LR_EOI_INT		(1 << 2)
++static int xgene_mcfg_fixup(struct acpi_pci_root *root,
++			    struct pci_mmcfg_region *cfg)
++{
++	struct acpi_device *device = root->device;
++	struct xgene_mcfg_info *info;
 +
-+struct vgic_lr {
-+	u16	irq;
-+	u8	source;
-+	u8	state;
-+};
++	info = kzalloc(sizeof(*info), GFP_KERNEL);
++	if (info == NULL)
++		return -ENOMEM;
 +
-+struct vgic_vmcr {
-+	u32	ctlr;
-+	u32	abpr;
-+	u32	bpr;
-+	u32	pmr;
-+};
++	cfg->data = info;
 +
-+struct vgic_ops {
-+	struct vgic_lr	(*get_lr)(const struct kvm_vcpu *, int);
-+	void	(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
-+	void	(*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
-+	u64	(*get_elrsr)(const struct kvm_vcpu *vcpu);
-+	u64	(*get_eisr)(const struct kvm_vcpu *vcpu);
-+	u32	(*get_interrupt_status)(const struct kvm_vcpu *vcpu);
-+	void	(*enable_underflow)(struct kvm_vcpu *vcpu);
-+	void	(*disable_underflow)(struct kvm_vcpu *vcpu);
-+	void	(*get_vmcr)(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-+	void	(*set_vmcr)(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-+	void	(*enable)(struct kvm_vcpu *vcpu);
-+};
++	acpi_walk_resources(device->handle, METHOD_NAME__CRS,
++			    find_csr_base, cfg);
 +
-+struct vgic_params {
-+	/* vgic type */
-+	enum vgic_type	type;
-+	/* Physical address of vgic virtual cpu interface */
-+	phys_addr_t	vcpu_base;
-+	/* Number of list registers */
-+	u32		nr_lr;
-+	/* Interrupt number */
-+	unsigned int	maint_irq;
-+	/* Virtual control interface base address */
-+	void __iomem	*vctrl_base;
-+};
++	if (!info->csr_base) {
++		kfree(info);
++		cfg->data = NULL;
++		return -ENODEV;
++	}
 +
- struct vgic_dist {
- #ifdef CONFIG_KVM_ARM_VGIC
- 	spinlock_t		lock;
-+	bool			in_kernel;
- 	bool			ready;
- 
- 	/* Virtual control interface mapping */
-@@ -110,6 +164,29 @@ struct vgic_dist {
- #endif
- };
- 
-+struct vgic_v2_cpu_if {
-+	u32		vgic_hcr;
-+	u32		vgic_vmcr;
-+	u32		vgic_misr;	/* Saved only */
-+	u32		vgic_eisr[2];	/* Saved only */
-+	u32		vgic_elrsr[2];	/* Saved only */
-+	u32		vgic_apr;
-+	u32		vgic_lr[VGIC_V2_MAX_LRS];
-+};
++	cfg->read = xgene_raw_pci_read;
++	cfg->write = xgene_raw_pci_write;
 +
-+struct vgic_v3_cpu_if {
-+#ifdef CONFIG_ARM_GIC_V3
-+	u32		vgic_hcr;
-+	u32		vgic_vmcr;
-+	u32		vgic_misr;	/* Saved only */
-+	u32		vgic_eisr;	/* Saved only */
-+	u32		vgic_elrsr;	/* Saved only */
-+	u32		vgic_ap0r[4];
-+	u32		vgic_ap1r[4];
-+	u64		vgic_lr[VGIC_V3_MAX_LRS];
-+#endif
-+};
++	/* actual last bus reachable through this mmconfig */
++	cfg->end_bus = root->secondary.end;
 +
- struct vgic_cpu {
- #ifdef CONFIG_KVM_ARM_VGIC
- 	/* per IRQ to LR mapping */
-@@ -120,24 +197,24 @@ struct vgic_cpu {
- 	DECLARE_BITMAP(	pending_shared, VGIC_NR_SHARED_IRQS);
- 
- 	/* Bitmap of used/free list registers */
--	DECLARE_BITMAP(	lr_used, VGIC_MAX_LRS);
-+	DECLARE_BITMAP(	lr_used, VGIC_V2_MAX_LRS);
- 
- 	/* Number of list registers on this CPU */
- 	int		nr_lr;
- 
- 	/* CPU vif control registers for world switch */
--	u32		vgic_hcr;
--	u32		vgic_vmcr;
--	u32		vgic_misr;	/* Saved only */
--	u32		vgic_eisr[2];	/* Saved only */
--	u32		vgic_elrsr[2];	/* Saved only */
--	u32		vgic_apr;
--	u32		vgic_lr[VGIC_MAX_LRS];
-+	union {
-+		struct vgic_v2_cpu_if	vgic_v2;
-+		struct vgic_v3_cpu_if	vgic_v3;
-+	};
- #endif
- };
- 
- #define LR_EMPTY	0xff
- 
-+#define INT_STATUS_EOI		(1 << 0)
-+#define INT_STATUS_UNDERFLOW	(1 << 1)
++	/* firmware should have done this */
++	xgene_raw_pci_write(cfg, cfg->start_bus, 0, PCI_PRIMARY_BUS, 4,
++			    cfg->start_bus | ((cfg->start_bus + 1) << 8) |
++			    (cfg->end_bus << 16));
 +
- struct kvm;
- struct kvm_vcpu;
- struct kvm_run;
-@@ -157,9 +234,25 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
- bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
- 		      struct kvm_exit_mmio *mmio);
- 
--#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.vctrl_base))
-+#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);
-+#ifdef CONFIG_ARM_GIC_V3
-+int vgic_v3_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)
-+{
-+	return -ENODEV;
++	return 0;
 +}
-+#endif
++DECLARE_ACPI_MCFG_FIXUP("APM   ", "XGENE   ", xgene_mcfg_fixup);
++#endif /* CONFIG_ACPI */
 +
- #else
- static inline int kvm_vgic_hyp_init(void)
+ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
  {
-diff --git a/include/linux/efi.h b/include/linux/efi.h
-index 41bbf8b..b3fac7c 100644
---- a/include/linux/efi.h
-+++ b/include/linux/efi.h
-@@ -20,6 +20,7 @@
- #include <linux/ioport.h>
- #include <linux/pfn.h>
- #include <linux/pstore.h>
-+#include <linux/reboot.h>
- 
- #include <asm/page.h>
- 
-@@ -875,6 +876,9 @@ extern void efi_reserve_boot_services(void);
- extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose);
- extern struct efi_memory_map memmap;
+ 	struct device_node *dn = pdev->dev.of_node;
+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 */
  
-+extern int efi_reboot_quirk_mode;
-+extern bool efi_poweroff_required(void);
-+
- /* Iterate through an efi_memory_map */
- #define for_each_efi_memory_desc(m, md)					   \
- 	for ((md) = (m)->map;						   \
-@@ -926,11 +930,14 @@ static inline bool efi_enabled(int feature)
- {
- 	return test_bit(feature, &efi.flags) != 0;
- }
-+extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
- #else
- static inline bool efi_enabled(int feature)
- {
- 	return false;
+ 	return 0;
  }
-+static inline void
-+efi_reboot(enum reboot_mode reboot_mode, const char *__unused) {}
- #endif
+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.
  
- /*
-diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
++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..30cb755
+index 0000000..0f44624
 --- /dev/null
-+++ b/include/linux/irqchip/arm-gic-v3.h
-@@ -0,0 +1,198 @@
++++ b/drivers/tty/sbsauart.c
+@@ -0,0 +1,358 @@
 +/*
-+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
-+ * Author: Marc Zyngier <marc.zyngier at arm.com>
++ * SBSA (Server Base System Architecture) Compatible UART driver
 + *
++ * Copyright (C) 2014 Linaro 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.
++ * 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.
 + *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+ */
-+#ifndef __LINUX_IRQCHIP_ARM_GIC_V3_H
-+#define __LINUX_IRQCHIP_ARM_GIC_V3_H
-+
-+/*
-+ * Distributor registers. We assume we're running non-secure, with ARE
-+ * being set. Secure-only and non-ARE registers are not described.
-+ */
-+#define GICD_CTLR			0x0000
-+#define GICD_TYPER			0x0004
-+#define GICD_IIDR			0x0008
-+#define GICD_STATUSR			0x0010
-+#define GICD_SETSPI_NSR			0x0040
-+#define GICD_CLRSPI_NSR			0x0048
-+#define GICD_SETSPI_SR			0x0050
-+#define GICD_CLRSPI_SR			0x0058
-+#define GICD_SEIR			0x0068
-+#define GICD_ISENABLER			0x0100
-+#define GICD_ICENABLER			0x0180
-+#define GICD_ISPENDR			0x0200
-+#define GICD_ICPENDR			0x0280
-+#define GICD_ISACTIVER			0x0300
-+#define GICD_ICACTIVER			0x0380
-+#define GICD_IPRIORITYR			0x0400
-+#define GICD_ICFGR			0x0C00
-+#define GICD_IROUTER			0x6000
-+#define GICD_PIDR2			0xFFE8
-+
-+#define GICD_CTLR_RWP			(1U << 31)
-+#define GICD_CTLR_ARE_NS		(1U << 4)
-+#define GICD_CTLR_ENABLE_G1A		(1U << 1)
-+#define GICD_CTLR_ENABLE_G1		(1U << 0)
-+
-+#define GICD_IROUTER_SPI_MODE_ONE	(0U << 31)
-+#define GICD_IROUTER_SPI_MODE_ANY	(1U << 31)
-+
-+#define GIC_PIDR2_ARCH_MASK		0xf0
-+#define GIC_PIDR2_ARCH_GICv3		0x30
-+#define GIC_PIDR2_ARCH_GICv4		0x40
-+
-+/*
-+ * Re-Distributor registers, offsets from RD_base
-+ */
-+#define GICR_CTLR			GICD_CTLR
-+#define GICR_IIDR			0x0004
-+#define GICR_TYPER			0x0008
-+#define GICR_STATUSR			GICD_STATUSR
-+#define GICR_WAKER			0x0014
-+#define GICR_SETLPIR			0x0040
-+#define GICR_CLRLPIR			0x0048
-+#define GICR_SEIR			GICD_SEIR
-+#define GICR_PROPBASER			0x0070
-+#define GICR_PENDBASER			0x0078
-+#define GICR_INVLPIR			0x00A0
-+#define GICR_INVALLR			0x00B0
-+#define GICR_SYNCR			0x00C0
-+#define GICR_MOVLPIR			0x0100
-+#define GICR_MOVALLR			0x0110
-+#define GICR_PIDR2			GICD_PIDR2
-+
-+#define GICR_WAKER_ProcessorSleep	(1U << 1)
-+#define GICR_WAKER_ChildrenAsleep	(1U << 2)
-+
-+/*
-+ * Re-Distributor registers, offsets from SGI_base
-+ */
-+#define GICR_ISENABLER0			GICD_ISENABLER
-+#define GICR_ICENABLER0			GICD_ICENABLER
-+#define GICR_ISPENDR0			GICD_ISPENDR
-+#define GICR_ICPENDR0			GICD_ICPENDR
-+#define GICR_ISACTIVER0			GICD_ISACTIVER
-+#define GICR_ICACTIVER0			GICD_ICACTIVER
-+#define GICR_IPRIORITYR0		GICD_IPRIORITYR
-+#define GICR_ICFGR0			GICD_ICFGR
-+
-+#define GICR_TYPER_VLPIS		(1U << 1)
-+#define GICR_TYPER_LAST			(1U << 4)
-+
-+/*
-+ * CPU interface registers
-+ */
-+#define ICC_CTLR_EL1_EOImode_drop_dir	(0U << 1)
-+#define ICC_CTLR_EL1_EOImode_drop	(1U << 1)
-+#define ICC_SRE_EL1_SRE			(1U << 0)
-+
-+/*
-+ * Hypervisor interface registers (SRE only)
 + */
-+#define ICH_LR_VIRTUAL_ID_MASK		((1UL << 32) - 1)
 +
-+#define ICH_LR_EOI			(1UL << 41)
-+#define ICH_LR_GROUP			(1UL << 60)
-+#define ICH_LR_STATE			(3UL << 62)
-+#define ICH_LR_PENDING_BIT		(1UL << 62)
-+#define ICH_LR_ACTIVE_BIT		(1UL << 63)
++#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>
 +
-+#define ICH_MISR_EOI			(1 << 0)
-+#define ICH_MISR_U			(1 << 1)
++struct sbsa_tty {
++	struct tty_port port;
++	spinlock_t lock;
++	void __iomem *base;
++	u32 irq;
++	int opencount;
++	struct console console;
++};
 +
-+#define ICH_HCR_EN			(1 << 0)
-+#define ICH_HCR_UIE			(1 << 1)
++static struct tty_driver *sbsa_tty_driver;
++static struct sbsa_tty *sbsa_tty;
 +
-+#define ICH_VMCR_CTLR_SHIFT		0
-+#define ICH_VMCR_CTLR_MASK		(0x21f << ICH_VMCR_CTLR_SHIFT)
-+#define ICH_VMCR_BPR1_SHIFT		18
-+#define ICH_VMCR_BPR1_MASK		(7 << ICH_VMCR_BPR1_SHIFT)
-+#define ICH_VMCR_BPR0_SHIFT		21
-+#define ICH_VMCR_BPR0_MASK		(7 << ICH_VMCR_BPR0_SHIFT)
-+#define ICH_VMCR_PMR_SHIFT		24
-+#define ICH_VMCR_PMR_MASK		(0xffUL << ICH_VMCR_PMR_SHIFT)
++#define SBSAUART_CHAR_MASK	0xFF
 +
-+#define ICC_EOIR1_EL1			S3_0_C12_C12_1
-+#define ICC_IAR1_EL1			S3_0_C12_C12_0
-+#define ICC_SGI1R_EL1			S3_0_C12_C11_5
-+#define ICC_PMR_EL1			S3_0_C4_C6_0
-+#define ICC_CTLR_EL1			S3_0_C12_C12_4
-+#define ICC_SRE_EL1			S3_0_C12_C12_5
-+#define ICC_GRPEN1_EL1			S3_0_C12_C12_7
++static void sbsa_raw_putc(struct uart_port *port, int c)
++{
++	while (readw(port->membase + UART01x_FR) & UART01x_FR_TXFF)
++		;
++	writew(c & 0xFF, port->membase + UART01x_DR);
++}
 +
-+#define ICC_IAR1_EL1_SPURIOUS		0x3ff
++static void sbsa_uart_early_write(struct console *con, const char *buf,
++				  unsigned count)
++{
++	struct earlycon_device *dev = con->data;
 +
-+#define ICC_SRE_EL2			S3_4_C12_C9_5
++	uart_console_write(&dev->port, buf, count, sbsa_raw_putc);
++}
 +
-+#define ICC_SRE_EL2_SRE			(1 << 0)
-+#define ICC_SRE_EL2_ENABLE		(1 << 3)
++static int __init sbsa_uart_early_console_setup(struct earlycon_device *device,
++						const char *opt)
++{
++	if (!device->port.membase)
++		return -ENODEV;
 +
-+/*
-+ * System register definitions
-+ */
-+#define ICH_VSEIR_EL2			S3_4_C12_C9_4
-+#define ICH_HCR_EL2			S3_4_C12_C11_0
-+#define ICH_VTR_EL2			S3_4_C12_C11_1
-+#define ICH_MISR_EL2			S3_4_C12_C11_2
-+#define ICH_EISR_EL2			S3_4_C12_C11_3
-+#define ICH_ELSR_EL2			S3_4_C12_C11_5
-+#define ICH_VMCR_EL2			S3_4_C12_C11_7
-+
-+#define __LR0_EL2(x)			S3_4_C12_C12_ ## x
-+#define __LR8_EL2(x)			S3_4_C12_C13_ ## x
-+
-+#define ICH_LR0_EL2			__LR0_EL2(0)
-+#define ICH_LR1_EL2			__LR0_EL2(1)
-+#define ICH_LR2_EL2			__LR0_EL2(2)
-+#define ICH_LR3_EL2			__LR0_EL2(3)
-+#define ICH_LR4_EL2			__LR0_EL2(4)
-+#define ICH_LR5_EL2			__LR0_EL2(5)
-+#define ICH_LR6_EL2			__LR0_EL2(6)
-+#define ICH_LR7_EL2			__LR0_EL2(7)
-+#define ICH_LR8_EL2			__LR8_EL2(0)
-+#define ICH_LR9_EL2			__LR8_EL2(1)
-+#define ICH_LR10_EL2			__LR8_EL2(2)
-+#define ICH_LR11_EL2			__LR8_EL2(3)
-+#define ICH_LR12_EL2			__LR8_EL2(4)
-+#define ICH_LR13_EL2			__LR8_EL2(5)
-+#define ICH_LR14_EL2			__LR8_EL2(6)
-+#define ICH_LR15_EL2			__LR8_EL2(7)
-+
-+#define __AP0Rx_EL2(x)			S3_4_C12_C8_ ## x
-+#define ICH_AP0R0_EL2			__AP0Rx_EL2(0)
-+#define ICH_AP0R1_EL2			__AP0Rx_EL2(1)
-+#define ICH_AP0R2_EL2			__AP0Rx_EL2(2)
-+#define ICH_AP0R3_EL2			__AP0Rx_EL2(3)
-+
-+#define __AP1Rx_EL2(x)			S3_4_C12_C9_ ## x
-+#define ICH_AP1R0_EL2			__AP1Rx_EL2(0)
-+#define ICH_AP1R1_EL2			__AP1Rx_EL2(1)
-+#define ICH_AP1R2_EL2			__AP1Rx_EL2(2)
-+#define ICH_AP1R3_EL2			__AP1Rx_EL2(3)
-+
-+#ifndef __ASSEMBLY__
-+
-+#include <linux/stringify.h>
-+
-+static inline void gic_write_eoir(u64 irq)
-+{
-+	asm volatile("msr " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" (irq));
-+	isb();
++	device->con->write = sbsa_uart_early_write;
++	return 0;
 +}
++EARLYCON_DECLARE(sbsauart, sbsa_uart_early_console_setup);
 +
-+#endif
-+
-+#endif
-diff --git a/include/linux/of_address.h b/include/linux/of_address.h
-index c13b878..33c0420 100644
---- a/include/linux/of_address.h
-+++ b/include/linux/of_address.h
-@@ -23,17 +23,8 @@ struct of_pci_range {
- #define for_each_of_pci_range(parser, range) \
- 	for (; of_pci_range_parser_one(parser, range);)
- 
--static inline void of_pci_range_to_resource(struct of_pci_range *range,
--					    struct device_node *np,
--					    struct resource *res)
--{
--	res->flags = range->flags;
--	res->start = range->cpu_addr;
--	res->end = range->cpu_addr + range->size - 1;
--	res->parent = res->child = res->sibling = NULL;
--	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);
- 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 int of_pci_range_parser_init(struct of_pci_range_parser *parser,
-diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
-index dde3a4a..71e36d0 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,
- 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);
++static void sbsa_tty_do_write(const char *buf, unsigned count)
++{
++	unsigned long irq_flags;
++	struct sbsa_tty *qtty = sbsa_tty;
++	void __iomem *base = qtty->base;
++	unsigned n;
 +
- #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)
- {
- 	return -EINVAL;
- }
++	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);
++}
 +
-+static inline struct pci_host_bridge *
-+of_create_pci_host_bridge(struct device *parent, struct pci_ops *ops,
-+			void *host_data)
++static void sbsauart_fifo_to_tty(struct sbsa_tty *qtty)
 +{
-+	return NULL;
-+}
- #endif
- 
- #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 466bcd1..65fb1fc 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);
-@@ -1095,6 +1100,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
- 						  resource_size_t),
- 			void *alignf_data);
- 
-+
-+int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-+
- static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
- {
- 	struct pci_bus_region region;
-@@ -1805,8 +1813,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) { }
++	void __iomem *base = qtty->base;
++	unsigned int flag, max_count = 32;
++	u16 status, ch;
 +
- #endif  /* CONFIG_OF */
- 
-+/* 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()
-+ */
-+extern int pcibios_fixup_bridge_ranges(struct list_head *resources);
++	while (max_count--) {
++		status = readw(base + UART01x_FR);
++		if (status & UART01x_FR_RXFE)
++			break;
 +
- #ifdef CONFIG_EEH
- static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev)
- {
-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
-+++ b/tools/perf/arch/arm64/include/perf_regs.h
-@@ -6,6 +6,8 @@
- #include <asm/perf_regs.h>
- 
- #define PERF_REGS_MASK	((1ULL << PERF_REG_ARM64_MAX) - 1)
-+#define PERF_REGS_MAX	PERF_REG_ARM64_MAX
++		/* Take chars from the FIFO and update status */
++		ch = readw(base + UART01x_DR);
++		flag = TTY_NORMAL;
 +
- #define PERF_REG_IP	PERF_REG_ARM64_PC
- #define PERF_REG_SP	PERF_REG_ARM64_SP
- 
-diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
-new file mode 100644
-index 0000000..ff597d8
---- /dev/null
-+++ b/virt/kvm/arm/vgic-v2.c
-@@ -0,0 +1,259 @@
-+/*
-+ * Copyright (C) 2012,2013 ARM Limited, All Rights Reserved.
-+ * Author: Marc Zyngier <marc.zyngier at arm.com>
-+ *
-+ * 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/>.
-+ */
++		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;
 +
-+#include <linux/cpu.h>
-+#include <linux/kvm.h>
-+#include <linux/kvm_host.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
++		ch &= SBSAUART_CHAR_MASK;
++
++		tty_insert_flip_char(&qtty->port, ch, flag);
++	}
 +
-+#include <linux/irqchip/arm-gic.h>
++	tty_schedule_flip(&qtty->port);
 +
-+#include <asm/kvm_emulate.h>
-+#include <asm/kvm_arm.h>
-+#include <asm/kvm_mmu.h>
++	/* Clear the RX IRQ */
++	writew(UART011_RXIC | UART011_RXIC, base + UART011_ICR);
++}
 +
-+static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr)
++static irqreturn_t sbsa_tty_interrupt(int irq, void *dev_id)
 +{
-+	struct vgic_lr lr_desc;
-+	u32 val = vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr];
++	struct sbsa_tty *qtty = sbsa_tty;
++	unsigned long irq_flags;
 +
-+	lr_desc.irq	= val & GICH_LR_VIRTUALID;
-+	if (lr_desc.irq <= 15)
-+		lr_desc.source	= (val >> GICH_LR_PHYSID_CPUID_SHIFT) & 0x7;
-+	else
-+		lr_desc.source = 0;
-+	lr_desc.state	= 0;
++	spin_lock_irqsave(&qtty->lock, irq_flags);
++	sbsauart_fifo_to_tty(qtty);
++	spin_unlock_irqrestore(&qtty->lock, irq_flags);
++
++	return IRQ_HANDLED;
++}
 +
-+	if (val & GICH_LR_PENDING_BIT)
-+		lr_desc.state |= LR_STATE_PENDING;
-+	if (val & GICH_LR_ACTIVE_BIT)
-+		lr_desc.state |= LR_STATE_ACTIVE;
-+	if (val & GICH_LR_EOI)
-+		lr_desc.state |= LR_EOI_INT;
++static int sbsa_tty_open(struct tty_struct *tty, struct file *filp)
++{
++	struct sbsa_tty *qtty = sbsa_tty;
 +
-+	return lr_desc;
++	return tty_port_open(&qtty->port, tty, filp);
 +}
 +
-+static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr,
-+			   struct vgic_lr lr_desc)
++static void sbsa_tty_close(struct tty_struct *tty, struct file *filp)
 +{
-+	u32 lr_val = (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | lr_desc.irq;
++	tty_port_close(tty->port, tty, filp);
++}
 +
-+	if (lr_desc.state & LR_STATE_PENDING)
-+		lr_val |= GICH_LR_PENDING_BIT;
-+	if (lr_desc.state & LR_STATE_ACTIVE)
-+		lr_val |= GICH_LR_ACTIVE_BIT;
-+	if (lr_desc.state & LR_EOI_INT)
-+		lr_val |= GICH_LR_EOI;
++static void sbsa_tty_hangup(struct tty_struct *tty)
++{
++	tty_port_hangup(tty->port);
++}
 +
-+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val;
++static int sbsa_tty_write(struct tty_struct *tty, const unsigned char *buf,
++								int count)
++{
++	sbsa_tty_do_write(buf, count);
++	return count;
 +}
 +
-+static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
-+				  struct vgic_lr lr_desc)
++static int sbsa_tty_write_room(struct tty_struct *tty)
 +{
-+	if (!(lr_desc.state & LR_STATE_MASK))
-+		set_bit(lr, (unsigned long *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr);
++	return 32;
 +}
 +
-+static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu)
++static void sbsa_tty_console_write(struct console *co, const char *b,
++								unsigned count)
 +{
-+	u64 val;
++	sbsa_tty_do_write(b, count);
 +
-+	val  = vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[1];
-+	val <<= 32;
-+	val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[0];
++	if (b[count - 1] == '\n')
++		sbsa_tty_do_write("\r", 1);
++}
 +
-+	return val;
++static struct tty_driver *sbsa_tty_console_device(struct console *c,
++								int *index)
++{
++	*index = c->index;
++	return sbsa_tty_driver;
 +}
 +
-+static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu)
++static int sbsa_tty_console_setup(struct console *co, char *options)
 +{
-+	u64 val;
++	if ((unsigned)co->index > 0)
++		return -ENODEV;
++	if (sbsa_tty->base == NULL)
++		return -ENODEV;
++	return 0;
++}
 +
-+	val  = vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[1];
-+	val <<= 32;
-+	val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[0];
++static struct tty_port_operations sbsa_port_ops = {
++};
 +
-+	return val;
-+}
++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 u32 vgic_v2_get_interrupt_status(const struct kvm_vcpu *vcpu)
++static int sbsa_tty_create_driver(void)
 +{
-+	u32 misr = vcpu->arch.vgic_cpu.vgic_v2.vgic_misr;
-+	u32 ret = 0;
++	int ret;
++	struct tty_driver *tty;
++
++	sbsa_tty = kzalloc(sizeof(*sbsa_tty), GFP_KERNEL);
++	if (sbsa_tty == NULL) {
++		ret = -ENOMEM;
++		goto err_alloc_sbsa_tty_failed;
++	}
++	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;
 +
-+	if (misr & GICH_MISR_EOI)
-+		ret |= INT_STATUS_EOI;
-+	if (misr & GICH_MISR_U)
-+		ret |= INT_STATUS_UNDERFLOW;
++	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 void vgic_v2_enable_underflow(struct kvm_vcpu *vcpu)
++static void sbsa_tty_delete_driver(void)
 +{
-+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr |= GICH_HCR_UIE;
++	tty_unregister_driver(sbsa_tty_driver);
++	put_tty_driver(sbsa_tty_driver);
++	sbsa_tty_driver = NULL;
++	kfree(sbsa_tty);
++	sbsa_tty = NULL;
 +}
 +
-+static void vgic_v2_disable_underflow(struct kvm_vcpu *vcpu)
++static int sbsa_tty_probe(struct platform_device *pdev)
 +{
-+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr &= ~GICH_HCR_UIE;
-+}
++	struct sbsa_tty *qtty;
++	int ret = -EINVAL;
++	int i;
++	struct resource *r;
++	struct device *ttydev;
++	void __iomem *base;
++	u32 irq;
 +
-+static void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-+{
-+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (r == NULL)
++		return -EINVAL;
 +
-+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >> GICH_VMCR_CTRL_SHIFT;
-+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >> GICH_VMCR_ALIAS_BINPOINT_SHIFT;
-+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >> GICH_VMCR_BINPOINT_SHIFT;
-+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >> GICH_VMCR_PRIMASK_SHIFT;
-+}
++	base = ioremap(r->start, r->end - r->start);
++	if (base == NULL)
++		pr_err("sbsa_tty: unable to remap base\n");
 +
-+static void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-+{
-+	u32 vmcr;
++	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++	if (r == NULL)
++		goto err_unmap;
 +
-+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
-+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) & GICH_VMCR_ALIAS_BINPOINT_MASK;
-+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) & GICH_VMCR_BINPOINT_MASK;
-+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) & GICH_VMCR_PRIMASK_MASK;
++	irq = r->start;
 +
-+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
-+}
++	if (pdev->id > 0)
++		goto err_unmap;
 +
-+static void vgic_v2_enable(struct kvm_vcpu *vcpu)
-+{
-+	/*
-+	 * By forcing VMCR to zero, the GIC will restore the binary
-+	 * points to their reset values. Anything else resets to zero
-+	 * anyway.
-+	 */
-+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
-+
-+	/* Get the show on the road... */
-+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
-+}
-+
-+static const struct vgic_ops vgic_v2_ops = {
-+	.get_lr			= vgic_v2_get_lr,
-+	.set_lr			= vgic_v2_set_lr,
-+	.sync_lr_elrsr		= vgic_v2_sync_lr_elrsr,
-+	.get_elrsr		= vgic_v2_get_elrsr,
-+	.get_eisr		= vgic_v2_get_eisr,
-+	.get_interrupt_status	= vgic_v2_get_interrupt_status,
-+	.enable_underflow	= vgic_v2_enable_underflow,
-+	.disable_underflow	= vgic_v2_disable_underflow,
-+	.get_vmcr		= vgic_v2_get_vmcr,
-+	.set_vmcr		= vgic_v2_set_vmcr,
-+	.enable			= vgic_v2_enable,
-+};
++	ret = sbsa_tty_create_driver();
++	if (ret)
++		goto err_unmap;
 +
-+static struct vgic_params vgic_v2_params;
++	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;
 +
-+/**
-+ * vgic_v2_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
-+ *
-+ * Returns 0 if a GICv2 has been found, with the low level operations
-+ * in *ops and the HW parameters in *params. Returns an error code
-+ * otherwise.
-+ */
-+int vgic_v2_probe(struct device_node *vgic_node,
-+		  const struct vgic_ops **ops,
-+		  const struct vgic_params **params)
-+{
-+	int ret;
-+	struct resource vctrl_res;
-+	struct resource vcpu_res;
-+	struct vgic_params *vgic = &vgic_v2_params;
++	/* Clear and Mask all IRQs */
++	writew(0, base + UART011_IMSC);
++	writew(0xFFFF, base + UART011_ICR);
 +
-+	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
-+	if (!vgic->maint_irq) {
-+		kvm_err("error getting vgic maintenance irq from DT\n");
-+		ret = -ENXIO;
-+		goto out;
-+	}
++	ret = request_irq(irq, sbsa_tty_interrupt, IRQF_SHARED,
++						"sbsa_tty", pdev);
++	if (ret)
++		goto err_request_irq_failed;
 +
-+	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
-+	if (ret) {
-+		kvm_err("Cannot obtain GICH resource\n");
-+		goto out;
-+	}
++	/* Unmask the RX IRQ */
++	writew(UART011_RXIM | UART011_RTIM, base + UART011_IMSC);
 +
-+	vgic->vctrl_base = of_iomap(vgic_node, 2);
-+	if (!vgic->vctrl_base) {
-+		kvm_err("Cannot ioremap GICH\n");
-+		ret = -ENOMEM;
-+		goto out;
++	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;
 +	}
 +
-+	vgic->nr_lr = readl_relaxed(vgic->vctrl_base + GICH_VTR);
-+	vgic->nr_lr = (vgic->nr_lr & 0x3f) + 1;
++	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;
++	/* if no console= on cmdline, make this the console device */
++	if (!console_set_on_cmdline)
++		qtty->console.flags |= CON_CONSDEV;
++	qtty->console.index = pdev->id;
++	register_console(&qtty->console);
 +
-+	ret = create_hyp_io_mappings(vgic->vctrl_base,
-+				     vgic->vctrl_base + resource_size(&vctrl_res),
-+				     vctrl_res.start);
-+	if (ret) {
-+		kvm_err("Cannot map VCTRL into hyp\n");
-+		goto out_unmap;
-+	}
++	return 0;
 +
-+	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
-+		kvm_err("Cannot obtain GICV resource\n");
-+		ret = -ENXIO;
-+		goto out_unmap;
-+	}
++	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 (!PAGE_ALIGNED(vcpu_res.start)) {
-+		kvm_err("GICV physical address 0x%llx not page aligned\n",
-+			(unsigned long long)vcpu_res.start);
-+		ret = -ENXIO;
-+		goto out_unmap;
-+	}
++static int sbsa_tty_remove(struct platform_device *pdev)
++{
++	struct sbsa_tty *qtty;
 +
-+	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
-+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-+			(unsigned long long)resource_size(&vcpu_res),
-+			PAGE_SIZE);
-+		ret = -ENXIO;
-+		goto out_unmap;
++	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;
++}
++
++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),
 +	}
++};
 +
-+	vgic->vcpu_base = vcpu_res.start;
++module_platform_driver(sbsa_tty_platform_driver);
 +
-+	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-+		 vgic->vctrl_base, vgic->maint_irq);
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index beea6ca..7038a2d 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -310,10 +310,18 @@ static int dw8250_probe_of(struct uart_port *p,
+ static int dw8250_probe_acpi(struct uart_8250_port *up,
+ 			     struct dw8250_data *data)
+ {
++	const struct acpi_device_id *id;
+ 	struct uart_port *p = &up->port;
+ 
+ 	dw8250_setup_port(up);
+ 
++	id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
++	if (!id)
++		return -ENODEV;
 +
-+	vgic->type = VGIC_V2;
-+	*ops = &vgic_v2_ops;
-+	*params = vgic;
-+	goto out;
++	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;
+@@ -536,6 +544,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/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
+index ef9a165..9f1939c 100644
+--- a/drivers/virtio/virtio_mmio.c
++++ b/drivers/virtio/virtio_mmio.c
+@@ -100,8 +100,7 @@
+ #include <linux/virtio_config.h>
+ #include <linux/virtio_mmio.h>
+ #include <linux/virtio_ring.h>
+-
+-
++#include <linux/acpi.h>
+ 
+ /* The alignment to use between consumer and producer parts of vring.
+  * Currently hardcoded to the page size. */
+@@ -634,6 +633,14 @@ static struct of_device_id virtio_mmio_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, virtio_mmio_match);
+ 
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id virtio_mmio_acpi_match[] = {
++	{ "LNRO0005", },
++	{ }
++};
++MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match);
++#endif
 +
-+out_unmap:
-+	iounmap(vgic->vctrl_base);
-+out:
-+	of_node_put(vgic_node);
-+	return ret;
+ static struct platform_driver virtio_mmio_driver = {
+ 	.probe		= virtio_mmio_probe,
+ 	.remove		= virtio_mmio_remove,
+@@ -641,6 +648,7 @@ static struct platform_driver virtio_mmio_driver = {
+ 		.name	= "virtio-mmio",
+ 		.owner	= THIS_MODULE,
+ 		.of_match_table	= virtio_mmio_match,
++		.acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
+ 	},
+ };
+ 
+diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c
+index 1f850c9..f745db2 100644
+--- a/drivers/xen/efi.c
++++ b/drivers/xen/efi.c
+@@ -294,6 +294,7 @@ static const struct efi efi_xen __initconst = {
+ 	.acpi                     = EFI_INVALID_TABLE_ADDR,
+ 	.acpi20                   = EFI_INVALID_TABLE_ADDR,
+ 	.smbios                   = EFI_INVALID_TABLE_ADDR,
++	.smbios3                  = EFI_INVALID_TABLE_ADDR,
+ 	.sal_systab               = EFI_INVALID_TABLE_ADDR,
+ 	.boot_info                = EFI_INVALID_TABLE_ADDR,
+ 	.hcdp                     = EFI_INVALID_TABLE_ADDR,
+diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
+index f34a083..04d02fc 100644
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -27,6 +27,7 @@
+ #define __ACPI_BUS_H__
+ 
+ #include <linux/device.h>
++#include <linux/property.h>
+ 
+ /* TBD: Make dynamic */
+ #define ACPI_MAX_HANDLES	10
+@@ -68,6 +69,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);
+ 
++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)
+@@ -337,10 +340,20 @@ struct acpi_device_physical_node {
+ 	bool put_online:1;
+ };
+ 
++/* ACPI Device Specific Data (_DSD) */
++struct acpi_device_data {
++	const union acpi_object *pointer;
++	const union acpi_object *properties;
++	const union acpi_object *of_compatible;
++};
++
++struct acpi_gpio_mapping;
++
+ /* Device */
+ struct acpi_device {
+ 	int device_type;
+ 	acpi_handle handle;		/* no handle for fixed hardware */
++	struct fwnode_handle fwnode;
+ 	struct acpi_device *parent;
+ 	struct list_head children;
+ 	struct list_head node;
+@@ -353,9 +366,11 @@ struct acpi_device {
+ 	struct acpi_device_wakeup wakeup;
+ 	struct acpi_device_perf performance;
+ 	struct acpi_device_dir dir;
++	struct acpi_device_data data;
+ 	struct acpi_scan_handler *handler;
+ 	struct acpi_hotplug_context *hp;
+ 	struct acpi_driver *driver;
++	const struct acpi_gpio_mapping *driver_gpios;
+ 	void *driver_data;
+ 	struct device dev;
+ 	unsigned int physical_node_count;
+@@ -364,6 +379,21 @@ struct acpi_device {
+ 	void (*remove)(struct acpi_device *);
+ };
+ 
++static inline bool is_acpi_node(struct fwnode_handle *fwnode)
++{
++	return fwnode && fwnode->type == FWNODE_ACPI;
 +}
-diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
-new file mode 100644
-index 0000000..f01d446
---- /dev/null
-+++ b/virt/kvm/arm/vgic-v3.c
-@@ -0,0 +1,231 @@
-+/*
-+ * Copyright (C) 2013 ARM Limited, All Rights Reserved.
-+ * Author: Marc Zyngier <marc.zyngier at arm.com>
-+ *
-+ * 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/cpu.h>
-+#include <linux/kvm.h>
-+#include <linux/kvm_host.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
++static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
++{
++	return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
++}
 +
-+#include <linux/irqchip/arm-gic-v3.h>
++static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
++{
++	return &adev->fwnode;
++}
 +
-+#include <asm/kvm_emulate.h>
-+#include <asm/kvm_arm.h>
-+#include <asm/kvm_mmu.h>
+ static inline void *acpi_driver_data(struct acpi_device *d)
+ {
+ 	return d->driver_data;
+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>
+ 
+ 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
 +
-+/* These are for GICv2 emulation only */
-+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+        return ioremap_cache(phys, size);
+ }
+ 
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index aa70cbd..1261fef 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -275,6 +275,13 @@
+ 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
+ 	}								\
+ 									\
++	/* ACPI quirks */						\
++	.acpi_fixup        : AT(ADDR(.acpi_fixup) - LOAD_OFFSET) {	\
++		VMLINUX_SYMBOL(__start_acpi_mcfg_fixups) = .;		\
++		*(.acpi_fixup_mcfg)					\
++		VMLINUX_SYMBOL(__end_acpi_mcfg_fixups) = .;		\
++	}								\
++									\
+ 	/* Built-in firmware blobs */					\
+ 	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
+ 		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
+diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
+index 206dcc3..660dbfc 100644
+--- a/include/kvm/arm_vgic.h
++++ b/include/kvm/arm_vgic.h
+@@ -289,17 +289,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 407a12f..de81de3 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -28,6 +28,7 @@
+ #include <linux/errno.h>
+ #include <linux/ioport.h>	/* for struct resource */
+ #include <linux/device.h>
++#include <linux/property.h>
+ 
+ #ifndef _LINUX
+ #define _LINUX
+@@ -71,6 +72,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 +125,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,
+@@ -423,12 +429,8 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
+ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ 					       const struct device *dev);
+ 
+-static inline bool acpi_driver_match_device(struct device *dev,
+-					    const struct device_driver *drv)
+-{
+-	return !!acpi_match_device(drv->acpi_match_table, dev);
+-}
+-
++extern bool acpi_driver_match_device(struct device *dev,
++				     const struct device_driver *drv);
+ int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
+ int acpi_device_modalias(struct device *, char *, int);
+ 
+@@ -443,6 +445,23 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *);
+ #define ACPI_COMPANION_SET(dev, adev)	do { } while (0)
+ #define ACPI_HANDLE(dev)		(NULL)
+ 
++struct fwnode_handle;
 +
-+/*
-+ * LRs are stored in reverse order in memory. make sure we index them
-+ * correctly.
-+ */
-+#define LR_INDEX(lr)			(VGIC_V3_MAX_LRS - 1 - lr)
++static inline bool is_acpi_node(struct fwnode_handle *fwnode)
++{
++	return false;
++}
 +
-+static u32 ich_vtr_el2;
++static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
++{
++	return NULL;
++}
 +
-+static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
++static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
 +{
-+	struct vgic_lr lr_desc;
-+	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
++	return NULL;
++}
 +
-+	lr_desc.irq	= val & GICH_LR_VIRTUALID;
-+	if (lr_desc.irq <= 15)
-+		lr_desc.source	= (val >> GICH_LR_PHYSID_CPUID_SHIFT) & 0x7;
-+	else
-+		lr_desc.source = 0;
-+	lr_desc.state	= 0;
+ static inline const char *acpi_dev_name(struct acpi_device *adev)
+ {
+ 	return NULL;
+@@ -659,4 +678,114 @@ do {									\
+ #endif
+ #endif
+ 
++struct acpi_gpio_params {
++	unsigned int crs_entry_index;
++	unsigned int line_index;
++	bool active_low;
++};
 +
-+	if (val & ICH_LR_PENDING_BIT)
-+		lr_desc.state |= LR_STATE_PENDING;
-+	if (val & ICH_LR_ACTIVE_BIT)
-+		lr_desc.state |= LR_STATE_ACTIVE;
-+	if (val & ICH_LR_EOI)
-+		lr_desc.state |= LR_EOI_INT;
++struct acpi_gpio_mapping {
++	const char *name;
++	const struct acpi_gpio_params *data;
++	unsigned int size;
++};
 +
-+	return lr_desc;
-+}
++#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)
++int acpi_dev_add_driver_gpios(struct acpi_device *adev,
++			      const struct acpi_gpio_mapping *gpios);
 +
-+static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
-+			   struct vgic_lr lr_desc)
++static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
++{
++	if (adev)
++		adev->driver_gpios = NULL;
++}
++#else
++static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
++			      const struct acpi_gpio_mapping *gpios)
 +{
-+	u64 lr_val = (((u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) |
-+		      lr_desc.irq);
++	return -ENXIO;
++}
++static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {}
++#endif
++
++/* Device properties */
 +
-+	if (lr_desc.state & LR_STATE_PENDING)
-+		lr_val |= ICH_LR_PENDING_BIT;
-+	if (lr_desc.state & LR_STATE_ACTIVE)
-+		lr_val |= ICH_LR_ACTIVE_BIT;
-+	if (lr_desc.state & LR_EOI_INT)
-+		lr_val |= ICH_LR_EOI;
++#define MAX_ACPI_REFERENCE_ARGS	8
++struct acpi_reference_args {
++	struct acpi_device *adev;
++	size_t nargs;
++	u64 args[MAX_ACPI_REFERENCE_ARGS];
++};
 +
-+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val;
++#ifdef CONFIG_ACPI
++int acpi_dev_get_property(struct acpi_device *adev, const char *name,
++			  acpi_object_type type, const union acpi_object **obj);
++int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
++				acpi_object_type type,
++				const union acpi_object **obj);
++int acpi_dev_get_property_reference(struct acpi_device *adev,
++				    const char *name, size_t index,
++				    struct acpi_reference_args *args);
++
++int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
++		      void **valptr);
++int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
++			      enum dev_prop_type proptype, void *val);
++int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
++		       enum dev_prop_type proptype, void *val, size_t nval);
++
++struct acpi_device *acpi_get_next_child(struct device *dev,
++					struct acpi_device *child);
++#else
++static inline int acpi_dev_get_property(struct acpi_device *adev,
++					const char *name, acpi_object_type type,
++					const union acpi_object **obj)
++{
++	return -ENXIO;
++}
++static inline int acpi_dev_get_property_array(struct acpi_device *adev,
++					      const char *name,
++					      acpi_object_type type,
++					      const union acpi_object **obj)
++{
++	return -ENXIO;
++}
++static inline int acpi_dev_get_property_reference(struct acpi_device *adev,
++				const char *name, const char *cells_name,
++				size_t index, struct acpi_reference_args *args)
++{
++	return -ENXIO;
 +}
 +
-+static void vgic_v3_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
-+				  struct vgic_lr lr_desc)
++static inline int acpi_dev_prop_get(struct acpi_device *adev,
++				    const char *propname,
++				    void **valptr)
 +{
-+	if (!(lr_desc.state & LR_STATE_MASK))
-+		vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr);
++	return -ENXIO;
 +}
 +
-+static u64 vgic_v3_get_elrsr(const struct kvm_vcpu *vcpu)
++static inline int acpi_dev_prop_read_single(struct acpi_device *adev,
++					    const char *propname,
++					    enum dev_prop_type proptype,
++					    void *val)
 +{
-+	return vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr;
++	return -ENXIO;
 +}
 +
-+static u64 vgic_v3_get_eisr(const struct kvm_vcpu *vcpu)
++static inline int acpi_dev_prop_read(struct acpi_device *adev,
++				     const char *propname,
++				     enum dev_prop_type proptype,
++				     void *val, size_t nval)
 +{
-+	return vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr;
++	return -ENXIO;
 +}
 +
-+static u32 vgic_v3_get_interrupt_status(const struct kvm_vcpu *vcpu)
++static inline struct acpi_device *acpi_get_next_child(struct device *dev,
++						      struct acpi_device *child)
 +{
-+	u32 misr = vcpu->arch.vgic_cpu.vgic_v3.vgic_misr;
-+	u32 ret = 0;
++	return NULL;
++}
 +
-+	if (misr & ICH_MISR_EOI)
-+		ret |= INT_STATUS_EOI;
-+	if (misr & ICH_MISR_U)
-+		ret |= INT_STATUS_UNDERFLOW;
++#endif
 +
-+	return ret;
+ #endif	/*_LINUX_ACPI_H*/
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index abcafaa..4f5caa1 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/efi.h b/include/linux/efi.h
+index 0949f9c..0238d61 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -547,6 +547,9 @@ void efi_native_runtime_setup(void);
+ #define SMBIOS_TABLE_GUID    \
+     EFI_GUID(  0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+ 
++#define SMBIOS3_TABLE_GUID    \
++    EFI_GUID(  0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 )
++
+ #define SAL_SYSTEM_TABLE_GUID    \
+     EFI_GUID(  0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+ 
+@@ -810,7 +813,8 @@ extern struct efi {
+ 	unsigned long mps;		/* MPS table */
+ 	unsigned long acpi;		/* ACPI table  (IA64 ext 0.71) */
+ 	unsigned long acpi20;		/* ACPI table  (ACPI 2.0) */
+-	unsigned long smbios;		/* SM BIOS table */
++	unsigned long smbios;		/* SMBIOS table (32 bit entry point) */
++	unsigned long smbios3;		/* SMBIOS table (64 bit entry point) */
+ 	unsigned long sal_systab;	/* SAL system table */
+ 	unsigned long boot_info;	/* boot info table */
+ 	unsigned long hcdp;		/* HCDP table */
+diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
+index 12f146f..00b1b70 100644
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -94,6 +94,13 @@ int gpiod_to_irq(const struct gpio_desc *desc);
+ struct gpio_desc *gpio_to_desc(unsigned gpio);
+ int desc_to_gpio(const struct gpio_desc *desc);
+ 
++/* Child properties interface */
++struct fwnode_handle;
++
++struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
++					 const char *propname);
++struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
++					    struct fwnode_handle *child);
+ #else /* CONFIG_GPIOLIB */
+ 
+ static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,
+diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
+index 8b62246..ee2d8c6 100644
+--- a/include/linux/gpio_keys.h
++++ b/include/linux/gpio_keys.h
+@@ -2,6 +2,7 @@
+ #define _GPIO_KEYS_H
+ 
+ struct device;
++struct gpio_desc;
+ 
+ /**
+  * struct gpio_keys_button - configuration parameters
+@@ -17,6 +18,7 @@ struct device;
+  *			disable button via sysfs
+  * @value:		axis value for %EV_ABS
+  * @irq:		Irq number in case of interrupt keys
++ * @gpiod:		GPIO descriptor
+  */
+ struct gpio_keys_button {
+ 	unsigned int code;
+@@ -29,6 +31,7 @@ struct gpio_keys_button {
+ 	bool can_disable;
+ 	int value;
+ 	unsigned int irq;
++	struct gpio_desc *gpiod;
+ };
+ 
+ /**
+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 13eed92..dc9cb5f 100644
+--- a/include/linux/irqchip/arm-gic.h
++++ b/include/linux/irqchip/arm-gic.h
+@@ -55,6 +55,8 @@
+ 					(GICD_INT_DEF_PRI << 8) |\
+ 					GICD_INT_DEF_PRI)
+ 
++#define GIC_DIST_SOFTINT_NSATT		0x8000
++
+ #define GICH_HCR			0x0
+ #define GICH_VTR			0x4
+ #define GICH_VMCR			0x8
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index a6059bd..e4d8f70 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -43,6 +43,7 @@
+  * include/linux/kvm_h.
+  */
+ #define KVM_MEMSLOT_INVALID	(1UL << 16)
++#define KVM_MEMSLOT_INCOHERENT	(1UL << 17)
+ 
+ /* Two fragments for cross MMIO pages. */
+ #define KVM_MAX_MMIO_FRAGMENTS	2
+diff --git a/include/linux/leds.h b/include/linux/leds.h
+index a57611d..361101f 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -261,6 +261,7 @@ struct gpio_led {
+ 	unsigned	retain_state_suspended : 1;
+ 	unsigned	default_state : 2;
+ 	/* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
++	struct gpio_desc *gpiod;
+ };
+ #define LEDS_GPIO_DEFSTATE_OFF		0
+ #define LEDS_GPIO_DEFSTATE_ON		1
+@@ -273,7 +274,7 @@ struct gpio_led_platform_data {
+ #define GPIO_LED_NO_BLINK_LOW	0	/* No blink GPIO state low */
+ #define GPIO_LED_NO_BLINK_HIGH	1	/* No blink GPIO state high */
+ #define GPIO_LED_BLINK		2	/* Please, blink */
+-	int		(*gpio_blink_set)(unsigned gpio, int state,
++	int		(*gpio_blink_set)(struct gpio_desc *desc, int state,
+ 					unsigned long *delay_on,
+ 					unsigned long *delay_off);
+ };
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 29f0adc..cf79be1 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -23,6 +23,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/topology.h>
+ #include <linux/notifier.h>
++#include <linux/property.h>
+ 
+ #include <asm/byteorder.h>
+ #include <asm/errno.h>
+@@ -49,6 +50,7 @@ struct device_node {
+ 	const char *type;
+ 	phandle phandle;
+ 	const char *full_name;
++	struct fwnode_handle fwnode;
+ 
+ 	struct	property *properties;
+ 	struct	property *deadprops;	/* removed properties */
+@@ -79,6 +81,7 @@ extern struct kobj_type of_node_ktype;
+ static inline void of_node_init(struct device_node *node)
+ {
+ 	kobject_init(&node->kobj, &of_node_ktype);
++	node->fwnode.type = FWNODE_OF;
+ }
+ 
+ /* true when node is initialized */
+@@ -114,6 +117,16 @@ extern struct device_node *of_aliases;
+ extern struct device_node *of_stdout;
+ extern raw_spinlock_t devtree_lock;
+ 
++static inline bool is_of_node(struct fwnode_handle *fwnode)
++{
++	return fwnode && fwnode->type == FWNODE_OF;
++}
++
++static inline struct device_node *of_node(struct fwnode_handle *fwnode)
++{
++	return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
 +}
 +
-+static void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+ static inline bool of_have_populated_dt(void)
+ {
+ 	return of_allnodes != NULL;
+@@ -263,6 +276,10 @@ extern int of_property_read_u32_array(const struct device_node *np,
+ 				      size_t sz);
+ extern int of_property_read_u64(const struct device_node *np,
+ 				const char *propname, u64 *out_value);
++extern int of_property_read_u64_array(const struct device_node *np,
++				      const char *propname,
++				      u64 *out_values,
++				      size_t sz);
+ 
+ extern int of_property_read_string(struct device_node *np,
+ 				   const char *propname,
+@@ -355,6 +372,16 @@ bool of_console_check(struct device_node *dn, char *name, int index);
+ 
+ #else /* CONFIG_OF */
+ 
++static inline bool is_of_node(struct fwnode_handle *fwnode)
 +{
-+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
++	return false;
++}
 +
-+	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
-+	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
-+	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
-+	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
++static inline struct device_node *of_node(struct fwnode_handle *fwnode)
++{
++	return NULL;
 +}
 +
-+static void vgic_v3_enable_underflow(struct kvm_vcpu *vcpu)
+ static inline const char* of_node_full_name(const struct device_node *np)
+ {
+ 	return "<no-node>";
+@@ -477,6 +504,13 @@ static inline int of_property_read_u32_array(const struct device_node *np,
+ 	return -ENOSYS;
+ }
+ 
++static inline int of_property_read_u64_array(const struct device_node *np,
++					     const char *propname,
++					     u64 *out_values, size_t sz)
 +{
-+	vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr |= ICH_HCR_UIE;
++	return -ENOSYS;
 +}
 +
-+static void vgic_v3_disable_underflow(struct kvm_vcpu *vcpu)
-+{
-+	vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr &= ~ICH_HCR_UIE;
-+}
+ static inline int of_property_read_string(struct device_node *np,
+ 					  const char *propname,
+ 					  const char **out_string)
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 4c8ac5f..ea663d8 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -563,15 +563,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;
+@@ -1326,6 +1317,16 @@ 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);
+ 
++/*
++ * 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);
++void pcibios_penalize_isa_irq(int irq, int active);
++
+ #else /* CONFIG_PCI is not enabled */
+ 
+ /*
+@@ -1427,6 +1428,23 @@ 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; }
+@@ -1636,7 +1654,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/include/linux/property.h b/include/linux/property.h
+new file mode 100644
+index 0000000..a6a3d98
+--- /dev/null
++++ b/include/linux/property.h
+@@ -0,0 +1,143 @@
++/*
++ * property.h - Unified device property interface.
++ *
++ * Copyright (C) 2014, Intel Corporation
++ * Authors: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
++ *          Mika Westerberg <mika.westerberg at linux.intel.com>
++ *
++ * 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.
++ */
 +
-+static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-+{
-+	u32 vmcr;
++#ifndef _LINUX_PROPERTY_H_
++#define _LINUX_PROPERTY_H_
 +
-+	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
-+	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
-+	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
-+	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
++#include <linux/types.h>
 +
-+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
-+}
++struct device;
 +
-+static void vgic_v3_enable(struct kvm_vcpu *vcpu)
-+{
-+	/*
-+	 * By forcing VMCR to zero, the GIC will restore the binary
-+	 * points to their reset values. Anything else resets to zero
-+	 * anyway.
-+	 */
-+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = 0;
-+
-+	/* Get the show on the road... */
-+	vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr = ICH_HCR_EN;
-+}
-+
-+static const struct vgic_ops vgic_v3_ops = {
-+	.get_lr			= vgic_v3_get_lr,
-+	.set_lr			= vgic_v3_set_lr,
-+	.sync_lr_elrsr		= vgic_v3_sync_lr_elrsr,
-+	.get_elrsr		= vgic_v3_get_elrsr,
-+	.get_eisr		= vgic_v3_get_eisr,
-+	.get_interrupt_status	= vgic_v3_get_interrupt_status,
-+	.enable_underflow	= vgic_v3_enable_underflow,
-+	.disable_underflow	= vgic_v3_disable_underflow,
-+	.get_vmcr		= vgic_v3_get_vmcr,
-+	.set_vmcr		= vgic_v3_set_vmcr,
-+	.enable			= vgic_v3_enable,
++enum dev_prop_type {
++	DEV_PROP_U8,
++	DEV_PROP_U16,
++	DEV_PROP_U32,
++	DEV_PROP_U64,
++	DEV_PROP_STRING,
++	DEV_PROP_MAX,
 +};
 +
-+static struct vgic_params vgic_v3_params;
-+
-+/**
-+ * vgic_v3_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
-+ *
-+ * Returns 0 if a GICv3 has been found, with the low level operations
-+ * 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 ret = 0;
-+	u32 gicv_idx;
-+	struct resource vcpu_res;
-+	struct vgic_params *vgic = &vgic_v3_params;
-+
-+	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
-+	if (!vgic->maint_irq) {
-+		kvm_err("error getting vgic maintenance irq from DT\n");
-+		ret = -ENXIO;
-+		goto out;
-+	}
++bool device_property_present(struct device *dev, const char *propname);
++int device_property_read_u8_array(struct device *dev, const char *propname,
++				  u8 *val, size_t nval);
++int device_property_read_u16_array(struct device *dev, const char *propname,
++				   u16 *val, size_t nval);
++int device_property_read_u32_array(struct device *dev, const char *propname,
++				   u32 *val, size_t nval);
++int device_property_read_u64_array(struct device *dev, const char *propname,
++				   u64 *val, size_t nval);
++int device_property_read_string_array(struct device *dev, const char *propname,
++				      const char **val, size_t nval);
++int device_property_read_string(struct device *dev, const char *propname,
++				const char **val);
++
++enum fwnode_type {
++	FWNODE_INVALID = 0,
++	FWNODE_OF,
++	FWNODE_ACPI,
++};
 +
-+	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
++struct fwnode_handle {
++	enum fwnode_type type;
++};
 +
-+	/*
-+	 * The ListRegs field is 5 bits, but there is a architectural
-+	 * maximum of 16 list registers. Just ignore bit 4...
-+	 */
-+	vgic->nr_lr = (ich_vtr_el2 & 0xf) + 1;
++bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
++int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
++				  const char *propname, u8 *val,
++				  size_t nval);
++int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
++				   const char *propname, u16 *val,
++				   size_t nval);
++int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
++				   const char *propname, u32 *val,
++				   size_t nval);
++int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
++				   const char *propname, u64 *val,
++				   size_t nval);
++int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
++				      const char *propname, const char **val,
++				      size_t nval);
++int fwnode_property_read_string(struct fwnode_handle *fwnode,
++				const char *propname, const char **val);
 +
-+	if (of_property_read_u32(vgic_node, "#redistributor-regions", &gicv_idx))
-+		gicv_idx = 1;
++struct fwnode_handle *device_get_next_child_node(struct device *dev,
++						 struct fwnode_handle *child);
 +
-+	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
-+	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
-+		kvm_err("Cannot obtain GICV region\n");
-+		ret = -ENXIO;
-+		goto out;
-+	}
-+	vgic->vcpu_base = vcpu_res.start;
-+	vgic->vctrl_base = NULL;
-+	vgic->type = VGIC_V3;
++#define device_for_each_child_node(dev, child) \
++	for (child = device_get_next_child_node(dev, NULL); child; \
++	     child = device_get_next_child_node(dev, child))
 +
-+	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-+		 vcpu_res.start, vgic->maint_irq);
++void fwnode_handle_put(struct fwnode_handle *fwnode);
 +
-+	*ops = &vgic_v3_ops;
-+	*params = vgic;
++unsigned int device_get_child_node_count(struct device *dev);
 +
-+out:
-+	of_node_put(vgic_node);
-+	return ret;
-+}
-diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
-index 476d3bf..795ab48 100644
---- a/virt/kvm/arm/vgic.c
-+++ b/virt/kvm/arm/vgic.c
-@@ -76,14 +76,6 @@
- #define IMPLEMENTER_ARM		0x43b
- #define GICC_ARCH_VERSION_V2	0x2
- 
--/* Physical address of vgic virtual cpu interface */
--static phys_addr_t vgic_vcpu_base;
--
--/* Virtual control interface base address */
--static void __iomem *vgic_vctrl_base;
--
--static struct device_node *vgic_node;
--
- #define ACCESS_READ_VALUE	(1 << 0)
- #define ACCESS_READ_RAZ		(0 << 0)
- #define ACCESS_READ_MASK(x)	((x) & (1 << 0))
-@@ -94,12 +86,17 @@ static struct device_node *vgic_node;
- #define ACCESS_WRITE_MASK(x)	((x) & (3 << 1))
- 
- static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu);
-+static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu);
- static void vgic_update_state(struct kvm *kvm);
- static void vgic_kick_vcpus(struct kvm *kvm);
- static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg);
--static u32 vgic_nr_lr;
-+static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr);
-+static void vgic_set_lr(struct kvm_vcpu *vcpu, int lr, struct vgic_lr lr_desc);
-+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
- 
--static unsigned int vgic_maint_irq;
-+static const struct vgic_ops *vgic_ops;
-+static const struct vgic_params *vgic;
- 
- static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x,
- 				int cpuid, u32 offset)
-@@ -593,18 +590,6 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
- 	return false;
- }
- 
--#define LR_CPUID(lr)	\
--	(((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT)
--#define LR_IRQID(lr)	\
--	((lr) & GICH_LR_VIRTUALID)
--
--static void vgic_retire_lr(int lr_nr, int irq, struct vgic_cpu *vgic_cpu)
--{
--	clear_bit(lr_nr, vgic_cpu->lr_used);
--	vgic_cpu->vgic_lr[lr_nr] &= ~GICH_LR_STATE;
--	vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
--}
--
- /**
-  * vgic_unqueue_irqs - move pending IRQs from LRs to the distributor
-  * @vgic_cpu: Pointer to the vgic_cpu struct holding the LRs
-@@ -622,13 +607,10 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
- 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
- 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
- 	int vcpu_id = vcpu->vcpu_id;
--	int i, irq, source_cpu;
--	u32 *lr;
-+	int i;
- 
- 	for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
--		lr = &vgic_cpu->vgic_lr[i];
--		irq = LR_IRQID(*lr);
--		source_cpu = LR_CPUID(*lr);
-+		struct vgic_lr lr = vgic_get_lr(vcpu, i);
- 
- 		/*
- 		 * There are three options for the state bits:
-@@ -640,7 +622,7 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
- 		 * If the LR holds only an active interrupt (not pending) then
- 		 * just leave it alone.
- 		 */
--		if ((*lr & GICH_LR_STATE) == GICH_LR_ACTIVE_BIT)
-+		if ((lr.state & LR_STATE_MASK) == LR_STATE_ACTIVE)
- 			continue;
- 
- 		/*
-@@ -649,18 +631,19 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
- 		 * is fine, then we are only setting a few bits that were
- 		 * already set.
- 		 */
--		vgic_dist_irq_set(vcpu, irq);
--		if (irq < VGIC_NR_SGIS)
--			dist->irq_sgi_sources[vcpu_id][irq] |= 1 << source_cpu;
--		*lr &= ~GICH_LR_PENDING_BIT;
-+		vgic_dist_irq_set(vcpu, lr.irq);
-+		if (lr.irq < VGIC_NR_SGIS)
-+			dist->irq_sgi_sources[vcpu_id][lr.irq] |= 1 << lr.source;
-+		lr.state &= ~LR_STATE_PENDING;
-+		vgic_set_lr(vcpu, i, lr);
- 
- 		/*
- 		 * If there's no state left on the LR (it could still be
- 		 * active), then the LR does not hold any useful info and can
- 		 * be marked as free for other use.
- 		 */
--		if (!(*lr & GICH_LR_STATE))
--			vgic_retire_lr(i, irq, vgic_cpu);
-+		if (!(lr.state & LR_STATE_MASK))
-+			vgic_retire_lr(i, lr.irq, vcpu);
- 
- 		/* Finally update the VGIC state. */
- 		vgic_update_state(vcpu->kvm);
-@@ -989,8 +972,73 @@ static void vgic_update_state(struct kvm *kvm)
- 	}
- }
- 
--#define MK_LR_PEND(src, irq)	\
--	(GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq))
-+static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr)
++static inline bool device_property_read_bool(struct device *dev,
++					     const char *propname)
 +{
-+	return vgic_ops->get_lr(vcpu, lr);
++	return device_property_present(dev, propname);
 +}
 +
-+static void vgic_set_lr(struct kvm_vcpu *vcpu, int lr,
-+			       struct vgic_lr vlr)
++static inline int device_property_read_u8(struct device *dev,
++					  const char *propname, u8 *val)
 +{
-+	vgic_ops->set_lr(vcpu, lr, vlr);
++	return device_property_read_u8_array(dev, propname, val, 1);
 +}
 +
-+static void vgic_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
-+			       struct vgic_lr vlr)
++static inline int device_property_read_u16(struct device *dev,
++					   const char *propname, u16 *val)
 +{
-+	vgic_ops->sync_lr_elrsr(vcpu, lr, vlr);
++	return device_property_read_u16_array(dev, propname, val, 1);
 +}
 +
-+static inline u64 vgic_get_elrsr(struct kvm_vcpu *vcpu)
++static inline int device_property_read_u32(struct device *dev,
++					   const char *propname, u32 *val)
 +{
-+	return vgic_ops->get_elrsr(vcpu);
++	return device_property_read_u32_array(dev, propname, val, 1);
 +}
 +
-+static inline u64 vgic_get_eisr(struct kvm_vcpu *vcpu)
++static inline int device_property_read_u64(struct device *dev,
++					   const char *propname, u64 *val)
 +{
-+	return vgic_ops->get_eisr(vcpu);
++	return device_property_read_u64_array(dev, propname, val, 1);
 +}
 +
-+static inline u32 vgic_get_interrupt_status(struct kvm_vcpu *vcpu)
++static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode,
++					     const char *propname)
 +{
-+	return vgic_ops->get_interrupt_status(vcpu);
++	return fwnode_property_present(fwnode, propname);
 +}
 +
-+static inline void vgic_enable_underflow(struct kvm_vcpu *vcpu)
++static inline int fwnode_property_read_u8(struct fwnode_handle *fwnode,
++					  const char *propname, u8 *val)
 +{
-+	vgic_ops->enable_underflow(vcpu);
++	return fwnode_property_read_u8_array(fwnode, propname, val, 1);
 +}
 +
-+static inline void vgic_disable_underflow(struct kvm_vcpu *vcpu)
++static inline int fwnode_property_read_u16(struct fwnode_handle *fwnode,
++					   const char *propname, u16 *val)
 +{
-+	vgic_ops->disable_underflow(vcpu);
++	return fwnode_property_read_u16_array(fwnode, propname, val, 1);
 +}
 +
-+static inline void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
++static inline int fwnode_property_read_u32(struct fwnode_handle *fwnode,
++					   const char *propname, u32 *val)
 +{
-+	vgic_ops->get_vmcr(vcpu, vmcr);
++	return fwnode_property_read_u32_array(fwnode, propname, val, 1);
 +}
 +
-+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
++static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
++					   const char *propname, u64 *val)
 +{
-+	vgic_ops->set_vmcr(vcpu, vmcr);
++	return fwnode_property_read_u64_array(fwnode, propname, val, 1);
 +}
 +
-+static inline void vgic_enable(struct kvm_vcpu *vcpu)
-+{
-+	vgic_ops->enable(vcpu);
-+}
++#endif /* _LINUX_PROPERTY_H_ */
+diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
+index 0f62326..2a47179 100644
+--- a/net/rfkill/rfkill-gpio.c
++++ b/net/rfkill/rfkill-gpio.c
+@@ -63,6 +63,15 @@ static const struct rfkill_ops rfkill_gpio_ops = {
+ 	.set_block = rfkill_gpio_set_power,
+ };
+ 
++static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
++static const struct acpi_gpio_params shutdown_gpios = { 1, 0, false };
 +
-+static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
-+{
-+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-+	struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr);
++static const struct acpi_gpio_mapping acpi_rfkill_default_gpios[] = {
++	{ "reset-gpios", &reset_gpios, 1 },
++	{ "shutdown-gpios", &shutdown_gpios, 1 },
++	{ },
++};
 +
-+	vlr.state = 0;
-+	vgic_set_lr(vcpu, lr_nr, vlr);
-+	clear_bit(lr_nr, vgic_cpu->lr_used);
-+	vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
-+}
- 
- /*
-  * An interrupt may have been disabled after being made pending on the
-@@ -1006,13 +1054,13 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
- 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
- 	int lr;
- 
--	for_each_set_bit(lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
--		int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
-+	for_each_set_bit(lr, vgic_cpu->lr_used, vgic->nr_lr) {
-+		struct vgic_lr vlr = vgic_get_lr(vcpu, lr);
- 
--		if (!vgic_irq_is_enabled(vcpu, irq)) {
--			vgic_retire_lr(lr, irq, vgic_cpu);
--			if (vgic_irq_is_active(vcpu, irq))
--				vgic_irq_clear_active(vcpu, irq);
-+		if (!vgic_irq_is_enabled(vcpu, vlr.irq)) {
-+			vgic_retire_lr(lr, vlr.irq, vcpu);
-+			if (vgic_irq_is_active(vcpu, vlr.irq))
-+				vgic_irq_clear_active(vcpu, vlr.irq);
- 		}
- 	}
- }
-@@ -1024,6 +1072,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
- static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
+ static int rfkill_gpio_acpi_probe(struct device *dev,
+ 				  struct rfkill_gpio_data *rfkill)
  {
- 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-+	struct vgic_lr vlr;
- 	int lr;
- 
- 	/* Sanitize the input... */
-@@ -1036,28 +1085,34 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
- 	lr = vgic_cpu->vgic_irq_lr_map[irq];
- 
- 	/* Do we have an active interrupt for the same CPUID? */
--	if (lr != LR_EMPTY &&
--	    (LR_CPUID(vgic_cpu->vgic_lr[lr]) == sgi_source_id)) {
--		kvm_debug("LR%d piggyback for IRQ%d %x\n",
--			  lr, irq, vgic_cpu->vgic_lr[lr]);
--		BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
--		vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
--		return true;
-+	if (lr != LR_EMPTY) {
-+		vlr = vgic_get_lr(vcpu, lr);
-+		if (vlr.source == sgi_source_id) {
-+			kvm_debug("LR%d piggyback for IRQ%d\n", lr, vlr.irq);
-+			BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
-+			vlr.state |= LR_STATE_PENDING;
-+			vgic_set_lr(vcpu, lr, vlr);
-+			return true;
-+		}
- 	}
+@@ -75,7 +84,8 @@ static int rfkill_gpio_acpi_probe(struct device *dev,
+ 	rfkill->name = dev_name(dev);
+ 	rfkill->type = (unsigned)id->driver_data;
  
- 	/* Try to use another LR for this interrupt */
- 	lr = find_first_zero_bit((unsigned long *)vgic_cpu->lr_used,
--			       vgic_cpu->nr_lr);
--	if (lr >= vgic_cpu->nr_lr)
-+			       vgic->nr_lr);
-+	if (lr >= vgic->nr_lr)
- 		return false;
- 
- 	kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id);
--	vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq);
- 	vgic_cpu->vgic_irq_lr_map[irq] = lr;
- 	set_bit(lr, vgic_cpu->lr_used);
- 
-+	vlr.irq = irq;
-+	vlr.source = sgi_source_id;
-+	vlr.state = LR_STATE_PENDING;
- 	if (!vgic_irq_is_edge(vcpu, irq))
--		vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
-+		vlr.state |= LR_EOI_INT;
-+
-+	vgic_set_lr(vcpu, lr, vlr);
- 
- 	return true;
+-	return 0;
++	return acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
++					 acpi_rfkill_default_gpios);
  }
-@@ -1155,9 +1210,9 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
- 
- epilog:
- 	if (overflow) {
--		vgic_cpu->vgic_hcr |= GICH_HCR_UIE;
-+		vgic_enable_underflow(vcpu);
- 	} else {
--		vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE;
-+		vgic_disable_underflow(vcpu);
- 		/*
- 		 * We're about to run this VCPU, and we've consumed
- 		 * everything the distributor had in store for
-@@ -1170,44 +1225,46 @@ epilog:
- 
- static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
- {
--	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-+	u32 status = vgic_get_interrupt_status(vcpu);
- 	bool level_pending = false;
  
--	kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr);
-+	kvm_debug("STATUS = %08x\n", status);
+ static int rfkill_gpio_probe(struct platform_device *pdev)
+@@ -102,7 +112,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
  
--	if (vgic_cpu->vgic_misr & GICH_MISR_EOI) {
-+	if (status & INT_STATUS_EOI) {
- 		/*
- 		 * Some level interrupts have been EOIed. Clear their
- 		 * active bit.
- 		 */
--		int lr, irq;
-+		u64 eisr = vgic_get_eisr(vcpu);
-+		unsigned long *eisr_ptr = (unsigned long *)&eisr;
-+		int lr;
- 
--		for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_eisr,
--				 vgic_cpu->nr_lr) {
--			irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
-+		for_each_set_bit(lr, eisr_ptr, vgic->nr_lr) {
-+			struct vgic_lr vlr = vgic_get_lr(vcpu, lr);
- 
--			vgic_irq_clear_active(vcpu, irq);
--			vgic_cpu->vgic_lr[lr] &= ~GICH_LR_EOI;
-+			vgic_irq_clear_active(vcpu, vlr.irq);
-+			WARN_ON(vlr.state & LR_STATE_MASK);
-+			vlr.state = 0;
-+			vgic_set_lr(vcpu, lr, vlr);
- 
- 			/* Any additional pending interrupt? */
--			if (vgic_dist_irq_is_pending(vcpu, irq)) {
--				vgic_cpu_irq_set(vcpu, irq);
-+			if (vgic_dist_irq_is_pending(vcpu, vlr.irq)) {
-+				vgic_cpu_irq_set(vcpu, vlr.irq);
- 				level_pending = true;
- 			} else {
--				vgic_cpu_irq_clear(vcpu, irq);
-+				vgic_cpu_irq_clear(vcpu, vlr.irq);
- 			}
- 
- 			/*
- 			 * Despite being EOIed, the LR may not have
- 			 * been marked as empty.
- 			 */
--			set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
--			vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
-+			vgic_sync_lr_elrsr(vcpu, lr, vlr);
- 		}
- 	}
- 
--	if (vgic_cpu->vgic_misr & GICH_MISR_U)
--		vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE;
-+	if (status & INT_STATUS_UNDERFLOW)
-+		vgic_disable_underflow(vcpu);
- 
- 	return level_pending;
- }
-@@ -1220,29 +1277,31 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
- {
- 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
- 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-+	u64 elrsr;
-+	unsigned long *elrsr_ptr;
- 	int lr, pending;
- 	bool level_pending;
- 
- 	level_pending = vgic_process_maintenance(vcpu);
-+	elrsr = vgic_get_elrsr(vcpu);
-+	elrsr_ptr = (unsigned long *)&elrsr;
- 
- 	/* Clear mappings for empty LRs */
--	for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr,
--			 vgic_cpu->nr_lr) {
--		int irq;
-+	for_each_set_bit(lr, elrsr_ptr, vgic->nr_lr) {
-+		struct vgic_lr vlr;
- 
- 		if (!test_and_clear_bit(lr, vgic_cpu->lr_used))
- 			continue;
- 
--		irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
-+		vlr = vgic_get_lr(vcpu, lr);
- 
--		BUG_ON(irq >= VGIC_NR_IRQS);
--		vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
-+		BUG_ON(vlr.irq >= VGIC_NR_IRQS);
-+		vgic_cpu->vgic_irq_lr_map[vlr.irq] = LR_EMPTY;
- 	}
- 
- 	/* Check if we still have something up our sleeve... */
--	pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_elrsr,
--				      vgic_cpu->nr_lr);
--	if (level_pending || pending < vgic_cpu->nr_lr)
-+	pending = find_first_zero_bit(elrsr_ptr, vgic->nr_lr);
-+	if (level_pending || pending < vgic->nr_lr)
- 		set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu);
- }
+ 	rfkill->clk = devm_clk_get(&pdev->dev, NULL);
  
-@@ -1432,21 +1491,20 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+-	gpio = devm_gpiod_get_index(&pdev->dev, "reset", 0);
++	gpio = devm_gpiod_get(&pdev->dev, "reset");
+ 	if (!IS_ERR(gpio)) {
+ 		ret = gpiod_direction_output(gpio, 0);
+ 		if (ret)
+@@ -110,7 +120,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
+ 		rfkill->reset_gpio = gpio;
  	}
  
- 	/*
--	 * By forcing VMCR to zero, the GIC will restore the binary
--	 * points to their reset values. Anything else resets to zero
--	 * anyway.
-+	 * Store the number of LRs per vcpu, so we don't have to go
-+	 * all the way to the distributor structure to find out. Only
-+	 * assembly code should use this one.
- 	 */
--	vgic_cpu->vgic_vmcr = 0;
-+	vgic_cpu->nr_lr = vgic->nr_lr;
- 
--	vgic_cpu->nr_lr = vgic_nr_lr;
--	vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */
-+	vgic_enable(vcpu);
+-	gpio = devm_gpiod_get_index(&pdev->dev, "shutdown", 1);
++	gpio = devm_gpiod_get(&pdev->dev, "shutdown");
+ 	if (!IS_ERR(gpio)) {
+ 		ret = gpiod_direction_output(gpio, 0);
+ 		if (ret)
+@@ -150,6 +160,8 @@ static int rfkill_gpio_remove(struct platform_device *pdev)
+ 	rfkill_unregister(rfkill->rfkill_dev);
+ 	rfkill_destroy(rfkill->rfkill_dev);
  
++	acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
++
  	return 0;
  }
  
- static void vgic_init_maintenance_interrupt(void *info)
- {
--	enable_percpu_irq(vgic_maint_irq, 0);
-+	enable_percpu_irq(vgic->maint_irq, 0);
- }
+diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
+index 22fa819..642dad4 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>
  
- static int vgic_cpu_notify(struct notifier_block *self,
-@@ -1459,7 +1517,7 @@ static int vgic_cpu_notify(struct notifier_block *self,
- 		break;
- 	case CPU_DYING:
- 	case CPU_DYING_FROZEN:
--		disable_percpu_irq(vgic_maint_irq);
-+		disable_percpu_irq(vgic->maint_irq);
- 		break;
- 	}
+ #include <clocksource/arm_arch_timer.h>
+ #include <asm/arch_timer.h>
++#include <asm/acpi.h>
  
-@@ -1470,30 +1528,37 @@ static struct notifier_block vgic_cpu_nb = {
- 	.notifier_call = vgic_cpu_notify,
+ #include <kvm/arm_vgic.h>
+ #include <kvm/arm_arch_timer.h>
+@@ -244,60 +246,91 @@ static const struct of_device_id arch_timer_of_match[] = {
+ 	{},
  };
  
-+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, },
-+	{},
-+};
-+
- int kvm_vgic_hyp_init(void)
+-int kvm_timer_hyp_init(void)
++static int kvm_timer_ppi_parse_dt(unsigned int *ppi)
  {
-+	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;
--	struct resource vctrl_res;
--	struct resource vcpu_res;
- 
--	vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic");
-+	vgic_node = of_find_matching_node_and_match(NULL,
-+						    vgic_ids, &matched_id);
- 	if (!vgic_node) {
--		kvm_err("error: no compatible vgic node in DT\n");
-+		kvm_err("error: no compatible GIC node found\n");
+ 	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;
  	}
  
--	vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0);
--	if (!vgic_maint_irq) {
--		kvm_err("error getting vgic maintenance irq from DT\n");
--		ret = -ENXIO;
+-	ppi = irq_of_parse_and_map(np, 2);
+-	if (!ppi) {
+-		kvm_err("kvm_arch_timer: no virtual timer interrupt\n");
+-		err = -EINVAL;
 -		goto out;
--	}
-+	vgic_probe = matched_id->data;
-+	ret = vgic_probe(vgic_node, &vgic_ops, &vgic);
-+	if (ret)
-+		return ret;
++	*ppi = irq_of_parse_and_map(np, 2);
++	if (*ppi == 0) {
++		of_node_put(np);
++		return -EINVAL;
+ 	}
  
--	ret = request_percpu_irq(vgic_maint_irq, vgic_maintenance_handler,
-+	ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
- 				 "vgic", kvm_get_running_vcpus());
- 	if (ret) {
--		kvm_err("Cannot register interrupt %d\n", vgic_maint_irq);
+-	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;
-+		kvm_err("Cannot register interrupt %d\n", vgic->maint_irq);
-+		return ret;
- 	}
+-	}
++	return 0;
++}
  
- 	ret = __register_cpu_notifier(&vgic_cpu_nb);
-@@ -1502,65 +1567,15 @@ int kvm_vgic_hyp_init(void)
- 		goto out_free_irq;
- 	}
+-	host_vtimer_irq = ppi;
++extern int arch_timer_ppi[];
  
--	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
--	if (ret) {
--		kvm_err("Cannot obtain VCTRL resource\n");
--		goto out_free_irq;
--	}
--
--	vgic_vctrl_base = of_iomap(vgic_node, 2);
--	if (!vgic_vctrl_base) {
--		kvm_err("Cannot ioremap VCTRL\n");
--		ret = -ENOMEM;
--		goto out_free_irq;
--	}
--
--	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 + resource_size(&vctrl_res),
--				     vctrl_res.start);
--	if (ret) {
--		kvm_err("Cannot map VCTRL into hyp\n");
--		goto out_unmap;
--	}
--
--	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
--		kvm_err("Cannot obtain VCPU resource\n");
--		ret = -ENXIO;
--		goto out_unmap;
--	}
--
--	if (!PAGE_ALIGNED(vcpu_res.start)) {
--		kvm_err("GICV physical address 0x%llx not page aligned\n",
--			(unsigned long long)vcpu_res.start);
--		ret = -ENXIO;
--		goto out_unmap;
+-	err = __register_cpu_notifier(&kvm_timer_cpu_nb);
+-	if (err) {
+-		kvm_err("Cannot register timer CPU notifier\n");
+-		goto out_free;
 -	}
--
--	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
--		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
--			(unsigned long long)resource_size(&vcpu_res),
--			PAGE_SIZE);
--		ret = -ENXIO;
--		goto out_unmap;
++static int kvm_timer_ppi_parse_acpi(unsigned int *ppi)
+ 
+-	wqueue = create_singlethread_workqueue("kvm_arch_timer");
+-	if (!wqueue) {
+-		err = -ENOMEM;
+-		goto out_free;
 -	}
--
--	vgic_vcpu_base = vcpu_res.start;
--
--	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
--		 vctrl_res.start, vgic_maint_irq);
- 	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
++{
++	/* retrieve VIRT_PPI info */
++	*ppi = arch_timer_ppi[2];
  
--	goto out;
-+	/* Callback into for arch code for setup */
-+	vgic_arch_setup(vgic);
+-	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;
++}
 +
-+	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);
  
--out_unmap:
--	iounmap(vgic_vctrl_base);
- out_free_irq:
--	free_percpu_irq(vgic_maint_irq, kvm_get_running_vcpus());
--out:
--	of_node_put(vgic_node);
-+	free_percpu_irq(vgic->maint_irq, kvm_get_running_vcpus());
- 	return ret;
+-	goto out;
++	/* if DT parsing fails, try ACPI next */
++	if (err && !acpi_disabled)
++		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;
  }
  
-@@ -1593,7 +1608,7 @@ int kvm_vgic_init(struct kvm *kvm)
- 	}
+ 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 2935405..510049c 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 @@
  
- 	ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
--				    vgic_vcpu_base, KVM_VGIC_V2_CPU_SIZE);
-+				    vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE);
- 	if (ret) {
- 		kvm_err("Unable to remap VGIC CPU to VCPU\n");
- 		goto out;
-@@ -1639,7 +1654,8 @@ int kvm_vgic_create(struct kvm *kvm)
- 	}
+ #include <linux/irqchip/arm-gic.h>
  
- 	spin_lock_init(&kvm->arch.vgic.lock);
--	kvm->arch.vgic.vctrl_base = vgic_vctrl_base;
-+	kvm->arch.vgic.in_kernel = true;
-+	kvm->arch.vgic.vctrl_base = vgic->vctrl_base;
- 	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
- 	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
++#include <asm/acpi.h>
+ #include <asm/kvm_emulate.h>
+ #include <asm/kvm_arm.h>
+ #include <asm/kvm_mmu.h>
+@@ -159,7 +161,7 @@ static const struct vgic_ops vgic_v2_ops = {
+ static struct vgic_params vgic_v2_params;
  
-@@ -1738,39 +1754,40 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
- static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu,
- 				 struct kvm_exit_mmio *mmio, phys_addr_t offset)
+ /**
+- * 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
+@@ -168,7 +170,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)
  {
--	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
--	u32 reg, mask = 0, shift = 0;
- 	bool updated = false;
-+	struct vgic_vmcr vmcr;
-+	u32 *vmcr_field;
-+	u32 reg;
-+
-+	vgic_get_vmcr(vcpu, &vmcr);
- 
- 	switch (offset & ~0x3) {
- 	case GIC_CPU_CTRL:
--		mask = GICH_VMCR_CTRL_MASK;
--		shift = GICH_VMCR_CTRL_SHIFT;
-+		vmcr_field = &vmcr.ctlr;
- 		break;
- 	case GIC_CPU_PRIMASK:
--		mask = GICH_VMCR_PRIMASK_MASK;
--		shift = GICH_VMCR_PRIMASK_SHIFT;
-+		vmcr_field = &vmcr.pmr;
- 		break;
- 	case GIC_CPU_BINPOINT:
--		mask = GICH_VMCR_BINPOINT_MASK;
--		shift = GICH_VMCR_BINPOINT_SHIFT;
-+		vmcr_field = &vmcr.bpr;
- 		break;
- 	case GIC_CPU_ALIAS_BINPOINT:
--		mask = GICH_VMCR_ALIAS_BINPOINT_MASK;
--		shift = GICH_VMCR_ALIAS_BINPOINT_SHIFT;
-+		vmcr_field = &vmcr.abpr;
- 		break;
-+	default:
-+		BUG();
+@@ -222,11 +224,22 @@ int vgic_v2_probe(struct device_node *vgic_node,
  	}
  
- 	if (!mmio->is_write) {
--		reg = (vgic_cpu->vgic_vmcr & mask) >> shift;
-+		reg = *vmcr_field;
- 		mmio_data_write(mmio, ~0, reg);
- 	} else {
- 		reg = mmio_data_read(mmio, ~0);
--		reg = (reg << shift) & mask;
--		if (reg != (vgic_cpu->vgic_vmcr & mask))
-+		if (reg != *vmcr_field) {
-+			*vmcr_field = reg;
-+			vgic_set_vmcr(vcpu, &vmcr);
- 			updated = true;
--		vgic_cpu->vgic_vmcr &= ~mask;
--		vgic_cpu->vgic_vmcr |= reg;
-+		}
+ 	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
++#if 0
+ 		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+ 			(unsigned long long)resource_size(&vcpu_res),
+ 			PAGE_SIZE);
+ 		ret = -ENXIO;
+ 		goto out_unmap;
++#else
++		/*
++		 * The check fails for arm64 with 64K pagesize and certain firmware.
++		 * Ignore for now until firmware takes care of the problem.
++		 */
++		kvm_info("GICV size 0x%llx not a multiple of page size 0x%lx\n",
++			(unsigned long long)resource_size(&vcpu_res),
++			PAGE_SIZE);
++		kvm_info("Update DT to assign GICV a multiple of kernel page size \n");
++#endif
  	}
- 	return updated;
+ 
+ 	vgic->vcpu_base = vcpu_res.start;
+@@ -245,3 +258,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 aacdb59..d972d63 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>
+@@ -2427,8 +2429,8 @@ 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, },
+ 	{},
+ };
+ 
+@@ -2438,20 +2440,26 @@ int kvm_vgic_hyp_init(void)
+ 	const 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) {
++		/* 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 4b5d28e..196a9b5 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -74,7 +74,7 @@ Summary: The Linux kernel
 %if 0%{?released_kernel}
 
 # Do we have a -stable update to apply?
-%define stable_update 6
+%define stable_update 7
 # Is it a -stable RC?
 %define stable_rc 0
 # Set rpm version accordingly
@@ -2291,6 +2291,9 @@ fi
 #                 ||----w |
 #                 ||     ||
 %changelog
+* Wed Feb 11 2015 Justin M. Forbes <jforbes at fedoraproject.org> - 3.18.7-100
+- Linux v3.18.7
+
 * Fri Feb 06 2015 Justin M. Forbes <jforbes at fedoraproject.org> - 3.18.6-100
 - Linux v3.18.6
 
diff --git a/sources b/sources
index 81f636a..31a89f1 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
 9e854df51ca3fef8bfe566dbd7b89241  linux-3.18.tar.xz
 813ccb96f0b379d656e57442c2587ca3  perf-man-3.18.tar.gz
-30aa769974e64fd17a01724d1577a913  patch-3.18.6.xz
+9db3178b87ddf7c05e6191bf57645610  patch-3.18.7.xz


More information about the scm-commits mailing list