diff options
-rw-r--r-- | config-arm64 | 5 | ||||
-rw-r--r-- | config-generic | 2 | ||||
-rw-r--r-- | config-x86-generic | 2 | ||||
-rw-r--r-- | kernel-arm64.patch | 9171 | ||||
-rw-r--r-- | kernel.spec | 11 |
5 files changed, 5697 insertions, 3494 deletions
diff --git a/config-arm64 b/config-arm64 index eac2b9acb..47174cd63 100644 --- a/config-arm64 +++ b/config-arm64 @@ -137,3 +137,8 @@ CONFIG_ACPI_CUSTOM_METHOD=m CONFIG_AMD_XGBE=m CONFIG_AMD_XGBE_PHY=m # CONFIG_AMD_XGBE_DCB is not set + +# CONFIG_IMX_THERMAL is not set + +# temporary 2014-10-21 +# CONFIG_BPF_JIT is not set diff --git a/config-generic b/config-generic index a0b1820a6..4f7848c00 100644 --- a/config-generic +++ b/config-generic @@ -5273,3 +5273,5 @@ CONFIG_FMC_CHARDEV=m # CONFIG_GLOB_SELFTEST is not set # CONFIG_SBSAUART_TTY is not set + +# CONFIG_SERIAL_8250_FINTEK is not set diff --git a/config-x86-generic b/config-x86-generic index 719f3e4b3..44f20161b 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -408,8 +408,6 @@ CONFIG_GPIO_ICH=m # CONFIG_TWL4030_CORE is not set # CONFIG_TWL6040_CORE is not set -# CONFIG_SERIAL_8250_FINTEK is not set - CONFIG_PCI_CNB20LE_QUIRK=y CONFIG_ACPI_EC_DEBUGFS=m diff --git a/kernel-arm64.patch b/kernel-arm64.patch index a05aa3383..0a0941da3 100644 --- a/kernel-arm64.patch +++ b/kernel-arm64.patch @@ -1,135 +1,62 @@ -commit 87257d3e584fad0b47e6304da54a1932f42b11bb +commit fb3aa1c1644a73bc36a47a6844c3ee6414787e9e Author: Mark Salter <msalter@redhat.com> -Date: Tue Sep 30 17:19:24 2014 -0400 +Date: Sun Oct 19 11:11:08 2014 -0400 - arm64: avoid need for console= to enable serial console + clocksource: arm_arch_timer: fix system hang - 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. + Arm allows for two possible architectural clock sources. One memory mapped + and the other coprocessor based. If both timers exist, then the driver waits + for both to be probed before registering a clocksource. - Signed-off-by: Mark Salter <msalter@redhat.com> - -commit 56db24589d311ea3590527030ede007ec339e2d7 -Author: Tom Lendacky <thomas.lendacky@amd.com> -Date: Tue Sep 9 23:33:17 2014 -0400 - - drivers: net: AMD Seattle XGBE PHY support for A0 silicon + Commit c387f07e6205 ("clocksource: arm_arch_timer: Discard unavailable timers + correctly") attempted to fix a hang occurring when one of the two possible + timers had a device node, but was disabled. In that case, the second probe + would never occur and the system would hang without a clocksource being + registered. - 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. + Unfortunately, incorrect logic in that commit made things worse such that + a hang would occur unless both timers had a device node and were enabled. + This patch fixes the logic so that we don't wait to probe a second timer + unless it exists and is enabled. Signed-off-by: Mark Salter <msalter@redhat.com> -commit 75554bb2e3c433a47e172d81a0b59df58810dc01 -Author: Tom Lendacky <thomas.lendacky@amd.com> -Date: Tue Sep 9 23:34:07 2014 -0400 - - drivers: net: AMD Seattle XGBE 10GbE support for A0 silicon - - 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. - - Signed-off-by: Mark Salter <msalter@redhat.com> - -commit 41cb1b3c9e62256b8a4e92c50cd51b2a68d0c9c6 -Author: Graeme Gregory <graeme.gregory@linaro.org> -Date: Fri Jul 26 17:55:02 2013 +0100 +commit 798bcf9c5057f0acd54154d09abf6fc4fc044e41 +Author: Mark Salter <msalter@redhat.com> +Date: Tue Oct 14 13:51:54 2014 -0400 - virtio-mmio: add ACPI probing + arm64: [NOT FOR UPSTREAM] fix dma_ops for ACPI and PCI devices - Added the match table and pointers for ACPI probing to the driver. + Commit 2189064795dc3fb4101e5: - Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> - -commit c06502fb4f00c6996c1f55cd342288508808c678 -Author: Graeme Gregory <graeme.gregory@linaro.org> -Date: Wed Jul 24 11:29:48 2013 +0100 - - net: smc91x: add ACPI probing support. - - Add device ID LINA0003 for this device and add the match table. + arm64: Implement set_arch_dma_coherent_ops() to replace bus notifiers - 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@linaro.org> - -commit aad559613ff05a13f940129675659297e7125979 -Author: Mark Salter <msalter@redhat.com> -Date: Tue Sep 23 12:48:48 2014 -0400 - - arm64/pci: add coherency inheritance for pci devices + 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@redhat.com> -commit 8d2a4226d96ccae17fbc0ef7d7d9c5a07ad8b31f +commit 4b7a879d4fe95e935a06bd5209026a2278251ce6 Author: Mark Salter <msalter@redhat.com> -Date: Tue Sep 23 12:35:17 2014 -0400 - - arm64/acpi: make acpi disabled by default - - Signed-off-by: Mark Salter <msalter@redhat.com> - -commit 0553f2b9fc94bfb0f9038003ad6f150cca196aad -Author: Wei Huang <wei@redhat.com> -Date: Thu Sep 18 20:32:03 2014 -0400 +Date: Thu Aug 14 12:32:13 2014 -0400 - KVM: fix VTTBR_BADDR_MASK - - The following is patch from AMD to fix VTTBR_BADDR_MASK. According to - AMD, this patch is required to enable KVM on Seattle. - - The current VTTBR_BADDR_MASK only masks 39 bits, which is broken on current - systems. Rather than just add a bit it seems like a good time to also set - things at run-time instead of compile time to accomodate more hardware. - - This patch sets TCR_EL2.PS, VTCR_EL2.T0SZ and vttbr_baddr_mask in runtime, - not compile time. - - In ARMv8, EL2 physical address size (TCR_EL2.PS) and stage2 input address - size (VTCR_EL2.T0SZE) cannot be determined in compile time since they - depend on hardware capability. - - According to Table D4-23 and Table D4-25 in ARM DDI 0487A.b document, - vttbr_x is calculated using different fixed values with consideration - of T0SZ, granule size and the level of translation tables. Therefore, - vttbr_baddr_mask should be determined dynamically. - - Changes since v5: - Fixed declaration of vttbr_baddr_mask to not create multiple instances - Refactored return codes based on feedback - For 32 bit included kvm_arm.h in kvm_mmu.h to explictly pick up - VTTBR_BADDR_MASK - - Changes since v4: - More minor cleanups from review - Moved some functions into headers - Added runtime check in kvm_alloc_stage2_pgd - - Changes since v3: - Another rebase - Addressed minor comments from v2 - - Changes since v2: - Rebased on https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next branch + acpi: add utility to test for device dma coherency - Changes since v1: - Rebased fix on Jungseok Lee's patch https://lkml.org/lkml/2014/5/12/189 to - provide better long term fix. Updated that patch to log error instead of - silently fail on unaligned vttbr. + 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. - Cc: Marc Zyngier <marc.zyngier@arm.com> - Cc: Christoffer Dall <christoffer.dall@linaro.org> - Cc: Sungjinn Chung <sungjinn.chung@samsung.com> - Signed-off-by: Jungseok Lee <jays.lee@samsung.com> - Signed-off-by: Joel Schopp <joel.schopp@amd.com> + 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: Wei Huang <wei@redhat.com> + Signed-off-by: Mark Salter <msalter@redhat.com> -commit f53d1278fe445b7130f1ff76b2f453b453368284 +commit 0e83bbc67aa2ced7b0f62bc9cdbf8026f3a83ea7 Author: Wei Huang <wei@redhat.com> Date: Thu Sep 18 20:02:57 2014 -0400 @@ -146,7 +73,7 @@ Date: Thu Sep 18 20:02:57 2014 -0400 Signed-off-by: Wei Huang <wei@redhat.com> -commit ba63e452ff5b09cc0314f94e163a51c3279b9ca7 +commit b01e346d3156935d05aada065b69dbd4e8e3c38e Author: Wei Huang <wei@redhat.com> Date: Thu Sep 18 20:02:56 2014 -0400 @@ -159,7 +86,7 @@ Date: Thu Sep 18 20:02:56 2014 -0400 Signed-off-by: Wei Huang <wei@redhat.com> -commit dd3f6094c2142786f40a3bc4d69c60b430ecc675 +commit 1f7fbdb23b3f616344bc6ab42d133528508b4183 Author: Wei Huang <wei@redhat.com> Date: Thu Sep 18 20:02:55 2014 -0400 @@ -176,143 +103,472 @@ Date: Thu Sep 18 20:02:55 2014 -0400 Signed-off-by: Wei Huang <wei@redhat.com> -commit cdfc19f1fbe88c1610db790ad55318d55ab00ee9 -Author: Mark Salter <msalter@redhat.com> -Date: Thu Sep 18 21:13:05 2014 -0400 +commit f1e1479c450a58b7fc68fec33c39b050dcc4b13d +Author: Al Stone <ahs3@redhat.com> +Date: Thu Sep 18 15:46:38 2014 -0600 - arm64/pci: fix dma coherency inheritance for PCI devices + DO NOT UPSTREAM -- patch to work around bad MAC of 0x0 - The default dma_ops for devices on arm64 systems are noncoherent in - nature and rely upon special operations and bounce buffers to - perform a device DMA operation to/from memory. Some drivers rely - upon coherent operations involving suitably capable hardware. In - this case, a "dma-coherent" property will exist on the corresponding - Device Tree node for the bridge device, or one of its ancestors. - This patch adds support for applying a DMA coherent dma_ops for - PCI devices in the case of such a property. + Signed-off-by: Al Stone <ahs3@redhat.com> + +commit b97981d8eaeef88d34b68d6bf6fae3088fce76f6 +Author: Tom Lendacky <thomas.lendacky@amd.com> +Date: Mon Sep 15 17:02:52 2014 -0600 + + amd-xgbe: AMD 10GbE driver APCI support for A0 - Signed-off-by: Mark Salter <msalter@redhat.com> + This patch provides ACPI support for the AMD 10GbE device driver + and AMD 10GbE phy driver. + + Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> -commit c8a62324eba5718fb43a94a168de7a81787aa94d +commit dd2c9edb72ff2e36152bae3bdf4f849b155c6178 Author: Mark Salter <msalter@redhat.com> -Date: Thu Sep 18 15:05:23 2014 -0400 +Date: Tue Oct 7 12:54:08 2014 -0400 - arm64: add sev to parking protocol + xgene acpi network - first cut + +commit 34f6f9c9a449fce5038a79ef74d85c0cd8aa983d +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:22:27 2014 +0200 + + misc: at25: Add ACPI probing support - 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. + Add support for matching using DT compatible string from ACPI _DSD. - Signed-off-by: Mark Salter <msalter@redhat.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> -commit e5f4ba1223515c46f1875597e77d5c32a37829ee -Author: Mark Salter <msalter@redhat.com> -Date: Sun Sep 14 09:44:44 2014 -0400 +commit a17b2b5016d76e752f706b5f6b04ffae8ec1728e +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:21:18 2014 +0200 - Revert "ahci_xgene: Skip the PHY and clock initialization if already configured by the firmware." + misc: at25: Make use of device property API - This reverts commit 0bed13bebd6c99d097796d2ca6c4f10fb5b2eabc. + Make use of device property API in this driver so that both DT and ACPI + based systems can use this driver. - Temporarily revert for backwards compatibility with rh-0.12-1 firmware + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> -commit aeff595a5d57264e5f01add5c43f584d88be6a92 -Author: Mark Salter <msalter@redhat.com> -Date: Mon Aug 11 13:46:43 2014 -0400 +commit 66442ae93d72f35bf046a6001403fdb89fbcfbdf +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:20:43 2014 +0200 - xgene: add support for ACPI-probed serial port + input: gpio_keys_polled - Add ACPI probing support + + Allow the driver to probe from ACPI namespace. + + Signed-off-by: Aaron Lu <aaron.lu@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 7f06c354929e2325f200de26e47189a13100647e +Author: Aaron Lu <aaron.lu@intel.com> +Date: Wed Oct 1 04:20:05 2014 +0200 + + input: gpio_keys_polled - Make use of device property API + + 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: Aaron Lu <aaron.lu@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 1fb6d8d9606826cf1dfdac8a75bc5e3f68e4d0de +Author: Aaron Lu <aaron.lu@intel.com> +Date: Wed Oct 1 04:17:46 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@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Acked-by: Alexandre Courbot <acourbot@nvidia.com> + Reviewed-by: Linus Walleij <linus.walleij@linaro.org> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 8cd8efd79a3f822db3ffc2f30f7646584b69d99f +Author: Max Eliaser <max@meliaserlow.dyndns.tv> +Date: Wed Oct 1 04:17:02 2014 +0200 + + leds: leds-gpio: Add ACPI probing support + + This allows the driver to probe from ACPI namespace. + + Signed-off-by: Max Eliaser <max.eliaser@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Acked-by: Bryan Wu <cooloney@gmail.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 14144259abecb65edd35b9d5e717688800628e27 +Author: Max Eliaser <max@meliaserlow.dyndns.tv> +Date: Wed Oct 1 04:16:25 2014 +0200 + + 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. + + Signed-off-by: Max Eliaser <max.eliaser@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 998f66211496063e464918fcdb4e40e99fcf2501 +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:15:41 2014 +0200 + + leds: leds-gpio: 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: Mika Westerberg <mika.westerberg@linux.intel.com> + Acked-by: Alexandre Courbot <acourbot@nvidia.com> + Acked-by: Bryan Wu <cooloney@gmail.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit ecf8d19a6019f60c567615c46bec6f4501c03c99 +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:15:01 2014 +0200 + + gpio: sch: Consolidate core and resume banks + + 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. + + 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@linux.intel.com> + Acked-by: Linus Walleij <linus.walleij@linaro.org> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit f87218916f4a9bcd2acdf8db1a4dbf8db5592036 +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:14:20 2014 +0200 -commit 02429d239f5ae917d870a7611a9d838b7822df1a + 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@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 2edae8da3e10c8b9d679637693e9d26a0cb9440f +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:12:41 2014 +0200 + + 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@linux.intel.com> + Acked-by: Linus Walleij <linus.walleij@linaro.org> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 01164a93badc2df11a1f1bfdf7d46e3253a0a6ec +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:11:20 2014 +0200 + + ACPI: Document ACPI device specific properties + + This document describes the data format and interfaces of ACPI device + specific properties. + + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Darren Hart <dvhart@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 1ea48df9784142befa0cdb6cb79f7fd405a7a103 +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:10:40 2014 +0200 + + ACPI: Allow drivers to match using Device Tree compatible property + + 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 there is a need to distinguish from where the device is enumerated + (DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev). + + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit f15380516841e837f8e20ed18c0039e052bb6187 +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Date: Wed Oct 1 04:10:03 2014 +0200 + + 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. + + Three general helper functions, device_get_property(), + device_read_property() and device_read_property_array() are provided. + The first one allows the raw value of a given device property to be + accessed. The remaining two allow the value of a numeric or string + property and multiple numeric or string values of one array + property to be acquired, respectively. Static inline wrappers are also + provided for the various property data types that can be passed to + device_read_property() or device_read_property_array() for extra type + checking. + + In addition to that, new generic routines are provided for retrieving + properties from device description objects in the platform firmware + in case a device driver needs/wants to access properties of a child + object of a given device object. There are cases in which there is + no struct device representation of such child objects and this + additional API is useful then. Again, three functions are provided, + device_get_child_property(), device_read_child_property(), + device_read_child_property_array(), in analogy with device_get_property(), + device_read_property() and device_read_property_array() described above, + respectively, along with static inline wrappers for all of the propery + data types that can be used. For all of them, the first argument is + a struct device pointer to the parent device object and the second + argument is a (void *) pointer to the child description provided by + the platform firmware (either ACPI or FDT). + + Finally, device_for_each_child_node() is added for iterating over + the children of the device description object associated with a + given device. + + 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@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit 6b0beaa05b29a299e62293fa4ea4dad0053f31b1 +Author: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Wed Oct 1 04:08:56 2014 +0200 + + 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>}, + ... + } + }) + + 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]. + + We add several helper functions that can be used to extract these + properties and convert them to different Linux data types. + + 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@linaro.org> + Reviewed-by: Josh Triplett <josh@joshtriplett.org> + Signed-off-by: Darren Hart <dvhart@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> + Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + +commit ca68950ecf22403e9d0cacdcd86fb4c245de6b9f Author: Mark Salter <msalter@redhat.com> -Date: Sat Aug 9 12:01:20 2014 -0400 +Date: Tue Sep 30 17:19:24 2014 -0400 - sata/xgene: support acpi probing + 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. Signed-off-by: Mark Salter <msalter@redhat.com> -commit 774385f250ebb7448ca3eeb344a064ac989c4988 -Author: Hanjun Guo <hanjun.guo@linaro.org> -Date: Thu Aug 28 14:26:16 2014 -0400 +commit 6194557254f1ed05638237a64f45f2ec08aa2523 +Author: Tom Lendacky <thomas.lendacky@amd.com> +Date: Tue Sep 9 23:33:17 2014 -0400 - ARM64 / ACPI: Introduce some PCI functions when PCI is enabled + drivers: net: AMD Seattle XGBE PHY support for A0 silicon - Introduce some PCI functions to make ACPI can be compiled when - CONFIG_PCI is enabled, these functions should be revisited when - implemented on ARM64. + 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. - Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> - [fixed up for 3.17-rc] Signed-off-by: Mark Salter <msalter@redhat.com> -commit 6f711c98b37f1b0a42c4a523d0380d47ed2f95b9 -Author: Al Stone <ahs3@redhat.com> -Date: Thu Aug 28 13:14:16 2014 -0400 +commit 0c9b242dd24b3ddf2e87209cb07c4bc7f5da21c4 +Author: Tom Lendacky <thomas.lendacky@amd.com> +Date: Tue Sep 9 23:34:07 2014 -0400 - Fix arm64 compilation error in PNP code + drivers: net: AMD Seattle XGBE 10GbE support for A0 silicon + + 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. Signed-off-by: Mark Salter <msalter@redhat.com> -commit f874873b7cb10f827bb7f8e08fa282878f740e77 -Author: Bob Moore <robert.moore@intel.com> -Date: Tue Sep 2 08:27:40 2014 +0800 +commit 7697f77962035de040c847f4c331eb91dc1c7c91 +Author: Graeme Gregory <graeme.gregory@linaro.org> +Date: Fri Jul 26 17:55:02 2013 +0100 - ACPICA: Update version to 20140828. + virtio-mmio: add ACPI probing - Version 20140828. + Added the match table and pointers for ACPI probing to the driver. - Signed-off-by: Bob Moore <robert.moore@intel.com> - Signed-off-by: Lv Zheng <lv.zheng@intel.com> + Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> -commit 26f9b7b90576cf808a50edf1ec86ceece9349c9f -Author: Bob Moore <robert.moore@intel.com> -Date: Tue Sep 2 08:27:27 2014 +0800 +commit 3025ec9f5711f2773be702464bf3150aa914bd66 +Author: Graeme Gregory <graeme.gregory@linaro.org> +Date: Wed Jul 24 11:29:48 2013 +0100 - ACPICA: Disassembler: Fix for gpio_int interrupt polarity flags. + net: smc91x: add ACPI probing support. - The field is actually 2 bits, not 1. + Add device ID LINA0003 for this device and add the match table. + + 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: Bob Moore <robert.moore@intel.com> - Signed-off-by: Lv Zheng <lv.zheng@intel.com> + Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> -commit 6e1eddc48f6f9b948be4126dd38841f6f70da080 -Author: Hanjun Guo <hanjun.guo@linaro.org> -Date: Tue Sep 2 08:27:19 2014 +0800 +commit a41a9bd6569e079f0572d4b106ffa95d2c16ad06 +Author: Mark Salter <msalter@redhat.com> +Date: Thu Sep 18 15:05:23 2014 -0400 - ACPICA: Headers: Add GTDT flag definitions for the timer subtable. + arm64: add sev to parking protocol - Mostly by Hanjun Guo <hanjun.guo@linaro.org> + 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. - Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> - Signed-off-by: Bob Moore <robert.moore@intel.com> - Signed-off-by: Lv Zheng <lv.zheng@intel.com> + Signed-off-by: Mark Salter <msalter@redhat.com> -commit 1091460efb5542ba87f40ef20daff44215587f26 -Author: Hanjun Guo <hanjun.guo@linaro.org> -Date: Tue Sep 2 08:27:12 2014 +0800 +commit 6e86c887dd05557830a38aa8fd93fab03a409b69 +Author: Mark Salter <msalter@redhat.com> +Date: Sun Sep 14 09:44:44 2014 -0400 - ACPICA: ACPI 5.1/Disassembler: Add GICC affinity subtable to SRAT table. - - Update template for SRAT. - Add clock_domain to standard CPU affinity subtable. + Revert "ahci_xgene: Skip the PHY and clock initialization if already configured by the firmware." - Mostly by Hanjun Guo <hanjun.guo@linaro.org> + This reverts commit 0bed13bebd6c99d097796d2ca6c4f10fb5b2eabc. - Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> - Signed-off-by: Bob Moore <robert.moore@intel.com> - Signed-off-by: Lv Zheng <lv.zheng@intel.com> + Temporarily revert for backwards compatibility with rh-0.12-1 firmware -commit 02ba5e067dbb83b0f481db821d05851e9623c401 -Author: Bob Moore <robert.moore@intel.com> -Date: Tue Sep 2 08:27:05 2014 +0800 +commit 81bcad4ccaf54357a6e3d51a135e07a67ce122ee +Author: Mark Salter <msalter@redhat.com> +Date: Mon Aug 11 13:46:43 2014 -0400 - ACPICA: Add _PSx names to the METHOD_NAME list. - - Will be used by iASL. + xgene: add support for ACPI-probed serial port + +commit d99f65d46bcc6a28262ff18506b0f2abd10d789e +Author: Mark Salter <msalter@redhat.com> +Date: Sat Aug 9 12:01:20 2014 -0400 + + sata/xgene: support acpi probing - Signed-off-by: Bob Moore <robert.moore@intel.com> - Signed-off-by: Lv Zheng <lv.zheng@intel.com> + Signed-off-by: Mark Salter <msalter@redhat.com> -commit f2ecef6608a1f74b236df4f93da9b7b5aba4d3fd +commit 977b4da81b8b80d02f54f2fc799fb292b22ade12 Author: Mark Salter <msalter@redhat.com> Date: Tue Sep 9 22:59:48 2014 -0400 @@ -328,7 +584,37 @@ Date: Tue Sep 9 22:59:48 2014 -0400 Signed-off-by: Mark Salter <msalter@redhat.com> -commit 63e220c94f072f10bfae2e1ed375af9dbc017571 +commit b0be9a425fd397fbed0b720a310e82d5d422f0da +Author: Mark Salter <msalter@redhat.com> +Date: Tue Sep 23 12:35:17 2014 -0400 + + arm64/acpi: make acpi disabled by default + + Signed-off-by: Mark Salter <msalter@redhat.com> + +commit 2dd589faf326c07b981093f73a9c7448ddf4afbf +Author: Hanjun Guo <hanjun.guo@linaro.org> +Date: Thu Aug 28 14:26:16 2014 -0400 + + ARM64 / ACPI: Introduce some PCI functions when PCI is enabled + + Introduce some PCI functions to make ACPI can be compiled when + CONFIG_PCI is enabled, these functions should be revisited when + implemented on ARM64. + + Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> + [fixed up for 3.17-rc] + Signed-off-by: Mark Salter <msalter@redhat.com> + +commit 1857c8d68b23fb57f6f6c64d09e3ce183244d399 +Author: Al Stone <ahs3@redhat.com> +Date: Thu Aug 28 13:14:16 2014 -0400 + + Fix arm64 compilation error in PNP code + + Signed-off-by: Mark Salter <msalter@redhat.com> + +commit 4529b4dbbaa8732c742300f3abe8db83e08670e8 Author: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Date: Tue Sep 9 15:37:15 2014 -0500 @@ -354,7 +640,7 @@ Date: Tue Sep 9 15:37:15 2014 -0500 Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> -commit d9d7224bd65fb3c1490f06d635b7aceb035acb1e +commit 2bf2a4a102bbe2abf7b2306e89d4d59fb7ade8d2 Author: Graeme Gregory <graeme.gregory@linaro.org> Date: Wed Aug 13 13:47:18 2014 +0100 @@ -369,37 +655,7 @@ Date: Wed Aug 13 13:47:18 2014 +0100 Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> -commit 4c67296fce53fed671a78b698d4552636f499b7f -Author: Mark Salter <msalter@redhat.com> -Date: Thu Aug 14 13:17:37 2014 -0400 - - arm64: set dma coherency ops for ACPI probed devices - - Search for a _CCA object and set the correct dma ops based - on device coherency attribute and architecture default. - - Signed-off-by: Mark Salter <msalter@redhat.com> - -commit 959c571815c440150b2f290bf3d13b2fbadbee70 -Author: Mark Salter <msalter@redhat.com> -Date: Thu Aug 14 12:32:13 2014 -0400 - - 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 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: Mark Salter <msalter@redhat.com> - -commit 0dbac48379d3aace2fd7468d83044116f176b4c9 +commit 5c62121c6de8268b06d563596953ce71d292733a Author: Mark Salter <msalter@redhat.com> Date: Mon Sep 8 11:58:46 2014 -0400 @@ -413,7 +669,7 @@ Date: Mon Sep 8 11:58:46 2014 -0400 Signed-off-by: Mark Salter <msalter@redhat.com> -commit c9eab819c2107e0c95cf57233de4de5404851ab6 +commit c4f70201c3e20f95c1a96929cf8e524a82dddf81 Author: Graeme Gregory <graeme.gregory@linaro.org> Date: Mon Sep 8 10:36:44 2014 -0400 @@ -425,7 +681,7 @@ Date: Mon Sep 8 10:36:44 2014 -0400 Signed-off-by: Al Stone <al.stone@linaro.org> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> -commit 7e772a485f980b826a58ecd9c39fbe82085c55fa +commit e632bb50e732757dd8ac56f94785b86c300585ba Author: Mark Salter <msalter@redhat.com> Date: Mon Sep 8 17:04:28 2014 -0400 @@ -437,7 +693,7 @@ Date: Mon Sep 8 17:04:28 2014 -0400 Signed-off-by: Mark Salter <msalter@redhat.com> -commit b42e8f7901e58b86a1cb3ffdf14cb2455fd91ede +commit 51ba60203fe3cb844f1b56389dc840ecf0264817 Author: Graeme Gregory <graeme.gregory@linaro.org> Date: Fri Sep 12 22:00:16 2014 +0800 @@ -449,7 +705,7 @@ Date: Fri Sep 12 22:00:16 2014 +0800 Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 57dc75b87d5663181e1c19802297e72e51a324ba +commit 49c2936aebfdc0d6fb6f8a2ed85295e4370afac7 Author: Graeme Gregory <graeme.gregory@linaro.org> Date: Fri Sep 12 22:00:15 2014 +0800 @@ -465,7 +721,7 @@ Date: Fri Sep 12 22:00:15 2014 +0800 Signed-off-by: Al Stone <al.stone@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 106c5cb3caff13c91cb6056f88a1c0e710b8e0eb +commit 4a1bcc17290231af1cfbef33aa6ec77aca609389 Author: Al Stone <al.stone@linaro.org> Date: Fri Sep 12 22:00:14 2014 +0800 @@ -479,7 +735,7 @@ Date: Fri Sep 12 22:00:14 2014 +0800 Signed-off-by: Al Stone <al.stone@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 73f4aca21985ace8989b6fc8af503940c469f1d7 +commit 2863c8dd559eaa85dbec982045ae8201bdd0216e Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:13 2014 +0800 @@ -491,7 +747,7 @@ Date: Fri Sep 12 22:00:13 2014 +0800 Originally-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 5efba15fb24c25139dd621a417f2b9cbe2e675f5 +commit 75398d7dfd0a9bb67c70568bbc49e79d43681516 Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> Date: Fri Sep 12 22:00:12 2014 +0800 @@ -509,7 +765,7 @@ Date: Fri Sep 12 22:00:12 2014 +0800 Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit e060d9d74cecff59ea96d6124ffb1c9c044a4f9d +commit 325e4412a370d58213bd1cd9de5a5f104dd2bab4 Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:11 2014 +0800 @@ -525,7 +781,7 @@ Date: Fri Sep 12 22:00:11 2014 +0800 Originally-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit c25e8f66c630713107967076933b5f349655ea6a +commit 4537275d3b1611bb1102eadfce56af2d36d1c25b Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:10 2014 +0800 @@ -539,7 +795,7 @@ Date: Fri Sep 12 22:00:10 2014 +0800 Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 5ce1c3ff91aa9d8012324518789363bb4ded33d4 +commit 5ae8a2bbb06f1833c6494fc7a5f30931cc4b5d9a Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:09 2014 +0800 @@ -558,7 +814,7 @@ Date: Fri Sep 12 22:00:09 2014 +0800 Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> -commit 8634cf0fcc8294c355d7cecb55da017ba9ff3ff7 +commit 4a3aed9caf1780e72030a7efc32d28a32d3ed603 Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:08 2014 +0800 @@ -570,7 +826,7 @@ Date: Fri Sep 12 22:00:08 2014 +0800 Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> -commit 05facef9c824235c82d8d9c2ae03fe7a729ceef8 +commit d9f88c9f5385ac2ae7c87ca0ee63e8e77a37ca09 Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:07 2014 +0800 @@ -599,7 +855,7 @@ Date: Fri Sep 12 22:00:07 2014 +0800 Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> -commit a13a8c748b6170a8a3f4876163ff74e460bd889f +commit f5b32d09a98c2d5353915d2bcc3d7fa3151b6890 Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 22:00:06 2014 +0800 @@ -614,7 +870,7 @@ Date: Fri Sep 12 22:00:06 2014 +0800 Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit a6bf98355490142fc3f6e9c0839af128e326f16d +commit 445abae9b9e86d9bd81b3cbffc5d20e8cb375ab0 Author: Graeme Gregory <graeme.gregory@linaro.org> Date: Fri Sep 12 22:00:05 2014 +0800 @@ -627,7 +883,7 @@ Date: Fri Sep 12 22:00:05 2014 +0800 Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit e3b9886532d1e13ddb68e4955ad776a8623f9766 +commit fad554282770ff7d0a0b002bb2c3d289ad5cc187 Author: Al Stone <al.stone@linaro.org> Date: Fri Sep 12 22:00:04 2014 +0800 @@ -643,7 +899,7 @@ Date: Fri Sep 12 22:00:04 2014 +0800 Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit cf1cbe39385d417286a98e3abd7ea3456be2e88c +commit ed545c4a15e82373747e2ca4dd44c313a5cbfdbc Author: Graeme Gregory <graeme.gregory@linaro.org> Date: Fri Sep 12 22:00:03 2014 +0800 @@ -658,7 +914,7 @@ Date: Fri Sep 12 22:00:03 2014 +0800 Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 90e5cfbaf183d0eb92f1977c24da20c4e0a2f6be +commit f6b5641dd6b5bf915ee9c18bb0f44f07b858bfc2 Author: Al Stone <al.stone@linaro.org> Date: Fri Sep 12 22:00:02 2014 +0800 @@ -690,7 +946,7 @@ Date: Fri Sep 12 22:00:02 2014 +0800 Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 2fe5d24887dea3f1bffabf04e364fa9f355ed553 +commit 7a5a04722c2527962e4b1ebc979e185a64ed11b4 Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> Date: Fri Sep 12 22:00:01 2014 +0800 @@ -708,7 +964,7 @@ Date: Fri Sep 12 22:00:01 2014 +0800 Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 8c278c76231f0ba0110e755678eefdd6d077f5da +commit 80eb7126770fd6b5c595e4733fb3194bda75f25b Author: Ashwin Chaugule <ashwin.chaugule@linaro.org> Date: Fri Sep 12 22:00:00 2014 +0800 @@ -725,7 +981,7 @@ Date: Fri Sep 12 22:00:00 2014 +0800 Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit 651ab5ff6804fa0f516715b4d47399e587944de0 +commit 36633ceecab0b57354030ba4e796c3eccb0084a8 Author: Hanjun Guo <hanjun.guo@linaro.org> Date: Fri Sep 12 21:59:59 2014 +0800 @@ -737,312 +993,7 @@ Date: Fri Sep 12 21:59:59 2014 +0800 Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> -commit b91246f1a7120de6de8fe630ed01e9a0d0415e88 -Author: Tanmay Inamdar <tinamdar@apm.com> -Date: Fri Sep 26 14:08:27 2014 -0700 - - MAINTAINERS: entry for APM X-Gene PCIe host driver - - Add entry for AppliedMicro X-Gene PCIe host driver. - - Signed-off-by: Tanmay Inamdar <tinamdar@apm.com> - -commit d20b104083718058b599a5ca1a925d8c5243e2e1 -Author: Tanmay Inamdar <tinamdar@apm.com> -Date: Fri Sep 26 14:08:26 2014 -0700 - - dt-bindings: pci: xgene pcie device tree bindings - - This patch adds the bindings for X-Gene PCIe driver. The driver resides - under 'drivers/pci/host/pci-xgene.c' file. - - Signed-off-by: Tanmay Inamdar <tinamdar@apm.com> - -commit 9c429c919b77a3a63ac2843e9e0e2e50e59d28f3 -Author: Tanmay Inamdar <tinamdar@apm.com> -Date: Fri Sep 26 14:08:25 2014 -0700 - - arm64: dts: APM X-Gene PCIe device tree nodes - - This patch adds the device tree nodes for APM X-Gene PCIe host controller and - PCIe clock interface. Since X-Gene SOC supports maximum 5 ports, 5 dts - nodes are added. - - Signed-off-by: Tanmay Inamdar <tinamdar@apm.com> - -commit 3aa4f71932b67e648aff4ae0dc5ace7162d74c1c -Author: Tanmay Inamdar <tinamdar@apm.com> -Date: Fri Sep 26 14:08:24 2014 -0700 - - pci:host: APM X-Gene PCIe host controller driver - - This patch adds the AppliedMicro X-Gene SOC PCIe host controller driver. - X-Gene PCIe controller supports maximum up to 8 lanes and GEN3 speed. - X-Gene SOC supports maximum 5 PCIe ports. - - Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com> - Tested-by: Ming Lei <ming.lei@canonical.com> - Tested-by: Dann Frazier <dann.frazier@canonical.com> - Signed-off-by: Tanmay Inamdar <tinamdar@apm.com> - -commit f3c00bd4ae49b19923049f0f4f9d6a95eaa61b1e -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:14 2014 +0100 - - arm64: Add architectural support for PCI - - Use the generic PCI domain and OF functions to provide support for PCI - on arm64. - - [bhelgaas: Change comments to use generic PCI, not just PCIe. Nothing at - this level is PCIe-specific.] - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Acked-by: Catalin Marinas <catalin.marinas@arm.com> - -commit 497220defa08534526ad7b20a9c7eb2d0d903ca4 -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:13 2014 +0100 - - PCI: Add pci_remap_iospace() to map bus I/O resources - - Add pci_remap_iospace() to map bus I/O resources into the CPU virtual - address space. Architectures with special needs may provide their own - version, but most should be able to use this one. - - This function is useful for PCI host bridge drivers that need to map the - PCI I/O resources into virtual memory space. - - [bhelgaas: phys_addr description, drop temporary "err" variable] - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Reviewed-by: Rob Herring <robh@kernel.org> - Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> - CC: Arnd Bergmann <arnd@arndb.de> - -commit 7a46ace11cf09b3713dcdc2ef4a17130a738f856 -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:12 2014 +0100 - - PCI: Assign unassigned bus resources in pci_scan_root_bus() - - If the firmware has not assigned all the bus resources and we are not just - probing the PCI buses, it makes sense to assign the unassigned resources - in pci_scan_root_bus(). - - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - CC: Arnd Bergmann <arnd@arndb.de> - CC: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - CC: Rob Herring <robh+dt@kernel.org> - -commit fe33bc876010c3ef700c863099f2c3c1a5e2c18b -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Wed Sep 24 11:27:33 2014 -0600 - - of/pci: Add support for parsing PCI host bridge resources from DT - - Provide a function to parse the PCI DT ranges that can be used to create a - pci_host_bridge structure together with its associated bus. - - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - [make io_base parameter optional] - Signed-off-by: Robert Richter <rrichter@cavium.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - CC: Arnd Bergmann <arnd@arndb.de> - CC: Grant Likely <grant.likely@linaro.org> - CC: Rob Herring <robh+dt@kernel.org> - CC: Catalin Marinas <catalin.marinas@arm.com> - -commit 71094afda69ac873bb3d6486307e3048e21e912c -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:10 2014 +0100 - - of/pci: Add of_pci_get_domain_nr() and of_get_pci_domain_nr() - - Add pci_get_new_domain_nr() to allocate a new domain number and - of_get_pci_domain_nr() to retrieve the PCI domain number of a given device - from DT. Host bridge drivers or architecture-specific code can choose to - implement their PCI domain number policy using these two functions. - - Using of_get_pci_domain_nr() guarantees a stable PCI domain number on every - boot provided that all host bridge controllers are assigned a number in the - device tree using "linux,pci-domain" property. Mixing use of - pci_get_new_domain_nr() and of_get_pci_domain_nr() is not recommended as it - can lead to potentially conflicting domain numbers being assigned to root - buses behind different host bridges. - - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - CC: Arnd Bergmann <arnd@arndb.de> - CC: Grant Likely <grant.likely@linaro.org> - CC: Rob Herring <robh+dt@kernel.org> - CC: Catalin Marinas <catalin.marinas@arm.com> - -commit 6b385455f18d15da6b5d60a3b67fdb846ae1a3b1 -Author: Catalin Marinas <catalin.marinas@arm.com> -Date: Tue Sep 23 20:01:09 2014 +0100 - - PCI: Add generic domain handling - - The handling of PCI domains (or PCI segments in ACPI speak) is usually a - straightforward affair but its implementation is currently left to the - architectural code, with pci_domain_nr(b) querying the value of the domain - associated with bus b. - - This patch introduces CONFIG_PCI_DOMAINS_GENERIC as an option that can be - selected if an architecture wants a simple implementation where the value - of the domain associated with a bus is stored in struct pci_bus. - - The architectures that select CONFIG_PCI_DOMAINS_GENERIC will then have to - implement pci_bus_assign_domain_nr() as a way of setting the domain number - associated with a root bus. All child buses except the root bus will - inherit the domain_nr value from their parent. - - Signed-off-by: Catalin Marinas <Catalin.Marinas@arm.com> - [Renamed pci_set_domain_nr() to pci_bus_assign_domain_nr()] - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - CC: Arnd Bergmann <arnd@arndb.de> - -commit 04b36e0e1da5a96a58dec4f1b393090f00e5b635 -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:08 2014 +0100 - - PCI: Create pci_host_bridge before root bus - - Before 7b5436635800 ("PCI: add generic device into pci_host_bridge - struct"), the pci_host_bridge was created before the root bus. 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. - - [bhelgaas: changelog] - Tested-by: Tanmay Inamdar <tinamdar@apm.com> - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> - Acked-by: Grant Likely <grant.likely@linaro.org> - -commit 7569c510218798bd7e5216bf14a42c656f14e891 -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:07 2014 +0100 - - of/pci: Fix the conversion of IO ranges into IO resources - - 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, - returning a CPU physical address instead of a port number. - - Also fix all the drivers that depend on the old behaviour by fetching the - CPU physical address based on the port number where it is being needed. - - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Acked-by: Linus Walleij <linus.walleij@linaro.org> - CC: Grant Likely <grant.likely@linaro.org> - CC: Rob Herring <robh+dt@kernel.org> - CC: Arnd Bergmann <arnd@arndb.de> - CC: Thierry Reding <thierry.reding@gmail.com> - CC: Simon Horman <horms@verge.net.au> - CC: Catalin Marinas <catalin.marinas@arm.com> - -commit 1b381671c9dd2c82cd6f04bc1588d0fc4e1aea59 -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:06 2014 +0100 - - of/pci: Move of_pci_range_to_resources() to of/address.c - - We need to enhance of_pci_range_to_resources() enough that it won't make - sense for it to be inline anymore. Move it to drivers/of/address.c, - keeping it under #ifdef CONFIG_PCI. - - [bhelgaas: drop extra detail from changelog, move def under CONFIG_PCI] - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - CC: Grant Likely <grant.likely@linaro.org> - CC: Rob Herring <robh+dt@kernel.org> - CC: Arnd Bergmann <arnd@arndb.de> - CC: Catalin Marinas <catalin.marinas@arm.com> - -commit eedd8f88d4895d5c6bc46cf3ddeb114a0fafb7c3 -Author: Bjorn Helgaas <bhelgaas@google.com> -Date: Tue Sep 23 17:27:42 2014 -0600 - - of/pci: Define of_pci_range_to_resource() only when CONFIG_PCI=y - - of_pci_range_to_resource() was previously defined always, but it's only - used by PCI code, so move the definition inside the CONFIG_OF_ADDRESS && - CONFIG_PCI block. - - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - -commit 4ac73f8ded507537318717bb2b5b6c765db633cd -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:05 2014 +0100 - - ARM: Define PCI_IOBASE as the base of virtual PCI IO space - - This is needed for calls into OF code that parses PCI ranges. It signals - support for memory mapped PCI I/O accesses that are described by device - trees. - - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> - Acked-by: Arnd Bergmann <arnd@arndb.de> - CC: Russell King <linux@arm.linux.org.uk> - CC: Rob Herring <robh+dt@kernel.org> - -commit ce7af33b6db857c95ac3b65fef37e589e839cc79 -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:04 2014 +0100 - - of/pci: Add pci_register_io_range() and pci_pio_to_address() - - 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. - - This patch introduces 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. - - In order to retrieve the CPU address associated with an I/O port, a new - helper function pci_pio_to_address() is introduced. This will search in - the list of ranges registered with pci_register_io_range() and return the - CPU address that corresponds to the given port. - - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> - Acked-by: Rob Herring <robh@kernel.org> - CC: Grant Likely <grant.likely@linaro.org> - CC: Arnd Bergmann <arnd@arndb.de> - -commit c5d57f95901af49149ebf6dfc3d7518157e41bfa -Author: Liviu Dudau <Liviu.Dudau@arm.com> -Date: Tue Sep 23 20:01:03 2014 +0100 - - asm-generic/io.h: Fix ioport_map() for !CONFIG_GENERIC_IOMAP - - The !CONFIG_GENERIC_IOMAP version of ioport_map() 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. - - Tested-by: Tanmay Inamdar <tinamdar@apm.com> - Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com> - Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> - Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> - Acked-by: Arnd Bergmann <arnd@arndb.de> - -commit a65e51156bec2c8d690b924bbddf1a740309e543 +commit 1029a72c660016d7b566f9b91156068f4a86ccb7 Author: Mark Salter <msalter@redhat.com> Date: Tue Jun 24 09:50:28 2014 -0400 @@ -1054,92 +1005,7 @@ Date: Tue Jun 24 09:50:28 2014 -0400 Signed-off-by: Mark Salter <msalter@redhat.com> -commit c6b81122978c39e52021cc7308edafff88c8b87a -Author: Ard Biesheuvel <ard.biesheuvel@linaro.org> -Date: Wed Jul 30 11:59:04 2014 +0100 - - arm64/efi: efistub: don't abort if base of DRAM is occupied - - 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. - - Acked-by: Mark Salter <msalter@redhat.com> - Acked-by: Mark Rutland <mark.rutland@arm.com> - Acked-by: Leif Lindholm <leif.lindholm@linaro.org> - Tested-by: Leif Lindholm <leif.lindholm@linaro.org> - Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> - Signed-off-by: Will Deacon <will.deacon@arm.com> - -commit 81fd1d315f3c5b13f9dcf71cce51dfd3a10331c3 -Author: Ard Biesheuvel <ard.biesheuvel@linaro.org> -Date: Wed Jul 30 11:59:03 2014 +0100 - - 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. - - 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. - - 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. - - Acked-by: Mark Salter <msalter@redhat.com> - Acked-by: Mark Rutland <mark.rutland@arm.com> - Acked-by: Leif Lindholm <leif.lindholm@linaro.org> - Tested-by: Leif Lindholm <leif.lindholm@linaro.org> - Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> - Signed-off-by: Will Deacon <will.deacon@arm.com> - -commit 8f5f73c2117c2dc4e8903d162023c34177327ae3 -Author: Mark Rutland <mark.rutland@arm.com> -Date: Wed Jul 30 11:59:02 2014 +0100 - - arm64: spin-table: handle unmapped cpu-release-addrs - - 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. - - 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. - - Acked-by: Leif Lindholm <leif.lindholm@linaro.org> - Tested-by: Leif Lindholm <leif.lindholm@linaro.org> - Tested-by: Mark Salter <msalter@redhat.com> - Signed-off-by: Mark Rutland <mark.rutland@arm.com> - [ardb: added (__force void *) cast] - Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> - Signed-off-by: Will Deacon <will.deacon@arm.com> - -commit b00c56bff1ffb6c77655479fb350ee3d5c8bcf63 -Author: Mark Salter <msalter@redhat.com> -Date: Tue Jun 24 23:16:45 2014 -0400 - - perf: fix arm64 build error - - I'm seeing the following build error 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]; - ^ - - This patch adds a PEFF_REGS_MAX definition for arm64. - - Signed-off-by: Mark Salter <msalter@redhat.com> - -commit f440dcb067bf1367719e8a41b96a2a83c1232690 +commit 0fdae79847bdc64aee1a765c0bb5ee99ed95eb0e Author: Mark Salter <msalter@redhat.com> Date: Thu Jul 17 13:34:50 2014 -0400 @@ -1157,7 +1023,7 @@ Date: Thu Jul 17 13:34:50 2014 -0400 Signed-off-by: Mark Salter <msalter@redhat.com> -commit 93b44dc9e1d73d4864a9350888509792f25e4210 +commit 6e00476b0a33370988b3fee8551c0a8d98206bd2 Author: Kyle McMartin <kmcmarti@redhat.com> Date: Tue May 13 22:25:26 2014 -0400 @@ -1227,109 +1093,513 @@ Date: Tue May 13 22:25:26 2014 -0400 Signed-off-by: Kyle McMartin <kmcmarti@redhat.com> Signed-off-by: Donald Dutile <ddutile@redhat.com> - Documentation/arm64/arm-acpi.txt | 218 +++++++ - .../devicetree/bindings/pci/xgene-pci.txt | 57 ++ - Documentation/kernel-parameters.txt | 3 +- - MAINTAINERS | 8 + - arch/arm/include/asm/io.h | 1 + - arch/arm/include/asm/kvm_mmu.h | 13 + - arch/arm/kvm/arm.c | 23 +- - arch/arm/mach-integrator/pci_v3.c | 23 +- - arch/arm64/Kconfig | 28 +- - arch/arm64/Makefile | 1 + - arch/arm64/boot/dts/apm-mustang.dts | 8 + - arch/arm64/boot/dts/apm-storm.dtsi | 165 ++++++ - arch/arm64/include/asm/Kbuild | 1 + - arch/arm64/include/asm/acenv.h | 18 + - arch/arm64/include/asm/acpi.h | 99 ++++ - arch/arm64/include/asm/cpu_ops.h | 1 + - arch/arm64/include/asm/elf.h | 3 +- - arch/arm64/include/asm/io.h | 3 +- - arch/arm64/include/asm/kvm_arm.h | 17 +- - arch/arm64/include/asm/kvm_mmu.h | 75 +++ - arch/arm64/include/asm/pci.h | 37 ++ - arch/arm64/include/asm/pgtable.h | 2 + - arch/arm64/include/asm/psci.h | 3 +- - arch/arm64/include/asm/smp.h | 10 +- - arch/arm64/kernel/Makefile | 5 +- - arch/arm64/kernel/acpi.c | 397 +++++++++++++ - arch/arm64/kernel/cpu_ops.c | 8 +- - arch/arm64/kernel/efi-stub.c | 16 +- - arch/arm64/kernel/efi.c | 11 + - arch/arm64/kernel/head.S | 6 +- - arch/arm64/kernel/pci.c | 70 +++ - arch/arm64/kernel/process.c | 6 + - arch/arm64/kernel/psci.c | 78 ++- - arch/arm64/kernel/setup.c | 64 +- - arch/arm64/kernel/smp.c | 2 +- - arch/arm64/kernel/smp_parking_protocol.c | 110 ++++ - arch/arm64/kernel/smp_spin_table.c | 22 +- - arch/arm64/kernel/time.c | 7 + - arch/arm64/kvm/hyp-init.S | 20 +- - arch/arm64/mm/dma-mapping.c | 65 ++ - arch/arm64/pci/Makefile | 1 + - arch/arm64/pci/pci.c | 28 + - drivers/acpi/Kconfig | 6 +- - drivers/acpi/Makefile | 6 +- - drivers/acpi/acpica/utresrc.c | 4 +- - drivers/acpi/bus.c | 3 + - drivers/acpi/internal.h | 5 + - drivers/acpi/osl.c | 6 +- - drivers/acpi/processor_core.c | 37 ++ - drivers/acpi/sleep-arm.c | 28 + - drivers/acpi/tables.c | 115 +++- - drivers/acpi/utils.c | 26 + - drivers/ata/Kconfig | 2 +- - drivers/ata/ahci_platform.c | 13 + - drivers/ata/ahci_xgene.c | 30 +- - drivers/clocksource/arm_arch_timer.c | 120 +++- - drivers/irqchip/irq-gic-v3.c | 10 + - drivers/irqchip/irq-gic.c | 116 ++++ - drivers/irqchip/irqchip.c | 3 + - drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 12 + - drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 3 + - drivers/net/ethernet/amd/xgbe/xgbe-main.c | 1 + - drivers/net/ethernet/amd/xgbe/xgbe.h | 3 + - drivers/net/ethernet/smsc/smc91x.c | 10 + - drivers/net/phy/amd-xgbe-phy.c | 408 +++++++------ - drivers/of/address.c | 154 +++++ - drivers/of/of_pci.c | 142 +++++ - drivers/pci/host/Kconfig | 10 + - drivers/pci/host/Makefile | 1 + - drivers/pci/host/pci-tegra.c | 10 +- - drivers/pci/host/pci-xgene.c | 659 +++++++++++++++++++++ - drivers/pci/host/pcie-rcar.c | 21 +- - drivers/pci/pci.c | 40 ++ - drivers/pci/probe.c | 46 +- - drivers/pnp/resource.c | 2 + - drivers/tty/Kconfig | 6 + - drivers/tty/Makefile | 1 + - drivers/tty/sbsauart.c | 355 +++++++++++ - drivers/tty/serial/8250/8250_dw.c | 9 + - drivers/virtio/virtio_mmio.c | 12 +- - include/acpi/acnames.h | 4 + - include/acpi/acpi_bus.h | 2 + - include/acpi/acpi_io.h | 6 + - include/acpi/acpixf.h | 2 +- - include/acpi/actbl1.h | 19 +- - include/acpi/actbl3.h | 9 +- - include/asm-generic/io.h | 2 +- - include/asm-generic/pgtable.h | 4 + - include/kvm/arm_vgic.h | 20 +- - include/linux/acpi.h | 5 + - include/linux/clocksource.h | 6 + - include/linux/irqchip/arm-gic-acpi.h | 31 + - include/linux/irqchip/arm-gic.h | 2 + - include/linux/of_address.h | 17 +- - include/linux/of_pci.h | 13 + - include/linux/pci.h | 64 +- - tools/perf/arch/arm64/include/perf_regs.h | 2 + - virt/kvm/arm/arch_timer.c | 108 ++-- - virt/kvm/arm/vgic-v2.c | 75 ++- - virt/kvm/arm/vgic-v3.c | 8 +- - virt/kvm/arm/vgic.c | 32 +- - 101 files changed, 4112 insertions(+), 487 deletions(-) - + Documentation/acpi/properties.txt | 410 ++++++++++++ + Documentation/arm64/arm-acpi.txt | 218 +++++++ + Documentation/kernel-parameters.txt | 3 +- + arch/arm64/Kconfig | 6 + + arch/arm64/Makefile | 1 + + arch/arm64/include/asm/acenv.h | 18 + + arch/arm64/include/asm/acpi.h | 99 +++ + arch/arm64/include/asm/cpu_ops.h | 1 + + arch/arm64/include/asm/elf.h | 3 +- + arch/arm64/include/asm/psci.h | 3 +- + arch/arm64/include/asm/smp.h | 10 +- + arch/arm64/kernel/Makefile | 4 +- + arch/arm64/kernel/acpi.c | 397 ++++++++++++ + arch/arm64/kernel/cpu_ops.c | 8 +- + arch/arm64/kernel/efi.c | 11 + + arch/arm64/kernel/process.c | 6 + + arch/arm64/kernel/psci.c | 78 ++- + arch/arm64/kernel/setup.c | 64 +- + arch/arm64/kernel/smp.c | 2 +- + arch/arm64/kernel/smp_parking_protocol.c | 110 ++++ + arch/arm64/kernel/time.c | 7 + + arch/arm64/mm/dma-mapping.c | 103 +++ + arch/arm64/pci/Makefile | 1 + + arch/arm64/pci/pci.c | 28 + + 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 | 586 +++++++++++++++++ + drivers/acpi/scan.c | 93 ++- + 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 | 235 +++++++ + drivers/clocksource/arm_arch_timer.c | 131 +++- + drivers/gpio/devres.c | 34 + + drivers/gpio/gpio-sch.c | 293 ++++----- + drivers/gpio/gpiolib-acpi.c | 78 ++- + drivers/gpio/gpiolib.c | 86 ++- + drivers/gpio/gpiolib.h | 7 +- + drivers/input/keyboard/gpio_keys_polled.c | 163 ++--- + drivers/irqchip/irq-gic-v3.c | 10 + + drivers/irqchip/irq-gic.c | 116 ++++ + drivers/irqchip/irqchip.c | 3 + + drivers/leds/leds-gpio.c | 185 +++--- + drivers/misc/eeprom/at25.c | 41 +- + 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 | 294 +++++++-- + 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 | 77 ++- + 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 | 186 ++++++ + drivers/pnp/resource.c | 2 + + drivers/tty/Kconfig | 6 + + drivers/tty/Makefile | 1 + + drivers/tty/sbsauart.c | 355 +++++++++++ + drivers/tty/serial/8250/8250_dw.c | 9 + + drivers/virtio/virtio_mmio.c | 12 +- + include/acpi/acpi_bus.h | 10 + + include/acpi/acpi_io.h | 6 + + include/kvm/arm_vgic.h | 20 +- + include/linux/acpi.h | 95 ++- + include/linux/clocksource.h | 6 + + include/linux/gpio/consumer.h | 5 + + include/linux/gpio_keys.h | 3 + + include/linux/irqchip/arm-gic-acpi.h | 31 + + include/linux/irqchip/arm-gic.h | 2 + + include/linux/leds.h | 1 + + include/linux/of.h | 37 ++ + include/linux/pci.h | 37 +- + include/linux/property.h | 207 ++++++ + virt/kvm/arm/arch_timer.c | 108 ++-- + virt/kvm/arm/vgic-v2.c | 75 ++- + virt/kvm/arm/vgic-v3.c | 8 +- + virt/kvm/arm/vgic.c | 32 +- + 89 files changed, 5425 insertions(+), 1054 deletions(-) + +diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt +new file mode 100644 +index 0000000..13a93c5 +--- /dev/null ++++ b/Documentation/acpi/properties.txt +@@ -0,0 +1,410 @@ ++ACPI device properties ++====================== ++This document describes the format and interfaces of ACPI device ++properties as specified in "Device Properties UUID For _DSD" available ++here: ++ ++http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf ++ ++1. Introduction ++--------------- ++In systems that use ACPI and want to take advantage of device specific ++properties, there needs to be a standard way to return and extract ++name-value pairs for a given ACPI device. ++ ++An ACPI device that wants to export its properties must implement a ++static name called _DSD that takes no arguments and returns a package of ++packages: ++ ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () {"name1", <VALUE1>}, ++ Package () {"name2", <VALUE2>} ++ } ++ }) ++ ++The UUID identifies contents of the following package. In case of ACPI ++device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301. ++ ++In each returned package, the first item is the name and must be a string. ++The corresponding value can be a string, integer, reference, or package. If ++a package it may only contain strings, integers, and references. ++ ++An example device where we might need properties is a device that uses ++GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to ++know which GPIO is used for which purpose. ++ ++To solve this we add the following ACPI device properties to the device: ++ ++ Device (DEV0) ++ { ++ Name (_CRS, ResourceTemplate () { ++ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, ++ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0} ++ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, ++ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1} ++ ... ++ }) ++ ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () {"reset-gpio", {^DEV0, 0, 0, 0}}, ++ Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}}, ++ } ++ }) ++ } ++ ++Now the device driver can reference the GPIOs using names instead of ++using indexes. ++ ++If there is an existing Device Tree binding for a device, it is expected ++that the same bindings are used with ACPI properties, so that the driver ++dealing with the device needs only minor modifications if any. ++ ++2. Formal definition of properties ++---------------------------------- ++The following chapters define the currently supported properties. For ++these there exists a helper function that can be used to extract the ++property value. ++ ++2.1 Integer types ++----------------- ++ACPI integers are always 64-bit. However, for drivers the full range is ++typically not needed so we provide a set of functions which convert the ++64-bit integer to a smaller Linux integer type. ++ ++An integer property looks like this: ++ ++ Package () {"i2c-sda-hold-time-ns", 300}, ++ Package () {"clock-frequency", 400000}, ++ ++To read a property value, use a unified property accessor as shown ++below: ++ ++ u32 val; ++ int ret; ++ ++ ret = device_property_read_u32(dev, "clock-frequency", &val); ++ if (ret) ++ /* Handle error */ ++ ++The function returns 0 if the property is copied to 'val' or negative ++errno if something went wrong (or the property does not exist). ++ ++2.2 Integer arrays ++------------------ ++An integer array is a package holding only integers. Arrays can be used to ++represent different things like Linux input key codes to GPIO mappings, pin ++control settings, dma request lines, etc. ++ ++An integer array looks like this: ++ ++ Package () { ++ "max8952,dvs-mode-microvolt", ++ Package () { ++ 1250000, ++ 1200000, ++ 1050000, ++ 950000, ++ } ++ } ++ ++The above array property can be accessed like: ++ ++ u32 voltages[4]; ++ int ret; ++ ++ ret = device_property_read_u32_array(dev, "max8952,dvs-mode-microvolt", ++ voltages, ARRAY_SIZE(voltages)); ++ if (ret) ++ /* Handle error */ ++ ++ ++All functions copy the resulting values cast to a requested type to the ++caller supplied array. If you pass NULL in the value pointer ('voltages' in ++this case), the function returns number of items in the array. This can be ++useful if caller does not know size of the array beforehand. ++ ++2.3 Strings ++----------- ++String properties can be used to describe many things like labels for GPIO ++buttons, compability ids, etc. ++ ++A string property looks like this: ++ ++ Package () {"pwm-names", "backlight"}, ++ Package () {"label", "Status-LED"}, ++ ++You can use device_property_read_string() to extract strings: ++ ++ const char *val; ++ int ret; ++ ++ ret = device_property_read_string(dev, "label", &val); ++ if (ret) ++ /* Handle error */ ++ ++Note that the function does not copy the returned string but instead the ++value is modified to point to the string property itself. ++ ++The memory is owned by the associated ACPI device object and released ++when it is removed. The user need not free the associated memory. ++ ++2.4 String arrays ++----------------- ++String arrays can be useful in describing a list of labels, names for ++DMA channels, etc. ++ ++A string array property looks like this: ++ ++ Package () {"dma-names", Package () {"tx", "rx", "rx-tx"}}, ++ Package () {"clock-output-names", Package () {"pll", "pll-switched"}}, ++ ++And these can be read in similar way that the integer arrrays: ++ ++ const char *dma_names[3]; ++ int ret; ++ ++ ret = device_property_read_string_array(dev, "dma-names", dma_names, ++ ARRAY_SIZE(dma_names)); ++ if (ret) ++ /* Handle error */ ++ ++The memory management rules follow what is specified for single strings. ++Specifically the returned pointers should be treated as constant and not to ++be freed. That is done automatically when the correspondig ACPI device ++object is released. ++ ++2.5 Object references ++--------------------- ++An ACPI object reference is used to refer to some object in the ++namespace. For example, if a device has dependencies with some other ++object, an object reference can be used. ++ ++An object reference looks like this: ++ ++ Package () {"dev0", \_SB.DEV0}, ++ ++At the time of writing this, there is no unified device_property_* accessor ++for references so one needs to use the following ACPI helper function: ++ ++ int acpi_dev_get_property_reference(struct acpi_device *adev, ++ const char *name, ++ const char *size_prop, int index, ++ struct acpi_reference_args *args); ++ ++The referenced ACPI device is returned in args->adev if found. ++ ++In addition to simple object references it is also possible to have object ++references with arguments. These are represented in ASL as follows: ++ ++ Device (\_SB.PCI0.PWM) ++ { ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () {"#pwm-cells", 2} ++ } ++ }) ++ } ++ ++ Device (\_SB.PCI0.BL) ++ { ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () { ++ "pwms", ++ Package () { ++ \_SB.PCI0.PWM, 0, 5000000, ++ \_SB.PCI0.PWM, 1, 4500000, ++ } ++ } ++ } ++ }) ++ } ++ ++In the above example, the referenced device declares a property that ++returns the number of expected arguments (here it is "#pwm-cells"). If ++no such property is given we assume that all the integers following the ++reference are arguments. ++ ++In the above example PWM device expects 2 additional arguments. This ++will be validated by the ACPI property core. ++ ++The additional arguments must be integers. Nothing else is supported. ++ ++It is possible, as in the above example, to have multiple references ++with varying number of integer arguments. It is up to the referenced ++device to declare how many arguments it expects. The 'index' parameter ++selects which reference is returned. ++ ++One can use acpi_dev_get_property_reference() as well to extract the ++information in additional parameters: ++ ++ struct acpi_reference_args args; ++ struct acpi_device *adev = /* this will point to the BL device */ ++ int ret; ++ ++ /* extract the first reference */ ++ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 0, &args); ++ ++ BUG_ON(args.nargs != 2); ++ BUG_ON(args.args[0] != 0); ++ BUG_ON(args.args[1] != 5000000); ++ ++ /* extract the second reference */ ++ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 1, &args); ++ ++ BUG_ON(args.nargs != 2); ++ BUG_ON(args.args[0] != 1); ++ BUG_ON(args.args[1] != 4500000); ++ ++In addition to arguments, args.adev now points to the ACPI device that ++corresponds to \_SB.PCI0.PWM. ++ ++It is intended that this function is not used directly but instead ++subsystems like pwm implement their ACPI support on top of this function ++in such way that it is hidden from the client drivers, such as via ++pwm_get(). ++ ++3. Device property hierarchies ++------------------------------ ++Devices are organized in a tree within the Linux kernel. It follows that ++the configuration data would also be hierarchical. In order to reach ++equivalence with Device Tree, the ACPI mechanism must also provide some ++sort of tree-like representation. Fortunately, the ACPI namespace is ++already such a structure. ++ ++For example, we could have the following device in ACPI namespace. The ++KEYS device is much like gpio_keys_polled.c in that it includes "pseudo" ++devices for each GPIO: ++ ++ Device (KEYS) ++ { ++ Name (_CRS, ResourceTemplate () { ++ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, ++ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0} ++ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, ++ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1} ++ ... ++ }) ++ ++ // "pseudo" devices declared under the parent device ++ Device (BTN0) { ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () {"label", "minnow_btn0"} ++ Package () {"gpios", Package () {^KEYS, 0, 0, 1}} ++ } ++ }) ++ } ++ ++ Device (BTN1) { ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () {"label", "minnow_btn1"} ++ Package () {"gpios", Package () {^KEYS, 1, 0, 1}} ++ } ++ }) ++ } ++ } ++ ++We can extract the above in gpio_keys_polled.c like: ++ ++ static int gpio_keys_polled_create_button(struct device *dev, void *child, ++ void *data) ++ { ++ struct button_data *bdata = data; ++ const char *label = NULL; ++ ++ /* ++ * We need to use device_child_ variant here to access ++ * properties of the child. ++ */ ++ device_child_property_read_string(dev, child, "label", &label); ++ /* and so on */ ++ } ++ ++ static void gpio_keys_polled_probe(struct device *dev) ++ { ++ /* Properties for the KEYS device itself */ ++ device_property_read(dev, ...); ++ ++ /* ++ * Iterate over button devices and extract their ++ * firmware configuration. ++ */ ++ ret = device_for_each_child_node(dev, gpio_keys_polled_create_button, ++ &bdata); ++ if (ret) ++ /* Handle error */ ++ } ++ ++Note that you still need proper error handling which is omitted in the ++above example. ++ ++4. Existing Device Tree enabled drivers ++--------------------------------------- ++At the time of writing this, there are ~250 existing DT enabled drivers. ++Allocating _HID/_CID for each would not be feasible. To make sure that ++those drivers can still be used on ACPI systems, we provide an ++alternative way to get these matched. ++ ++There is a special _HID "PRP0001" which means that use the DT bindings ++for matching this device to a driver. The driver needs to have ++.of_match_table filled in even when !CONFIG_OF. ++ ++An example device would be leds that can be controlled via GPIOs. This ++is represented as "leds-gpio" device and looks like this in the ACPI ++namespace: ++ ++ Device (LEDS) ++ { ++ Name (_DSD, Package () { ++ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), ++ Package () { ++ Package () {"compatible", Package () {"gpio-leds"}}, ++ } ++ }) ++ ... ++ } ++ ++In order to get the existing drivers/leds/leds-gpio.c bound to this ++device, we take advantage of "PRP0001": ++ ++ /* Following already exists in the driver */ ++ static const struct of_device_id of_gpio_leds_match[] = { ++ { .compatible = "gpio-leds", }, ++ {}, ++ }; ++ MODULE_DEVICE_TABLE(of, of_gpio_leds_match); ++ ++ /* This we add to the driver to get it probed */ ++ static const struct acpi_device_id acpi_gpio_leds_match[] = { ++ { "PRP0001" }, /* Device Tree shoehorned into ACPI */ ++ {}, ++ }; ++ MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match); ++ ++ static struct platform_driver gpio_led_driver = { ++ .driver = { ++ /* ++ * No of_match_ptr() here because we want this ++ * table to be visible even when !CONFIG_OF to ++ * match against "compatible" in _DSD. ++ */ ++ .of_match_table = of_gpio_leds_match, ++ .acpi_match_table = acpi_gpio_leds_match, ++ }, ++ }; ++ ++Once ACPI core sees "PRP0001" and that the device has "compatible" ++property it will do the match using .of_match_table instead. ++ ++It is preferred that new devices get a proper _HID allocated for them ++instead of inventing new DT "compatible" devices. diff --git a/Documentation/arm64/arm-acpi.txt b/Documentation/arm64/arm-acpi.txt new file mode 100644 index 0000000..b7dc826 @@ -1554,71 +1824,8 @@ index 0000000..b7dc826 +standards from UEFI ASWG. If there are features missing from ACPI to make it +function on a platform, ECRs should be submitted to ASWG and go through the +approval process. -diff --git a/Documentation/devicetree/bindings/pci/xgene-pci.txt b/Documentation/devicetree/bindings/pci/xgene-pci.txt -new file mode 100644 -index 0000000..1070b06 ---- /dev/null -+++ b/Documentation/devicetree/bindings/pci/xgene-pci.txt -@@ -0,0 +1,57 @@ -+* 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". -+- dma-coherent: Present if dma operations are coherent -+ -+Example: -+ -+SoC specific DT Entry: -+ -+ pcie0: pcie@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 0x00040000>; /* PCI config space */ -+ reg-names = "csr", "cfg"; -+ ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000 /* io */ -+ 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */ -+ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 -+ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; -+ interrupt-map-mask = <0x0 0x0 0x0 0x7>; -+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1 -+ 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1 -+ 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1 -+ 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; -+ dma-coherent; -+ clocks = <&pcie0clk 0>; -+ }; -+ -+ -+Board specific DT Entry: -+ &pcie0 { -+ status = "ok"; -+ }; diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 10d51c2..9464c6d 100644 +index 7dbe5ec..bb69b63 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 @@ -1638,205 +1845,8 @@ index 10d51c2..9464c6d 100644 See also Documentation/power/runtime_pm.txt, pci=noacpi -diff --git a/MAINTAINERS b/MAINTAINERS -index 3705430..f6b49e4 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -6940,6 +6940,14 @@ L: linux-pci@vger.kernel.org - S: Maintained - F: drivers/pci/host/*spear* - -+PCI DRIVER FOR APPLIEDMICRO XGENE -+M: Tanmay Inamdar <tinamdar@apm.com> -+L: linux-pci@vger.kernel.org -+L: linux-arm-kernel@lists.infradead.org -+S: Maintained -+F: Documentation/devicetree/bindings/pci/xgene-pci.txt -+F: drivers/pci/host/pci-xgene.c -+ - PCMCIA SUBSYSTEM - P: Linux PCMCIA Team - L: linux-pcmcia@lists.infradead.org -diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h -index 3d23418..22b7529 100644 ---- a/arch/arm/include/asm/io.h -+++ b/arch/arm/include/asm/io.h -@@ -178,6 +178,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr) - - /* PCI fixed i/o mapping */ - #define PCI_IO_VIRT_BASE 0xfee00000 -+#define PCI_IOBASE PCI_IO_VIRT_BASE - - #if defined(CONFIG_PCI) - void pci_ioremap_set_mem_type(int mem_type); -diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h -index 5cc0b0f..03a08bb 100644 ---- a/arch/arm/include/asm/kvm_mmu.h -+++ b/arch/arm/include/asm/kvm_mmu.h -@@ -21,6 +21,7 @@ - - #include <asm/memory.h> - #include <asm/page.h> -+#include <asm/kvm_arm.h> - - /* - * We directly use the kernel VA for the HYP, as we can directly share -@@ -178,6 +179,18 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, - - void stage2_flush_vm(struct kvm *kvm); - -+static inline int kvm_get_phys_addr_shift(void) -+{ -+ return KVM_PHYS_SHIFT; -+} -+ -+ -+static inline u32 get_vttbr_baddr_mask(void) -+{ -+ return VTTBR_BADDR_MASK; -+} -+ -+ - #endif /* !__ASSEMBLY__ */ - - #endif /* __ARM_KVM_MMU_H__ */ -diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c -index a99e0cd..d0fca8f 100644 ---- a/arch/arm/kvm/arm.c -+++ b/arch/arm/kvm/arm.c -@@ -37,6 +37,7 @@ - #include <asm/mman.h> - #include <asm/tlbflush.h> - #include <asm/cacheflush.h> -+#include <asm/cputype.h> - #include <asm/virt.h> - #include <asm/kvm_arm.h> - #include <asm/kvm_asm.h> -@@ -61,6 +62,12 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); - static u8 kvm_next_vmid; - static DEFINE_SPINLOCK(kvm_vmid_lock); - -+#ifdef CONFIG_ARM64 -+static u64 vttbr_baddr_mask; -+#else -+static u32 vttbr_baddr_mask; -+#endif -+ - static bool vgic_present; - - static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) -@@ -429,8 +436,14 @@ static void update_vttbr(struct kvm *kvm) - /* update vttbr to be used with the new vmid */ - pgd_phys = virt_to_phys(kvm->arch.pgd); - vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; -- kvm->arch.vttbr = pgd_phys & VTTBR_BADDR_MASK; -- kvm->arch.vttbr |= vmid; -+ -+ /* -+ * If the VTTBR isn't aligned there is something wrong with the system -+ * or kernel. -+ */ -+ BUG_ON(pgd_phys & ~vttbr_baddr_mask); -+ -+ kvm->arch.vttbr = pgd_phys | vmid; - - spin_unlock(&kvm_vmid_lock); - } -@@ -1015,6 +1028,12 @@ int kvm_arch_init(void *opaque) - } - } - -+ vttbr_baddr_mask = get_vttbr_baddr_mask(); -+ if (vttbr_baddr_mask == ~0) { -+ kvm_err("Cannot set vttbr_baddr_mask\n"); -+ return -EINVAL; -+ } -+ - cpu_notifier_register_begin(); - - err = init_hyp_mode(); -diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c -index 05e1f73..c186a17 100644 ---- a/arch/arm/mach-integrator/pci_v3.c -+++ b/arch/arm/mach-integrator/pci_v3.c -@@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void) - { - unsigned long flags; - unsigned int temp; -+ phys_addr_t io_address = pci_pio_to_address(io_mem.start); - - pcibios_min_mem = 0x00100000; - -@@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void) - /* - * Setup window 2 - PCI IO - */ -- v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) | -+ v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) | - V3_LB_BASE_ENABLE); - v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0)); - -@@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void) - static void __init pci_v3_postinit(void) - { - unsigned int pci_cmd; -+ phys_addr_t io_address = pci_pio_to_address(io_mem.start); - - pci_cmd = PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; -@@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void) - "interrupt: %d\n", ret); - #endif - -- register_isa_ports(non_mem.start, io_mem.start, 0); -+ register_isa_ports(non_mem.start, io_address, 0); - } - - /* -@@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev) - - for_each_of_pci_range(&parser, &range) { - if (!range.flags) { -- of_pci_range_to_resource(&range, np, &conf_mem); -+ ret = of_pci_range_to_resource(&range, np, &conf_mem); - conf_mem.name = "PCIv3 config"; - } - if (range.flags & IORESOURCE_IO) { -- of_pci_range_to_resource(&range, np, &io_mem); -+ ret = of_pci_range_to_resource(&range, np, &io_mem); - io_mem.name = "PCIv3 I/O"; - } - if ((range.flags & IORESOURCE_MEM) && - !(range.flags & IORESOURCE_PREFETCH)) { - non_mem_pci = range.pci_addr; - non_mem_pci_sz = range.size; -- of_pci_range_to_resource(&range, np, &non_mem); -+ ret = of_pci_range_to_resource(&range, np, &non_mem); - non_mem.name = "PCIv3 non-prefetched mem"; - } - if ((range.flags & IORESOURCE_MEM) && - (range.flags & IORESOURCE_PREFETCH)) { - pre_mem_pci = range.pci_addr; - pre_mem_pci_sz = range.size; -- of_pci_range_to_resource(&range, np, &pre_mem); -+ ret = of_pci_range_to_resource(&range, np, &pre_mem); - pre_mem.name = "PCIv3 prefetched mem"; - } -- } - -- if (!conf_mem.start || !io_mem.start || -- !non_mem.start || !pre_mem.start) { -- dev_err(&pdev->dev, "missing ranges in device node\n"); -- return -EINVAL; -+ if (ret < 0) { -+ dev_err(&pdev->dev, "missing ranges in device node\n"); -+ return ret; -+ } - } - - pci_v3.map_irq = of_irq_parse_and_map_pci; diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index fd4e81a..e57b91a 100644 +index ac9afde..14423f3 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1,5 +1,6 @@ @@ -1846,43 +1856,7 @@ index fd4e81a..e57b91a 100644 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_SG_CHAIN select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST -@@ -81,7 +82,7 @@ config MMU - def_bool y - - config NO_IOPORT_MAP -- def_bool y -+ def_bool y if !PCI - - config STACKTRACE_SUPPORT - def_bool y -@@ -156,6 +157,26 @@ menu "Bus support" - config ARM_AMBA - bool - -+config PCI -+ bool "PCI support" -+ help -+ This feature enables support for PCI bus system. If you say Y -+ here, the kernel will include drivers and infrastructure code -+ to support PCI bus devices. -+ -+config PCI_DOMAINS -+ def_bool PCI -+ -+config PCI_DOMAINS_GENERIC -+ 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" -@@ -235,6 +256,9 @@ config SMP +@@ -267,6 +268,9 @@ config SMP If you don't know what to do here, say N. @@ -1892,7 +1866,7 @@ index fd4e81a..e57b91a 100644 config SCHED_MC bool "Multi-core scheduler support" depends on SMP -@@ -421,6 +445,8 @@ source "drivers/Kconfig" +@@ -453,6 +457,8 @@ source "drivers/Kconfig" source "drivers/firmware/Kconfig" @@ -1902,10 +1876,10 @@ index fd4e81a..e57b91a 100644 source "arch/arm64/kvm/Kconfig" diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile -index 2df5e5d..bddd4e3 100644 +index 20901ff..983d72a 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile -@@ -50,6 +50,7 @@ core-y += arch/arm64/kernel/ arch/arm64/mm/ +@@ -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/ @@ -1913,213 +1887,6 @@ index 2df5e5d..bddd4e3 100644 libs-y := arch/arm64/lib/ $(libs-y) libs-y += $(LIBGCC) libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/ -diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts -index b2f5622..f649000 100644 ---- a/arch/arm64/boot/dts/apm-mustang.dts -+++ b/arch/arm64/boot/dts/apm-mustang.dts -@@ -25,6 +25,14 @@ - }; - }; - -+&pcie0clk { -+ status = "ok"; -+}; -+ -+&pcie0 { -+ status = "ok"; -+}; -+ - &serial0 { - status = "ok"; - }; -diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi -index c0aceef..403197a 100644 ---- a/arch/arm64/boot/dts/apm-storm.dtsi -+++ b/arch/arm64/boot/dts/apm-storm.dtsi -@@ -269,6 +269,171 @@ - enable-mask = <0x2>; - clock-output-names = "rtcclk"; - }; -+ -+ pcie0clk: pcie0clk@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@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@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@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@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@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 0x00040000>; /* PCI config space */ -+ reg-names = "csr", "cfg"; -+ ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000 /* io */ -+ 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */ -+ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 -+ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; -+ interrupt-map-mask = <0x0 0x0 0x0 0x7>; -+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1 -+ 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1 -+ 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1 -+ 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; -+ dma-coherent; -+ clocks = <&pcie0clk 0>; -+ }; -+ -+ pcie1: pcie@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 0x00040000>; /* PCI config space */ -+ reg-names = "csr", "cfg"; -+ ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000 /* io */ -+ 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */ -+ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 -+ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; -+ interrupt-map-mask = <0x0 0x0 0x0 0x7>; -+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1 -+ 0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1 -+ 0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1 -+ 0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>; -+ dma-coherent; -+ clocks = <&pcie1clk 0>; -+ }; -+ -+ pcie2: pcie@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 0x00040000>; /* PCI config space */ -+ reg-names = "csr", "cfg"; -+ ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000 /* io */ -+ 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */ -+ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 -+ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; -+ interrupt-map-mask = <0x0 0x0 0x0 0x7>; -+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1 -+ 0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1 -+ 0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1 -+ 0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>; -+ dma-coherent; -+ clocks = <&pcie2clk 0>; -+ }; -+ -+ pcie3: pcie@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 0x00040000>; /* PCI config space */ -+ reg-names = "csr", "cfg"; -+ ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000 /* io */ -+ 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem */ -+ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 -+ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; -+ interrupt-map-mask = <0x0 0x0 0x0 0x7>; -+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1 -+ 0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1 -+ 0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1 -+ 0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>; -+ dma-coherent; -+ clocks = <&pcie3clk 0>; -+ }; -+ -+ pcie4: pcie@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 0x10000000 0x0 0x00010000 /* io */ -+ 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */ -+ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 -+ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; -+ interrupt-map-mask = <0x0 0x0 0x0 0x7>; -+ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1 -+ 0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1 -+ 0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1 -+ 0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>; -+ dma-coherent; -+ clocks = <&pcie4clk 0>; - }; - - serial0: serial@1c020000 { -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/acenv.h b/arch/arm64/include/asm/acenv.h new file mode 100644 index 0000000..b49166f @@ -2250,16 +2017,16 @@ index 0000000..7f6cd91 + +#endif /*_ASM_ACPI_H*/ diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h -index d7b4b38..d149580 100644 +index 6f8e2ef..978f567 100644 --- a/arch/arm64/include/asm/cpu_ops.h +++ b/arch/arm64/include/asm/cpu_ops.h -@@ -61,6 +61,7 @@ struct cpu_operations { +@@ -64,6 +64,7 @@ struct cpu_operations { }; extern const struct cpu_operations *cpu_ops[NR_CPUS]; +const struct cpu_operations *cpu_get_ops(const char *name); - extern int __init cpu_read_ops(struct device_node *dn, int cpu); - extern void __init cpu_read_bootcpu_ops(void); + int __init cpu_read_ops(struct device_node *dn, int cpu); + void __init cpu_read_bootcpu_ops(void); diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 01d3aab..8186df6 100644 @@ -2275,222 +2042,6 @@ index 01d3aab..8186df6 100644 #define CORE_DUMP_USE_REGSET #define ELF_EXEC_PAGESIZE PAGE_SIZE -diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h -index e0ecdcf..f998d90 100644 ---- a/arch/arm64/include/asm/io.h -+++ b/arch/arm64/include/asm/io.h -@@ -121,7 +121,8 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) - /* - * I/O port access primitives. - */ --#define IO_SPACE_LIMIT 0xffff -+#define arch_has_dev_port() (1) -+#define IO_SPACE_LIMIT (SZ_32M - 1) - #define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_32M)) - - static inline u8 inb(unsigned long addr) -diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h -index cc83520..ff4a4fa 100644 ---- a/arch/arm64/include/asm/kvm_arm.h -+++ b/arch/arm64/include/asm/kvm_arm.h -@@ -95,7 +95,6 @@ - /* TCR_EL2 Registers bits */ - #define TCR_EL2_TBI (1 << 20) - #define TCR_EL2_PS (7 << 16) --#define TCR_EL2_PS_40B (2 << 16) - #define TCR_EL2_TG0 (1 << 14) - #define TCR_EL2_SH0 (3 << 12) - #define TCR_EL2_ORGN0 (3 << 10) -@@ -104,8 +103,6 @@ - #define TCR_EL2_MASK (TCR_EL2_TG0 | TCR_EL2_SH0 | \ - TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ) - --#define TCR_EL2_FLAGS (TCR_EL2_PS_40B) -- - /* VTCR_EL2 Registers bits */ - #define VTCR_EL2_PS_MASK (7 << 16) - #define VTCR_EL2_TG0_MASK (1 << 14) -@@ -120,36 +117,28 @@ - #define VTCR_EL2_SL0_MASK (3 << 6) - #define VTCR_EL2_SL0_LVL1 (1 << 6) - #define VTCR_EL2_T0SZ_MASK 0x3f --#define VTCR_EL2_T0SZ_40B 24 -+#define VTCR_EL2_T0SZ(bits) (64 - (bits)) - - #ifdef CONFIG_ARM64_64K_PAGES - /* - * Stage2 translation configuration: -- * 40bits output (PS = 2) -- * 40bits input (T0SZ = 24) - * 64kB pages (TG0 = 1) - * 2 level page tables (SL = 1) - */ - #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \ - VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ -- VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B) --#define VTTBR_X (38 - VTCR_EL2_T0SZ_40B) -+ VTCR_EL2_SL0_LVL1) - #else - /* - * Stage2 translation configuration: -- * 40bits output (PS = 2) -- * 40bits input (T0SZ = 24) - * 4kB pages (TG0 = 0) - * 3 level page tables (SL = 1) - */ - #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \ - VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ -- VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B) --#define VTTBR_X (37 - VTCR_EL2_T0SZ_40B) -+ VTCR_EL2_SL0_LVL1) - #endif - --#define VTTBR_BADDR_SHIFT (VTTBR_X - 1) --#define VTTBR_BADDR_MASK (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) - #define VTTBR_VMID_SHIFT (48LLU) - #define VTTBR_VMID_MASK (0xffLLU << VTTBR_VMID_SHIFT) - -diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h -index 8e138c7..1c70b2f 100644 ---- a/arch/arm64/include/asm/kvm_mmu.h -+++ b/arch/arm64/include/asm/kvm_mmu.h -@@ -167,5 +167,80 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, - - void stage2_flush_vm(struct kvm *kvm); - -+/* -+ * ARMv8 64K architecture limitations: -+ * 16 <= T0SZ <= 21 is valid under 3 level of translation tables -+ * 18 <= T0SZ <= 34 is valid under 2 level of translation tables -+ * 31 <= T0SZ <= 39 is valid under 1 level of transltaion tables -+ * -+ * ARMv8 4K architecture limitations: -+ * 16 <= T0SZ <= 24 is valid under 4 level of translation tables -+ * 21 <= T0SZ <= 33 is valid under 3 level of translation tables -+ * 30 <= T0SZ <= 39 is valid under 2 level of translation tables -+ * -+ * For 4K pages we only support 3 or 4 level, giving T0SZ a range of 16 to 33. -+ * For 64K pages we only support 2 or 3 level, giving T0SZ a range of 16 to 34. -+ * -+ * See Table D4-23 and Table D4-25 in ARM DDI 0487A.b to figure out -+ * the origin of the hardcoded values, 38 and 37. -+ */ -+ -+#ifdef CONFIG_ARM64_64K_PAGES -+static inline int t0sz_to_vttbr_x(int t0sz) -+{ -+ if (t0sz < 16 || t0sz > 34) { -+ kvm_err("Cannot support %d-bit address space\n", 64 - t0sz); -+ return -EINVAL; -+ } -+ -+ return 38 - t0sz; -+} -+#else /* 4K pages */ -+static inline int t0sz_to_vttbr_x(int t0sz) -+{ -+ if (t0sz < 16 || t0sz > 33) { -+ kvm_err("Cannot support %d-bit address space\n", 64 - t0sz); -+ return -EINVAL; -+ } -+ return 37 - t0sz; -+} -+#endif -+static inline int kvm_get_phys_addr_shift(void) -+{ -+ int pa_range = read_cpuid(ID_AA64MMFR0_EL1) & 0xf; -+ -+ switch (pa_range) { -+ case 0: return 32; -+ case 1: return 36; -+ case 2: return 40; -+ case 3: return 42; -+ case 4: return 44; -+ case 5: return 48; -+ default: -+ BUG(); -+ return 0; -+ } -+} -+ -+/** -+ * get_vttbr_baddr_mask - get mask value for vttbr base address -+ * -+ * In ARMv8, vttbr_baddr_mask cannot be determined in compile time since the -+ * stage2 input address size depends on hardware capability. Thus, we first -+ * need to read ID_AA64MMFR0_EL1.PARange and then set vttbr_baddr_mask with -+ * consideration of both the granule size and the level of translation tables. -+ */ -+static inline u64 get_vttbr_baddr_mask(void) -+{ -+ int t0sz, vttbr_x; -+ -+ t0sz = VTCR_EL2_T0SZ(kvm_get_phys_addr_shift()); -+ vttbr_x = t0sz_to_vttbr_x(t0sz); -+ if (vttbr_x < 0) -+ return ~0; -+ return GENMASK_ULL(48, (vttbr_x - 1)); -+ -+} -+ - #endif /* __ASSEMBLY__ */ - #endif /* __ARM64_KVM_MMU_H__ */ -diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h -new file mode 100644 -index 0000000..872ba93 ---- /dev/null -+++ b/arch/arm64/include/asm/pci.h -@@ -0,0 +1,37 @@ -+#ifndef __ASM_PCI_H -+#define __ASM_PCI_H -+#ifdef __KERNEL__ -+ -+#include <linux/types.h> -+#include <linux/slab.h> -+#include <linux/dma-mapping.h> -+ -+#include <asm/io.h> -+#include <asm-generic/pci-bridge.h> -+#include <asm-generic/pci-dma-compat.h> -+ -+#define PCIBIOS_MIN_IO 0x1000 -+#define PCIBIOS_MIN_MEM 0 -+ -+/* -+ * 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)) -+ -+/* -+ * PCI address space differs from physical memory address space -+ */ -+#define PCI_DMA_BUS_IS_PHYS (0) -+ -+extern int isa_dma_bridge_buggy; -+ -+#ifdef CONFIG_PCI -+static inline int pci_proc_domain(struct pci_bus *bus) -+{ -+ return 1; -+} -+#endif /* CONFIG_PCI */ -+ -+#endif /* __KERNEL__ */ -+#endif /* __ASM_PCI_H */ -diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h -index ffe1ba0..a968523 100644 ---- a/arch/arm64/include/asm/pgtable.h -+++ b/arch/arm64/include/asm/pgtable.h -@@ -296,6 +296,8 @@ static inline int has_transparent_hugepage(void) - __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN) - #define pgprot_writecombine(prot) \ - __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) -+#define pgprot_device(prot) \ -+ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN) - #define __HAVE_PHYS_MEM_ACCESS_PROT - struct file; - extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h index e5312ea..2454bc5 100644 --- a/arch/arm64/include/asm/psci.h @@ -2505,7 +2056,7 @@ index e5312ea..2454bc5 100644 #endif /* __ASM_PSCI_H */ diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h -index a498f2c..2ebbd55 100644 +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); @@ -2521,8 +2072,8 @@ index a498f2c..2ebbd55 100644 /* * Provide a function to raise an IPI cross call on CPUs in callmap. -@@ -49,6 +50,11 @@ extern void smp_init_cpus(void); - extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int)); +@@ -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); /* + * Provide a function to signal a parked secondary CPU. @@ -2534,7 +2085,7 @@ index a498f2c..2ebbd55 100644 */ asmlinkage void secondary_start_kernel(void); diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile -index df7ef87..b0bad2e 100644 +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 \ @@ -2547,11 +2098,10 @@ index df7ef87..b0bad2e 100644 arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o -@@ -29,6 +30,8 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o - arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o +@@ -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_PCI) += pci.o +arm64-obj-$(CONFIG_ACPI) += acpi.o obj-y += $(arm64-obj-y) vdso/ @@ -2989,37 +2539,6 @@ index cce9524..1d90f31 100644 { const struct cpu_operations **ops = supported_cpu_ops; -diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c -index 1317fef..d27dd98 100644 ---- a/arch/arm64/kernel/efi-stub.c -+++ b/arch/arm64/kernel/efi-stub.c -@@ -28,20 +28,16 @@ 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_LOAD_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; - } - - diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 03aaa99..6c4de44 100644 --- a/arch/arm64/kernel/efi.c @@ -3039,115 +2558,8 @@ index 03aaa99..6c4de44 100644 +{ + return pm_power_off == NULL; +} -diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S -index 8730690..0a6e4f9 100644 ---- a/arch/arm64/kernel/head.S -+++ b/arch/arm64/kernel/head.S -@@ -151,7 +151,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 -@@ -169,7 +169,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 -@@ -216,7 +216,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 -diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c -new file mode 100644 -index 0000000..ce5836c ---- /dev/null -+++ b/arch/arm64/kernel/pci.c -@@ -0,0 +1,70 @@ -+/* -+ * Code borrowed from powerpc/kernel/pci-common.c -+ * -+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM -+ * Copyright (C) 2014 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. -+ * -+ */ -+ -+#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> -+ -+#include <asm/pci-bridge.h> -+ -+/* -+ * Called after each bus is probed, but before its children are examined -+ */ -+void pcibios_fixup_bus(struct pci_bus *bus) -+{ -+ /* nothing to do, expected to be removed in the future */ -+} -+ -+/* -+ * We don't have to worry about legacy ISA devices, so nothing to do here -+ */ -+resource_size_t pcibios_align_resource(void *data, const struct resource *res, -+ resource_size_t size, resource_size_t align) -+{ -+ return res->start; -+} -+ -+/* -+ * Try to assign the IRQ number from DT when adding a new device -+ */ -+int pcibios_add_device(struct pci_dev *dev) -+{ -+ dev->irq = of_irq_parse_and_map_pci(dev, 0, 0); -+ -+ return 0; -+} -+ -+ -+#ifdef CONFIG_PCI_DOMAINS_GENERIC -+static bool dt_domain_found = false; -+ -+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) -+{ -+ int domain = of_get_pci_domain_nr(parent->of_node); -+ -+ if (domain >= 0) { -+ dt_domain_found = true; -+ } else if (dt_domain_found == true) { -+ dev_err(parent, "Node %s is missing \"linux,pci-domain\" property in DT\n", -+ parent->of_node->full_name); -+ return; -+ } else { -+ domain = pci_get_new_domain_nr(); -+ } -+ -+ bus->domain_nr = domain; -+} -+#endif diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c -index 29d4869..c0427bc 100644 +index c3065db..99edd1f 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -43,6 +43,7 @@ @@ -3158,8 +2570,8 @@ index 29d4869..c0427bc 100644 #include <asm/compat.h> #include <asm/cacheflush.h> -@@ -182,6 +183,11 @@ void machine_restart(char *cmd) - arm_pm_restart(reboot_mode, cmd); +@@ -157,6 +158,11 @@ void machine_restart(char *cmd) + do_kernel_restart(cmd); /* + * If all else fails, try EFI @@ -3171,7 +2583,7 @@ index 29d4869..c0427bc 100644 */ printk("Reboot failed -- System halted\n"); diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c -index 5539547..15ba470 100644 +index 866c1c8..f8a981e 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -15,6 +15,7 @@ @@ -3182,15 +2594,15 @@ index 5539547..15ba470 100644 #include <linux/init.h> #include <linux/of.h> #include <linux/smp.h> -@@ -23,6 +24,7 @@ - #include <linux/delay.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> -@@ -231,6 +233,33 @@ static void psci_sys_poweroff(void) +@@ -304,6 +306,33 @@ static void psci_sys_poweroff(void) invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); } @@ -3224,7 +2636,7 @@ index 5539547..15ba470 100644 /* * PSCI Function IDs for v0.2+ are well defined so use * standard values. -@@ -264,29 +293,7 @@ static int __init psci_0_2_init(struct device_node *np) +@@ -337,29 +366,7 @@ static int __init psci_0_2_init(struct device_node *np) } } @@ -3255,7 +2667,7 @@ index 5539547..15ba470 100644 out_put_node: of_node_put(np); -@@ -339,7 +346,7 @@ static const struct of_device_id psci_of_match[] __initconst = { +@@ -412,7 +419,7 @@ static const struct of_device_id psci_of_match[] __initconst = { {}, }; @@ -3264,7 +2676,7 @@ index 5539547..15ba470 100644 { struct device_node *np; const struct of_device_id *matched_np; -@@ -354,6 +361,29 @@ int __init psci_init(void) +@@ -427,6 +434,29 @@ int __init psci_init(void) return init_fn(np); } @@ -3295,7 +2707,7 @@ index 5539547..15ba470 100644 static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c -index edb146d..a793a20 100644 +index 2437196..c1144a1 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -43,6 +43,7 @@ @@ -3317,9 +2729,9 @@ index edb146d..a793a20 100644 unsigned int processor_id; EXPORT_SYMBOL(processor_id); -@@ -385,22 +390,34 @@ void __init setup_arch(char **cmdline_p) - - parse_early_param(); +@@ -386,22 +391,34 @@ void __init setup_arch(char **cmdline_p) + */ + local_async_enable(); + if (acpi_disabled) + disable_acpi(); @@ -3358,7 +2770,7 @@ index edb146d..a793a20 100644 smp_build_mpidr_hash(); #endif -@@ -413,6 +430,19 @@ void __init setup_arch(char **cmdline_p) +@@ -414,6 +431,19 @@ void __init setup_arch(char **cmdline_p) #endif } @@ -3378,7 +2790,7 @@ index edb146d..a793a20 100644 static int __init arm64_device_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -@@ -505,3 +535,25 @@ const struct seq_operations cpuinfo_op = { +@@ -506,3 +536,25 @@ const struct seq_operations cpuinfo_op = { .stop = c_stop, .show = c_show }; @@ -3405,7 +2817,7 @@ index edb146d..a793a20 100644 +} +early_initcall(arm64_console_setup); diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c -index 4743397..4e390ac 100644 +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) @@ -3533,63 +2945,6 @@ index 0000000..e1153ce + .cpu_prepare = smp_parking_protocol_cpu_prepare, + .cpu_boot = smp_parking_protocol_cpu_boot, +}; -diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c -index 0347d38..4f93c67 100644 ---- a/arch/arm64/kernel/smp_spin_table.c -+++ b/arch/arm64/kernel/smp_spin_table.c -@@ -20,6 +20,7 @@ - #include <linux/init.h> - #include <linux/of.h> - #include <linux/smp.h> -+#include <linux/types.h> - - #include <asm/cacheflush.h> - #include <asm/cpu_ops.h> -@@ -65,12 +66,21 @@ static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu) - - static int smp_spin_table_cpu_prepare(unsigned int cpu) - { -- void **release_addr; -+ __le64 __iomem *release_addr; - - if (!cpu_release_addr[cpu]) - return -ENODEV; - -- release_addr = __va(cpu_release_addr[cpu]); -+ /* -+ * The cpu-release-addr may or may not be inside the linear mapping. -+ * As ioremap_cache will either give us a new mapping or reuse the -+ * 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; - - /* - * We write the release address as LE regardless of the native -@@ -79,15 +89,17 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu) - * boot-loader's endianess before jumping. This is mandated by - * the boot protocol. - */ -- 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((__force void *)release_addr, -+ sizeof(*release_addr)); - - /* - * Send an event to wake up the secondary CPU. - */ - sev(); - -+ iounmap(release_addr); -+ - return 0; - } - diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index 1a7125c..42f9195 100644 --- a/arch/arm64/kernel/time.c @@ -3615,99 +2970,36 @@ index 1a7125c..42f9195 100644 arch_timer_rate = arch_timer_get_rate(); if (!arch_timer_rate) panic("Unable to initialise architected timer.\n"); -diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S -index c319116..fa7e67e 100644 ---- a/arch/arm64/kvm/hyp-init.S -+++ b/arch/arm64/kvm/hyp-init.S -@@ -63,17 +63,21 @@ __do_hyp_init: - mrs x4, tcr_el1 - ldr x5, =TCR_EL2_MASK - and x4, x4, x5 -- ldr x5, =TCR_EL2_FLAGS -- orr x4, x4, x5 -- msr tcr_el2, x4 -- -- ldr x4, =VTCR_EL2_FLAGS - /* - * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in -- * VTCR_EL2. -+ * TCR_EL2 and both PS bits and T0SZ bits in VTCR_EL2. - */ - mrs x5, ID_AA64MMFR0_EL1 - bfi x4, x5, #16, #3 -+ msr tcr_el2, x4 -+ -+ ldr x4, =VTCR_EL2_FLAGS -+ bfi x4, x5, #16, #3 -+ and x5, x5, #0xf -+ adr x6, t0sz -+ add x6, x6, x5, lsl #2 -+ ldr w5, [x6] -+ orr x4, x4, x5 - msr vtcr_el2, x4 - - mrs x4, mair_el1 -@@ -113,6 +117,10 @@ target: /* We're now in the trampoline code, switch page tables */ - - /* Hello, World! */ - eret -+ -+t0sz: -+ .word VTCR_EL2_T0SZ(32), VTCR_EL2_T0SZ(36), VTCR_EL2_T0SZ(40) -+ .word VTCR_EL2_T0SZ(42), VTCR_EL2_T0SZ(44), VTCR_EL2_T0SZ(48) - ENDPROC(__kvm_hyp_init) - - .ltorg diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c -index 4164c5a..b864a24 100644 +index d920942..fda70ab 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c -@@ -23,10 +23,13 @@ +@@ -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.h> +#include <linux/of_address.h> - #include <linux/platform_device.h> ++#include <linux/platform_device.h> #include <linux/vmalloc.h> #include <linux/swiotlb.h> - #include <linux/amba/bus.h> ++#include <linux/amba/bus.h> +#include <linux/acpi.h> +#include <linux/pci.h> #include <asm/cacheflush.h> -@@ -319,6 +322,63 @@ static int dma_bus_notifier(struct notifier_block *nb, - if (of_property_read_bool(dev->of_node, "dma-coherent")) - set_dma_ops(dev, &coherent_swiotlb_dma_ops); +@@ -423,10 +429,107 @@ out: + return -ENOMEM; + } -+#ifdef CONFIG_ACPI -+ else if (ACPI_HANDLE(dev)) { -+ acpi_status status; -+ int coherent; -+ -+ /* -+ * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64 -+ * defaults to coherent. Set coherent ops if _CCA not found or _CCA -+ * found and non-zero. -+ */ -+ status = acpi_check_coherency(ACPI_HANDLE(dev), &coherent); -+ if (ACPI_FAILURE(status) || coherent) -+ set_dma_ops(dev, &coherent_swiotlb_dma_ops); -+ } -+#endif -+ return NOTIFY_OK; -+} -+ -+static int dma_bus_notifier_pci(struct notifier_block *nb, -+ unsigned long event, void *_dev) ++#ifdef CONFIG_PCI ++static void arm64_of_set_dma_ops(void *_dev) +{ + struct device *dev = _dev; + -+ if (event != BUS_NOTIFY_ADD_DEVICE) -+ return NOTIFY_DONE; -+ + /* -+ * PCI devices won't have an of_node but the bridge will. ++ * 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. + */ @@ -3717,48 +3009,94 @@ index 4164c5a..b864a24 100644 + set_dma_ops(_dev, &coherent_swiotlb_dma_ops); + break; + } ++ dev = dev->parent; ++ } ++} ++#else ++static inline arm64_of_set_dma_ops(void *_dev) {} ++#endif ++ ++ +#ifdef CONFIG_ACPI ++static void arm64_acpi_set_dma_ops(void *_dev) ++{ ++ struct device *dev = _dev; ++ ++ /* ++ * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64 ++ * defaults to coherent. Set coherent ops if _CCA not found or _CCA ++ * found and non-zero. ++ * ++ * PCI devices won't have an of_node but the bridge will. ++ * Search up the device chain until we find an ACPI handle ++ * to check. ++ */ ++ while (dev) { + if (ACPI_HANDLE(dev)) { + acpi_status status; + int coherent; -+ -+ /* -+ * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64 -+ * defaults to coherent. Set coherent ops if _CCA not found or _CCA -+ * found and non-zero. -+ */ -+ status = acpi_check_coherency(ACPI_HANDLE(dev), &coherent); -+ if (ACPI_FAILURE(status) || coherent) { ++ status = acpi_check_coherency(ACPI_HANDLE(dev), ++ &coherent); ++ if (ACPI_FAILURE(status) || coherent) + set_dma_ops(dev, &coherent_swiotlb_dma_ops); -+ break; -+ } ++ break; + } -+#endif + dev = dev->parent; + } ++} ++#else ++static inline arm64_acpi_set_dma_ops(void *_dev) {} ++#endif + - return NOTIFY_OK; - } - -@@ -330,6 +390,10 @@ static struct notifier_block amba_bus_nb = { - .notifier_call = dma_bus_notifier, - }; - ++static int dma_bus_notifier(struct notifier_block *nb, ++ unsigned long event, void *_dev) ++{ ++ if (event != BUS_NOTIFY_ADD_DEVICE) ++ return NOTIFY_DONE; ++ ++ if (acpi_disabled) ++ arm64_of_set_dma_ops(_dev); ++ else ++ arm64_acpi_set_dma_ops(_dev); ++ ++ return NOTIFY_OK; ++} ++ ++#ifdef CONFIG_ACPI ++static struct notifier_block platform_bus_nb = { ++ .notifier_call = dma_bus_notifier, ++}; ++ ++static struct notifier_block amba_bus_nb = { ++ .notifier_call = dma_bus_notifier, ++}; ++#endif ++ ++#ifdef CONFIG_PCI +static struct notifier_block pci_bus_nb = { -+ .notifier_call = dma_bus_notifier_pci, ++ .notifier_call = dma_bus_notifier, +}; ++#endif + - extern int swiotlb_late_init_with_default_size(size_t default_size); - static int __init swiotlb_late_init(void) -@@ -341,6 +405,7 @@ static int __init swiotlb_late_init(void) - */ - bus_register_notifier(&platform_bus_type, &platform_bus_nb); - bus_register_notifier(&amba_bustype, &amba_bus_nb); -+ bus_register_notifier(&pci_bus_type, &pci_bus_nb); + { + size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT); ++ /* ++ * These must be registered before of_platform_populate(). ++ */ ++#ifdef CONFIG_ACPI ++ bus_register_notifier(&platform_bus_type, &platform_bus_nb); ++ bus_register_notifier(&amba_bustype, &amba_bus_nb); ++#endif ++ ++#ifdef CONFIG_PCI ++ bus_register_notifier(&pci_bus_type, &pci_bus_nb); ++#endif ++ dma_ops = &noncoherent_swiotlb_dma_ops; + 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..b8d5dbd @@ -3832,7 +3170,7 @@ index d0f3265..3343080 100644 help This driver creates entries in /sys/bus/pci/slots/ for all PCI diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile -index 505d4d7..6f3a74d 100644 +index 505d4d7..252d0ff 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -23,7 +23,11 @@ acpi-y += nvs.o @@ -3847,7 +3185,7 @@ index 505d4d7..6f3a74d 100644 acpi-y += device_pm.o acpi-$(CONFIG_ACPI_SLEEP) += proc.o -@@ -39,7 +43,7 @@ acpi-y += processor_core.o +@@ -39,13 +43,14 @@ 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 @@ -3856,21 +3194,13 @@ index 505d4d7..6f3a74d 100644 acpi-y += acpi_lpss.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o -diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c -index 14cb6c0..5cd017c 100644 ---- a/drivers/acpi/acpica/utresrc.c -+++ b/drivers/acpi/acpica/utresrc.c -@@ -87,7 +87,9 @@ const char *acpi_gbl_io_decode[] = { - - const char *acpi_gbl_ll_decode[] = { - "ActiveHigh", -- "ActiveLow" -+ "ActiveLow", -+ "ActiveBoth", -+ "Reserved" - }; - - const char *acpi_gbl_max_decode[] = { + 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 @@ -3886,7 +3216,7 @@ index 8b67bd0..c412fdb 100644 message = "platform specific model"; break; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h -index 4c5cf77..e1e6487 100644 +index 4c5cf77..926ca5c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -26,8 +26,13 @@ @@ -3903,11 +3233,22 @@ index 4c5cf77..e1e6487 100644 void acpi_processor_init(void); void acpi_platform_init(void); void acpi_pnp_init(void); +@@ -181,4 +186,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev); + 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 3abe9b2..c50757b 100644 +index 9964f70..5c480d5 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c -@@ -326,11 +326,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) +@@ -336,11 +336,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) return NULL; } @@ -3923,7 +3264,7 @@ index 3abe9b2..c50757b 100644 static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c -index e32321c..4007313 100644 +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, @@ -3984,6 +3325,724 @@ index e32321c..4007313 100644 } exit: +diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c +new file mode 100644 +index 0000000..ff53eb8 +--- /dev/null ++++ b/drivers/acpi/property.c +@@ -0,0 +1,586 @@ ++/* ++ * ACPI device specific properties support. ++ * ++ * Copyright (C) 2014, Intel Corporation ++ * All rights reserved. ++ * ++ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> ++ * Darren Hart <dvhart@linux.intel.com> ++ * Rafael J. Wysocki <rafael.j.wysocki@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. ++ */ ++ ++#include <linux/acpi.h> ++#include <linux/device.h> ++#include <linux/export.h> ++ ++#include "internal.h" ++ ++/* 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 bool acpi_property_value_ok(const union acpi_object *value) ++{ ++ 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; ++ } ++ ++ return true; ++ } ++ return false; ++} ++ ++static bool acpi_properties_format_valid(const union acpi_object *properties) ++{ ++ int 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 void acpi_init_of_compatible(struct acpi_device *adev) ++{ ++ const union acpi_object *of_compatible; ++ struct acpi_hardware_id *hwid; ++ bool acpi_of = false; ++ ++ /* ++ * 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; ++ } ++ } ++ ++ if (!acpi_of) ++ return; ++ ++ if (acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, ++ &of_compatible)) { ++ acpi_handle_warn(adev->handle, ++ "PRP0001 requires compatible property\n"); ++ return; ++ } ++ ++ adev->data.of_compatible = of_compatible; ++} ++ ++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; ++ ++ status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, ++ ACPI_TYPE_PACKAGE); ++ if (ACPI_FAILURE(status)) ++ return; ++ ++ desc = buf.pointer; ++ if (desc->package.count % 2) ++ goto fail; ++ ++ /* Look for the device properties UUID. */ ++ for (i = 0; i < desc->package.count; i += 2) { ++ const union acpi_object *uuid, *properties; ++ ++ uuid = &desc->package.elements[i]; ++ properties = &desc->package.elements[i + 1]; ++ ++ /* ++ * 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; ++ ++ if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid))) ++ continue; ++ ++ /* ++ * We found the matching UUID. Now validate the format of the ++ * package immediately following it. ++ */ ++ if (!acpi_properties_format_valid(properties)) ++ break; ++ ++ adev->data.pointer = buf.pointer; ++ adev->data.properties = properties; ++ ++ acpi_init_of_compatible(adev); ++ return; ++ } ++ ++ fail: ++ dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n"); ++ ACPI_FREE(buf.pointer); ++} ++ ++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; ++} ++ ++/** ++ * 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) ++ * ++ * Look up a 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. These objects will be ++ * freed by the ACPI core automatically during the removal of @adev. ++ * ++ * 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. ++ */ ++int acpi_dev_get_property(struct acpi_device *adev, const char *name, ++ acpi_object_type type, const union acpi_object **obj) ++{ ++ const union acpi_object *properties; ++ int i; ++ ++ if (!adev || !name) ++ return -EINVAL; ++ ++ if (!adev->data.pointer || !adev->data.properties) ++ return -ENODATA; ++ ++ properties = adev->data.properties; ++ for (i = 0; i < properties->package.count; i++) { ++ const union acpi_object *propname, *propvalue; ++ const union acpi_object *property; ++ ++ property = &properties->package.elements[i]; ++ ++ propname = &property->package.elements[0]; ++ propvalue = &property->package.elements[1]; ++ ++ if (!strcmp(name, propname->string.pointer)) { ++ if (type != ACPI_TYPE_ANY && propvalue->type != type) ++ return -EPROTO; ++ else if (obj) ++ *obj = propvalue; ++ ++ return 0; ++ } ++ } ++ return -ENODATA; ++} ++EXPORT_SYMBOL_GPL(acpi_dev_get_property); ++ ++/** ++ * 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) ++{ ++ const union acpi_object *prop; ++ int ret, i; ++ ++ ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop); ++ if (ret) ++ return ret; ++ ++ 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 0; ++} ++EXPORT_SYMBOL_GPL(acpi_dev_get_property_array); ++ ++/** ++ * acpi_dev_get_property_reference - returns handle to the referenced object ++ * @adev: ACPI device to get property ++ * @name: Name of the property ++ * @size_prop: Name of the "size" property in referenced object ++ * @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 (@size_prop is not %NULL) follow the ++ * reference and check whether or not there is an integer property @size_prop ++ * under the target object and if so, whether or not its value matches the ++ * number of arguments that follow the reference. 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, ++ const char *size_prop, size_t index, ++ struct acpi_reference_args *args) ++{ ++ const union acpi_object *element, *end; ++ const union acpi_object *obj; ++ struct acpi_device *device; ++ int ret, idx = 0; ++ ++ ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj); ++ if (ret) ++ return ret; ++ ++ /* ++ * The simplest case is when the value is a single reference. Just ++ * return that reference then. ++ */ ++ if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) { ++ if (size_prop || index) ++ return -EINVAL; ++ ++ ret = acpi_bus_get_device(obj->reference.handle, &device); ++ if (ret) ++ return ret; ++ ++ args->adev = device; ++ args->nargs = 0; ++ return 0; ++ } ++ ++ /* ++ * 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; ++ ++ element = obj->package.elements; ++ end = element + obj->package.count; ++ ++ while (element < end) { ++ u32 nargs, i; ++ ++ if (element->type != ACPI_TYPE_LOCAL_REFERENCE) ++ return -EPROTO; ++ ++ ret = acpi_bus_get_device(element->reference.handle, &device); ++ if (ret) ++ return -ENODEV; ++ ++ element++; ++ nargs = 0; ++ ++ if (size_prop) { ++ const union acpi_object *prop; ++ ++ /* ++ * Find out how many arguments the refenced object ++ * expects by reading its size_prop property. ++ */ ++ ret = acpi_dev_get_property(device, size_prop, ++ ACPI_TYPE_INTEGER, &prop); ++ if (ret) ++ return ret; ++ ++ nargs = prop->integer.value; ++ if (nargs > MAX_ACPI_REFERENCE_ARGS ++ || element + nargs > end) ++ return -EPROTO; ++ ++ /* ++ * Skip to the start of the arguments and verify ++ * that they all are in fact integers. ++ */ ++ for (i = 0; i < nargs; i++) ++ if (element[i].type != ACPI_TYPE_INTEGER) ++ return -EPROTO; ++ } else { ++ /* assume following integer elements are all args */ ++ for (i = 0; element + i < end; i++) { ++ int type = element[i].type; ++ ++ if (type == ACPI_TYPE_INTEGER) ++ nargs++; ++ else if (type == ACPI_TYPE_LOCAL_REFERENCE) ++ break; ++ else ++ return -EPROTO; ++ } ++ } ++ ++ if (idx++ == index) { ++ args->adev = device; ++ args->nargs = nargs; ++ for (i = 0; i < nargs; i++) ++ args->args[i] = element[i].integer.value; ++ ++ return 0; ++ } ++ ++ element += nargs; ++ } ++ ++ return -EPROTO; ++} ++EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); ++ ++int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, ++ void **valptr) ++{ ++ return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, ++ (const union acpi_object **)valptr); ++} ++ ++int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val) ++{ ++ const union acpi_object *obj; ++ int ret = -EINVAL; ++ ++ if (!val) ++ return -EINVAL; ++ ++ if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { ++ ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj); ++ if (ret) ++ return ret; ++ ++ switch (proptype) { ++ case DEV_PROP_U8: ++ if (obj->integer.value > U8_MAX) ++ return -EOVERFLOW; ++ *(u8 *)val = obj->integer.value; ++ break; ++ 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; ++ } ++ } else if (proptype == DEV_PROP_STRING) { ++ ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj); ++ if (ret) ++ return ret; ++ ++ *(char **)val = obj->string.pointer; ++ } ++ return ret; ++} ++ ++static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val, ++ size_t nval) ++{ ++ int i; ++ ++ for (i = 0; i < nval; i++) { ++ if (items[i].type != ACPI_TYPE_INTEGER) ++ return -EPROTO; ++ if (items[i].integer.value > U8_MAX) ++ return -EOVERFLOW; ++ ++ val[i] = items[i].integer.value; ++ } ++ return 0; ++} ++ ++static int acpi_copy_property_array_u16(const union acpi_object *items, ++ u16 *val, size_t nval) ++{ ++ int i; ++ ++ for (i = 0; i < nval; i++) { ++ if (items[i].type != ACPI_TYPE_INTEGER) ++ return -EPROTO; ++ if (items[i].integer.value > U16_MAX) ++ return -EOVERFLOW; ++ ++ val[i] = items[i].integer.value; ++ } ++ return 0; ++} ++ ++static int acpi_copy_property_array_u32(const union acpi_object *items, ++ u32 *val, size_t nval) ++{ ++ int i; ++ ++ for (i = 0; i < nval; i++) { ++ if (items[i].type != ACPI_TYPE_INTEGER) ++ return -EPROTO; ++ if (items[i].integer.value > U32_MAX) ++ return -EOVERFLOW; ++ ++ val[i] = items[i].integer.value; ++ } ++ return 0; ++} ++ ++static int acpi_copy_property_array_u64(const union acpi_object *items, ++ u64 *val, size_t nval) ++{ ++ int i; ++ ++ for (i = 0; i < nval; i++) { ++ if (items[i].type != ACPI_TYPE_INTEGER) ++ return -EPROTO; ++ ++ val[i] = items[i].integer.value; ++ } ++ return 0; ++} ++ ++static int acpi_copy_property_array_string(const union acpi_object *items, ++ char **val, size_t nval) ++{ ++ int i; ++ ++ for (i = 0; i < nval; i++) { ++ if (items[i].type != ACPI_TYPE_STRING) ++ return -EPROTO; ++ ++ val[i] = items[i].string.pointer; ++ } ++ return 0; ++} ++ ++int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val, ++ size_t nval) ++{ ++ const union acpi_object *obj; ++ const union acpi_object *items; ++ int ret; ++ ++ ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj); ++ if (ret) ++ return ret; ++ ++ if (!val) ++ return obj->package.count; ++ ++ if (nval > obj->package.count) ++ nval = obj->package.count; ++ ++ items = obj->package.elements; ++ switch (proptype) { ++ case DEV_PROP_U8: ++ ret = acpi_copy_property_array_u8(items, (u8 *)val, nval); ++ break; ++ case DEV_PROP_U16: ++ ret = acpi_copy_property_array_u16(items, (u16 *)val, nval); ++ break; ++ case DEV_PROP_U32: ++ ret = acpi_copy_property_array_u32(items, (u32 *)val, nval); ++ break; ++ case DEV_PROP_U64: ++ ret = acpi_copy_property_array_u64(items, (u64 *)val, nval); ++ break; ++ case DEV_PROP_STRING: ++ ret = acpi_copy_property_array_string(items, (char **)val, nval); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ ++int acpi_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data) ++{ ++ struct acpi_device *adev = ACPI_COMPANION(dev); ++ struct acpi_device *child; ++ int ret = 0; ++ ++ if (!adev) ++ return -EINVAL; ++ ++ list_for_each_entry(child, &adev->children, node) { ++ ret = fn(dev, child, data); ++ if (ret) ++ break; ++ } ++ return ret; ++} +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index ae44d86..4da55d8 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -124,17 +124,43 @@ 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; ++ /* ++ * If the device has PRP0001 we expose DT compatible modalias ++ * instead. ++ */ ++ if (acpi_dev->data.of_compatible) { ++ const union acpi_object *of_compatible, *obj; ++ int i; ++ ++ len = snprintf(modalias, size, "of:Nprp0001Tacpi"); ++ ++ of_compatible = acpi_dev->data.of_compatible; ++ for (i = 0; i < of_compatible->package.count; i++) { ++ obj = &of_compatible->package.elements[i]; + +- 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; ++ 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'; +@@ -864,6 +890,51 @@ int acpi_match_device_ids(struct acpi_device *device, + } + EXPORT_SYMBOL(acpi_match_device_ids); + ++/* Performs match for special "PRP0001" shoehorn ACPI ID */ ++static bool acpi_of_driver_match_device(struct device *dev, ++ const struct device_driver *drv) ++{ ++ struct acpi_device *adev = ACPI_COMPANION(dev); ++ const union acpi_object *of_compatible; ++ int i; ++ ++ /* ++ * If the ACPI device does not have corresponding compatible ++ * property or the driver in question does not have DT matching ++ * table we consider the match succesful (matches the ACPI ID). ++ */ ++ of_compatible = adev->data.of_compatible; ++ if (!drv->of_match_table || !of_compatible) ++ return true; ++ ++ /* Now we can look for the driver DT compatible strings */ ++ for (i = 0; i < of_compatible->package.count; i++) { ++ const struct of_device_id *id; ++ const union acpi_object *obj; ++ ++ obj = &of_compatible->package.elements[i]; ++ ++ for (id = drv->of_match_table; id->compatible[0]; id++) ++ if (!strcasecmp(obj->string.pointer, id->compatible)) ++ return true; ++ } ++ ++ return false; ++} ++ ++bool acpi_driver_match_device(struct device *dev, ++ const struct device_driver *drv) ++{ ++ const struct acpi_device_id *id; ++ ++ id = acpi_match_device(drv->acpi_match_table, dev); ++ if (!id) ++ return false; ++ ++ return acpi_of_driver_match_device(dev, drv); ++} ++EXPORT_SYMBOL_GPL(acpi_driver_match_device); ++ + static void acpi_free_power_resources_lists(struct acpi_device *device) + { + int i; +@@ -884,6 +955,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); +@@ -1888,6 +1960,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, + 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 @@ -4189,10 +4248,10 @@ index 6d5a6cd..47f36d4 100644 int __init diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c -index 07c8c5a..aec9656 100644 +index 834f35c..b163f73 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c -@@ -698,3 +698,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) +@@ -697,3 +697,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) return false; } EXPORT_SYMBOL(acpi_check_dsm); @@ -4223,7 +4282,7 @@ index 07c8c5a..aec9656 100644 +} +EXPORT_SYMBOL(acpi_check_coherency); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig -index e1b9278..f2e6c9e 100644 +index cd4cccb..edb00c6 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -48,7 +48,7 @@ config ATA_VERBOSE_ERROR @@ -4236,7 +4295,7 @@ index e1b9278..f2e6c9e 100644 help This option adds support for ATA-related ACPI objects. diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c -index f61ddb9..3499bab 100644 +index 06f1d59..df2ea85 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -20,6 +20,9 @@ @@ -4249,7 +4308,7 @@ index f61ddb9..3499bab 100644 #include "ahci.h" static const struct ata_port_info ahci_port_info = { -@@ -87,6 +90,13 @@ static const struct of_device_id ahci_of_match[] = { +@@ -71,6 +74,13 @@ static const struct of_device_id ahci_of_match[] = { }; MODULE_DEVICE_TABLE(of, ahci_of_match); @@ -4263,7 +4322,7 @@ index f61ddb9..3499bab 100644 static struct platform_driver ahci_driver = { .probe = ahci_probe, .remove = ata_platform_remove_one, -@@ -94,6 +104,9 @@ static struct platform_driver ahci_driver = { +@@ -78,6 +88,9 @@ static struct platform_driver ahci_driver = { .name = "ahci", .owner = THIS_MODULE, .of_match_table = ahci_of_match, @@ -4274,7 +4333,7 @@ index f61ddb9..3499bab 100644 }, }; diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c -index f03aab1..b02ba9d 100644 +index 0f8538f..2d8103a 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -28,6 +28,7 @@ @@ -4310,7 +4369,7 @@ index f03aab1..b02ba9d 100644 /** * xgene_ahci_read_id - Read ID data from the specified device * @dev: device -@@ -495,11 +489,6 @@ static int xgene_ahci_probe(struct platform_device *pdev) +@@ -501,11 +495,6 @@ static int xgene_ahci_probe(struct platform_device *pdev) return -ENODEV; } @@ -4322,7 +4381,7 @@ index f03aab1..b02ba9d 100644 /* Due to errata, HW requires full toggle transition */ rc = ahci_platform_enable_clks(hpriv); if (rc) -@@ -512,7 +501,7 @@ static int xgene_ahci_probe(struct platform_device *pdev) +@@ -518,7 +507,7 @@ static int xgene_ahci_probe(struct platform_device *pdev) /* Configure the host controller */ xgene_ahci_hw_init(hpriv); @@ -4331,7 +4390,7 @@ index f03aab1..b02ba9d 100644 hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ; rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info); -@@ -527,6 +516,16 @@ disable_resources: +@@ -533,6 +522,16 @@ disable_resources: return rc; } @@ -4348,7 +4407,7 @@ index f03aab1..b02ba9d 100644 static const struct of_device_id xgene_ahci_of_match[] = { {.compatible = "apm,xgene-ahci"}, {}, -@@ -540,6 +539,7 @@ static struct platform_driver xgene_ahci_driver = { +@@ -546,6 +545,7 @@ static struct platform_driver xgene_ahci_driver = { .name = "xgene-ahci", .owner = THIS_MODULE, .of_match_table = xgene_ahci_of_match, @@ -4356,8 +4415,262 @@ index f03aab1..b02ba9d 100644 }, }; +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..7bf5708 +--- /dev/null ++++ b/drivers/base/property.c +@@ -0,0 +1,235 @@ ++/* ++ * property.c - Unified device property interface. ++ * ++ * Copyright (C) 2014, Intel Corporation ++ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com> ++ * Mika Westerberg <mika.westerberg@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. ++ */ ++ ++#include <linux/property.h> ++#include <linux/export.h> ++#include <linux/acpi.h> ++#include <linux/of.h> ++ ++/** ++ * device_get_property - return a raw property of a device ++ * @dev: Device get the property of ++ * @propname: Name of the property ++ * @valptr: The raw property value is stored here ++ * ++ * Function reads property @propname from the device firmware description and ++ * stores the raw value into @valptr if found. Otherwise returns a negative ++ * errno as specified below. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not exist. ++ */ ++int device_get_property(struct device *dev, const char *propname, void **valptr) ++{ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_dev_prop_get(dev->of_node, propname, valptr); ++ ++ return acpi_dev_prop_get(ACPI_COMPANION(dev), propname, valptr); ++} ++EXPORT_SYMBOL_GPL(device_get_property); ++ ++/** ++ * device_get_child_property - return a raw property of a device's child ++ * @dev: Parent device ++ * @child: Child to get a property of ++ * @propname: Name of the property ++ * @valptr: The raw property value is stored here ++ * ++ * Function reads property @propname from the firmware description of @child and ++ * stores the raw value into @valptr if found. Otherwise returns a negative ++ * errno as specified below. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not exist. ++ */ ++int device_get_child_property(struct device *dev, void *child, ++ const char *propname, void **valptr) ++{ ++ if (!child) ++ return -EINVAL; ++ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_dev_prop_get(child, propname, valptr); ++ else if (ACPI_COMPANION(dev)) ++ return acpi_dev_prop_get(child, propname, valptr); ++ ++ return -ENODATA; ++} ++EXPORT_SYMBOL_GPL(device_get_child_property); ++ ++/** ++ * device_read_property - read a typed property of a device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @proptype: Type 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 of type ++ * @proptype. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not exist, ++ * %-EPROTO if the property type does not match @proptype, ++ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ */ ++int device_read_property(struct device *dev, const char *propname, ++ enum dev_prop_type proptype, void *val) ++{ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_dev_prop_read(dev->of_node, propname, proptype, val); ++ ++ return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, proptype, val); ++} ++EXPORT_SYMBOL_GPL(device_read_property); ++ ++/** ++ * device_read_child_property - read a typed property of a device's child ++ * @dev: Parent device ++ * @child: Child to read a property of ++ * @propname: Name of the property ++ * @proptype: Type of the property ++ * @val: The value is stored here ++ * ++ * Function reads property @propname from the firmware description of @child and ++ * stores the value into @val if found. The value is checked to be of type ++ * @proptype. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not exist, ++ * %-EPROTO if the property type does not match @proptype, ++ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ */ ++int device_read_child_property(struct device *dev, void *child, ++ const char *propname, enum dev_prop_type proptype, ++ void *val) ++{ ++ if (!child) ++ return -EINVAL; ++ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_dev_prop_read(child, propname, proptype, val); ++ else if (ACPI_COMPANION(dev)) ++ return acpi_dev_prop_read(child, propname, proptype, val); ++ ++ return -ENODATA; ++} ++EXPORT_SYMBOL_GPL(device_read_child_property); ++ ++/** ++ * device_read_property_array - read an array property of a device ++ * @dev: Device to get the property of ++ * @propname: Name of the property ++ * @proptype: Type of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of properties with @propname from the device ++ * firmware description and stores them to @val if found. All the values ++ * in the array must be of type @proptype. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not exist, ++ * %-EPROTO if the property type does not match @proptype, ++ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ */ ++int device_read_property_array(struct device *dev, const char *propname, ++ enum dev_prop_type proptype, void *val, ++ size_t nval) ++{ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_dev_prop_read_array(dev->of_node, propname, proptype, ++ val, nval); ++ ++ return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, proptype, ++ val, nval); ++} ++EXPORT_SYMBOL_GPL(device_read_property_array); ++ ++/** ++ * device_read_child_property_array - read an array property of a device's child ++ * @dev: Parent device ++ * @child: Child to get the property of ++ * @propname: Name of the property ++ * @proptype: Type of the property ++ * @val: The values are stored here ++ * @nval: Size of the @val array ++ * ++ * Function reads an array of properties with @propname from the firmware ++ * description of @child and stores them to @val if found. All the values ++ * in the array must be of type @proptype. ++ * ++ * Return: %0 if the property was found (success), ++ * %-EINVAL if given arguments are not valid, ++ * %-ENODATA if the property does not exist, ++ * %-EPROTO if the property type does not match @proptype, ++ * %-EOVERFLOW if the property value is out of bounds of @proptype. ++ */ ++int device_read_child_property_array(struct device *dev, void *child, ++ const char *propname, ++ enum dev_prop_type proptype, void *val, ++ size_t nval) ++{ ++ if (!child) ++ return -EINVAL; ++ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_dev_prop_read_array(child, propname, proptype, ++ val, nval); ++ else if (ACPI_COMPANION(dev)) ++ return acpi_dev_prop_read_array(child, propname, proptype, ++ val, nval); ++ ++ return -ENODATA; ++} ++EXPORT_SYMBOL_GPL(device_read_child_property_array); ++ ++/** ++ * device_for_each_child_node - execute function for each child node of device ++ * @dev: Device to run the function for ++ * @fn: Function to run ++ * @data: Additional data to pass to the function ++ */ ++int device_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data) ++{ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) ++ return of_for_each_child_node(dev, fn, data); ++ ++ return acpi_for_each_child_node(dev, fn, data); ++} ++EXPORT_SYMBOL_GPL(device_for_each_child_node); ++ ++static int increment_count(struct device *dev, void *child, void *data) ++{ ++ *((unsigned int *)data) += 1; ++ return 0; ++} ++ ++/** ++ * 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) ++{ ++ unsigned int count = 0; ++ ++ device_for_each_child_node(dev, increment_count, &count); ++ 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 5163ec1..1bec05b 100644 +index 2133f9d..b73392b 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -21,6 +21,7 @@ @@ -4378,7 +4691,7 @@ index 5163ec1..1bec05b 100644 static struct clock_event_device __percpu *arch_timer_evt; -@@ -338,8 +340,12 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) +@@ -370,8 +372,12 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) if (arch_timer_rate) return; @@ -4393,7 +4706,27 @@ index 5163ec1..1bec05b 100644 if (cntbase) arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); else -@@ -635,20 +641,8 @@ static void __init arch_timer_common_init(void) +@@ -660,13 +666,14 @@ static bool __init + arch_timer_probed(int type, const struct of_device_id *matches) + { + struct device_node *dn; +- bool probed = false; ++ bool probed = true; + + dn = of_find_matching_node(NULL, matches); +- if (dn && of_device_is_available(dn) && (arch_timers_present & type)) +- probed = true; +- of_node_put(dn); +- ++ if (dn) { ++ if (of_device_is_available(dn) && !(arch_timers_present & type)) ++ probed = false; ++ of_node_put(dn); ++ } + return probed; + } + +@@ -687,20 +694,8 @@ static void __init arch_timer_common_init(void) arch_timer_arch_init(); } @@ -4415,7 +4748,7 @@ index 5163ec1..1bec05b 100644 /* * If HYP mode is available, we know that the physical timer * has been configured to be accessible from PL1. Use it, so -@@ -667,13 +661,31 @@ static void __init arch_timer_init(struct device_node *np) +@@ -719,13 +714,31 @@ static void __init arch_timer_init(struct device_node *np) } } @@ -4451,7 +4784,7 @@ index 5163ec1..1bec05b 100644 static void __init arch_timer_mem_init(struct device_node *np) { -@@ -740,3 +752,71 @@ static void __init arch_timer_mem_init(struct device_node *np) +@@ -792,3 +805,71 @@ static void __init arch_timer_mem_init(struct device_node *np) } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mem_init); @@ -4523,11 +4856,975 @@ index 5163ec1..1bec05b 100644 + acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); +} +#endif +diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c +index 954b9f6..a1f7e55 100644 +--- a/drivers/gpio/devres.c ++++ b/drivers/gpio/devres.c +@@ -109,6 +109,40 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, + EXPORT_SYMBOL(__devm_gpiod_get_index); + + /** ++ * devm_get_named_gpiod_from_child - managed dev_get_named_gpiod_from_child() ++ * @dev: GPIO consumer ++ * @child: firmware node (child of @dev) ++ * @propname: name of the firmware property ++ * @index: index of the GPIO in the property value in case of many ++ * ++ * GPIO descriptors returned from this function are automatically disposed on ++ * driver detach. ++ */ ++struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child, ++ const char *propname, int index) ++{ ++ struct gpio_desc **dr; ++ struct gpio_desc *desc; ++ ++ dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), ++ GFP_KERNEL); ++ if (!dr) ++ return ERR_PTR(-ENOMEM); ++ ++ desc = dev_get_named_gpiod_from_child(dev, child, propname, index); ++ if (IS_ERR(desc)) { ++ devres_free(dr); ++ return desc; ++ } ++ ++ *dr = desc; ++ devres_add(dev, dr); ++ ++ return desc; ++} ++EXPORT_SYMBOL(devm_get_named_gpiod_from_child); ++ ++/** + * 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 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 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) + { +- 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); + +- /* +- * 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); + } + +-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; + } + +-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); ++ ++ 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; ++ + /* + * 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..8aa6ca4 100644 +--- a/drivers/gpio/gpiolib-acpi.c ++++ b/drivers/gpio/gpiolib-acpi.c +@@ -290,6 +290,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) + struct acpi_gpio_lookup { + struct acpi_gpio_info info; + int index; ++ int pin_index; + struct gpio_desc *desc; + int n; + }; +@@ -303,13 +304,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; ++ ++ 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; ++ ++ /* ++ * 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 +329,75 @@ 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, NULL, ++ index, &args); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ /* ++ * 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]; ++ } ++ ++ 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); ++ } ++ + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, + &lookup); +@@ -359,8 +406,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..0fa5f79 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]); ++ } ++ ++ desc = acpi_get_gpiod_by_index(adev, propname, 0, &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; ++ } ++ ++ if (info.active_low) + *flags |= GPIO_ACTIVE_LOW; + + return desc; +@@ -1713,6 +1735,62 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, + EXPORT_SYMBOL_GPL(__gpiod_get_index); + + /** ++ * dev_get_named_gpiod_from_child - obtain a GPIO from firmware node ++ * @dev: parent device ++ * @child: firmware node (child of @dev) ++ * @propname: name of the firmware property ++ * @idx: index of the GPIO in the property value in case of many ++ * ++ * This function can be used for drivers that get their configuration ++ * from firmware in such a way that some properties are described as child ++ * nodes for the parent device in DT or ACPI. ++ * ++ * 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. ++ */ ++struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child, ++ const char *propname, int index) ++{ ++ struct gpio_desc *desc = ERR_PTR(-ENODEV); ++ bool active_low = false; ++ int ret; ++ ++ if (!child) ++ return ERR_PTR(-EINVAL); ++ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ++ enum of_gpio_flags flags; ++ ++ desc = of_get_named_gpiod_flags(child, propname, index, &flags); ++ if (!IS_ERR(desc)) ++ active_low = flags & OF_GPIO_ACTIVE_LOW; ++ } else if (ACPI_COMPANION(dev)) { ++ struct acpi_gpio_info info; ++ ++ desc = acpi_get_gpiod_by_index(child, propname, index, &info); ++ if (!IS_ERR(desc)) ++ active_low = info.active_low; ++ } ++ ++ if (IS_ERR(desc)) ++ return desc; ++ ++ 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(dev_get_named_gpiod_from_child); ++ ++/** + * 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..3563850 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,57 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev) + pdata->disable(bdev->dev); + } + +-#ifdef CONFIG_OF ++static int gpio_keys_polled_get_button(struct device *dev, void *child, ++ void *data) ++{ ++ struct gpio_keys_platform_data *pdata = data; ++ struct gpio_keys_button *button; ++ struct gpio_desc *desc; ++ ++ desc = devm_get_named_gpiod_from_child(dev, child, "gpios", 0); ++ if (IS_ERR(desc)) { ++ int err = PTR_ERR(desc); ++ ++ if (err != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get gpio flags, error: %d\n", ++ err); ++ return err; ++ } ++ ++ button = &pdata->buttons[pdata->nbuttons++]; ++ button->gpiod = desc; ++ ++ if (device_child_property_read_u32(dev, child, "linux,code", ++ &button->code)) { ++ dev_err(dev, "Button without keycode: %d\n", ++ pdata->nbuttons - 1); ++ return -EINVAL; ++ } ++ ++ device_child_property_read_string(dev, child, "label", &button->desc); ++ ++ if (device_child_property_read_u32(dev, child, "linux,input-type", ++ &button->type)) ++ button->type = EV_KEY; ++ ++ button->wakeup = !device_get_child_property(dev, child, ++ "gpio-key,wakeup", NULL); ++ ++ if (device_child_property_read_u32(dev, child, "debounce-interval", ++ &button->debounce_interval)) ++ button->debounce_interval = 5; ++ ++ return 0; ++} ++ + 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; + 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,54 +160,14 @@ 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_get_property(dev, "autorepeat", NULL); ++ 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; +- +- 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; +- if (error != -EPROBE_DEFER) +- dev_err(dev, +- "Failed to get gpio flags, error: %d\n", +- error); +- return ERR_PTR(error); +- } +- +- button = &pdata->buttons[i++]; +- +- button->gpio = gpio; +- button->active_low = flags & OF_GPIO_ACTIVE_LOW; +- +- if (of_property_read_u32(pp, "linux,code", &button->code)) { +- dev_err(dev, "Button without keycode: 0x%x\n", +- button->gpio); +- return ERR_PTR(-EINVAL); +- } +- +- button->desc = of_get_property(pp, "label", NULL); +- +- if (of_property_read_u32(pp, "linux,input-type", &button->type)) +- button->type = EV_KEY; +- +- button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); +- +- if (of_property_read_u32(pp, "debounce-interval", +- &button->debounce_interval)) +- button->debounce_interval = 5; +- } ++ error = device_for_each_child_node(dev, gpio_keys_polled_get_button, ++ pdata); ++ if (error) ++ return ERR_PTR(error); + + if (pdata->nbuttons == 0) + return ERR_PTR(-EINVAL); +@@ -187,14 +181,11 @@ 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 const struct acpi_device_id gpio_keys_polled_acpi_match[] = { ++ { "PRP0001" }, /* Device Tree shoehorned into ACPI */ ++ { }, ++}; ++MODULE_DEVICE_TABLE(acpi, gpio_keys_polled_acpi_match); + + static int gpio_keys_polled_probe(struct platform_device *pdev) + { +@@ -259,7 +250,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 +257,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; ++ } ++ ++ 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 +314,8 @@ 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, ++ .acpi_match_table = gpio_keys_polled_acpi_match, + }, + }; + module_platform_driver(gpio_keys_polled_driver); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c -index a0698b4..d2da911 100644 +index aa17ae8..d330dab 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c -@@ -490,9 +490,19 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) +@@ -506,9 +506,19 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) isb(); } @@ -4548,7 +5845,7 @@ index a0698b4..d2da911 100644 } diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c -index dda6dbc..5d9bdd3 100644 +index 38493ff..26e6773 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -33,12 +33,14 @@ @@ -4566,7 +5863,7 @@ index dda6dbc..5d9bdd3 100644 #include <asm/cputype.h> #include <asm/irq.h> -@@ -622,6 +624,13 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) +@@ -641,6 +643,13 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) raw_spin_unlock_irqrestore(&irq_controller_lock, flags); } @@ -4580,7 +5877,7 @@ index dda6dbc..5d9bdd3 100644 #endif #ifdef CONFIG_BL_SWITCHER -@@ -977,6 +986,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, +@@ -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); @@ -4590,7 +5887,7 @@ index dda6dbc..5d9bdd3 100644 #endif set_handle_irq(gic_handle_irq); } -@@ -1029,3 +1041,107 @@ IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init); +@@ -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 @@ -4717,11 +6014,470 @@ index 0fe2f71..9106c6d 100644 + + acpi_gic_init(); } +diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c +index 57ff20f..681efd5 100644 +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -13,22 +13,20 @@ + #include <linux/kernel.h> + #include <linux/platform_device.h> + #include <linux/gpio.h> ++#include <linux/gpio/consumer.h> + #include <linux/leds.h> +-#include <linux/of.h> +-#include <linux/of_platform.h> +-#include <linux/of_gpio.h> + #include <linux/slab.h> + #include <linux/workqueue.h> + #include <linux/module.h> + #include <linux/err.h> ++#include <linux/property.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, + unsigned long *delay_on, unsigned long *delay_off); +@@ -40,12 +38,16 @@ 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); ++ int gpio = desc_to_gpio(led_dat->gpiod); ++ int level = led_dat->new_level; ++ ++ if (gpiod_is_active_low(led_dat->gpiod)) ++ level = !level; ++ ++ led_dat->platform_gpio_blink_set(gpio, 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 +62,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 +71,16 @@ 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, +- NULL, NULL); ++ int gpio = desc_to_gpio(led_dat->gpiod); ++ ++ if (gpiod_is_active_low(led_dat->gpiod)) ++ level = !level; ++ ++ led_dat->platform_gpio_blink_set(gpio, level, NULL, ++ NULL); + led_dat->blinking = 0; + } else +- gpio_set_value(led_dat->gpio, level); ++ gpiod_set_value(led_dat->gpiod, level); + } + } + +@@ -85,9 +89,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev, + { + struct gpio_led_data *led_dat = + container_of(led_cdev, struct gpio_led_data, cdev); ++ int gpio = desc_to_gpio(led_dat->gpiod); + + led_dat->blinking = 1; +- return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK, ++ return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK, + delay_on, delay_off); + } + +@@ -97,24 +102,33 @@ static int create_gpio_led(const struct gpio_led *template, + { + int ret, state; + +- led_dat->gpio = -1; ++ if (!template->gpiod) { ++ 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; ++ } + +- ret = devm_gpio_request(parent, template->gpio, template->name); +- if (ret < 0) +- return ret; ++ if (template->active_low) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ 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->gpiod = template->gpiod; ++ led_dat->can_sleep = gpiod_cansleep(template->gpiod); + led_dat->blinking = 0; + if (blink_set) { + led_dat->platform_gpio_blink_set = blink_set; +@@ -122,30 +136,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,65 +169,59 @@ 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 int gpio_leds_create_led(struct device *dev, void *child, void *data) ++{ ++ struct gpio_leds_priv *priv = data; ++ struct gpio_led led = {}; ++ const char *state = NULL; ++ ++ led.gpiod = devm_get_named_gpiod_from_child(dev, child, "gpios", 0); ++ if (IS_ERR(led.gpiod)) ++ return PTR_ERR(led.gpiod); ++ ++ device_child_property_read_string(dev, child, "label", &led.name); ++ device_child_property_read_string(dev, child, "linux,default-trigger", ++ &led.default_trigger); ++ ++ device_child_property_read_string(dev, child, "linux,default_state", ++ &state); ++ if (state) { ++ if (!strcmp(state, "keep")) ++ led.default_state = LEDS_GPIO_DEFSTATE_KEEP; ++ else if (!strcmp(state, "on")) ++ led.default_state = LEDS_GPIO_DEFSTATE_ON; ++ else ++ led.default_state = LEDS_GPIO_DEFSTATE_OFF; ++ } ++ ++ if (!device_get_child_property(dev, child, "retain-state-suspended", NULL)) ++ led.retain_state_suspended = 1; ++ ++ return create_gpio_led(&led, &priv->leds[priv->num_leds++], dev, NULL); ++} ++ ++static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) + { +- struct device_node *np = pdev->dev.of_node, *child; + struct gpio_leds_priv *priv; +- int count, ret; ++ int ret, count; + +- /* 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(&pdev->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); + if (!priv) + return ERR_PTR(-ENOMEM); + +- for_each_available_child_of_node(np, 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) { +- if (!strcmp(state, "keep")) +- led.default_state = LEDS_GPIO_DEFSTATE_KEEP; +- else if (!strcmp(state, "on")) +- led.default_state = LEDS_GPIO_DEFSTATE_ON; +- else +- led.default_state = LEDS_GPIO_DEFSTATE_OFF; +- } +- +- if (of_get_property(child, "retain-state-suspended", NULL)) +- led.retain_state_suspended = 1; +- +- ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], +- &pdev->dev, NULL); +- if (ret < 0) { +- of_node_put(child); +- goto err; +- } ++ ret = device_for_each_child_node(&pdev->dev, gpio_leds_create_led, priv); ++ if (ret) { ++ for (count = priv->num_leds - 2; count >= 0; count--) ++ delete_gpio_led(&priv->leds[count]); ++ return ERR_PTR(ret); + } + + return priv; +- +-err: +- for (count = priv->num_leds - 2; count >= 0; count--) +- delete_gpio_led(&priv->leds[count]); +- return ERR_PTR(-ENODEV); + } + + static const struct of_device_id of_gpio_leds_match[] = { +@@ -228,13 +230,13 @@ 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 const struct acpi_device_id acpi_gpio_leds_match[] = { ++ { "PRP0001" }, /* Device Tree shoehorned into ACPI */ ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match); + + static int gpio_led_probe(struct platform_device *pdev) + { +@@ -263,7 +265,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); + } +@@ -290,7 +292,8 @@ 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, ++ .acpi_match_table = acpi_gpio_leds_match, + }, + }; + +diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c +index 634f729..1a760cd 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_get_property(dev, "read-only", NULL)) + 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; + +@@ -467,11 +459,18 @@ static const struct of_device_id at25_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, at25_of_match); + ++static const struct acpi_device_id at25_acpi_match[] = { ++ { "PRP0001" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(acpi, at25_acpi_match); ++ + static struct spi_driver at25_driver = { + .driver = { + .name = "at25", + .owner = THIS_MODULE, + .of_match_table = at25_of_match, ++ .acpi_match_table = at25_acpi_match, + }, + .probe = at25_probe, + .remove = at25_remove, +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 ea27383..d0d3ab5 100644 +index 9da3a03..a34cad2 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -@@ -696,6 +696,18 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, +@@ -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); @@ -4741,10 +6497,10 @@ index ea27383..d0d3ab5 100644 * 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 b26d758..ca7895c 100644 +index 2955499..423ae3d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -@@ -426,6 +426,9 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) +@@ -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++; @@ -4755,22 +6511,490 @@ index b26d758..ca7895c 100644 } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c -index bdf9cfa..ba53e41 100644 +index f5a8fa0..db29dec 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c -@@ -533,6 +533,7 @@ static int xgbe_resume(struct device *dev) +@@ -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,210 @@ 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); ++#if 0 ++ return -EINVAL; ++#else ++ dev_err(dev, "invalid MAC address, using random address\n"); ++ eth_random_addr(pdata->mac_addr); ++#endif ++ } ++ ++ /* 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 +427,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 +442,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 +468,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 +485,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 +507,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 +684,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 +707,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 e9fe6e6..389bfec 100644 +index 789957d..59498eb 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h -@@ -187,8 +187,11 @@ +@@ -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) @@ -4782,8 +7006,315 @@ index e9fe6e6..389bfec 100644 /* 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 63ea194..bb059b4 100644 +--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c ++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +@@ -579,9 +579,11 @@ static void xgene_enet_reset(struct xgene_enet_pdata *pdata) + { + u32 val; + +- clk_prepare_enable(pdata->clk); +- clk_disable_unprepare(pdata->clk); +- clk_prepare_enable(pdata->clk); ++ if (pdata->clk) { ++ 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); + +@@ -647,15 +649,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; + } +@@ -665,11 +672,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; +@@ -686,7 +734,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; + } +@@ -704,7 +752,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 3c208cc..6370ff4 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; +@@ -873,7 +918,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) +@@ -934,7 +979,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; +@@ -981,6 +1026,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",}, + {}, +@@ -992,6 +1045,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 874e5a0..8b7e2cf 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 bcaa41a..ebad872 100644 +index 5e94d00..a6131a9 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -81,6 +81,7 @@ static const char version[] = @@ -4794,7 +7325,7 @@ index bcaa41a..ebad872 100644 #include <linux/netdevice.h> #include <linux/etherdevice.h> -@@ -2408,6 +2409,14 @@ static struct dev_pm_ops smc_drv_pm_ops = { +@@ -2405,6 +2406,14 @@ static struct dev_pm_ops smc_drv_pm_ops = { .resume = smc_drv_resume, }; @@ -4809,7 +7340,7 @@ index bcaa41a..ebad872 100644 static struct platform_driver smc_driver = { .probe = smc_drv_probe, .remove = smc_drv_remove, -@@ -2416,6 +2425,7 @@ static struct platform_driver smc_driver = { +@@ -2413,6 +2422,7 @@ static struct platform_driver smc_driver = { .owner = THIS_MODULE, .pm = &smc_drv_pm_ops, .of_match_table = of_match_ptr(smc91x_match), @@ -4817,11 +7348,29 @@ index bcaa41a..ebad872 100644 }, }; +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 f3230ee..90145d9 100644 +index c456559..d852c6e 100644 --- a/drivers/net/phy/amd-xgbe-phy.c +++ b/drivers/net/phy/amd-xgbe-phy.c -@@ -78,12 +78,14 @@ +@@ -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@amd.com>"); MODULE_LICENSE("Dual BSD/GPL"); @@ -4838,10 +7387,39 @@ index f3230ee..90145d9 100644 #define XGBE_PHY_SPEEDSET_PROPERTY "amd,speed-set" #define XGBE_AN_INT_CMPLT 0x01 -@@ -118,77 +120,6 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); +@@ -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 @@ -4885,7 +7463,6 @@ index f3230ee..90145d9 100644 -#define SPEED_1000_TXAMP 0xf -#define SPEED_1000_WORD 0x1 - -- -/* SerDes RxTx register offsets */ -#define RXTX_REG20 0x0050 -#define RXTX_REG114 0x01c8 @@ -4916,7 +7493,7 @@ index f3230ee..90145d9 100644 #define GET_BITS(_var, _index, _width) \ (((_var) >> (_index)) & ((0x1 << (_width)) - 1)) -@@ -198,71 +129,12 @@ do { \ +@@ -207,70 +130,12 @@ do { \ (_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \ } while (0) @@ -4929,9 +7506,7 @@ index f3230ee..90145d9 100644 - SET_BITS((_var), \ - _prefix##_##_field##_INDEX, \ - _prefix##_##_field##_WIDTH, (_val)) -+#define XCMU_IOREAD(_priv, _reg) \ -+ ioread16((_priv)->cmu_regs + _reg) - +- -/* 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 @@ -4941,9 +7516,7 @@ index f3230ee..90145d9 100644 - */ -#define XSIR0_IOREAD(_priv, _reg) \ - ioread16((_priv)->sir0_regs + _reg) -+#define XCMU_IOWRITE(_priv, _reg, _val) \ -+ iowrite16((_val), (_priv)->cmu_regs + _reg) - +- -#define XSIR0_IOREAD_BITS(_priv, _reg, _field) \ - GET_BITS(XSIR0_IOREAD((_priv), _reg), \ - _reg##_##_field##_INDEX, \ @@ -4968,10 +7541,14 @@ index f3230ee..90145d9 100644 - 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); \ @@ -4981,7 +7558,6 @@ index f3230ee..90145d9 100644 - 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 @@ -4992,7 +7568,7 @@ index f3230ee..90145d9 100644 #define XRXTX_IOREAD(_priv, _reg) \ ioread16((_priv)->rxtx_regs + _reg) -@@ -283,6 +155,77 @@ do { \ +@@ -291,6 +156,78 @@ do { \ XRXTX_IOWRITE((_priv), _reg, reg_val); \ } while (0) @@ -5067,10 +7643,25 @@ index f3230ee..90145d9 100644 + + +DEFINE_SPINLOCK(cmu_lock); - ++ enum amd_xgbe_phy_an { AMD_XGBE_AN_READY = 0, -@@ -321,18 +264,18 @@ struct amd_xgbe_phy_priv { + 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; @@ -5089,12 +7680,20 @@ index f3230ee..90145d9 100644 /* Maintain link status for re-starting auto-negotiation */ unsigned int link; - enum amd_xgbe_phy_mode mode; - unsigned int speed_set; ++ enum amd_xgbe_phy_mode mode; /* Auto-negotiation state machine support */ struct mutex an_mutex; -@@ -394,33 +337,51 @@ static int amd_xgbe_phy_pcs_power_cycle(struct phy_device *phydev) +@@ -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; @@ -5157,7 +7756,7 @@ index f3230ee..90145d9 100644 } static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) -@@ -428,8 +389,8 @@ 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; @@ -5168,7 +7767,7 @@ index f3230ee..90145d9 100644 if (ret < 0) return ret; -@@ -455,19 +416,30 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) +@@ -462,19 +418,32 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) return ret; /* Set SerDes to 10G speed */ @@ -5183,14 +7782,14 @@ index f3230ee..90145d9 100644 - 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, RXTX_10000_BLWC); -- XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_10000_PQ); ++ + XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, 0); + + XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_10G_PLL); @@ -5203,10 +7802,12 @@ index f3230ee..90145d9 100644 + spin_unlock(&cmu_lock); + - priv->mode = AMD_XGBE_MODE_KR; - ++ priv->mode = AMD_XGBE_MODE_KR; ++ return 0; -@@ -505,19 +477,30 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev) + } + +@@ -510,19 +479,32 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev) return ret; /* Set SerDes to 2.5G speed */ @@ -5223,12 +7824,12 @@ index f3230ee..90145d9 100644 + XRXTX_IOWRITE_BITS(priv, RXTX_REG3, TX_WORD_MODE, RXTX_10BIT_WORD); + + XRXTX_IOWRITE_BITS(priv, RXTX_REG5, TXAMP_CNTL, RXTX_1G_TX_AMP); ++ ++ 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_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, 1); + + XRXTX_IOWRITE_BITS(priv, RXTX_REG53, RX_PLLSELECT, RXTX_1G_PLL); @@ -5241,10 +7842,12 @@ index f3230ee..90145d9 100644 + spin_unlock(&cmu_lock); + - priv->mode = AMD_XGBE_MODE_KX; - ++ priv->mode = AMD_XGBE_MODE_KX; ++ return 0; -@@ -555,19 +538,30 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev) + } + +@@ -558,47 +540,33 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev) return ret; /* Set SerDes to 1G speed */ @@ -5259,30 +7862,102 @@ index f3230ee..90145d9 100644 - 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_REG5, TXAMP_CNTL, RXTX_1G_TX_AMP); - 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); - amd_xgbe_phy_serdes_complete_ratechange(phydev); +- 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); -+ - priv->mode = AMD_XGBE_MODE_KX; - return 0; -@@ -639,13 +633,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, +- 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; @@ -5296,20 +7971,234 @@ index f3230ee..90145d9 100644 return AMD_XGBE_AN_EVENT; } -@@ -1291,21 +1281,33 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) - goto err_priv; - } +@@ -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; -- 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); +@@ -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; ++ + /* 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) ++{ ++ struct device *dev = priv->dev; ++ int ret; ++ ++ /* 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); ++ } ++ + /* 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(pdev, IORESOURCE_MEM, 1); ++ 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; @@ -5320,54 +8209,258 @@ index f3230ee..90145d9 100644 + if (!priv->cmu_regs) { + dev_err(dev, "cmu ioremap failed\n"); + ret = -ENOMEM; - goto err_rxtx; ++ goto err_rxtx; ++ } ++ ++ return 0; ++ ++err_rxtx: ++ devm_iounmap(dev, priv->rxtx_regs); ++ devm_release_mem_region(dev, priv->rxtx_res->start, ++ resource_size(priv->rxtx_res)); ++ ++ return ret; ++} ++ ++static void amd_xgbe_phy_unmap_resources(struct amd_xgbe_phy_priv *priv) ++{ ++ struct device *dev = priv->dev; ++ ++ devm_iounmap(dev, priv->cmu_regs); ++ ++ devm_iounmap(dev, priv->rxtx_regs); ++ devm_release_mem_region(dev, priv->rxtx_res->start, ++ resource_size(priv->rxtx_res)); ++} ++ ++#ifdef CONFIG_ACPI ++static int amd_xgbe_phy_acpi_support(struct amd_xgbe_phy_priv *priv) ++{ ++ 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; ++ ++ /* Map the memory resources */ ++ ret = amd_xgbe_phy_map_resources(priv, phy_pdev, 2); ++ if (ret) ++ return 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; ++ ++ /* 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; ++ } ++ priv->speed_set = property->integer.value; ++ ++ return 0; ++ ++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) ++{ ++ return -EINVAL; ++} ++#endif /* CONFIG_ACPI */ ++ ++#ifdef CONFIG_OF ++static int amd_xgbe_phy_of_support(struct amd_xgbe_phy_priv *priv) ++{ ++ 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; ++ ++ 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; ++ } ++ ++ 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; ++ } ++ ++ /* 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); ++ ++ /* 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); ++ ++ of_node_put(phy_node); ++ ++ return 0; ++ ++err_resources: ++ amd_xgbe_phy_unmap_resources(priv); ++ ++err_put: ++ of_node_put(phy_node); ++ ++ return ret; ++} ++#else /* CONFIG_OF */ ++static int amd_xgbe_phy_of_support(struct amd_xgbe_phy_priv *priv) ++{ ++ return -EINVAL; ++} ++#endif /* CONFIG_OF */ ++ + 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; + + 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) + 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 serdes channel property */ -+ property = of_get_property(dev->of_node, XGBE_PHY_CHANNEL_PROPERTY, -+ NULL); -+ if (!property) { -+ dev_err(dev, "unable to obtain serdes_channel property\n"); -+ ret = -EINVAL; -+ goto err_cmu; - } -+ priv->serdes_channel = be32_to_cpu(*property); +- } - /* Get the device speed set property */ - speed_set = 0; -@@ -1324,14 +1326,14 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) +- /* 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_cmu; ++ goto err_resources; } priv->link = 1; - ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); - if (ret < 0) -- goto err_sir1; -+ goto err_cmu; - if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR) - priv->mode = AMD_XGBE_MODE_KR; - else -@@ -1342,7 +1344,7 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) ++ 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_cmu; ++ goto err_resources; } phydev->priv = priv; -@@ -1352,15 +1354,8 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) + + kfree(wq_name); +- of_dev_put(pdev); return 0; @@ -5380,12 +8473,27 @@ index f3230ee..90145d9 100644 - devm_iounmap(dev, priv->sir0_regs); - devm_release_mem_region(dev, priv->sir0_res->start, - resource_size(priv->sir0_res)); -+err_cmu: -+ devm_iounmap(dev, priv->cmu_regs); +- +-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; + } - err_rxtx: - devm_iounmap(dev, priv->rxtx_regs); -@@ -1392,14 +1387,7 @@ static void amd_xgbe_phy_remove(struct phy_device *phydev) +@@ -1424,18 +1500,7 @@ static void amd_xgbe_phy_remove(struct phy_device *phydev) flush_workqueue(priv->an_workqueue); destroy_workqueue(priv->an_workqueue); @@ -5397,1334 +8505,222 @@ index f3230ee..90145d9 100644 - devm_iounmap(dev, priv->sir0_regs); - devm_release_mem_region(dev, priv->sir0_res->start, - resource_size(priv->sir0_res)); -+ devm_iounmap(dev, priv->cmu_regs); - - devm_iounmap(dev, priv->rxtx_regs); - devm_release_mem_region(dev, priv->rxtx_res->start, -diff --git a/drivers/of/address.c b/drivers/of/address.c -index e371825..afdb782 100644 ---- a/drivers/of/address.c -+++ b/drivers/of/address.c -@@ -5,6 +5,8 @@ - #include <linux/module.h> - #include <linux/of_address.h> - #include <linux/pci_regs.h> -+#include <linux/sizes.h> -+#include <linux/slab.h> - #include <linux/string.h> +- +- 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); - /* Max address size we deal with */ -@@ -293,6 +295,51 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, + devm_kfree(dev, priv); } - EXPORT_SYMBOL_GPL(of_pci_range_parser_one); +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 2305dc0..43999a8 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_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. + /** ++ * of_property_read_u64_array - Find and read an array of 64 bit integers ++ * from a property. + * -+ * Returns EINVAL if the range cannot be converted to resource. ++ * @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 + * -+ * 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. -+ */ -+int of_pci_range_to_resource(struct of_pci_range *range, -+ struct device_node *np, struct resource *res) -+{ -+ int err; -+ res->flags = range->flags; -+ res->parent = res->child = res->sibling = NULL; -+ res->name = np->full_name; -+ -+ if (res->flags & IORESOURCE_IO) { -+ unsigned long port; -+ err = pci_register_io_range(range->cpu_addr, range->size); -+ if (err) -+ goto invalid_range; -+ port = pci_address_to_pio(range->cpu_addr); -+ if (port == (unsigned long)-1) { -+ err = -EINVAL; -+ goto invalid_range; -+ } -+ res->start = port; -+ } else { -+ res->start = range->cpu_addr; -+ } -+ res->end = res->start + range->size - 1; -+ return 0; -+ -+invalid_range: -+ res->start = (resource_size_t)OF_BAD_ADDR; -+ res->end = (resource_size_t)OF_BAD_ADDR; -+ return err; -+} - #endif /* CONFIG_PCI */ - - /* -@@ -601,12 +648,119 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, - } - EXPORT_SYMBOL(of_get_address); - -+#ifdef PCI_IOBASE -+struct io_range { -+ struct list_head list; -+ phys_addr_t start; -+ resource_size_t size; -+}; -+ -+static LIST_HEAD(io_range_list); -+static DEFINE_SPINLOCK(io_range_lock); -+#endif -+ -+/* -+ * Record the PCI IO range (expressed as CPU physical address + size). -+ * Return a negative value if an error has occured, zero otherwise ++ * 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 __weak pci_register_io_range(phys_addr_t addr, resource_size_t size) ++int of_property_read_u64_array(const struct device_node *np, ++ const char *propname, u64 *out_values, ++ size_t sz) +{ -+ int err = 0; ++ const __be32 *val = of_find_property_value_of_size(np, propname, ++ (sz * sizeof(*out_values))); + -+#ifdef PCI_IOBASE -+ struct io_range *range; -+ resource_size_t allocated_size = 0; ++ if (IS_ERR(val)) ++ return PTR_ERR(val); + -+ /* check if the range hasn't been previously recorded */ -+ spin_lock(&io_range_lock); -+ list_for_each_entry(range, &io_range_list, list) { -+ if (addr >= range->start && addr + size <= range->start + size) { -+ /* range already registered, bail out */ -+ goto end_register; -+ } -+ allocated_size += range->size; -+ } -+ -+ /* range not registed yet, check for available space */ -+ if (allocated_size + size - 1 > IO_SPACE_LIMIT) { -+ /* if it's too big check if 64K space can be reserved */ -+ if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) { -+ err = -E2BIG; -+ goto end_register; -+ } -+ -+ size = SZ_64K; -+ pr_warn("Requested IO range too big, new size set to 64K\n"); -+ } -+ -+ /* add the range to the list */ -+ range = kzalloc(sizeof(*range), GFP_KERNEL); -+ if (!range) { -+ err = -ENOMEM; -+ goto end_register; -+ } -+ -+ range->start = addr; -+ range->size = size; -+ -+ list_add_tail(&range->list, &io_range_list); -+ -+end_register: -+ spin_unlock(&io_range_lock); -+#endif -+ -+ return err; -+} -+ -+phys_addr_t pci_pio_to_address(unsigned long pio) -+{ -+ phys_addr_t address = (phys_addr_t)OF_BAD_ADDR; -+ -+#ifdef PCI_IOBASE -+ struct io_range *range; -+ resource_size_t allocated_size = 0; -+ -+ if (pio > IO_SPACE_LIMIT) -+ return address; -+ -+ spin_lock(&io_range_lock); -+ list_for_each_entry(range, &io_range_list, list) { -+ if (pio >= allocated_size && pio < allocated_size + range->size) { -+ address = range->start + pio - allocated_size; -+ break; -+ } -+ allocated_size += range->size; ++ while (sz--) { ++ *out_values++ = of_read_number(val, 2); ++ val += 2; + } -+ spin_unlock(&io_range_lock); -+#endif -+ -+ return address; ++ return 0; +} + - unsigned long __weak pci_address_to_pio(phys_addr_t address) - { -+#ifdef PCI_IOBASE -+ struct io_range *res; -+ resource_size_t offset = 0; -+ unsigned long addr = -1; -+ -+ spin_lock(&io_range_lock); -+ list_for_each_entry(res, &io_range_list, list) { -+ if (address >= res->start && address < res->start + res->size) { -+ addr = res->start - address + offset; -+ break; -+ } -+ offset += res->size; -+ } -+ spin_unlock(&io_range_lock); -+ -+ return addr; -+#else - if (address > IO_SPACE_LIMIT) - return (unsigned long)-1; - - return (unsigned long) address; -+#endif - } - - static int __of_address_to_resource(struct device_node *dev, -diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c -index 8481996..8882b46 100644 ---- a/drivers/of/of_pci.c -+++ b/drivers/of/of_pci.c -@@ -1,7 +1,9 @@ - #include <linux/kernel.h> - #include <linux/export.h> - #include <linux/of.h> -+#include <linux/of_address.h> - #include <linux/of_pci.h> -+#include <linux/slab.h> - - static inline int __of_pci_pci_compare(struct device_node *node, - unsigned int data) -@@ -89,6 +91,146 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res) ++/** + * 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. +@@ -1397,6 +1430,49 @@ int of_property_count_strings(struct device_node *np, const char *propname) } - EXPORT_SYMBOL_GPL(of_pci_parse_bus_range); + EXPORT_SYMBOL_GPL(of_property_count_strings); +/** -+ * This function will try to obtain the host bridge domain number by -+ * finding a property called "linux,pci-domain" of the given device node. ++ * of_property_read_string_array - Find and read an array of strings ++ * from a multiple strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * @out_string: pointer to null terminated return string, modified only if ++ * return value is 0. ++ * @sz: number of array elements to read + * -+ * @node: device tree node with the domain information ++ * Search for a property in a device tree node and retrieve a list of ++ * terminated string value (pointer to data, not a copy) in that property. ++ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * property does not have a value, and -EOVERFLOW if the string is not ++ * null-terminated within the length of the property data. + * -+ * Returns the associated domain number from DT in the range [0-0xffff], or -+ * a negative value if the required property is not found. ++ * The out_string pointer is modified only if a valid string can be decoded. + */ -+int of_get_pci_domain_nr(struct device_node *node) ++int of_property_read_string_array(struct device_node *np, const char *propname, ++ char **output, size_t sz) +{ -+ const __be32 *value; -+ int len; -+ u16 domain; ++ struct property *prop = of_find_property(np, propname, NULL); ++ int i = 0; ++ size_t l = 0, total = 0; ++ char *p; + -+ value = of_get_property(node, "linux,pci-domain", &len); -+ if (!value || len < sizeof(*value)) ++ if (!prop) + return -EINVAL; + -+ domain = (u16)be32_to_cpup(value); -+ -+ return domain; -+} -+EXPORT_SYMBOL_GPL(of_get_pci_domain_nr); -+ -+#if defined(CONFIG_OF_ADDRESS) -+/** -+ * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT -+ * @dev: device node of the host bridge having the range property -+ * @busno: bus number associated with the bridge root bus -+ * @bus_max: maximum number of buses for this bridge -+ * @resources: list where the range of resources will be added after DT parsing -+ * @io_base: pointer to a variable that will contain on return the physical -+ * address for the start of the I/O range. Can be NULL if the caller doesn't -+ * expect IO ranges to be present in the device tree. -+ * -+ * It is the caller's job to free the @resources list. -+ * -+ * This function will parse the "ranges" property of a PCI host bridge device -+ * node and setup the resource mapping based on its content. It is expected -+ * that the property conforms with the Power ePAPR document. -+ * -+ * It returns zero if the range parsing has been successful or a standard error -+ * value if it failed. -+ */ -+int of_pci_get_host_bridge_resources(struct device_node *dev, -+ unsigned char busno, unsigned char bus_max, -+ struct list_head *resources, resource_size_t *io_base) -+{ -+ struct resource *res; -+ struct resource *bus_range; -+ struct of_pci_range range; -+ struct of_pci_range_parser parser; -+ char range_type[4]; -+ int err; -+ -+ if (io_base) -+ *io_base = (resource_size_t)OF_BAD_ADDR; -+ -+ bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL); -+ if (!bus_range) -+ return -ENOMEM; -+ -+ pr_info("PCI host bridge %s ranges:\n", dev->full_name); -+ -+ err = of_pci_parse_bus_range(dev, bus_range); -+ if (err) { -+ bus_range->start = busno; -+ bus_range->end = bus_max; -+ bus_range->flags = IORESOURCE_BUS; -+ pr_info(" No bus range found for %s, using %pR\n", -+ dev->full_name, bus_range); -+ } else { -+ if (bus_range->end > bus_range->start + bus_max) -+ bus_range->end = bus_range->start + bus_max; -+ } -+ pci_add_resource(resources, bus_range); -+ -+ /* Check for ranges property */ -+ err = of_pci_range_parser_init(&parser, dev); -+ if (err) -+ goto parse_failed; -+ -+ pr_debug("Parsing ranges property...\n"); -+ for_each_of_pci_range(&parser, &range) { -+ /* Read next ranges element */ -+ if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO) -+ snprintf(range_type, 4, " IO"); -+ else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM) -+ snprintf(range_type, 4, "MEM"); -+ else -+ snprintf(range_type, 4, "err"); -+ pr_info(" %s %#010llx..%#010llx -> %#010llx\n", range_type, -+ range.cpu_addr, range.cpu_addr + range.size - 1, -+ range.pci_addr); -+ -+ /* -+ * If we failed translation or got a zero-sized region -+ * then skip this range -+ */ -+ if (range.cpu_addr == OF_BAD_ADDR || range.size == 0) -+ continue; ++ if (!prop->value) ++ return -ENODATA; + -+ res = kzalloc(sizeof(struct resource), GFP_KERNEL); -+ if (!res) { -+ err = -ENOMEM; -+ goto parse_failed; -+ } ++ if (strnlen(prop->value, prop->length) >= prop->length) ++ return -EOVERFLOW; + -+ err = of_pci_range_to_resource(&range, dev, res); -+ if (err) -+ goto conversion_failed; -+ -+ if (resource_type(res) == IORESOURCE_IO) { -+ if (!io_base) { -+ pr_err("I/O range found for %s. Please provide an io_base pointer to save CPU base address\n", -+ dev->full_name); -+ err = -EINVAL; -+ goto conversion_failed; -+ } -+ if (*io_base != (resource_size_t)OF_BAD_ADDR) -+ pr_warn("More than one I/O resource converted for %s. CPU base address for old range lost!\n", -+ dev->full_name); -+ *io_base = range.cpu_addr; -+ } ++ p = prop->value; + -+ pci_add_resource_offset(resources, res, res->start - range.pci_addr); ++ for (i = 0; total < prop->length; total += l, p += l) { ++ output[i++] = p; ++ l = strlen(p) + 1; + } -+ + return 0; -+ -+conversion_failed: -+ kfree(res); -+parse_failed: -+ pci_free_resource_list(resources); -+ return err; +} -+EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources); -+#endif /* CONFIG_OF_ADDRESS */ + - #ifdef CONFIG_PCI_MSI - - static LIST_HEAD(of_pci_msi_chip_list); -diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig -index 90f5cca..382fd3d 100644 ---- a/drivers/pci/host/Kconfig -+++ b/drivers/pci/host/Kconfig -@@ -63,4 +63,14 @@ config PCIE_SPEAR13XX - help - Say Y here if you want PCIe support on SPEAr13XX SoCs. - -+config PCI_XGENE -+ bool "X-Gene PCIe controller" -+ depends on ARCH_XGENE -+ depends on OF -+ select PCIEPORTBUS -+ help -+ Say Y here if you want internal PCI support on APM X-Gene SoC. -+ There are 5 internal PCIe ports available. Each port is GEN3 capable -+ and have varied lanes from x1 to x8. -+ - endmenu -diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile -index d0e88f1..845611f 100644 ---- a/drivers/pci/host/Makefile -+++ b/drivers/pci/host/Makefile -@@ -8,3 +8,4 @@ obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o - obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o - obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o - obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o -+obj-$(CONFIG_PCI_XGENE) += pci-xgene.o -diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c -index 0fb0fdb..946935d 100644 ---- a/drivers/pci/host/pci-tegra.c -+++ b/drivers/pci/host/pci-tegra.c -@@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable); - static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) + void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) { - struct tegra_pcie *pcie = sys_to_pcie(sys); -+ phys_addr_t io_start = pci_pio_to_address(pcie->io.start); - - pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); - pci_add_resource_offset(&sys->resources, &pcie->prefetch, - sys->mem_offset); - pci_add_resource(&sys->resources, &pcie->busn); - -- pci_ioremap_io(nr * SZ_64K, pcie->io.start); -+ pci_ioremap_io(nr * SZ_64K, io_start); - - return 1; + int i; +@@ -2186,3 +2262,113 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) + return of_get_next_parent(np); } -@@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg) - static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) - { - u32 fpci_bar, size, axi_address; -+ phys_addr_t io_start = pci_pio_to_address(pcie->io.start); - - /* Bar 0: type 1 extended configuration space */ - fpci_bar = 0xfe100000; -@@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) - /* Bar 1: downstream IO bar */ - fpci_bar = 0xfdfc0000; - size = resource_size(&pcie->io); -- axi_address = pcie->io.start; -+ axi_address = io_start; - afi_writel(pcie, axi_address, AFI_AXI_BAR1_START); - afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); - afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1); -@@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) - } - - for_each_of_pci_range(&parser, &range) { -- of_pci_range_to_resource(&range, np, &res); -+ err = of_pci_range_to_resource(&range, np, &res); -+ if (err < 0) -+ return err; - - switch (res.flags & IORESOURCE_TYPE_BITS) { - case IORESOURCE_IO: -diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c -new file mode 100644 -index 0000000..41c76b8 ---- /dev/null -+++ b/drivers/pci/host/pci-xgene.c -@@ -0,0 +1,659 @@ -+/** -+ * APM X-Gene PCIe Driver -+ * -+ * Copyright (c) 2014 Applied Micro Circuits Corporation. -+ * -+ * Author: Tanmay Inamdar <tinamdar@apm.com>. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+#include <linux/clk-private.h> -+#include <linux/delay.h> -+#include <linux/io.h> -+#include <linux/jiffies.h> -+#include <linux/memblock.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/of_irq.h> -+#include <linux/of_pci.h> -+#include <linux/pci.h> -+#include <linux/platform_device.h> -+#include <linux/slab.h> -+ -+#define PCIECORE_CTLANDSTATUS 0x50 -+#define PIM1_1L 0x80 -+#define IBAR2 0x98 -+#define IR2MSK 0x9c -+#define PIM2_1L 0xa0 -+#define IBAR3L 0xb4 -+#define IR3MSKL 0xbc -+#define PIM3_1L 0xc4 -+#define OMR1BARL 0x100 -+#define OMR2BARL 0x118 -+#define OMR3BARL 0x130 -+#define CFGBARL 0x154 -+#define CFGBARH 0x158 -+#define CFGCTL 0x15c -+#define RTDID 0x160 -+#define BRIDGE_CFG_0 0x2000 -+#define BRIDGE_CFG_4 0x2010 -+#define BRIDGE_STATUS_0 0x2600 -+ -+#define LINK_UP_MASK 0x00000100 -+#define AXI_EP_CFG_ACCESS 0x10000 -+#define EN_COHERENCY 0xF0000000 -+#define EN_REG 0x00000001 -+#define OB_LO_IO 0x00000002 -+#define XGENE_PCIE_VENDORID 0x10E8 -+#define XGENE_PCIE_DEVICEID 0xE004 -+#define SZ_1T (SZ_1G*1024ULL) -+#define PIPE_PHY_RATE_RD(src) ((0xc000 & (u32)(src)) >> 0xe) -+ -+struct xgene_pcie_port { -+ struct device_node *node; -+ struct device *dev; -+ struct clk *clk; -+ void __iomem *csr_base; -+ void __iomem *cfg_base; -+ unsigned long cfg_addr; -+ bool link_up; -+}; -+ -+static inline u32 pcie_bar_low_val(u32 addr, u32 flags) -+{ -+ return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags; -+} -+ -+/* PCIE Configuration Out/In */ -+static inline void xgene_pcie_cfg_out32(void __iomem *addr, int offset, u32 val) -+{ -+ writel(val, addr + offset); -+} -+ -+static inline void xgene_pcie_cfg_out16(void __iomem *addr, int offset, u16 val) -+{ -+ u32 val32 = readl(addr + (offset & ~0x3)); -+ -+ switch (offset & 0x3) { -+ case 2: -+ val32 &= ~0xFFFF0000; -+ val32 |= (u32)val << 16; -+ break; -+ case 0: -+ default: -+ val32 &= ~0xFFFF; -+ val32 |= val; -+ break; -+ } -+ writel(val32, addr + (offset & ~0x3)); -+} -+ -+static inline void xgene_pcie_cfg_out8(void __iomem *addr, int offset, u8 val) -+{ -+ u32 val32 = readl(addr + (offset & ~0x3)); -+ -+ switch (offset & 0x3) { -+ case 0: -+ val32 &= ~0xFF; -+ val32 |= val; -+ break; -+ case 1: -+ val32 &= ~0xFF00; -+ val32 |= (u32)val << 8; -+ break; -+ case 2: -+ val32 &= ~0xFF0000; -+ val32 |= (u32)val << 16; -+ break; -+ case 3: -+ default: -+ val32 &= ~0xFF000000; -+ val32 |= (u32)val << 24; -+ break; -+ } -+ writel(val32, addr + (offset & ~0x3)); -+} -+ -+static inline void xgene_pcie_cfg_in32(void __iomem *addr, int offset, u32 *val) -+{ -+ *val = readl(addr + offset); -+} -+ -+static inline void xgene_pcie_cfg_in16(void __iomem *addr, int offset, u32 *val) -+{ -+ *val = readl(addr + (offset & ~0x3)); -+ -+ switch (offset & 0x3) { -+ case 2: -+ *val >>= 16; -+ break; -+ } -+ -+ *val &= 0xFFFF; -+} -+ -+static inline void xgene_pcie_cfg_in8(void __iomem *addr, int offset, u32 *val) -+{ -+ *val = readl(addr + (offset & ~0x3)); -+ -+ switch (offset & 0x3) { -+ case 3: -+ *val = *val >> 24; -+ break; -+ case 2: -+ *val = *val >> 16; -+ break; -+ case 1: -+ *val = *val >> 8; -+ break; -+ } -+ *val &= 0xFF; -+} -+ -+/* -+ * When the address bit [17:16] is 2'b01, the Configuration access will be -+ * treated as Type 1 and it will be forwarded to external PCIe device. -+ */ -+static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus) -+{ -+ struct xgene_pcie_port *port = bus->sysdata; -+ -+ if (bus->number >= (bus->primary + 1)) -+ return port->cfg_base + AXI_EP_CFG_ACCESS; -+ -+ return port->cfg_base; -+} -+ -+/* -+ * For Configuration request, RTDID register is used as Bus Number, -+ * Device Number and Function number of the header fields. -+ */ -+static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn) -+{ -+ struct xgene_pcie_port *port = bus->sysdata; -+ unsigned int b, d, f; -+ u32 rtdid_val = 0; -+ -+ b = bus->number; -+ d = PCI_SLOT(devfn); -+ f = PCI_FUNC(devfn); -+ -+ if (!pci_is_root_bus(bus)) -+ rtdid_val = (b << 8) | (d << 3) | f; -+ -+ writel(rtdid_val, port->csr_base + RTDID); -+ /* read the register back to ensure flush */ -+ readl(port->csr_base + RTDID); -+} -+ -+/* -+ * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as -+ * the translation between PCI bus to native BUS. Entire DDR region -+ * is mapped on to PCIe space using these registers, so that it is -+ * accessible for EP devices for DMA. The BAR0/1 of bridge should be -+ * hidden during enumeration to avoid the sizing and resource allocation -+ * by PCIe core. -+ */ -+static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset) -+{ -+ if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) || -+ (offset == PCI_BASE_ADDRESS_1))) -+ return true; -+ -+ return false; -+} -+ -+static int xgene_pcie_read_config(struct pci_bus *bus, unsigned int devfn, -+ int offset, int len, u32 *val) -+{ -+ struct xgene_pcie_port *port = bus->sysdata; -+ void __iomem *addr; -+ -+ if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ -+ if (xgene_pcie_hide_rc_bars(bus, offset)) { -+ *val = 0; -+ return PCIBIOS_SUCCESSFUL; -+ } -+ -+ xgene_pcie_set_rtdid_reg(bus, devfn); -+ addr = xgene_pcie_get_cfg_base(bus); -+ switch (len) { -+ case 1: -+ xgene_pcie_cfg_in8(addr, offset, val); -+ break; -+ case 2: -+ xgene_pcie_cfg_in16(addr, offset, val); -+ break; -+ default: -+ xgene_pcie_cfg_in32(addr, offset, val); -+ break; -+ } -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int xgene_pcie_write_config(struct pci_bus *bus, unsigned int devfn, -+ int offset, int len, u32 val) -+{ -+ struct xgene_pcie_port *port = bus->sysdata; -+ void __iomem *addr; + EXPORT_SYMBOL(of_graph_get_remote_port); + -+ if ((pci_is_root_bus(bus) && devfn != 0) || !port->link_up) -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ -+ if (xgene_pcie_hide_rc_bars(bus, offset)) -+ return PCIBIOS_SUCCESSFUL; -+ -+ xgene_pcie_set_rtdid_reg(bus, devfn); -+ addr = xgene_pcie_get_cfg_base(bus); -+ switch (len) { -+ case 1: -+ xgene_pcie_cfg_out8(addr, offset, (u8)val); -+ break; -+ case 2: -+ xgene_pcie_cfg_out16(addr, offset, (u16)val); -+ break; -+ default: -+ xgene_pcie_cfg_out32(addr, offset, val); -+ break; -+ } -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static struct pci_ops xgene_pcie_ops = { -+ .read = xgene_pcie_read_config, -+ .write = xgene_pcie_write_config -+}; -+ -+static u64 xgene_pcie_set_ib_mask(void __iomem *csr_base, u32 addr, -+ u32 flags, u64 size) -+{ -+ u64 mask = (~(size - 1) & PCI_BASE_ADDRESS_MEM_MASK) | flags; -+ u32 val32 = 0; -+ u32 val; -+ -+ val32 = readl(csr_base + addr); -+ val = (val32 & 0x0000ffff) | (lower_32_bits(mask) << 16); -+ writel(val, csr_base + addr); -+ -+ val32 = readl(csr_base + addr + 0x04); -+ val = (val32 & 0xffff0000) | (lower_32_bits(mask) >> 16); -+ writel(val, csr_base + addr + 0x04); -+ -+ val32 = readl(csr_base + addr + 0x04); -+ val = (val32 & 0x0000ffff) | (upper_32_bits(mask) << 16); -+ writel(val, csr_base + addr + 0x04); -+ -+ val32 = readl(csr_base + addr + 0x08); -+ val = (val32 & 0xffff0000) | (upper_32_bits(mask) >> 16); -+ writel(val, csr_base + addr + 0x08); -+ -+ return mask; -+} -+ -+static void xgene_pcie_linkup(struct xgene_pcie_port *port, -+ u32 *lanes, u32 *speed) ++int of_dev_prop_get(struct device_node *dn, const char *propname, void **valptr) +{ -+ void __iomem *csr_base = port->csr_base; -+ u32 val32; ++ struct property *pp = of_find_property(dn, propname, NULL); + -+ port->link_up = false; -+ val32 = readl(csr_base + PCIECORE_CTLANDSTATUS); -+ if (val32 & LINK_UP_MASK) { -+ port->link_up = true; -+ *speed = PIPE_PHY_RATE_RD(val32); -+ val32 = readl(csr_base + BRIDGE_STATUS_0); -+ *lanes = val32 >> 26; -+ } -+} -+ -+static int xgene_pcie_init_port(struct xgene_pcie_port *port) -+{ -+ int rc; -+ -+ port->clk = clk_get(port->dev, NULL); -+ if (IS_ERR(port->clk)) { -+ dev_err(port->dev, "clock not available\n"); -+ return -ENODEV; -+ } -+ -+ rc = clk_prepare_enable(port->clk); -+ if (rc) { -+ dev_err(port->dev, "clock enable failed\n"); -+ return rc; -+ } ++ if (!pp) ++ return -ENODATA; + ++ if (valptr) ++ *valptr = pp->value; + return 0; +} + -+static int xgene_pcie_map_reg(struct xgene_pcie_port *port, -+ struct platform_device *pdev) ++int of_dev_prop_read(struct device_node *dn, const char *propname, ++ enum dev_prop_type proptype, void *val) +{ -+ 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); ++ void *value; ++ int ret = of_dev_prop_get(dn, propname, &value); + -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg"); -+ port->cfg_base = devm_ioremap_resource(port->dev, res); -+ if (IS_ERR(port->cfg_base)) -+ return PTR_ERR(port->cfg_base); -+ port->cfg_addr = res->start; -+ -+ return 0; -+} -+ -+static void xgene_pcie_setup_ob_reg(struct xgene_pcie_port *port, -+ struct resource *res, u32 offset, -+ u64 cpu_addr, u64 pci_addr) -+{ -+ void __iomem *base = port->csr_base + offset; -+ resource_size_t size = resource_size(res); -+ u64 restype = resource_type(res); -+ u64 mask = 0; -+ u32 min_size; -+ u32 flag = EN_REG; ++ if (ret) ++ return ret; + -+ if (restype == IORESOURCE_MEM) { -+ min_size = SZ_128M; -+ } else { -+ min_size = 128; -+ flag |= OB_LO_IO; ++ if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { ++ switch (proptype) { ++ case DEV_PROP_U8: { ++ *(u8 *)val = *(u8 *)value; ++ break; ++ } ++ case DEV_PROP_U16: ++ *(u16 *)val = *(u16 *)value; ++ break; ++ case DEV_PROP_U32: ++ *(u32 *)val = *(u32 *)value; ++ break; ++ default: ++ *(u64 *)val = *(u64 *)value; ++ break; ++ } ++ } else if (proptype == DEV_PROP_STRING) { ++ *(char **)val = value; + } ++ return ret; + -+ if (size >= min_size) -+ mask = ~(size - 1) | flag; -+ else -+ dev_warn(port->dev, "res size 0x%llx less than minimum 0x%x\n", -+ (u64)size, min_size); -+ -+ writel(lower_32_bits(cpu_addr), base); -+ writel(upper_32_bits(cpu_addr), base + 0x04); -+ writel(lower_32_bits(mask), base + 0x08); -+ writel(upper_32_bits(mask), base + 0x0c); -+ writel(lower_32_bits(pci_addr), base + 0x10); -+ writel(upper_32_bits(pci_addr), base + 0x14); +} + -+static void xgene_pcie_setup_cfg_reg(void __iomem *csr_base, u64 addr) ++int of_dev_prop_read_array(struct device_node *dn, const char *propname, ++ enum dev_prop_type proptype, void *val, size_t nval) +{ -+ writel(lower_32_bits(addr), csr_base + CFGBARL); -+ writel(upper_32_bits(addr), csr_base + CFGBARH); -+ writel(EN_REG, csr_base + CFGCTL); -+} ++ int ret, elem_size; + -+static int xgene_pcie_map_ranges(struct xgene_pcie_port *port, -+ struct list_head *res, -+ resource_size_t io_base) -+{ -+ struct pci_host_bridge_window *window; -+ struct device *dev = port->dev; -+ int ret; -+ -+ list_for_each_entry(window, res, list) { -+ struct resource *res = window->res; -+ u64 restype = resource_type(res); -+ -+ dev_dbg(port->dev, "%pR\n", res); -+ -+ switch (restype) { -+ case IORESOURCE_IO: -+ xgene_pcie_setup_ob_reg(port, res, OMR3BARL, io_base, -+ res->start - window->offset); -+ ret = pci_remap_iospace(res, io_base); -+ if (ret < 0) -+ return ret; ++ if (!val) { ++ switch (proptype) { ++ case DEV_PROP_U8: ++ elem_size = sizeof(u8); ++ break; ++ case DEV_PROP_U16: ++ elem_size = sizeof(u16); + break; -+ case IORESOURCE_MEM: -+ xgene_pcie_setup_ob_reg(port, res, OMR1BARL, res->start, -+ res->start - window->offset); ++ case DEV_PROP_U32: ++ elem_size = sizeof(u32); + break; -+ case IORESOURCE_BUS: ++ case DEV_PROP_U64: ++ elem_size = sizeof(u64); + break; ++ case DEV_PROP_STRING: ++ return of_property_count_strings(dn, propname); + default: -+ dev_err(dev, "invalid io resource - %pR\n", res); + return -EINVAL; + } -+ } -+ xgene_pcie_setup_cfg_reg(port->csr_base, port->cfg_addr); -+ -+ return 0; -+} -+ -+static void xgene_pcie_setup_pims(void *addr, u64 pim, u64 size) -+{ -+ writel(lower_32_bits(pim), addr); -+ writel(upper_32_bits(pim) | EN_COHERENCY, addr + 0x04); -+ writel(lower_32_bits(size), addr + 0x10); -+ writel(upper_32_bits(size), addr + 0x14); -+} -+ -+/* -+ * X-Gene PCIe support maximum 3 inbound memory regions -+ * This function helps to select a region based on size of region -+ */ -+static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size) -+{ -+ if ((size > 4) && (size < SZ_16M) && !(*ib_reg_mask & (1 << 1))) { -+ *ib_reg_mask |= (1 << 1); -+ return 1; -+ } -+ -+ if ((size > SZ_1K) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 0))) { -+ *ib_reg_mask |= (1 << 0); -+ return 0; -+ } -+ -+ if ((size > SZ_1M) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 2))) { -+ *ib_reg_mask |= (1 << 2); -+ return 2; ++ return of_property_count_elems_of_size(dn, propname, elem_size); + } + -+ return -EINVAL; -+} -+ -+static void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port, -+ struct of_pci_range *range, u8 *ib_reg_mask) -+{ -+ void __iomem *csr_base = port->csr_base; -+ void __iomem *cfg_base = port->cfg_base; -+ void *bar_addr; -+ void *pim_addr; -+ u64 cpu_addr = range->cpu_addr; -+ u64 pci_addr = range->pci_addr; -+ u64 size = range->size; -+ u64 mask = ~(size - 1) | EN_REG; -+ u32 flags = PCI_BASE_ADDRESS_MEM_TYPE_64; -+ u32 bar_low; -+ int region; -+ -+ region = xgene_pcie_select_ib_reg(ib_reg_mask, range->size); -+ if (region < 0) { -+ dev_warn(port->dev, "invalid pcie dma-range config\n"); -+ return; -+ } -+ -+ if (range->flags & IORESOURCE_PREFETCH) -+ flags |= PCI_BASE_ADDRESS_MEM_PREFETCH; -+ -+ bar_low = pcie_bar_low_val((u32)cpu_addr, flags); -+ switch (region) { -+ case 0: -+ xgene_pcie_set_ib_mask(csr_base, BRIDGE_CFG_4, flags, size); -+ bar_addr = cfg_base + PCI_BASE_ADDRESS_0; -+ writel(bar_low, bar_addr); -+ writel(upper_32_bits(cpu_addr), bar_addr + 0x4); -+ pim_addr = csr_base + PIM1_1L; ++ switch (proptype) { ++ case DEV_PROP_U8: ++ ret = of_property_read_u8_array(dn, propname, (u8 *)val, nval); ++ break; ++ case DEV_PROP_U16: ++ ret = of_property_read_u16_array(dn, propname, (u16 *)val, nval); ++ break; ++ case DEV_PROP_U32: ++ ret = of_property_read_u32_array(dn, propname, (u32 *)val, nval); + 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; ++ case DEV_PROP_U64: ++ ret = of_property_read_u64_array(dn, propname, (u64 *)val, nval); + 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; ++ case DEV_PROP_STRING: ++ ret = of_property_read_string_array(dn, propname, ++ (char **)val, nval); ++ break; ++ default: ++ ret = -EINVAL; + break; + } -+ -+ xgene_pcie_setup_pims(pim_addr, pci_addr, ~(size - 1)); -+} -+ -+static int pci_dma_range_parser_init(struct of_pci_range_parser *parser, -+ struct device_node *node) -+{ -+ const int na = 3, ns = 2; -+ int rlen; -+ -+ parser->node = node; -+ parser->pna = of_n_addr_cells(node); -+ parser->np = parser->pna + na + ns; -+ -+ parser->range = of_get_property(node, "dma-ranges", &rlen); -+ if (!parser->range) -+ return -ENOENT; -+ parser->end = parser->range + rlen / sizeof(__be32); -+ -+ return 0; ++ return ret; +} + -+static int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port) ++int of_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data) +{ -+ 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; ++ struct device_node *child; ++ int ret = 0; + -+ if (pci_dma_range_parser_init(&parser, np)) { -+ dev_err(dev, "missing dma-ranges property\n"); -+ return -EINVAL; -+ } -+ -+ /* Get the dma-ranges from DT */ -+ for_each_of_pci_range(&parser, &range) { -+ u64 end = range.cpu_addr + range.size - 1; -+ -+ dev_dbg(port->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n", -+ range.flags, range.cpu_addr, end, range.pci_addr); -+ xgene_pcie_setup_ib_reg(port, &range, &ib_reg_mask); ++ for_each_child_of_node(dev->of_node, child) { ++ ret = fn(dev, child, data); ++ if (ret) ++ break; + } -+ return 0; -+} -+ -+/* clear bar configuration which was done by firmware */ -+static void xgene_pcie_clear_config(struct xgene_pcie_port *port) -+{ -+ int i; -+ -+ for (i = PIM1_1L; i <= CFGCTL; i += 4) -+ writel(0x0, port->csr_base + i); -+} -+ -+static int xgene_pcie_setup(struct xgene_pcie_port *port, -+ struct list_head *res, -+ resource_size_t io_base) -+{ -+ u32 val, lanes = 0, speed = 0; -+ int ret; -+ -+ xgene_pcie_clear_config(port); -+ -+ /* setup the vendor and device IDs correctly */ -+ val = (XGENE_PCIE_DEVICEID << 16) | XGENE_PCIE_VENDORID; -+ writel(val, port->csr_base + BRIDGE_CFG_0); -+ -+ ret = xgene_pcie_map_ranges(port, res, io_base); -+ if (ret) -+ return ret; -+ -+ ret = xgene_pcie_parse_map_dma_ranges(port); -+ if (ret) -+ return ret; -+ -+ xgene_pcie_linkup(port, &lanes, &speed); -+ if (!port->link_up) -+ dev_info(port->dev, "(rc) link down\n"); -+ else -+ dev_info(port->dev, "(rc) x%d gen-%d link up\n", -+ lanes, speed + 1); -+ return 0; -+} -+ -+static int xgene_pcie_probe_bridge(struct platform_device *pdev) -+{ -+ struct device_node *dn = pdev->dev.of_node; -+ struct xgene_pcie_port *port; -+ resource_size_t iobase = 0; -+ struct pci_bus *bus; -+ int ret; -+ LIST_HEAD(res); -+ -+ port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); -+ if (!port) -+ return -ENOMEM; -+ port->node = of_node_get(pdev->dev.of_node); -+ port->dev = &pdev->dev; -+ -+ ret = xgene_pcie_map_reg(port, pdev); -+ if (ret) -+ return ret; -+ -+ ret = xgene_pcie_init_port(port); -+ if (ret) -+ return ret; -+ -+ ret = of_pci_get_host_bridge_resources(dn, 0, 0xff, &res, &iobase); -+ if (ret) -+ return ret; -+ -+ ret = xgene_pcie_setup(port, &res, iobase); -+ if (ret) -+ return ret; -+ -+ bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res); -+ if (!bus) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, port); -+ return 0; -+} -+ -+static const struct of_device_id xgene_pcie_match_table[] = { -+ {.compatible = "apm,xgene-pcie",}, -+ {}, -+}; -+ -+static struct platform_driver xgene_pcie_driver = { -+ .driver = { -+ .name = "xgene-pcie", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(xgene_pcie_match_table), -+ }, -+ .probe = xgene_pcie_probe_bridge, -+}; -+module_platform_driver(xgene_pcie_driver); -+ -+MODULE_AUTHOR("Tanmay Inamdar <tinamdar@apm.com>"); -+MODULE_DESCRIPTION("APM X-Gene PCIe driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c -index 4884ee5..61158e0 100644 ---- a/drivers/pci/host/pcie-rcar.c -+++ b/drivers/pci/host/pcie-rcar.c -@@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) - - /* Setup PCIe address space mappings for each resource */ - resource_size_t size; -+ resource_size_t res_start; - u32 mask; - - rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win)); -@@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) - mask = (roundup_pow_of_two(size) / SZ_128) - 1; - rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win)); - -- rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win)); -- rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win)); -+ if (res->flags & IORESOURCE_IO) -+ res_start = pci_pio_to_address(res->start); -+ else -+ res_start = res->start; -+ -+ rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win)); -+ rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win)); - - /* First resource is for IO */ - mask = PAR_ENABLE; -@@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys) - - rcar_pcie_setup_window(i, pcie); - -- if (res->flags & IORESOURCE_IO) -- pci_ioremap_io(nr * SZ_64K, res->start); -- else -+ if (res->flags & IORESOURCE_IO) { -+ phys_addr_t io_start = pci_pio_to_address(res->start); -+ pci_ioremap_io(nr * SZ_64K, io_start); -+ } else - pci_add_resource(&sys->resources, res); - } - pci_add_resource(&sys->resources, &pcie->busn); -@@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev) - } - - for_each_of_pci_range(&parser, &range) { -- of_pci_range_to_resource(&range, pdev->dev.of_node, -+ err = of_pci_range_to_resource(&range, pdev->dev.of_node, - &pcie->res[win++]); -+ if (err < 0) -+ return err; - - if (win > RCAR_PCI_MAX_RESOURCES) - break; -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index 2c9ac70..6e994fc 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -2704,6 +2704,37 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) - } - EXPORT_SYMBOL(pci_request_regions_exclusive); - -+/** -+ * pci_remap_iospace - Remap the memory mapped I/O space -+ * @res: Resource describing the I/O space -+ * @phys_addr: physical address of range to be mapped -+ * -+ * Remap the memory mapped I/O space described by the @res -+ * and the CPU physical address @phys_addr into virtual address space. -+ * Only architectures that have memory mapped IO functions defined -+ * (and the PCI_IOBASE value defined) should call this function. -+ */ -+int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr) -+{ -+#if defined(PCI_IOBASE) && defined(CONFIG_MMU) -+ unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start; -+ -+ if (!(res->flags & IORESOURCE_IO)) -+ return -EINVAL; -+ -+ if (res->end > IO_SPACE_LIMIT) -+ return -EINVAL; -+ -+ return ioremap_page_range(vaddr, vaddr + resource_size(res), phys_addr, -+ pgprot_device(PAGE_KERNEL)); -+#else -+ /* this architecture does not have memory mapped I/O space, -+ so this function should never be called */ -+ WARN_ONCE(1, "This architecture does not support memory mapped I/O\n"); -+ return -ENODEV; -+#endif -+} -+ - static void __pci_set_master(struct pci_dev *dev, bool enable) - { - u16 old_cmd, cmd; -@@ -4406,6 +4437,15 @@ static void pci_no_domains(void) - #endif - } - -+#ifdef CONFIG_PCI_DOMAINS -+static atomic_t __domain_nr = ATOMIC_INIT(-1); -+ -+int pci_get_new_domain_nr(void) -+{ -+ return atomic_inc_return(&__domain_nr); ++ return ret; +} -+#endif -+ - /** - * pci_ext_cfg_avail - can we access extended PCI config space? - * -diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c -index 4170113..c3cec34 100644 ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -485,7 +485,7 @@ void pci_read_bridge_bases(struct pci_bus *child) - } - } - --static struct pci_bus *pci_alloc_bus(void) -+static struct pci_bus *pci_alloc_bus(struct pci_bus *parent) - { - struct pci_bus *b; - -@@ -500,6 +500,10 @@ static struct pci_bus *pci_alloc_bus(void) - INIT_LIST_HEAD(&b->resources); - b->max_bus_speed = PCI_SPEED_UNKNOWN; - b->cur_bus_speed = PCI_SPEED_UNKNOWN; -+#ifdef CONFIG_PCI_DOMAINS_GENERIC -+ if (parent) -+ b->domain_nr = parent->domain_nr; -+#endif - return b; - } - -@@ -515,7 +519,7 @@ static void pci_release_host_bridge_dev(struct device *dev) - kfree(bridge); - } - --static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b) -+static struct pci_host_bridge *pci_alloc_host_bridge(void) - { - struct pci_host_bridge *bridge; - -@@ -524,7 +528,8 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b) - return NULL; - - INIT_LIST_HEAD(&bridge->windows); -- bridge->bus = b; -+ bridge->dev.release = pci_release_host_bridge_dev; -+ - return bridge; - } - -@@ -671,7 +676,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, - /* - * Allocate a new bus, and inherit stuff from the parent.. - */ -- child = pci_alloc_bus(); -+ child = pci_alloc_bus(parent); - if (!child) - return NULL; - -@@ -1751,37 +1756,37 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, - char bus_addr[64]; - char *fmt; - -- b = pci_alloc_bus(); -- if (!b) -+ bridge = pci_alloc_host_bridge(); -+ if (!bridge) - return NULL; - -+ bridge->dev.parent = parent; -+ -+ b = pci_alloc_bus(NULL); -+ if (!b) -+ goto err_out; -+ - b->sysdata = sysdata; - b->ops = ops; - b->number = b->busn_res.start = bus; -+ pci_bus_assign_domain_nr(b, parent); - b2 = pci_find_bus(pci_domain_nr(b), bus); - if (b2) { - /* If we already got to this bus through a different bridge, ignore it */ - dev_dbg(&b2->dev, "bus already known\n"); -- goto err_out; -+ goto err_bus_out; - } - -- bridge = pci_alloc_host_bridge(b); -- if (!bridge) -- goto err_out; -- -- bridge->dev.parent = parent; -- bridge->dev.release = pci_release_host_bridge_dev; -+ bridge->bus = b; - dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); - error = pcibios_root_bridge_prepare(bridge); -- if (error) { -- kfree(bridge); -+ if (error) - goto err_out; -- } - - error = device_register(&bridge->dev); - if (error) { - put_device(&bridge->dev); -- goto err_out; -+ goto err_bus_out; - } - b->bridge = get_device(&bridge->dev); - device_enable_async_suspend(b->bridge); -@@ -1838,8 +1843,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, - class_dev_reg_err: - put_device(&bridge->dev); - device_unregister(&bridge->dev); --err_out: -+err_bus_out: - kfree(b); -+err_out: -+ kfree(bridge); - return NULL; - } - -@@ -1936,6 +1943,9 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, - if (!found) - pci_bus_update_busn_res_end(b, max); - -+ if (!pci_has_flag(PCI_PROBE_ONLY)) -+ pci_assign_unassigned_bus_resources(b); -+ - pci_bus_add_devices(b); - return b; - } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 782e822..d952462 100644 --- a/drivers/pnp/resource.c @@ -7133,10 +9129,10 @@ index 0000000..402f168 + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c -index 57d9df8..e075437 100644 +index beea6ca..7038a2d 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c -@@ -313,10 +313,18 @@ static int dw8250_probe_of(struct uart_port *p, +@@ -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) { @@ -7155,7 +9151,7 @@ index 57d9df8..e075437 100644 p->iotype = UPIO_MEM32; p->serial_in = dw8250_serial_in32; p->serial_out = dw8250_serial_out32; -@@ -541,6 +549,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { +@@ -536,6 +544,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { { "INT3435", 0 }, { "80860F0A", 0 }, { "8086228A", 0 }, @@ -7164,7 +9160,7 @@ index 57d9df8..e075437 100644 }; MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c -index c600ccf..10c4775 100644 +index ef9a165..9f1939c 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -100,8 +100,7 @@ @@ -7177,7 +9173,7 @@ index c600ccf..10c4775 100644 /* The alignment to use between consumer and producer parts of vring. * Currently hardcoded to the page size. */ -@@ -637,6 +636,14 @@ static struct of_device_id virtio_mmio_match[] = { +@@ -634,6 +633,14 @@ static struct of_device_id virtio_mmio_match[] = { }; MODULE_DEVICE_TABLE(of, virtio_mmio_match); @@ -7192,7 +9188,7 @@ index c600ccf..10c4775 100644 static struct platform_driver virtio_mmio_driver = { .probe = virtio_mmio_probe, .remove = virtio_mmio_remove, -@@ -644,6 +651,7 @@ static struct platform_driver virtio_mmio_driver = { +@@ -641,6 +648,7 @@ static struct platform_driver virtio_mmio_driver = { .name = "virtio-mmio", .owner = THIS_MODULE, .of_match_table = virtio_mmio_match, @@ -7200,23 +9196,8 @@ index c600ccf..10c4775 100644 }, }; -diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h -index c728113..f97804b 100644 ---- a/include/acpi/acnames.h -+++ b/include/acpi/acnames.h -@@ -59,6 +59,10 @@ - #define METHOD_NAME__PRS "_PRS" - #define METHOD_NAME__PRT "_PRT" - #define METHOD_NAME__PRW "_PRW" -+#define METHOD_NAME__PS0 "_PS0" -+#define METHOD_NAME__PS1 "_PS1" -+#define METHOD_NAME__PS2 "_PS2" -+#define METHOD_NAME__PS3 "_PS3" - #define METHOD_NAME__REG "_REG" - #define METHOD_NAME__SB_ "_SB_" - #define METHOD_NAME__SEG "_SEG" diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h -index 57ee052..a483e61 100644 +index 57ee052..a1ef42f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -68,6 +68,8 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); @@ -7228,6 +9209,28 @@ index 57ee052..a483e61 100644 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,6 +339,13 @@ 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; ++}; ++ + /* Device */ + struct acpi_device { + int device_type; +@@ -353,6 +362,7 @@ 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; diff --git a/include/acpi/acpi_io.h b/include/acpi/acpi_io.h index 444671e..9d573db 100644 --- a/include/acpi/acpi_io.h @@ -7250,118 +9253,11 @@ index 444671e..9d573db 100644 return ioremap_cache(phys, size); } -diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h -index b7c89d4..dc9d037 100644 ---- a/include/acpi/acpixf.h -+++ b/include/acpi/acpixf.h -@@ -46,7 +46,7 @@ - - /* Current ACPICA subsystem version in YYYYMMDD format */ - --#define ACPI_CA_VERSION 0x20140724 -+#define ACPI_CA_VERSION 0x20140828 - - #include <acpi/acconfig.h> - #include <acpi/actypes.h> -diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h -index 7626bfe..29e7937 100644 ---- a/include/acpi/actbl1.h -+++ b/include/acpi/actbl1.h -@@ -952,7 +952,8 @@ enum acpi_srat_type { - ACPI_SRAT_TYPE_CPU_AFFINITY = 0, - ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1, - ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2, -- ACPI_SRAT_TYPE_RESERVED = 3 /* 3 and greater are reserved */ -+ ACPI_SRAT_TYPE_GICC_AFFINITY = 3, -+ ACPI_SRAT_TYPE_RESERVED = 4 /* 4 and greater are reserved */ - }; - - /* -@@ -968,7 +969,7 @@ struct acpi_srat_cpu_affinity { - u32 flags; - u8 local_sapic_eid; - u8 proximity_domain_hi[3]; -- u32 reserved; /* Reserved, must be zero */ -+ u32 clock_domain; - }; - - /* Flags */ -@@ -1010,6 +1011,20 @@ struct acpi_srat_x2apic_cpu_affinity { - - #define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */ - -+/* 3: GICC Affinity (ACPI 5.1) */ -+ -+struct acpi_srat_gicc_affinity { -+ struct acpi_subtable_header header; -+ u32 proximity_domain; -+ u32 acpi_processor_uid; -+ u32 flags; -+ u32 clock_domain; -+}; -+ -+/* Flags for struct acpi_srat_gicc_affinity */ -+ -+#define ACPI_SRAT_GICC_ENABLED (1) /* 00: Use affinity structure */ -+ - /* Reset to default packing */ - - #pragma pack() -diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h -index 787bcc8..5480cb2 100644 ---- a/include/acpi/actbl3.h -+++ b/include/acpi/actbl3.h -@@ -310,10 +310,15 @@ struct acpi_gtdt_timer_entry { - u32 common_flags; - }; - -+/* Flag Definitions: timer_flags and virtual_timer_flags above */ -+ -+#define ACPI_GTDT_GT_IRQ_MODE (1) -+#define ACPI_GTDT_GT_IRQ_POLARITY (1<<1) -+ - /* Flag Definitions: common_flags above */ - --#define ACPI_GTDT_GT_IS_SECURE_TIMER (1) --#define ACPI_GTDT_GT_ALWAYS_ON (1<<1) -+#define ACPI_GTDT_GT_IS_SECURE_TIMER (1) -+#define ACPI_GTDT_GT_ALWAYS_ON (1<<1) - - /* 1: SBSA Generic Watchdog Structure */ - -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/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 53b2acc..977e545 100644 ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b) - #define pgprot_writecombine pgprot_noncached - #endif - -+#ifndef pgprot_device -+#define pgprot_device pgprot_noncached -+#endif -+ - /* - * When walking page tables, get the address of the next boundary, - * or the end address of the range if that comes earlier. Although no diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h -index 35b0c12..d98e96b 100644 +index 206dcc3..660dbfc 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h -@@ -237,17 +237,19 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, +@@ -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) @@ -7391,10 +9287,18 @@ index 35b0c12..d98e96b 100644 return -ENODEV; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h -index 807cbc4..4615eb1 100644 +index b7926bb..6c22abf 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h -@@ -71,6 +71,7 @@ enum acpi_irq_model_id { +@@ -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, @@ -7402,7 +9306,7 @@ index 807cbc4..4615eb1 100644 ACPI_IRQ_MODEL_COUNT }; -@@ -123,6 +124,10 @@ int acpi_numa_init (void); +@@ -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); @@ -7413,6 +9317,107 @@ index 807cbc4..4615eb1 100644 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); + +@@ -658,4 +660,85 @@ do { \ + #endif + #endif + ++/* Device properties */ ++ ++#define MAX_ACPI_REFERENCE_ARGS 8 ++struct acpi_reference_args { ++ struct acpi_device *adev; ++ size_t nargs; ++ u64 args[MAX_ACPI_REFERENCE_ARGS]; ++}; ++ ++#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, ++ const char *cells_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(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val); ++int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname, ++ enum dev_prop_type proptype, void *val, ++ size_t nval); ++int acpi_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data); ++#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 inline int acpi_dev_prop_get(struct acpi_device *adev, ++ const char *propname, ++ void **valptr) ++{ ++ return -ENXIO; ++} ++ ++static inline int acpi_dev_prop_read(struct acpi_device *adev, ++ const char *propname, ++ enum dev_prop_type proptype, void *val) ++{ ++ return -ENXIO; ++} ++ ++static inline int acpi_dev_prop_read_array(struct acpi_device *adev, ++ const char *propname, ++ enum dev_prop_type proptype, ++ void *val, size_t nval) ++{ ++ return -ENXIO; ++} ++ ++static inline int acpi_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data) ++{ ++ return -ENXIO; ++} ++ ++#endif ++ + #endif /*_LINUX_ACPI_H*/ diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 653f0e2..5839f98 100644 --- a/include/linux/clocksource.h @@ -7428,6 +9433,50 @@ index 653f0e2..5839f98 100644 +#endif + #endif /* _LINUX_CLOCKSOURCE_H */ +diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h +index 12f146f..033d2fd 100644 +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -94,6 +94,11 @@ 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 gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child, ++ const char *propname, int index); ++struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child, ++ const char *propname, int index); + #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 @@ -7466,111 +9515,97 @@ index 0000000..ad5b577 + +#endif /* ARM_GIC_ACPI_H_ */ diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h -index 45e2d8c..2b0f246 100644 +index 13eed92..dc9cb5f 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h -@@ -39,6 +39,8 @@ - #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 - #define GIC_DIST_SGI_PENDING_SET 0xf20 +@@ -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/of_address.h b/include/linux/of_address.h -index fb7b722..7ebb877 100644 ---- a/include/linux/of_address.h -+++ b/include/linux/of_address.h -@@ -23,17 +23,6 @@ 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; --} -- - /* 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,7 +44,9 @@ extern void __iomem *of_iomap(struct device_node *device, int index); - extern const __be32 *of_get_address(struct device_node *dev, int index, - u64 *size, unsigned int *flags); - -+extern int pci_register_io_range(phys_addr_t addr, resource_size_t size); - extern unsigned long pci_address_to_pio(phys_addr_t addr); -+extern phys_addr_t pci_pio_to_address(unsigned long pio); - - extern int of_pci_range_parser_init(struct of_pci_range_parser *parser, - struct device_node *node); -@@ -138,6 +129,9 @@ extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, - u64 *size, unsigned int *flags); - extern int of_pci_address_to_resource(struct device_node *dev, int bar, - struct resource *r); -+extern int of_pci_range_to_resource(struct of_pci_range *range, -+ struct device_node *np, -+ struct resource *res); - #else /* CONFIG_OF_ADDRESS && CONFIG_PCI */ - static inline int of_pci_address_to_resource(struct device_node *dev, int bar, - struct resource *r) -@@ -153,4 +147,3 @@ static inline const __be32 *of_get_pci_address(struct device_node *dev, - #endif /* CONFIG_OF_ADDRESS && CONFIG_PCI */ - - #endif /* __OF_ADDRESS_H */ -- -diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h -index dde3a4a..1fd207e 100644 ---- a/include/linux/of_pci.h -+++ b/include/linux/of_pci.h -@@ -15,6 +15,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent, - int of_pci_get_devfn(struct device_node *np); - int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin); - int of_pci_parse_bus_range(struct device_node *node, struct resource *res); -+int of_get_pci_domain_nr(struct device_node *node); - #else - static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq) - { -@@ -43,6 +44,18 @@ of_pci_parse_bus_range(struct device_node *node, struct resource *res) - { - return -EINVAL; +diff --git a/include/linux/leds.h b/include/linux/leds.h +index e436864..879a113 100644 +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -246,6 +246,7 @@ struct led_platform_data { + struct gpio_led { + const char *name; + const char *default_trigger; ++ struct gpio_desc *gpiod; + unsigned gpio; + unsigned active_low : 1; + unsigned retain_state_suspended : 1; +diff --git a/include/linux/of.h b/include/linux/of.h +index 6545e7a..9962b70 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> +@@ -355,6 +356,15 @@ const char *of_prop_next_string(struct property *prop, const char *cur); + + bool of_console_check(struct device_node *dn, char *name, int index); + ++int of_dev_prop_get(struct device_node *dn, const char *propname, void **valptr); ++int of_dev_prop_read(struct device_node *dn, const char *propname, ++ enum dev_prop_type proptype, void *val); ++int of_dev_prop_read_array(struct device_node *dn, const char *propname, ++ enum dev_prop_type proptype, void *val, size_t nval); ++int of_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data); ++ + #else /* CONFIG_OF */ + + static inline const char* of_node_full_name(const struct device_node *np) +@@ -582,6 +592,33 @@ static inline const char *of_prop_next_string(struct property *prop, + return NULL; } + ++static inline int of_dev_prop_get(struct device_node *dn, const char *propname, ++ void **valptr) ++{ ++ return -ENXIO; ++} + -+static inline int -+of_get_pci_domain_nr(struct device_node *node) ++static inline int of_dev_prop_read(struct device_node *dn, const char *propname, ++ enum dev_prop_type proptype, void *val) +{ -+ return -1; ++ return -ENXIO; +} -+#endif + -+#if defined(CONFIG_OF_ADDRESS) -+int of_pci_get_host_bridge_resources(struct device_node *dev, -+ unsigned char busno, unsigned char bus_max, -+ struct list_head *resources, resource_size_t *io_base); - #endif - - #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI) ++static inline int of_dev_prop_read_array(struct device_node *dn, ++ const char *propname, ++ enum dev_prop_type proptype, ++ void *val, size_t nval) ++{ ++ return -ENXIO; ++} ++ ++static inline int of_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data) ++{ ++ return -ENXIO; ++} ++ + #define of_match_ptr(_ptr) NULL + #define of_match_node(_matches, _node) NULL + #endif /* CONFIG_OF */ diff --git a/include/linux/pci.h b/include/linux/pci.h -index 96453f9..6d540b9 100644 +index 5be8db4..6afba72 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h -@@ -457,6 +457,9 @@ struct pci_bus { - unsigned char primary; /* number of primary bridge */ - unsigned char max_bus_speed; /* enum pci_bus_speed */ - unsigned char cur_bus_speed; /* enum pci_bus_speed */ -+#ifdef CONFIG_PCI_DOMAINS_GENERIC -+ int domain_nr; -+#endif - - char name[48]; - -@@ -559,15 +562,6 @@ struct pci_ops { +@@ -562,15 +562,6 @@ struct pci_ops { int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); }; @@ -7586,48 +9621,7 @@ index 96453f9..6d540b9 100644 struct pci_bus_region { dma_addr_t start; dma_addr_t end; -@@ -1103,6 +1097,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, - resource_size_t), - void *alignf_data); - -+ -+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; -@@ -1288,17 +1285,47 @@ void pci_cfg_access_unlock(struct pci_dev *dev); - */ - #ifdef CONFIG_PCI_DOMAINS - extern int pci_domains_supported; -+int pci_get_new_domain_nr(void); - #else - enum { pci_domains_supported = 0 }; - static inline int pci_domain_nr(struct pci_bus *bus) { return 0; } - static inline int pci_proc_domain(struct pci_bus *bus) { return 0; } -+static inline int pci_get_new_domain_nr(void) { return -ENOSYS; } - #endif /* CONFIG_PCI_DOMAINS */ - -+/* -+ * Generic implementation for PCI domain support. If your -+ * architecture does not need custom management of PCI -+ * domains then this implementation will be used -+ */ -+#ifdef CONFIG_PCI_DOMAINS_GENERIC -+static inline int pci_domain_nr(struct pci_bus *bus) -+{ -+ return bus->domain_nr; -+} -+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent); -+#else -+static inline void pci_bus_assign_domain_nr(struct pci_bus *bus, -+ struct device *parent) -+{ -+} -+#endif -+ - /* some architectures require additional setup to direct VGA traffic */ - typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode, +@@ -1325,6 +1316,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); @@ -7644,7 +9638,7 @@ index 96453f9..6d540b9 100644 #else /* CONFIG_PCI is not enabled */ /* -@@ -1400,8 +1427,26 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, +@@ -1426,6 +1427,23 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) { return NULL; } @@ -7667,11 +9661,8 @@ index 96453f9..6d540b9 100644 + static inline int pci_domain_nr(struct pci_bus *bus) { return 0; } static inline struct pci_dev *pci_dev_get(struct pci_dev *dev) { return NULL; } -+static inline int pci_get_new_domain_nr(void) { return -ENOSYS; } - - #define dev_is_pci(d) (false) - #define dev_is_pf(d) (false) -@@ -1613,7 +1658,6 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, + static inline int pci_get_new_domain_nr(void) { return -ENOSYS; } +@@ -1635,7 +1653,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); @@ -7679,19 +9670,219 @@ index 96453f9..6d540b9 100644 #ifdef CONFIG_HIBERNATE_CALLBACKS extern struct dev_pm_ops pcibios_pm_ops; -diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h -index e9441b9..1d3f39c 100644 ---- a/tools/perf/arch/arm64/include/perf_regs.h -+++ 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 +diff --git a/include/linux/property.h b/include/linux/property.h +new file mode 100644 +index 0000000..1a42878 +--- /dev/null ++++ b/include/linux/property.h +@@ -0,0 +1,207 @@ ++/* ++ * property.h - Unified device property interface. ++ * ++ * Copyright (C) 2014, Intel Corporation ++ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com> ++ * Mika Westerberg <mika.westerberg@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. ++ */ + - #define PERF_REG_IP PERF_REG_ARM64_PC - #define PERF_REG_SP PERF_REG_ARM64_SP - ++#ifndef _LINUX_PROPERTY_H_ ++#define _LINUX_PROPERTY_H_ ++ ++#include <linux/device.h> ++ ++enum dev_prop_type { ++ DEV_PROP_U8, ++ DEV_PROP_U16, ++ DEV_PROP_U32, ++ DEV_PROP_U64, ++ DEV_PROP_STRING, ++ DEV_PROP_MAX, ++}; ++ ++int device_get_property(struct device *dev, const char *propname, ++ void **valptr); ++int device_read_property(struct device *dev, const char *propname, ++ enum dev_prop_type proptype, void *val); ++int device_read_property_array(struct device *dev, const char *propname, ++ enum dev_prop_type proptype, void *val, ++ size_t nval); ++int device_get_child_property(struct device *dev, void *child, ++ const char *propname, void **valptr); ++int device_read_child_property(struct device *dev, void *child, ++ const char *propname, ++ enum dev_prop_type proptype, void *val); ++int device_read_child_property_array(struct device *dev, void *child, ++ const char *propname, ++ enum dev_prop_type proptype, void *val, ++ size_t nval); ++int device_for_each_child_node(struct device *dev, ++ int (*fn)(struct device *dev, void *child, void *data), ++ void *data); ++unsigned int device_get_child_node_count(struct device *dev); ++ ++static inline int device_property_read_u8(struct device *dev, ++ const char *propname, u8 *out_value) ++{ ++ return device_read_property(dev, propname, DEV_PROP_U8, out_value); ++} ++ ++static inline int device_property_read_u16(struct device *dev, ++ const char *propname, u16 *out_value) ++{ ++ return device_read_property(dev, propname, DEV_PROP_U16, out_value); ++} ++ ++static inline int device_property_read_u32(struct device *dev, ++ const char *propname, u32 *out_value) ++{ ++ return device_read_property(dev, propname, DEV_PROP_U32, out_value); ++} ++ ++static inline int device_property_read_u64(struct device *dev, ++ const char *propname, u64 *out_value) ++{ ++ return device_read_property(dev, propname, DEV_PROP_U64, out_value); ++} ++ ++static inline int device_property_read_u8_array(struct device *dev, ++ const char *propname, ++ u8 *val, size_t nval) ++{ ++ return device_read_property_array(dev, propname, DEV_PROP_U8, val, ++ nval); ++} ++ ++static inline int device_property_read_u16_array(struct device *dev, ++ const char *propname, ++ u16 *val, size_t nval) ++{ ++ return device_read_property_array(dev, propname, DEV_PROP_U16, val, ++ nval); ++} ++ ++static inline int device_property_read_u32_array(struct device *dev, ++ const char *propname, ++ u32 *val, size_t nval) ++{ ++ return device_read_property_array(dev, propname, DEV_PROP_U32, val, ++ nval); ++} ++ ++static inline int device_property_read_u64_array(struct device *dev, ++ const char *propname, ++ u64 *val, size_t nval) ++{ ++ return device_read_property_array(dev, propname, DEV_PROP_U64, val, ++ nval); ++} ++ ++static inline int device_property_read_string(struct device *dev, ++ const char *propname, ++ const char **out_string) ++{ ++ return device_read_property(dev, propname, DEV_PROP_STRING, out_string); ++} ++ ++static inline int device_property_read_string_array(struct device *dev, ++ const char *propname, ++ const char **out_strings, ++ size_t nstrings) ++{ ++ return device_read_property_array(dev, propname, DEV_PROP_STRING, ++ out_strings, nstrings); ++} ++ ++static inline int device_child_property_read_u8(struct device *dev, void *child, ++ const char *propname, ++ u8 *out_value) ++{ ++ return device_read_child_property(dev, child, propname, DEV_PROP_U8, ++ out_value); ++} ++ ++static inline int device_child_property_read_u16(struct device *dev, void *child, ++ const char *propname, ++ u16 *out_value) ++{ ++ return device_read_child_property(dev, child, propname, DEV_PROP_U16, ++ out_value); ++} ++ ++static inline int device_child_property_read_u32(struct device *dev, void *child, ++ const char *propname, ++ u32 *out_value) ++{ ++ return device_read_child_property(dev, child, propname, DEV_PROP_U32, ++ out_value); ++} ++ ++static inline int device_child_property_read_u64(struct device *dev, void *child, ++ const char *propname, ++ u64 *out_value) ++{ ++ return device_read_child_property(dev, child, propname, DEV_PROP_U64, ++ out_value); ++} ++ ++static inline int device_child_property_read_u8_array(struct device *dev, ++ void *child, ++ const char *propname, ++ u8 *val, size_t nval) ++{ ++ return device_read_child_property_array(dev, child, propname, ++ DEV_PROP_U8, val, nval); ++} ++ ++static inline int device_child_property_read_u16_array(struct device *dev, ++ void *child, ++ const char *propname, ++ u16 *val, size_t nval) ++{ ++ return device_read_child_property_array(dev, child, propname, ++ DEV_PROP_U16, val, nval); ++} ++ ++static inline int device_child_property_read_u32_array(struct device *dev, ++ void *child, ++ const char *propname, ++ u32 *val, size_t nval) ++{ ++ return device_read_child_property_array(dev, child, propname, ++ DEV_PROP_U32, val, nval); ++} ++ ++static inline int device_child_property_read_u64_array(struct device *dev, ++ void *child, ++ const char *propname, ++ u64 *val, size_t nval) ++{ ++ return device_read_child_property_array(dev, child, propname, ++ DEV_PROP_U64, val, nval); ++} ++ ++static inline int device_child_property_read_string(struct device *dev, ++ void *child, ++ const char *propname, ++ const char **out_string) ++{ ++ return device_read_child_property(dev, child, propname, DEV_PROP_STRING, ++ out_string); ++} ++ ++static inline int device_child_property_read_string_array(struct device *dev, ++ void *child, ++ const char *propname, ++ const char **out_strings, ++ size_t nstrings) ++{ ++ return device_read_child_property_array(dev, child, propname, ++ DEV_PROP_STRING, ++ out_strings, nstrings); ++} ++#endif /* _LINUX_PROPERTY_H_ */ diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 22fa819..9cd5dbd 100644 --- a/virt/kvm/arm/arch_timer.c @@ -7839,7 +10030,7 @@ index 22fa819..9cd5dbd 100644 void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c -index 416baed..53bdd33 100644 +index 2935405..196f49e 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -19,6 +19,7 @@ @@ -7858,7 +10049,7 @@ index 416baed..53bdd33 100644 #include <asm/kvm_emulate.h> #include <asm/kvm_arm.h> #include <asm/kvm_mmu.h> -@@ -177,7 +179,7 @@ static const struct vgic_ops vgic_v2_ops = { +@@ -159,7 +161,7 @@ static const struct vgic_ops vgic_v2_ops = { static struct vgic_params vgic_v2_params; /** @@ -7867,7 +10058,7 @@ index 416baed..53bdd33 100644 * @node: pointer to the DT node * @ops: address of a pointer to the GICv2 operations * @params: address of a pointer to HW-specific parameters -@@ -186,7 +188,7 @@ static struct vgic_params vgic_v2_params; +@@ -168,7 +170,7 @@ static struct vgic_params vgic_v2_params; * in *ops and the HW parameters in *params. Returns an error code * otherwise. */ @@ -7876,7 +10067,7 @@ index 416baed..53bdd33 100644 const struct vgic_ops **ops, const struct vgic_params **params) { -@@ -263,3 +265,72 @@ out: +@@ -245,3 +247,72 @@ out: of_node_put(vgic_node); return ret; } @@ -7976,7 +10167,7 @@ index 1c2c8ee..8b56920 100644 int ret = 0; u32 gicv_idx; diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c -index 73eba79..ca98a3b 100644 +index 3aaca49..f6e9922 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -25,9 +25,11 @@ @@ -7991,7 +10182,7 @@ index 73eba79..ca98a3b 100644 #include <asm/kvm_emulate.h> #include <asm/kvm_arm.h> #include <asm/kvm_mmu.h> -@@ -1549,31 +1551,39 @@ static struct notifier_block vgic_cpu_nb = { +@@ -2427,31 +2429,39 @@ static struct notifier_block vgic_cpu_nb = { }; static const struct of_device_id vgic_ids[] = { @@ -8007,8 +10198,8 @@ index 73eba79..ca98a3b 100644 int kvm_vgic_hyp_init(void) { const struct of_device_id *matched_id; - int (*vgic_probe)(struct device_node *,const struct vgic_ops **, - const struct vgic_params **); + 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; diff --git a/kernel.spec b/kernel.spec index 3b402378b..d25ed4a3c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -8,7 +8,7 @@ Summary: The Linux kernel # be 0. %global released_kernel 0 -%global aarch64patches 0 +%global aarch64patches 1 # Sign modules on x86. Make sure the config files match this setting if more # architectures are added. @@ -42,7 +42,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2208,6 +2208,13 @@ fi # ||----w | # || || %changelog +* Tue Oct 21 2014 Kyle McMartin <kyle@fedoraproject.org> - 3.18.0-0.rc1.git1.2 +- Re-enable kernel-arm64.patch after updating. +- CONFIG_SERIAL_8250_FINTEK moved to generic since it appears on x86-generic + and arm64 now. +- CONFIG_IMX_THERMAL=n added to config-arm64. +- arm64: disable BPF_JIT temporarily + * Tue Oct 21 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc1.git1.1 - Linux v3.18-rc1-68-gc2661b806092 - Make LOG_BUF_SHIFT on arm64 the same as the rest of the arches (rhbz 1123327) |