Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2016-04-15 16:05:31 +0200
committerMichal Marek <mmarek@suse.cz>2016-04-15 16:05:31 +0200
commitd63b55a9e1d03330c4476f23bc0eea4e7a604190 (patch)
treeb435817a1e27cc977e79c5efc3404ea574623801
parent47cd15738bd1ea7020d30b190f6f430018562de9 (diff)
parent83462478089ec12c07db475dda176380f505ac38 (diff)
Merge branch 'users/mbrugger/SLE12-SP2/for-next' into SLE12-SP2
Pull ARM64 updates from Matthias Brugger (fate#319481, fate#319483, fate#319900, fate#319980, fate#320030, fate#320554).
-rw-r--r--config/arm64/default249
-rw-r--r--patches.arch/arm64-0001-PCI-layerscape-Add-fsl-ls2085a-pcie-compatible-ID.patch34
-rw-r--r--patches.arch/arm64-0001-Staging-fsl-mc-bus-Drop-owner-assignment-from-platfo.patch38
-rw-r--r--patches.arch/arm64-0001-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch48
-rw-r--r--patches.arch/arm64-0001-amd-xgbe-Disable-VLAN-filtering-when-in-promiscuous-.patch293
-rw-r--r--patches.arch/arm64-0001-arm64-defconfig-Add-Broadcom-Vulcan-to-defconfig.patch28
-rw-r--r--patches.arch/arm64-0001-irqdomain-Added-domain-bus-token-DOMAIN_BUS_FSL_MC_M.patch34
-rw-r--r--patches.arch/arm64-0001-mailbox-Add-support-for-APM-X-Gene-platform-mailbox-.patch342
-rw-r--r--patches.arch/arm64-0001-staging-fsl-mc-Do-not-allow-building-as-a-module.patch39
-rw-r--r--patches.arch/arm64-0001-staging-fsl-mc-Drop-unneeded-void-pointer-cast.patch52
-rw-r--r--patches.arch/arm64-0001-staging-fsl-mc-fix-incorrect-type-passed-to-dev_dbg-.patch57
-rw-r--r--patches.arch/arm64-0001-staging-fsl-mc-read-version-of-root-dprc-from-mc.patch112
-rw-r--r--patches.arch/arm64-0001-staging-fsl-mc-update-dpmcp-binary-interface-to-v3.0.patch134
-rw-r--r--patches.arch/arm64-0001-v6-dt-bindings-Add-bindings-for-Layerscape-SCFG-MSI.patch74
-rw-r--r--patches.arch/arm64-0002-Documentation-mailbox-Add-APM-X-Gene-SLIMpro-mailbox.patch65
-rw-r--r--patches.arch/arm64-0002-PCI-layerscape-Fix-MSG-TLP-drop-setting.patch75
-rw-r--r--patches.arch/arm64-0002-ahci-qoriq-Update-the-default-Rx-watermark-value.patch46
-rw-r--r--patches.arch/arm64-0002-amd-xgbe-Change-from-napi_complete-to-napi_complete_.patch60
-rw-r--r--patches.arch/arm64-0002-arm64-Broadcom-Vulcan-support.patch237
-rw-r--r--patches.arch/arm64-0002-fsl-mc-msi-Added-FSL-MC-specific-member-to-the-msi_d.patch49
-rw-r--r--patches.arch/arm64-0002-staging-fsl-mc-Avoid-section-mismatch.patch54
-rw-r--r--patches.arch/arm64-0002-staging-fsl-mc-Remove-unneeded-else-following-a-retu.patch53
-rw-r--r--patches.arch/arm64-0002-staging-fsl-mc-add-dprc-version-check.patch112
-rw-r--r--patches.arch/arm64-0002-staging-fsl-mc-bus-Eliminate-double-function-call.patch82
-rw-r--r--patches.arch/arm64-0002-staging-fsl-mc-fix-incorrect-type-passed-to-dev_err-.patch47
-rw-r--r--patches.arch/arm64-0002-staging-fsl-mc-update-dpbp-binary-interface-to-v2.2.patch219
-rw-r--r--patches.arch/arm64-0002-v6-irqchip-Layerscape-Add-SCFG-MSI-controller-support.patch312
-rw-r--r--patches.arch/arm64-0003-Staging-fsl-mc-Replace-pr_debug-with-dev_dbg.patch105
-rw-r--r--patches.arch/arm64-0003-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch68
-rw-r--r--patches.arch/arm64-0003-amd-xgbe-Use-__napi_schedule_irqoff.patch43
-rw-r--r--patches.arch/arm64-0003-arm64-cputype-info-for-Broadcom-Vulcan.patch39
-rw-r--r--patches.arch/arm64-0003-staging-fsl-mc-Added-generic-MSI-support-for-FSL-MC-.patch420
-rw-r--r--patches.arch/arm64-0003-staging-fsl-mc-add-dpmcp-version-check.patch61
-rw-r--r--patches.arch/arm64-0003-staging-fsl-mc-update-dprc-binary-interface-to-v5.1.patch221
-rw-r--r--patches.arch/arm64-0004-Staging-fsl-mc-Replace-pr_err-with-dev_err.patch92
-rw-r--r--patches.arch/arm64-0004-amd-xgbe-Verify-forced-speed-matches-the-active-spee.patch63
-rw-r--r--patches.arch/arm64-0004-staging-fsl-mc-Added-GICv3-ITS-support-for-FSL-MC-MS.patch181
-rw-r--r--patches.arch/arm64-0004-staging-fsl-mc-change-binding-rules.patch140
-rw-r--r--patches.arch/arm64-0004-staging-fsl-mc-return-EINVAL-for-all-fsl_mc_portal_a.patch37
-rw-r--r--patches.arch/arm64-0005-amd-xgbe-Enable-disable-PFC-per-traffic-class.patch74
-rw-r--r--patches.arch/arm64-0005-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch339
-rw-r--r--patches.arch/arm64-0005-staging-fsl-mc-set-up-coherent-dma-ops-for-added-dev.patch37
-rw-r--r--patches.arch/arm64-0006-amd-xgbe-Fix-the-mapping-of-priorities-to-traffic-cl.patch103
-rw-r--r--patches.arch/arm64-0006-staging-fsl-mc-Changed-DPRC-built-in-portal-s-mc_io-.patch55
-rw-r--r--patches.arch/arm64-0006-staging-fsl-mc-set-cacheable-flag-for-added-devices-.patch39
-rw-r--r--patches.arch/arm64-0007-staging-fsl-mc-Populate-the-IRQ-pool-for-an-MC-bus-i.patch120
-rw-r--r--patches.arch/arm64-0007-staging-fsl-mc-update-dpcon-binary-interface-to-v2.2.patch981
-rw-r--r--patches.arch/arm64-0008-amd-xgbe-Check-Rx-queue-fifos-before-stopping-Rx-DMA.patch109
-rw-r--r--patches.arch/arm64-0008-staging-fsl-mc-set-MSI-domain-for-DPRC-objects.patch112
-rw-r--r--patches.arch/arm64-0008-staging-fsl-mc-static-inline-function-to-differentia.patch115
-rw-r--r--patches.arch/arm64-0009-amd-xgbe-Mask-auto-negotiation-interrupts-in-ISR.patch251
-rw-r--r--patches.arch/arm64-0009-staging-fsl-mc-Fixed-bug-in-dprc_probe-error-path.patch80
-rw-r--r--patches.arch/arm64-0009-staging-fsl-mc-dprc-device-s-sysfs-rescan-documentat.patch42
-rw-r--r--patches.arch/arm64-0010-staging-fsl-mc-Added-DPRC-interrupt-handler.patch310
-rw-r--r--patches.arch/arm64-0010-staging-fsl-mc-root-dprc-rescan-attribute-to-sync-ke.patch84
-rw-r--r--patches.arch/arm64-0011-staging-fsl-mc-Added-MSI-support-to-the-MC-bus-drive.patch67
-rw-r--r--patches.arch/arm64-0011-staging-fsl-mc-fsl-mc-bus-s-sysfs-rescan-documentati.patch40
-rw-r--r--patches.arch/arm64-0012-staging-fsl-mc-bus-rescan-attribute-to-sync-kernel-w.patch88
-rw-r--r--patches.arch/arm64-1-2-ARM-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-008585.patch381
-rw-r--r--patches.arch/arm64-1-4-MAINTAINERS-Add-entry-for-APM-X-Gene-SoC-PMU-driver.patch42
-rw-r--r--patches.arch/arm64-1-6-Documentation-arm64-pmu-Add-Broadcom-Vulcan-PMU-binding.patch43
-rw-r--r--patches.arch/arm64-2-2-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-009971.patch139
-rw-r--r--patches.arch/arm64-2-4-Documentation-Add-documentation-for-APM-X-Gene-SoC-PMU-DTS-binding.patch148
-rw-r--r--patches.arch/arm64-2-6-arm64-dts-Add-Broadcom-Vulcan-PMU-in-dts.patch37
-rw-r--r--patches.arch/arm64-3-4-perf-xgene-Add-APM-X-Gene-SoC-Performance-Monitoring-Unit-driver.patch1517
-rw-r--r--patches.arch/arm64-3-6-arm64-perf-Changed-events-naming-as-per-ARM-ARM.patch456
-rw-r--r--patches.arch/arm64-4-4-arm64-dts-apm-Add-APM-X-Gene-SoC-PMU-DTS-entries.patch93
-rw-r--r--patches.arch/arm64-4-6-arm64-perf-Define-complete-ARMv8-recommended-implementation-defined-events.patch121
-rw-r--r--patches.arch/arm64-5-6-arm64-perf-Filter-common-events-based-on-PMCEIDn_EL0.patch185
-rw-r--r--patches.arch/arm64-6-6-arm64-perf-Add-Broadcom-Vulcan-PMU-support.patch124
-rw-r--r--patches.arch/arm64-clk-xgene-Add-SoC-and-PMD-PLL-clocks-with-v2-hardwar.patch189
-rw-r--r--patches.arch/arm64-clk-xgene-Add-missing-parenthesis-when-clearing-divi.patch38
-rw-r--r--patches.arch/arm64-clk-xgene-Fix-divider-with-non-zero-shift-value.patch35
-rw-r--r--patches.arch/arm64-clk-xgene-Remove-return-from-void-function.patch33
-rw-r--r--patches.arch/arm64-drivers-net-xgene-Add-support-for-Classifier-engine.patch792
-rw-r--r--patches.arch/arm64-drivers-net-xgene-Add-support-for-RSS.patch538
-rw-r--r--patches.arch/arm64-drivers-net-xgene-Add-support-for-multiple-queues.patch886
-rw-r--r--patches.arch/arm64-drivers-net-xgene-constify-xgene_mac_ops-and-xgene_p.patch194
-rw-r--r--patches.arch/arm64-drivers-net-xgene-fix-extra-IRQ-issue.patch82
-rw-r--r--patches.arch/arm64-drivers-net-xgene-optimizing-the-code.patch83
-rw-r--r--patches.arch/arm64-dt-bindings-Add-documentation-for-Broadcom-Vulcan.patch50
-rw-r--r--patches.arch/arm64-dts-vulcan-Update-PCI-ranges.patch58
-rw-r--r--patches.arch/arm64-gpio-change-member-.dev-to-.parent.patch2722
-rw-r--r--patches.arch/arm64-gpio-xgene-Prevent-NULL-pointer-dereference.patch36
-rw-r--r--patches.arch/arm64-gpio-xgene-sb-Use-irq_domain_free_irqs_common.patch52
-rw-r--r--patches.arch/arm64-gpio-xlp-Add-GPIO-driver-support-for-Broadcom-Vulcan.patch115
-rw-r--r--patches.arch/arm64-gpio-xlp-use-gpiochip-data-pointer.patch114
-rw-r--r--patches.arch/arm64-lib-bitmap.c-conversion-routines-to-from-u32-array.patch161
-rw-r--r--patches.arch/arm64-mmc-sdhci-of-esdhc-add-remove-some-quirks-according-.patch65
-rw-r--r--patches.arch/arm64-net-thunder-bgx-Rework-driver-to-support-ACPI-bindin.patch89
-rw-r--r--patches.arch/arm64-net-thunderx-Alloc-higher-order-pages-when-pagesize-.patch28
-rw-r--r--patches.arch/arm64-net-thunderx-Assign-affinity-hints-to-vf-s-interrupt.patch97
-rw-r--r--patches.arch/arm64-net-thunderx-Cleanup-PHY-probing-code.patch85
-rw-r--r--patches.arch/arm64-net-thunderx-Don-t-leak-phy-device-references-on-EPR.patch87
-rw-r--r--patches.arch/arm64-net-thunderx-Fix-for-HW-TSO-not-enabled-for-secondar.patch39
-rw-r--r--patches.arch/arm64-net-thunderx-Fix-for-Qset-error-due-to-CQ-full.patch86
-rw-r--r--patches.arch/arm64-net-thunderx-Fix-for-multiqset-not-configured-upon-i.patch28
-rw-r--r--patches.arch/arm64-net-thunderx-Fix-receive-packet-stats.patch105
-rw-r--r--patches.arch/arm64-net-thunderx-bgx-Add-log-message-when-setting-mac-ad.patch64
-rw-r--r--patches.arch/arm64-net-thunderx-bgx-dont-use-mdio.patch20
-rw-r--r--patches.arch/arm64-spi-xlp-Enable-SPI-driver-for-Broadcom-Vulcan-ARM64.patch36
-rw-r--r--patches.arch/arm64-staging-fsl-mc-Remove-unneeded-parentheses.patch48
-rw-r--r--patches.arch/arm64-staging-fsl-mc-bus-Drop-warning.patch57
-rw-r--r--patches.arch/arm64-thd-pmu-2-5-arm64-perf-Add-Cavium-ThunderX-PMU-support.patch12
-rw-r--r--patches.drivers/arm64-ata-add-AMD-Seattle-platform-driver.patch282
-rw-r--r--series.conf113
-rw-r--r--supported.conf7
107 files changed, 18170 insertions, 103 deletions
diff --git a/config/arm64/default b/config/arm64/default
index acf24a7e47..d143a233e7 100644
--- a/config/arm64/default
+++ b/config/arm64/default
@@ -347,6 +347,7 @@ CONFIG_ARCH_TEGRA_132_SOC=y
CONFIG_ARCH_SPRD=y
CONFIG_ARCH_THUNDER=y
CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_VULCAN=y
CONFIG_ARCH_XGENE=y
CONFIG_ARCH_ZYNQMP=y
@@ -397,6 +398,7 @@ CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_PCIE_PME=y
CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_ACPI is not set
CONFIG_HOTPLUG_PCI_CPCI=y
CONFIG_HOTPLUG_PCI_SHPC=m
@@ -599,6 +601,7 @@ CONFIG_ARM_HISI_ACPU_CPUFREQ=m
CONFIG_ARM_MT8173_CPUFREQ=y
# CONFIG_ARM_TEGRA20_CPUFREQ is not set
# CONFIG_ARM_TEGRA124_CPUFREQ is not set
+# CONFIG_ACPI_CPPC_CPUFREQ is not set
CONFIG_NET=y
CONFIG_COMPAT_NETLINK_MESSAGES=y
CONFIG_NET_INGRESS=y
@@ -1245,6 +1248,11 @@ CONFIG_CAN_M_CAN=m
# CONFIG_CAN_CC770 is not set
#
+# CAN SPI interfaces
+#
+# CONFIG_CAN_MCP251X is not set
+
+#
# CAN USB interfaces
#
CONFIG_CAN_EMS_USB=m
@@ -1403,6 +1411,7 @@ CONFIG_CEPH_LIB=m
CONFIG_NFC=m
CONFIG_NFC_DIGITAL=m
CONFIG_NFC_NCI=m
+# CONFIG_NFC_NCI_SPI is not set
CONFIG_NFC_NCI_UART=m
CONFIG_NFC_HCI=m
CONFIG_NFC_SHDLC=y
@@ -1412,6 +1421,7 @@ CONFIG_NFC_SHDLC=y
#
CONFIG_NFC_PN533=m
CONFIG_NFC_WILINK=m
+# CONFIG_NFC_TRF7970A is not set
CONFIG_NFC_SIM=m
CONFIG_NFC_PORT100=m
# CONFIG_NFC_FDP is not set
@@ -1427,6 +1437,7 @@ CONFIG_NFC_ST21NFCA=m
CONFIG_NFC_ST21NFCA_I2C=m
CONFIG_NFC_ST_NCI=m
CONFIG_NFC_ST_NCI_I2C=m
+# CONFIG_NFC_ST_NCI_SPI is not set
CONFIG_NFC_NXP_NCI=m
CONFIG_NFC_NXP_NCI_I2C=m
CONFIG_NFC_S3FWRN5=m
@@ -1562,6 +1573,9 @@ CONFIG_MTD_LATCH_ADDR=m
CONFIG_MTD_PMC551=m
CONFIG_MTD_PMC551_BUGFIX=y
# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
CONFIG_MTD_SLRAM=m
CONFIG_MTD_PHRAM=m
CONFIG_MTD_MTDRAM=m
@@ -1639,6 +1653,13 @@ CONFIG_PARPORT=m
CONFIG_PARPORT_AX88796=m
CONFIG_PARPORT_1284=y
CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_NULL_BLK is not set
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
@@ -1678,6 +1699,7 @@ CONFIG_BLK_DEV_NVME_SCSI=y
CONFIG_SENSORS_LIS3LV02D=m
CONFIG_AD525X_DPOT=m
CONFIG_AD525X_DPOT_I2C=m
+# CONFIG_AD525X_DPOT_SPI is not set
CONFIG_DUMMY_IRQ=m
CONFIG_PHANTOM=m
CONFIG_SGI_IOC4=m
@@ -1696,9 +1718,12 @@ CONFIG_SENSORS_BH1770=m
CONFIG_SENSORS_APDS990X=m
CONFIG_HMC6352=m
CONFIG_DS1682=m
+# CONFIG_TI_DAC7512 is not set
CONFIG_BMP085=y
CONFIG_BMP085_I2C=m
+# CONFIG_BMP085_SPI is not set
CONFIG_USB_SWITCH_FSA9480=m
+# CONFIG_LATTICE_ECP3_CONFIG is not set
# CONFIG_SRAM is not set
CONFIG_VEXPRESS_SYSCFG=y
CONFIG_C2PORT=m
@@ -1707,9 +1732,11 @@ CONFIG_C2PORT=m
# EEPROM support
#
CONFIG_EEPROM_AT24=m
+# CONFIG_EEPROM_AT25 is not set
CONFIG_EEPROM_LEGACY=m
CONFIG_EEPROM_MAX6875=m
CONFIG_EEPROM_93CX6=m
+# CONFIG_EEPROM_93XX46 is not set
CONFIG_CB710_CORE=m
# CONFIG_CB710_DEBUG is not set
CONFIG_CB710_DEBUG_ASSUMPTIONS=y
@@ -1886,6 +1913,8 @@ CONFIG_HAVE_PATA_PLATFORM=y
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+# CONFIG_SATA_ZPODD is not set
CONFIG_SATA_PMP=y
#
@@ -1897,6 +1926,7 @@ CONFIG_AHCI_CEVA=m
CONFIG_AHCI_TEGRA=m
CONFIG_AHCI_XGENE=m
CONFIG_AHCI_QORIQ=m
+CONFIG_SATA_AHCI_SEATTLE=m
CONFIG_SATA_INIC162X=m
CONFIG_SATA_ACARD_AHCI=m
CONFIG_SATA_SIL24=m
@@ -1975,6 +2005,7 @@ CONFIG_PATA_RZ1000=m
#
# Generic fallback / legacy drivers
#
+# CONFIG_PATA_ACPI is not set
CONFIG_ATA_GENERIC=m
# CONFIG_PATA_LEGACY is not set
CONFIG_MD=y
@@ -2278,8 +2309,12 @@ CONFIG_MLXSW_SWITCHX2=m
CONFIG_MLXSW_SPECTRUM=m
CONFIG_NET_VENDOR_MICREL=y
CONFIG_KS8842=m
+# CONFIG_KS8851 is not set
CONFIG_KS8851_MLL=m
CONFIG_KSZ884X_PCI=m
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
CONFIG_NET_VENDOR_MYRI=y
CONFIG_MYRI10GE=m
CONFIG_FEALNX=m
@@ -2307,6 +2342,7 @@ CONFIG_NETXEN_NIC=m
CONFIG_QED=m
CONFIG_QEDE=m
CONFIG_NET_VENDOR_QUALCOMM=y
+# CONFIG_QCA7000 is not set
CONFIG_NET_VENDOR_REALTEK=y
CONFIG_8139CP=m
CONFIG_8139TOO=m
@@ -2380,6 +2416,7 @@ CONFIG_SKFP=m
CONFIG_HIPPI=y
CONFIG_ROADRUNNER=m
# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+# CONFIG_NET_SB1000 is not set
CONFIG_PHYLIB=m
#
@@ -2418,6 +2455,7 @@ CONFIG_MDIO_BUS_MUX_GPIO=m
# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
CONFIG_MDIO_BCM_UNIMAC=m
# CONFIG_MDIO_BCM_IPROC is not set
+# CONFIG_MICREL_KS8995MA is not set
CONFIG_PLIP=m
CONFIG_PPP=m
CONFIG_PPP_BSDCOMP=m
@@ -2617,6 +2655,7 @@ CONFIG_IWL3945=m
CONFIG_LIBERTAS=m
CONFIG_LIBERTAS_USB=m
CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
# CONFIG_LIBERTAS_DEBUG is not set
CONFIG_LIBERTAS_MESH=y
CONFIG_HERMES=m
@@ -2629,6 +2668,7 @@ CONFIG_ORINOCO_USB=m
CONFIG_P54_COMMON=m
CONFIG_P54_USB=m
CONFIG_P54_PCI=m
+# CONFIG_P54_SPI is not set
CONFIG_P54_LEDS=y
CONFIG_RT2X00=m
CONFIG_RT2400PCI=m
@@ -2682,10 +2722,12 @@ CONFIG_RTL8XXXU=m
CONFIG_RTL8XXXU_UNTESTED=y
CONFIG_WL_TI=y
CONFIG_WL1251=m
+# CONFIG_WL1251_SPI is not set
CONFIG_WL1251_SDIO=m
CONFIG_WL12XX=m
CONFIG_WL18XX=m
CONFIG_WLCORE=m
+# CONFIG_WLCORE_SPI is not set
CONFIG_WLCORE_SDIO=m
# CONFIG_WILINK_PLATFORM_DATA is not set
CONFIG_ZD1211RW=m
@@ -2696,6 +2738,7 @@ CONFIG_MWIFIEX_PCIE=m
CONFIG_MWIFIEX_USB=m
CONFIG_CW1200=m
CONFIG_CW1200_WLAN_SDIO=m
+# CONFIG_CW1200_WLAN_SPI is not set
CONFIG_RSI_91X=m
# CONFIG_RSI_DEBUGFS is not set
CONFIG_RSI_SDIO=m
@@ -2706,6 +2749,7 @@ CONFIG_RSI_USB=m
#
# CONFIG_WAN is not set
CONFIG_VMXNET3=m
+# CONFIG_FUJITSU_ES is not set
CONFIG_ISDN=y
CONFIG_ISDN_I4L=m
CONFIG_ISDN_PPP=y
@@ -2942,8 +2986,11 @@ CONFIG_TABLET_USB_KBTAB=m
CONFIG_TABLET_SERIAL_WACOM4=m
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_PROPERTIES=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
CONFIG_TOUCHSCREEN_AD7879=m
CONFIG_TOUCHSCREEN_AD7879_I2C=m
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
CONFIG_TOUCHSCREEN_AR1021_I2C=m
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
@@ -3007,6 +3054,7 @@ CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
CONFIG_TOUCHSCREEN_TSC200X_CORE=m
CONFIG_TOUCHSCREEN_TSC2004=m
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_TOUCHSCREEN_ST1232=m
CONFIG_TOUCHSCREEN_SUR40=m
@@ -3017,6 +3065,7 @@ CONFIG_TOUCHSCREEN_ROHM_BU21023=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_AD714X=m
CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
# CONFIG_INPUT_BMA150 is not set
# CONFIG_INPUT_E3X0_BUTTON is not set
CONFIG_INPUT_PM8941_PWRKEY=m
@@ -3038,6 +3087,7 @@ CONFIG_INPUT_PCF8574=m
CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
CONFIG_INPUT_ADXL34X=m
CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
# CONFIG_INPUT_IMS_PCU is not set
CONFIG_INPUT_CMA3000=m
CONFIG_INPUT_CMA3000_I2C=m
@@ -3100,6 +3150,7 @@ CONFIG_DEVKMEM=y
CONFIG_SERIAL_EARLYCON=y
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DMA=y
CONFIG_SERIAL_8250_PCI=y
@@ -3109,6 +3160,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_8250_DW=y
# CONFIG_SERIAL_8250_RT288X is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
# CONFIG_SERIAL_8250_MT6577 is not set
# CONFIG_SERIAL_8250_INGENIC is not set
# CONFIG_SERIAL_8250_MID is not set
@@ -3123,6 +3175,8 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
# CONFIG_SERIAL_KGDB_NMI is not set
# CONFIG_SERIAL_SAMSUNG is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
@@ -3134,8 +3188,10 @@ CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_SC16IS7XX_CORE=m
CONFIG_SERIAL_SC16IS7XX=m
CONFIG_SERIAL_SC16IS7XX_I2C=y
+# CONFIG_SERIAL_SC16IS7XX_SPI is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
# CONFIG_SERIAL_ARC is not set
@@ -3176,13 +3232,16 @@ CONFIG_APPLICOM=m
#
CONFIG_RAW_DRIVER=m
CONFIG_MAX_RAW_DEVS=4096
+# CONFIG_HPET is not set
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS_I2C_ATMEL=m
CONFIG_TCG_TIS_I2C_INFINEON=m
CONFIG_TCG_TIS_I2C_NUVOTON=m
CONFIG_TCG_ATMEL=m
+# CONFIG_TCG_INFINEON is not set
CONFIG_TCG_TIS_ST33ZP24=m
CONFIG_TCG_TIS_ST33ZP24_I2C=m
+# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
CONFIG_DEVPORT=y
CONFIG_CRASHER=m
CONFIG_XILLYBUS=m
@@ -3193,6 +3252,7 @@ CONFIG_XILLYBUS_OF=m
# I2C support
#
CONFIG_I2C=y
+CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=m
@@ -3234,6 +3294,11 @@ CONFIG_I2C_SIS96X=m
CONFIG_I2C_VIAPRO=m
#
+# ACPI drivers
+#
+# CONFIG_I2C_SCMI is not set
+
+#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_BCM_IPROC=m
@@ -3245,7 +3310,7 @@ CONFIG_I2C_DESIGNWARE_PCI=m
# CONFIG_I2C_EMEV2 is not set
# CONFIG_I2C_EXYNOS5 is not set
# CONFIG_I2C_GPIO is not set
-# CONFIG_I2C_IMX is not set
+CONFIG_I2C_IMX=m
CONFIG_I2C_MT65XX=m
# CONFIG_I2C_NOMADIK is not set
# CONFIG_I2C_OCORES is not set
@@ -3280,7 +3345,43 @@ CONFIG_I2C_STUB=m
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_BUTTERFLY is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DLN2 is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_LM70_LLP is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_FSL_DSPI is not set
+# CONFIG_SPI_MT65XX is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PL022 is not set
+# CONFIG_SPI_PXA2XX is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_QUP is not set
+# CONFIG_SPI_S3C64XX is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_TEGRA20_SFLASH is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPI_XLP=m
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
CONFIG_SPMI=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_HSI=m
@@ -3342,6 +3443,10 @@ CONFIG_PINCTRL_BERLIN=y
# CONFIG_PINCTRL_BERLIN_BG2CD is not set
# CONFIG_PINCTRL_BERLIN_BG2Q is not set
CONFIG_PINCTRL_BERLIN_BG4CT=y
+# CONFIG_PINCTRL_BAYTRAIL is not set
+# CONFIG_PINCTRL_CHERRYVIEW is not set
+# CONFIG_PINCTRL_BROXTON is not set
+# CONFIG_PINCTRL_SUNRISEPOINT is not set
# CONFIG_PINCTRL_APQ8064 is not set
# CONFIG_PINCTRL_APQ8084 is not set
# CONFIG_PINCTRL_IPQ8064 is not set
@@ -3349,6 +3454,7 @@ CONFIG_PINCTRL_BERLIN_BG4CT=y
# CONFIG_PINCTRL_MSM8960 is not set
# CONFIG_PINCTRL_MSM8X74 is not set
# CONFIG_PINCTRL_MSM8916 is not set
+# CONFIG_PINCTRL_QDF2XXX is not set
# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_SAMSUNG=y
@@ -3362,6 +3468,7 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_DEVRES=y
CONFIG_OF_GPIO=y
+CONFIG_GPIO_ACPI=y
CONFIG_GPIOLIB_IRQCHIP=y
# CONFIG_DEBUG_GPIO is not set
CONFIG_GPIO_SYSFS=y
@@ -3373,6 +3480,7 @@ CONFIG_GPIO_MAX730X=m
#
CONFIG_GPIO_74XX_MMIO=m
# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_AMDPT is not set
CONFIG_GPIO_DWAPB=m
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_GPIO_GRGPIO=m
@@ -3382,7 +3490,8 @@ CONFIG_GPIO_VX855=m
CONFIG_GPIO_XGENE=y
CONFIG_GPIO_XGENE_SB=m
CONFIG_GPIO_XILINX=m
-CONFIG_GPIO_ZYNQ=m
+CONFIG_GPIO_XLP=m
+# CONFIG_GPIO_ZYNQ is not set
# CONFIG_GPIO_ZX is not set
#
@@ -3410,6 +3519,13 @@ CONFIG_GPIO_ML_IOH=m
# CONFIG_GPIO_RDC321X is not set
#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
# SPI or I2C GPIO expanders
#
# CONFIG_GPIO_MCP23S08 is not set
@@ -3465,6 +3581,7 @@ CONFIG_HWMON_VID=m
#
# Native drivers
#
+# CONFIG_SENSORS_AD7314 is not set
CONFIG_SENSORS_AD7414=m
CONFIG_SENSORS_AD7418=m
CONFIG_SENSORS_ADM1021=m
@@ -3474,6 +3591,7 @@ CONFIG_SENSORS_ADM1029=m
CONFIG_SENSORS_ADM1031=m
CONFIG_SENSORS_ADM9240=m
CONFIG_SENSORS_ADT7X10=m
+# CONFIG_SENSORS_ADT7310 is not set
CONFIG_SENSORS_ADT7410=m
CONFIG_SENSORS_ADT7411=m
CONFIG_SENSORS_ADT7462=m
@@ -3506,6 +3624,7 @@ CONFIG_SENSORS_LTC4222=m
# CONFIG_SENSORS_LTC4245 is not set
CONFIG_SENSORS_LTC4260=m
# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX16065 is not set
CONFIG_SENSORS_MAX1619=m
CONFIG_SENSORS_MAX1668=m
@@ -3518,7 +3637,9 @@ CONFIG_SENSORS_MAX31790=m
# CONFIG_SENSORS_HTU21 is not set
# CONFIG_SENSORS_MCP3021 is not set
# CONFIG_SENSORS_MENF21BMC_HWMON is not set
+# CONFIG_SENSORS_ADCXX is not set
CONFIG_SENSORS_LM63=m
+# CONFIG_SENSORS_LM70 is not set
CONFIG_SENSORS_LM73=m
CONFIG_SENSORS_LM75=m
CONFIG_SENSORS_LM77=m
@@ -3574,6 +3695,7 @@ CONFIG_SENSORS_SCH5636=m
CONFIG_SENSORS_ADC128D818=m
CONFIG_SENSORS_ADS1015=m
CONFIG_SENSORS_ADS7828=m
+# CONFIG_SENSORS_ADS7871 is not set
CONFIG_SENSORS_AMC6821=m
# CONFIG_SENSORS_INA209 is not set
CONFIG_SENSORS_INA2XX=m
@@ -3597,6 +3719,11 @@ CONFIG_SENSORS_W83L785TS=m
CONFIG_SENSORS_W83L786NG=m
CONFIG_SENSORS_W83627HF=m
CONFIG_SENSORS_W83627EHF=m
+
+#
+# ACPI drivers
+#
+# CONFIG_SENSORS_ACPI_POWER is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_OF=y
@@ -3706,12 +3833,14 @@ CONFIG_MFD_ATMEL_HLCDC=m
# CONFIG_MFD_BCM590XX is not set
# CONFIG_MFD_AXP20X is not set
# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_DA9052_I2C is not set
# CONFIG_MFD_DA9055 is not set
# CONFIG_MFD_DA9062 is not set
# CONFIG_MFD_DA9063 is not set
# CONFIG_MFD_DA9150 is not set
CONFIG_MFD_DLN2=m
+# CONFIG_MFD_MC13XXX_SPI is not set
# CONFIG_MFD_MC13XXX_I2C is not set
# CONFIG_MFD_HI6421_PMIC is not set
CONFIG_HTC_PASIC3=m
@@ -3734,6 +3863,7 @@ CONFIG_LPC_SCH=m
# CONFIG_MFD_MAX8998 is not set
# CONFIG_MFD_MT6397 is not set
CONFIG_MFD_MENF21BMC=m
+# CONFIG_EZX_PCAP is not set
CONFIG_MFD_VIPERBOARD=m
# CONFIG_MFD_RETU is not set
# CONFIG_MFD_PCF50633 is not set
@@ -3769,6 +3899,7 @@ CONFIG_TPS6507X=m
# CONFIG_MFD_TPS65910 is not set
# CONFIG_MFD_TPS65912 is not set
# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
# CONFIG_MFD_TPS80031 is not set
# CONFIG_TWL4030_CORE is not set
# CONFIG_TWL6040_CORE is not set
@@ -3778,8 +3909,10 @@ CONFIG_MFD_WL1273_CORE=m
# CONFIG_MFD_TMIO is not set
CONFIG_MFD_VX855=m
# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
# CONFIG_MFD_WM8350_I2C is not set
# CONFIG_MFD_WM8994 is not set
CONFIG_MFD_VEXPRESS_SYSREG=y
@@ -3818,6 +3951,7 @@ CONFIG_REGULATOR_SKY81452=m
# CONFIG_REGULATOR_TPS62360 is not set
# CONFIG_REGULATOR_TPS65023 is not set
# CONFIG_REGULATOR_TPS6507X is not set
+# CONFIG_REGULATOR_TPS6524X is not set
CONFIG_REGULATOR_VEXPRESS=m
CONFIG_MEDIA_SUPPORT=m
@@ -3872,9 +4006,13 @@ CONFIG_IR_MCE_KBD_DECODER=m
CONFIG_IR_XMP_DECODER=m
CONFIG_RC_DEVICES=y
CONFIG_RC_ATI_REMOTE=m
+# CONFIG_IR_ENE is not set
CONFIG_IR_HIX5HD2=m
CONFIG_IR_IMON=m
CONFIG_IR_MCEUSB=m
+# CONFIG_IR_ITE_CIR is not set
+# CONFIG_IR_FINTEK is not set
+# CONFIG_IR_NUVOTON is not set
CONFIG_IR_REDRAT3=m
CONFIG_IR_STREAMZAP=m
CONFIG_IR_IGORPLUGUSB=m
@@ -4043,6 +4181,7 @@ CONFIG_VIDEO_EM28XX_RC=m
#
CONFIG_USB_AIRSPY=m
CONFIG_USB_HACKRF=m
+# CONFIG_USB_MSI2500 is not set
CONFIG_MEDIA_PCI_SUPPORT=y
#
@@ -4110,6 +4249,7 @@ CONFIG_DVB_HOPPER=m
CONFIG_DVB_NGENE=m
CONFIG_DVB_DDBRIDGE=m
CONFIG_DVB_SMIPCIE=m
+# CONFIG_DVB_NETUP_UNIDVB is not set
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
@@ -4485,12 +4625,15 @@ CONFIG_DRM_MSM_DSI_20NM_PHY=y
CONFIG_DRM_TEGRA=m
CONFIG_DRM_TEGRA_FBDEV=y
# CONFIG_DRM_TEGRA_DEBUG is not set
+# CONFIG_DRM_TEGRA_STAGING is not set
CONFIG_DRM_PANEL=y
#
# Display Panels
#
# CONFIG_DRM_PANEL_SIMPLE is not set
+# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
+# CONFIG_DRM_PANEL_LG_LG4573 is not set
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set
CONFIG_DRM_BRIDGE=y
@@ -4573,7 +4716,19 @@ CONFIG_EXYNOS_VIDEO=y
# CONFIG_FB_SM712 is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI922X is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
CONFIG_LCD_PLATFORM=m
+# CONFIG_LCD_S6E63M0 is not set
+# CONFIG_LCD_LD9040 is not set
+# CONFIG_LCD_AMS369FG06 is not set
+# CONFIG_LCD_LMS501KF03 is not set
+# CONFIG_LCD_HX8357 is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=m
# CONFIG_BACKLIGHT_PWM is not set
@@ -4749,6 +4904,7 @@ CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
CONFIG_SND_HDA_CORE=m
CONFIG_SND_HDA_DSP_LOADER=y
CONFIG_SND_HDA_PREALLOC_SIZE=1024
+CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_USB_UA101=m
@@ -4934,6 +5090,7 @@ CONFIG_USB_EHCI_HCD_PLATFORM=m
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_OHCI_HCD_PCI=m
# CONFIG_USB_OHCI_HCD_SSB is not set
@@ -5158,6 +5315,7 @@ CONFIG_MMC_SDHCI=m
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_PCI=m
CONFIG_MMC_RICOH_MMC=y
+# CONFIG_MMC_SDHCI_ACPI is not set
CONFIG_MMC_SDHCI_PLTFM=m
CONFIG_MMC_SDHCI_OF_ARASAN=m
# CONFIG_MMC_SDHCI_OF_AT91 is not set
@@ -5168,6 +5326,7 @@ CONFIG_MMC_SDHCI_F_SDH30=m
CONFIG_MMC_SDHCI_IPROC=m
CONFIG_MMC_SDHCI_MSM=m
CONFIG_MMC_TIFM_SD=m
+# CONFIG_MMC_SPI is not set
CONFIG_MMC_CB710=m
CONFIG_MMC_VIA_SDMMC=m
CONFIG_MMC_DW=m
@@ -5225,6 +5384,7 @@ CONFIG_LEDS_LP8501=m
CONFIG_LEDS_LP8860=m
CONFIG_LEDS_PCA955X=m
CONFIG_LEDS_PCA963X=m
+# CONFIG_LEDS_DAC124S085 is not set
CONFIG_LEDS_PWM=m
# CONFIG_LEDS_REGULATOR is not set
CONFIG_LEDS_BD2802=m
@@ -5346,6 +5506,19 @@ CONFIG_RTC_DRV_RV8803=y
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
#
# Platform RTC drivers
@@ -5399,6 +5572,7 @@ CONFIG_DMADEVICES=y
CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_VIRTUAL_CHANNELS=m
+CONFIG_DMA_ACPI=y
CONFIG_DMA_OF=y
# CONFIG_AMBA_PL08X is not set
# CONFIG_FSL_EDMA is not set
@@ -5452,7 +5626,47 @@ CONFIG_VIRTIO_MMIO=m
#
# Microsoft Hyper-V guest support
#
-# CONFIG_STAGING is not set
+CONFIG_STAGING=y
+# CONFIG_PRISM2_USB is not set
+# CONFIG_COMEDI is not set
+# CONFIG_PANEL is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_R8712U is not set
+# CONFIG_R8188EU is not set
+# CONFIG_R8723AU is not set
+# CONFIG_RTS5208 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+# CONFIG_FB_SM750 is not set
+# CONFIG_FB_XGI is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+# CONFIG_MFD_NVEC is not set
+# CONFIG_STAGING_MEDIA is not set
+# CONFIG_STAGING_RDMA is not set
+
+#
+# Android
+#
+# CONFIG_STAGING_BOARD is not set
+# CONFIG_WIMAX_GDM72XX is not set
+# CONFIG_LTE_GDM724X is not set
+# CONFIG_FIREWIRE_SERIAL is not set
+# CONFIG_MTD_SPINAND_MT29F is not set
+# CONFIG_LUSTRE_FS is not set
+# CONFIG_DGNC is not set
+# CONFIG_DGAP is not set
+# CONFIG_GS_FPGABOOT is not set
+# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set
+# CONFIG_FB_TFT is not set
+CONFIG_FSL_MC_BUS=y
+# CONFIG_WILC1000_DRIVER is not set
+# CONFIG_MOST is not set
CONFIG_CHROME_PLATFORMS=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_HAVE_CLK_PREPARE=y
@@ -5488,6 +5702,7 @@ CONFIG_HWSPINLOCK_QCOM=m
# Clock Source drivers
#
CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_ACPI=y
CONFIG_CLKSRC_PROBE=y
CONFIG_CLKSRC_MMIO=y
CONFIG_ARM_ARCH_TIMER=y
@@ -5501,8 +5716,10 @@ CONFIG_ARM_TIMER_SP804=y
CONFIG_MAILBOX=y
# CONFIG_ARM_MHU is not set
# CONFIG_PL320_MBOX is not set
+# CONFIG_PCC is not set
# CONFIG_ALTERA_MBOX is not set
# CONFIG_MAILBOX_TEST is not set
+CONFIG_XGENE_SLIMPRO_MBOX=m
CONFIG_IOMMU_API=y
CONFIG_IOMMU_SUPPORT=y
@@ -5591,6 +5808,7 @@ CONFIG_ARM_GIC_V2M=y
CONFIG_ARM_GIC_V3=y
CONFIG_ARM_GIC_V3_ITS=y
CONFIG_DW_APB_ICTL=y
+CONFIG_LS_SCFG_MSI=y
CONFIG_IPACK_BUS=m
CONFIG_BOARD_TPCI200=m
CONFIG_SERIAL_IPOCTAL=m
@@ -5625,6 +5843,7 @@ CONFIG_PHY_QCOM_UFS=m
# Performance monitor support
#
CONFIG_ARM_PMU=y
+CONFIG_XGENE_PMU=y
CONFIG_RAS=y
CONFIG_THUNDERBOLT=m
@@ -5671,7 +5890,27 @@ CONFIG_EFI_ESRT=y
CONFIG_EFI_PARAMS_FROM_FDT=y
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_EFI_ARMSTUB=y
-# CONFIG_ACPI is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_GENERIC_GSI=y
+CONFIG_ACPI_CCA_REQUIRED=y
+# CONFIG_ACPI_DEBUGGER is not set
+# CONFIG_ACPI_EC_DEBUGFS is not set
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_IPMI=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_CUSTOM_DSDT_FILE=""
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_CUSTOM_METHOD=m
+CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y
+# CONFIG_PMIC_OPREGION is not set
#
# File systems
diff --git a/patches.arch/arm64-0001-PCI-layerscape-Add-fsl-ls2085a-pcie-compatible-ID.patch b/patches.arch/arm64-0001-PCI-layerscape-Add-fsl-ls2085a-pcie-compatible-ID.patch
new file mode 100644
index 0000000000..10bf17d055
--- /dev/null
+++ b/patches.arch/arm64-0001-PCI-layerscape-Add-fsl-ls2085a-pcie-compatible-ID.patch
@@ -0,0 +1,34 @@
+From dbae40b76abef2f8a7e7bf1701f77df9e73def48 Mon Sep 17 00:00:00 2001
+From: Yang Shi <yang.shi@linaro.org>
+Date: Wed, 27 Jan 2016 09:32:05 -0800
+Subject: [PATCH] PCI: layerscape: Add "fsl,ls2085a-pcie" compatible ID
+Patch-mainline: v4.6-rc1
+Git-commit: dbae40b76abef2f8a7e7bf1701f77df9e73def48
+References: fate#319900
+
+The Layerscape PCI host driver must recognize ls2085a compatible when using
+firmware with ls2085a compatible property, otherwise the PCI bus won't be
+detected even though ls2085a compatible is included by the dts.
+
+Signed-off-by: Yang Shi <yang.shi@linaro.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/pci/host/pci-layerscape.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
+index 3923bed..c40d8b2 100644
+--- a/drivers/pci/host/pci-layerscape.c
++++ b/drivers/pci/host/pci-layerscape.c
+@@ -203,6 +203,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
+ { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
+ { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
+ { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
++ { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0001-Staging-fsl-mc-bus-Drop-owner-assignment-from-platfo.patch b/patches.arch/arm64-0001-Staging-fsl-mc-bus-Drop-owner-assignment-from-platfo.patch
new file mode 100644
index 0000000000..45ffbf61b9
--- /dev/null
+++ b/patches.arch/arm64-0001-Staging-fsl-mc-bus-Drop-owner-assignment-from-platfo.patch
@@ -0,0 +1,38 @@
+From 453dd922c4db55905796209af4be1503c54cd84f Mon Sep 17 00:00:00 2001
+From: Bhumika Goyal <bhumirks@gmail.com>
+Date: Thu, 18 Feb 2016 11:19:38 +0530
+Subject: [PATCH 1/2] Staging: fsl-mc: bus: Drop owner assignment from
+ platform_driver
+Patch-mainline: v4.6-rc1
+Git-commit: 453dd922c4db55905796209af4be1503c54cd84f
+References: fate#319900
+
+For platform_driver, we don't need to set .owner field as is set by
+platform driver core. The semantic patch used here first checks whether
+platform_driver struct was actually used in a call to set the .owner
+field.
+The coccinelle script that generated the patch can be found here:
+http://www.spinics.net/lists/kernel/msg2029903.html
+
+Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 9317561..c42bfac 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -795,7 +795,6 @@ MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
+ static struct platform_driver fsl_mc_bus_driver = {
+ .driver = {
+ .name = "fsl_mc_bus",
+- .owner = THIS_MODULE,
+ .pm = NULL,
+ .of_match_table = fsl_mc_bus_match_table,
+ },
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0001-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch b/patches.arch/arm64-0001-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch
new file mode 100644
index 0000000000..ef69ad104e
--- /dev/null
+++ b/patches.arch/arm64-0001-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch
@@ -0,0 +1,48 @@
+From ef0cc7fef4721aa19663da7475c8b862f0a35e0b Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Wed, 16 Dec 2015 13:43:49 +0800
+Subject: [PATCH 1/3] ahci: qoriq: Adjust the default register values on
+ ls1043a
+Patch-mainline: v4.5-rc1
+Git-commit: ef0cc7fef4721aa19663da7475c8b862f0a35e0b
+References: fate#319900
+
+Updated the registers' values to enhance SATA performance and
+reliability.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/ata/ahci_qoriq.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+index d0f9de9..4d613f8 100644
+--- a/drivers/ata/ahci_qoriq.c
++++ b/drivers/ata/ahci_qoriq.c
+@@ -39,6 +39,8 @@
+ #define AHCI_PORT_PHY_4_CFG 0x00480811
+ #define AHCI_PORT_PHY_5_CFG 0x192c96a4
+ #define AHCI_PORT_TRANS_CFG 0x08000025
++#define LS1043A_PORT_PHY2 0x28184d1f
++#define LS1043A_PORT_PHY3 0x0e081509
+
+ #define SATA_ECC_DISABLE 0x00020000
+
+@@ -159,6 +161,12 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
+ break;
+
+ case AHCI_LS1043A:
++ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
++ writel(LS1043A_PORT_PHY2, reg_base + PORT_PHY2);
++ writel(LS1043A_PORT_PHY3, reg_base + PORT_PHY3);
++ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
++ break;
++
+ case AHCI_LS2080A:
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ break;
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0001-amd-xgbe-Disable-VLAN-filtering-when-in-promiscuous-.patch b/patches.arch/arm64-0001-amd-xgbe-Disable-VLAN-filtering-when-in-promiscuous-.patch
new file mode 100644
index 0000000000..747614555a
--- /dev/null
+++ b/patches.arch/arm64-0001-amd-xgbe-Disable-VLAN-filtering-when-in-promiscuous-.patch
@@ -0,0 +1,293 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:48:08 -0600
+Subject: amd-xgbe: Disable VLAN filtering when in promiscuous mode
+Git-commit: b4eee84fcd8ecae88a7d6ab437f88284f9693d9c
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+When the hardware is placed in promiscuous mode it will still perform
+VLAN filtering and therefore may not pass all packets to the driver.
+
+Disable all VLAN filtering when entering promiscuous mode and restore
+VLAN filtering upon exit from promiscuous mode. In order to avoid adding
+forward declarations, move the VLAN related functions earlier in the
+file.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 229 ++++++++++++++++---------------
+ 1 file changed, 117 insertions(+), 112 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index f6a7161..931e374 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -6,7 +6,7 @@
+ *
+ * License 1: GPLv2
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -56,7 +56,7 @@
+ *
+ * License 2: Modified BSD
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -702,6 +702,113 @@ static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata)
+ return 0;
+ }
+
++static int xgbe_enable_rx_vlan_stripping(struct xgbe_prv_data *pdata)
++{
++ /* Put the VLAN tag in the Rx descriptor */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1);
++
++ /* Don't check the VLAN type */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1);
++
++ /* Check only C-TAG (0x8100) packets */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0);
++
++ /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0);
++
++ /* Enable VLAN tag stripping */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3);
++
++ return 0;
++}
++
++static int xgbe_disable_rx_vlan_stripping(struct xgbe_prv_data *pdata)
++{
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0);
++
++ return 0;
++}
++
++static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
++{
++ /* Enable VLAN filtering */
++ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1);
++
++ /* Enable VLAN Hash Table filtering */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1);
++
++ /* Disable VLAN tag inverse matching */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0);
++
++ /* Only filter on the lower 12-bits of the VLAN tag */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1);
++
++ /* In order for the VLAN Hash Table filtering to be effective,
++ * the VLAN tag identifier in the VLAN Tag Register must not
++ * be zero. Set the VLAN tag identifier to "1" to enable the
++ * VLAN Hash Table filtering. This implies that a VLAN tag of
++ * 1 will always pass filtering.
++ */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1);
++
++ return 0;
++}
++
++static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
++{
++ /* Disable VLAN filtering */
++ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0);
++
++ return 0;
++}
++
++static u32 xgbe_vid_crc32_le(__le16 vid_le)
++{
++ u32 poly = 0xedb88320; /* CRCPOLY_LE */
++ u32 crc = ~0;
++ u32 temp = 0;
++ unsigned char *data = (unsigned char *)&vid_le;
++ unsigned char data_byte = 0;
++ int i, bits;
++
++ bits = get_bitmask_order(VLAN_VID_MASK);
++ for (i = 0; i < bits; i++) {
++ if ((i % 8) == 0)
++ data_byte = data[i / 8];
++
++ temp = ((crc & 1) ^ data_byte) & 1;
++ crc >>= 1;
++ data_byte >>= 1;
++
++ if (temp)
++ crc ^= poly;
++ }
++
++ return crc;
++}
++
++static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata)
++{
++ u32 crc;
++ u16 vid;
++ __le16 vid_le;
++ u16 vlan_hash_table = 0;
++
++ /* Generate the VLAN Hash Table value */
++ for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) {
++ /* Get the CRC32 value of the VLAN ID */
++ vid_le = cpu_to_le16(vid);
++ crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28;
++
++ vlan_hash_table |= (1 << crc);
++ }
++
++ /* Set the VLAN Hash Table filtering register */
++ XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table);
++
++ return 0;
++}
++
+ static int xgbe_set_promiscuous_mode(struct xgbe_prv_data *pdata,
+ unsigned int enable)
+ {
+@@ -714,6 +821,14 @@ static int xgbe_set_promiscuous_mode(struct xgbe_prv_data *pdata,
+ enable ? "entering" : "leaving");
+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, PR, val);
+
++ /* Hardware will still perform VLAN filtering in promiscuous mode */
++ if (enable) {
++ xgbe_disable_rx_vlan_filtering(pdata);
++ } else {
++ if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
++ xgbe_enable_rx_vlan_filtering(pdata);
++ }
++
+ return 0;
+ }
+
+@@ -944,116 +1059,6 @@ static int xgbe_enable_rx_csum(struct xgbe_prv_data *pdata)
+ return 0;
+ }
+
+-static int xgbe_enable_rx_vlan_stripping(struct xgbe_prv_data *pdata)
+-{
+- /* Put the VLAN tag in the Rx descriptor */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1);
+-
+- /* Don't check the VLAN type */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1);
+-
+- /* Check only C-TAG (0x8100) packets */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0);
+-
+- /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0);
+-
+- /* Enable VLAN tag stripping */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3);
+-
+- return 0;
+-}
+-
+-static int xgbe_disable_rx_vlan_stripping(struct xgbe_prv_data *pdata)
+-{
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0);
+-
+- return 0;
+-}
+-
+-static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
+-{
+- /* Enable VLAN filtering */
+- XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1);
+-
+- /* Enable VLAN Hash Table filtering */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1);
+-
+- /* Disable VLAN tag inverse matching */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0);
+-
+- /* Only filter on the lower 12-bits of the VLAN tag */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1);
+-
+- /* In order for the VLAN Hash Table filtering to be effective,
+- * the VLAN tag identifier in the VLAN Tag Register must not
+- * be zero. Set the VLAN tag identifier to "1" to enable the
+- * VLAN Hash Table filtering. This implies that a VLAN tag of
+- * 1 will always pass filtering.
+- */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1);
+-
+- return 0;
+-}
+-
+-static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
+-{
+- /* Disable VLAN filtering */
+- XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0);
+-
+- return 0;
+-}
+-
+-#ifndef CRCPOLY_LE
+-#define CRCPOLY_LE 0xedb88320
+-#endif
+-static u32 xgbe_vid_crc32_le(__le16 vid_le)
+-{
+- u32 poly = CRCPOLY_LE;
+- u32 crc = ~0;
+- u32 temp = 0;
+- unsigned char *data = (unsigned char *)&vid_le;
+- unsigned char data_byte = 0;
+- int i, bits;
+-
+- bits = get_bitmask_order(VLAN_VID_MASK);
+- for (i = 0; i < bits; i++) {
+- if ((i % 8) == 0)
+- data_byte = data[i / 8];
+-
+- temp = ((crc & 1) ^ data_byte) & 1;
+- crc >>= 1;
+- data_byte >>= 1;
+-
+- if (temp)
+- crc ^= poly;
+- }
+-
+- return crc;
+-}
+-
+-static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata)
+-{
+- u32 crc;
+- u16 vid;
+- __le16 vid_le;
+- u16 vlan_hash_table = 0;
+-
+- /* Generate the VLAN Hash Table value */
+- for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) {
+- /* Get the CRC32 value of the VLAN ID */
+- vid_le = cpu_to_le16(vid);
+- crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28;
+-
+- vlan_hash_table |= (1 << crc);
+- }
+-
+- /* Set the VLAN Hash Table filtering register */
+- XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table);
+-
+- return 0;
+-}
+-
+ static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata)
+ {
+ struct xgbe_ring_desc *rdesc = rdata->rdesc;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0001-arm64-defconfig-Add-Broadcom-Vulcan-to-defconfig.patch b/patches.arch/arm64-0001-arm64-defconfig-Add-Broadcom-Vulcan-to-defconfig.patch
new file mode 100644
index 0000000000..e1f24fe7d1
--- /dev/null
+++ b/patches.arch/arm64-0001-arm64-defconfig-Add-Broadcom-Vulcan-to-defconfig.patch
@@ -0,0 +1,28 @@
+From 4cf430ee0c2ba1da97cab10b904291eb6fc5f170 Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Sat, 20 Feb 2016 19:49:22 +0530
+Subject: [PATCH] arm64: defconfig: Add Broadcom Vulcan to defconfig
+Patch-mainline: v4.6-rc1
+Git-commit: 4cf430ee0c2ba1da97cab10b904291eb6fc5f170
+References: fate#319481
+
+Enable Broadcom Vulcan support in arm64 default configuration. This will
+build the device tree needed to boot on a Broadcom Vulcan board.
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ arch/arm64/configs/defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -46,6 +46,7 @@ CONFIG_ARCH_QCOM=y
+ CONFIG_ARCH_SPRD=y
+ CONFIG_ARCH_THUNDER=y
+ CONFIG_ARCH_VEXPRESS=y
++CONFIG_ARCH_VULCAN=y
+ CONFIG_ARCH_XGENE=y
+ CONFIG_ARCH_ZYNQMP=y
+ CONFIG_PCI=y
diff --git a/patches.arch/arm64-0001-irqdomain-Added-domain-bus-token-DOMAIN_BUS_FSL_MC_M.patch b/patches.arch/arm64-0001-irqdomain-Added-domain-bus-token-DOMAIN_BUS_FSL_MC_M.patch
new file mode 100644
index 0000000000..ff4aa9108f
--- /dev/null
+++ b/patches.arch/arm64-0001-irqdomain-Added-domain-bus-token-DOMAIN_BUS_FSL_MC_M.patch
@@ -0,0 +1,34 @@
+From 9b1b282ccd8195e3264dbb3cd15b9d60b6345230 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:19 -0600
+Subject: [PATCH 01/11] irqdomain: Added domain bus token DOMAIN_BUS_FSL_MC_MSI
+Patch-mainline: v4.6-rc1
+Git-commit: 9b1b282ccd8195e3264dbb3cd15b9d60b6345230
+References: fate#319900 fate#320030
+
+Since an FSL-MC bus is a new bus type that is neither PCI nor
+PLATFORM, we need a new domain bus token to disambiguate the
+IRQ domain for FSL-MC MSIs.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ include/linux/irqdomain.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
+index 04579d9..0934d06 100644
+--- a/include/linux/irqdomain.h
++++ b/include/linux/irqdomain.h
+@@ -74,6 +74,7 @@ enum irq_domain_bus_token {
+ DOMAIN_BUS_PCI_MSI,
+ DOMAIN_BUS_PLATFORM_MSI,
+ DOMAIN_BUS_NEXUS,
++ DOMAIN_BUS_FSL_MC_MSI,
+ };
+
+ /**
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0001-mailbox-Add-support-for-APM-X-Gene-platform-mailbox-.patch b/patches.arch/arm64-0001-mailbox-Add-support-for-APM-X-Gene-platform-mailbox-.patch
new file mode 100644
index 0000000000..e8e0cafbef
--- /dev/null
+++ b/patches.arch/arm64-0001-mailbox-Add-support-for-APM-X-Gene-platform-mailbox-.patch
@@ -0,0 +1,342 @@
+From: Duc Dang <dhdang@apm.com>
+Date: Fri, 12 Feb 2016 19:39:26 -0800
+Subject: mailbox: Add support for APM X-Gene platform mailbox driver
+Git-commit: f700e84f417b98f867c5db0555e6f01724d53cd2
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+X-Gene mailbox controller provides 8 mailbox channels, with
+each channel has a dedicated interrupt line.
+
+Signed-off-by: Feng Kan <fkan@apm.com>
+Signed-off-by: Duc Dang <dhdang@apm.com>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/mailbox/Kconfig | 9 +
+ drivers/mailbox/Makefile | 2 +
+ drivers/mailbox/mailbox-xgene-slimpro.c | 284 ++++++++++++++++++++++++++++++++
+ 3 files changed, 295 insertions(+)
+ create mode 100644 drivers/mailbox/mailbox-xgene-slimpro.c
+
+diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
+index b2bbe86..1107666 100644
+--- a/drivers/mailbox/Kconfig
++++ b/drivers/mailbox/Kconfig
+@@ -86,4 +86,13 @@ config MAILBOX_TEST
+ Test client to help with testing new Controller driver
+ implementations.
+
++config XGENE_SLIMPRO_MBOX
++ tristate "APM SoC X-Gene SLIMpro Mailbox Controller"
++ depends on ARCH_XGENE
++ help
++ An implementation of the APM X-Gene Interprocessor Communication
++ Mailbox (IPCM) between the ARM 64-bit cores and SLIMpro controller.
++ It is used to send short messages between ARM64-bit cores and
++ the SLIMpro Management Engine, primarily for PM. Say Y here if you
++ want to use the APM X-Gene SLIMpro IPCM support.
+ endif
+diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
+index 92435ef..b602ef8 100644
+--- a/drivers/mailbox/Makefile
++++ b/drivers/mailbox/Makefile
+@@ -17,3 +17,5 @@ obj-$(CONFIG_ALTERA_MBOX) += mailbox-altera.o
+ obj-$(CONFIG_BCM2835_MBOX) += bcm2835-mailbox.o
+
+ obj-$(CONFIG_STI_MBOX) += mailbox-sti.o
++
++obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o
+diff --git a/drivers/mailbox/mailbox-xgene-slimpro.c b/drivers/mailbox/mailbox-xgene-slimpro.c
+new file mode 100644
+index 0000000..b5f5106
+--- /dev/null
++++ b/drivers/mailbox/mailbox-xgene-slimpro.c
+@@ -0,0 +1,284 @@
++/*
++ * APM X-Gene SLIMpro MailBox Driver
++ *
++ * Copyright (c) 2015, Applied Micro Circuits Corporation
++ * Author: Feng Kan fkan@apm.com
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ *
++ */
++#include <linux/acpi.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/mailbox_controller.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++
++#define MBOX_CON_NAME "slimpro-mbox"
++#define MBOX_REG_SET_OFFSET 0x1000
++#define MBOX_CNT 8
++#define MBOX_STATUS_AVAIL_MASK BIT(16)
++#define MBOX_STATUS_ACK_MASK BIT(0)
++
++/* Configuration and Status Registers */
++#define REG_DB_IN 0x00
++#define REG_DB_DIN0 0x04
++#define REG_DB_DIN1 0x08
++#define REG_DB_OUT 0x10
++#define REG_DB_DOUT0 0x14
++#define REG_DB_DOUT1 0x18
++#define REG_DB_STAT 0x20
++#define REG_DB_STATMASK 0x24
++
++/**
++ * X-Gene SlimPRO mailbox channel information
++ *
++ * @dev: Device to which it is attached
++ * @chan: Pointer to mailbox communication channel
++ * @reg: Base address to access channel registers
++ * @irq: Interrupt number of the channel
++ * @rx_msg: Received message storage
++ */
++struct slimpro_mbox_chan {
++ struct device *dev;
++ struct mbox_chan *chan;
++ void __iomem *reg;
++ int irq;
++ u32 rx_msg[3];
++};
++
++/**
++ * X-Gene SlimPRO Mailbox controller data
++ *
++ * X-Gene SlimPRO Mailbox controller has 8 commnunication channels.
++ * Each channel has a separate IRQ number assgined to it.
++ *
++ * @mb_ctrl: Representation of the commnunication channel controller
++ * @mc: Array of SlimPRO mailbox channels of the controller
++ * @chans: Array of mailbox communication channels
++ *
++ */
++struct slimpro_mbox {
++ struct mbox_controller mb_ctrl;
++ struct slimpro_mbox_chan mc[MBOX_CNT];
++ struct mbox_chan chans[MBOX_CNT];
++};
++
++static void mb_chan_send_msg(struct slimpro_mbox_chan *mb_chan, u32 *msg)
++{
++ writel(msg[1], mb_chan->reg + REG_DB_DOUT0);
++ writel(msg[2], mb_chan->reg + REG_DB_DOUT1);
++ writel(msg[0], mb_chan->reg + REG_DB_OUT);
++}
++
++static void mb_chan_recv_msg(struct slimpro_mbox_chan *mb_chan)
++{
++ mb_chan->rx_msg[1] = readl(mb_chan->reg + REG_DB_DIN0);
++ mb_chan->rx_msg[2] = readl(mb_chan->reg + REG_DB_DIN1);
++ mb_chan->rx_msg[0] = readl(mb_chan->reg + REG_DB_IN);
++}
++
++static int mb_chan_status_ack(struct slimpro_mbox_chan *mb_chan)
++{
++ u32 val = readl(mb_chan->reg + REG_DB_STAT);
++
++ if (val & MBOX_STATUS_ACK_MASK) {
++ writel(MBOX_STATUS_ACK_MASK, mb_chan->reg + REG_DB_STAT);
++ return 1;
++ }
++ return 0;
++}
++
++static int mb_chan_status_avail(struct slimpro_mbox_chan *mb_chan)
++{
++ u32 val = readl(mb_chan->reg + REG_DB_STAT);
++
++ if (val & MBOX_STATUS_AVAIL_MASK) {
++ mb_chan_recv_msg(mb_chan);
++ writel(MBOX_STATUS_AVAIL_MASK, mb_chan->reg + REG_DB_STAT);
++ return 1;
++ }
++ return 0;
++}
++
++static irqreturn_t slimpro_mbox_irq(int irq, void *id)
++{
++ struct slimpro_mbox_chan *mb_chan = id;
++
++ if (mb_chan_status_ack(mb_chan))
++ mbox_chan_txdone(mb_chan->chan, 0);
++
++ if (mb_chan_status_avail(mb_chan))
++ mbox_chan_received_data(mb_chan->chan, mb_chan->rx_msg);
++
++ return IRQ_HANDLED;
++}
++
++static int slimpro_mbox_send_data(struct mbox_chan *chan, void *msg)
++{
++ struct slimpro_mbox_chan *mb_chan = chan->con_priv;
++
++ mb_chan_send_msg(mb_chan, msg);
++ return 0;
++}
++
++static int slimpro_mbox_startup(struct mbox_chan *chan)
++{
++ struct slimpro_mbox_chan *mb_chan = chan->con_priv;
++ int rc;
++ u32 val;
++
++ rc = devm_request_irq(mb_chan->dev, mb_chan->irq, slimpro_mbox_irq, 0,
++ MBOX_CON_NAME, mb_chan);
++ if (unlikely(rc)) {
++ dev_err(mb_chan->dev, "failed to register mailbox interrupt %d\n",
++ mb_chan->irq);
++ return rc;
++ }
++
++ /* Enable HW interrupt */
++ writel(MBOX_STATUS_ACK_MASK | MBOX_STATUS_AVAIL_MASK,
++ mb_chan->reg + REG_DB_STAT);
++ /* Unmask doorbell status interrupt */
++ val = readl(mb_chan->reg + REG_DB_STATMASK);
++ val &= ~(MBOX_STATUS_ACK_MASK | MBOX_STATUS_AVAIL_MASK);
++ writel(val, mb_chan->reg + REG_DB_STATMASK);
++
++ return 0;
++}
++
++static void slimpro_mbox_shutdown(struct mbox_chan *chan)
++{
++ struct slimpro_mbox_chan *mb_chan = chan->con_priv;
++ u32 val;
++
++ /* Mask doorbell status interrupt */
++ val = readl(mb_chan->reg + REG_DB_STATMASK);
++ val |= (MBOX_STATUS_ACK_MASK | MBOX_STATUS_AVAIL_MASK);
++ writel(val, mb_chan->reg + REG_DB_STATMASK);
++
++ devm_free_irq(mb_chan->dev, mb_chan->irq, mb_chan);
++}
++
++static struct mbox_chan_ops slimpro_mbox_ops = {
++ .send_data = slimpro_mbox_send_data,
++ .startup = slimpro_mbox_startup,
++ .shutdown = slimpro_mbox_shutdown,
++};
++
++static int slimpro_mbox_probe(struct platform_device *pdev)
++{
++ struct slimpro_mbox *ctx;
++ struct resource *regs;
++ void __iomem *mb_base;
++ int rc;
++ int i;
++
++ ctx = devm_kzalloc(&pdev->dev, sizeof(struct slimpro_mbox), GFP_KERNEL);
++ if (IS_ERR(ctx))
++ return PTR_ERR(ctx);
++
++ platform_set_drvdata(pdev, ctx);
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ mb_base = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
++ if (IS_ERR(mb_base))
++ return PTR_ERR(mb_base);
++
++ /* Setup mailbox links */
++ for (i = 0; i < MBOX_CNT; i++) {
++ ctx->mc[i].irq = platform_get_irq(pdev, i);
++ if (ctx->mc[i].irq < 0) {
++ if (i == 0) {
++ dev_err(&pdev->dev, "no available IRQ\n");
++ return -EINVAL;
++ }
++ dev_info(&pdev->dev, "no IRQ for channel %d\n", i);
++ break;
++ }
++
++ ctx->mc[i].dev = &pdev->dev;
++ ctx->mc[i].reg = mb_base + i * MBOX_REG_SET_OFFSET;
++ ctx->mc[i].chan = &ctx->chans[i];
++ ctx->chans[i].con_priv = &ctx->mc[i];
++ }
++
++ /* Setup mailbox controller */
++ ctx->mb_ctrl.dev = &pdev->dev;
++ ctx->mb_ctrl.chans = ctx->chans;
++ ctx->mb_ctrl.txdone_irq = true;
++ ctx->mb_ctrl.ops = &slimpro_mbox_ops;
++ ctx->mb_ctrl.num_chans = i;
++
++ rc = mbox_controller_register(&ctx->mb_ctrl);
++ if (rc) {
++ dev_err(&pdev->dev,
++ "APM X-Gene SLIMpro MailBox register failed:%d\n", rc);
++ return rc;
++ }
++
++ dev_info(&pdev->dev, "APM X-Gene SLIMpro MailBox registered\n");
++ return 0;
++}
++
++static int slimpro_mbox_remove(struct platform_device *pdev)
++{
++ struct slimpro_mbox *smb = platform_get_drvdata(pdev);
++
++ mbox_controller_unregister(&smb->mb_ctrl);
++ return 0;
++}
++
++static const struct of_device_id slimpro_of_match[] = {
++ {.compatible = "apm,xgene-slimpro-mbox" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, slimpro_of_match);
++
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id slimpro_acpi_ids[] = {
++ {"APMC0D01", 0},
++ {}
++};
++MODULE_DEVICE_TABLE(acpi, slimpro_acpi_ids);
++#endif
++
++static struct platform_driver slimpro_mbox_driver = {
++ .probe = slimpro_mbox_probe,
++ .remove = slimpro_mbox_remove,
++ .driver = {
++ .name = "xgene-slimpro-mbox",
++ .of_match_table = of_match_ptr(slimpro_of_match),
++ .acpi_match_table = ACPI_PTR(slimpro_acpi_ids)
++ },
++};
++
++static int __init slimpro_mbox_init(void)
++{
++ return platform_driver_register(&slimpro_mbox_driver);
++}
++
++static void __exit slimpro_mbox_exit(void)
++{
++ platform_driver_unregister(&slimpro_mbox_driver);
++}
++
++subsys_initcall(slimpro_mbox_init);
++module_exit(slimpro_mbox_exit);
++
++MODULE_DESCRIPTION("APM X-Gene SLIMpro Mailbox Driver");
++MODULE_LICENSE("GPL");
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0001-staging-fsl-mc-Do-not-allow-building-as-a-module.patch b/patches.arch/arm64-0001-staging-fsl-mc-Do-not-allow-building-as-a-module.patch
new file mode 100644
index 0000000000..24b239ca93
--- /dev/null
+++ b/patches.arch/arm64-0001-staging-fsl-mc-Do-not-allow-building-as-a-module.patch
@@ -0,0 +1,39 @@
+From dfb11fe2281cf6e6e62170513604ca4b51cabe9f Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding@nvidia.com>
+Date: Mon, 15 Feb 2016 14:22:22 +0100
+Subject: [PATCH] staging: fsl-mc: Do not allow building as a module
+
+This driver uses functionality (MSI IRQ domain) whose symbols aren't
+exported, and hence the modular build fails. While arguably there might
+be reasons to make these symbols available to modules, that change would
+be fairly involved and the set of exported functions should be carefully
+auditioned. Fix the build failure for now by marking the driver boolean.
+Patch-mainline: v4.6-rc1
+Git-commit: dfb11fe2281cf6e6e62170513604ca4b51cabe9f
+References: fate#319900
+
+Cc: J. German Rivera <German.Rivera@freescale.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig
+index c498ac6..1f95933 100644
+--- a/drivers/staging/fsl-mc/bus/Kconfig
++++ b/drivers/staging/fsl-mc/bus/Kconfig
+@@ -7,7 +7,7 @@
+ #
+
+ config FSL_MC_BUS
+- tristate "Freescale Management Complex (MC) bus driver"
++ bool "Freescale Management Complex (MC) bus driver"
+ depends on OF && ARM64
+ select GENERIC_MSI_IRQ_DOMAIN
+ help
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0001-staging-fsl-mc-Drop-unneeded-void-pointer-cast.patch b/patches.arch/arm64-0001-staging-fsl-mc-Drop-unneeded-void-pointer-cast.patch
new file mode 100644
index 0000000000..751336c794
--- /dev/null
+++ b/patches.arch/arm64-0001-staging-fsl-mc-Drop-unneeded-void-pointer-cast.patch
@@ -0,0 +1,52 @@
+From 36b64670fae87abd190f2896de24277c6c8ae8ac Mon Sep 17 00:00:00 2001
+From: Janani Ravichandran <janani.rvchndrn@gmail.com>
+Date: Thu, 25 Feb 2016 14:46:11 -0500
+Subject: [PATCH 1/4] staging: fsl-mc: Drop unneeded void pointer cast
+Patch-mainline: v4.6-rc1
+Git-commit: 36b64670fae87abd190f2896de24277c6c8ae8ac
+References: fate#319900
+
+Void pointers need not be cast to other pointer types.
+Semantic patch used:
+
+@r@
+expression x;
+void *e;
+type T;
+identifier f;
+@@
+
+(
+ *((T *)e)
+|
+ ((T *)x) [...]
+|
+ ((T *)x)->f
+|
+- (T *)
+ e
+)
+
+Signed-off-by: Janani Ravichandran <janani.rvchndrn@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 9380ebc..31488a7 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -407,7 +407,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
+ {
+ int error;
+ u32 status;
+- struct device *dev = (struct device *)arg;
++ struct device *dev = arg;
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
+ struct fsl_mc_io *mc_io = mc_dev->mc_io;
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0001-staging-fsl-mc-fix-incorrect-type-passed-to-dev_dbg-.patch b/patches.arch/arm64-0001-staging-fsl-mc-fix-incorrect-type-passed-to-dev_dbg-.patch
new file mode 100644
index 0000000000..f9b542d0c1
--- /dev/null
+++ b/patches.arch/arm64-0001-staging-fsl-mc-fix-incorrect-type-passed-to-dev_dbg-.patch
@@ -0,0 +1,57 @@
+From e79e344a3d2fce5f75a80f028d41b2b9a88a34dc Mon Sep 17 00:00:00 2001
+From: Cihangir Akturk <cakturk@gmail.com>
+Date: Mon, 14 Mar 2016 18:14:06 +0200
+Subject: [PATCH 1/2] staging: fsl-mc: fix incorrect type passed to dev_dbg
+ macros
+Patch-mainline: v4.6-rc1
+Git-commit: e79e344a3d2fce5f75a80f028d41b2b9a88a34dc
+References: fate#319900
+
+dev_dbg macros expect const struct device ** as its second
+argument but here the argument we are passing is of type
+struct device ** this patch fixes this error.
+
+Fixes: de71daf5c839 ("Staging: fsl-mc: Replace pr_debug with dev_dbg")
+Cc: Bhumika Goyal <bhumirks@gmail.com>
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Cihangir Akturk <cakturk@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-sys.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c
+index 8101c46..810a611 100644
+--- a/drivers/staging/fsl-mc/bus/mc-sys.c
++++ b/drivers/staging/fsl-mc/bus/mc-sys.c
+@@ -328,7 +328,7 @@ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
+ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+
+ if (time_after_eq(jiffies, jiffies_until_timeout)) {
+- dev_dbg(&mc_io->dev,
++ dev_dbg(mc_io->dev,
+ "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
+ mc_io->portal_phys_addr,
+ (unsigned int)
+@@ -370,7 +370,7 @@ static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
+ udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+ timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
+ if (timeout_usecs == 0) {
+- dev_dbg(&mc_io->dev,
++ dev_dbg(mc_io->dev,
+ "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
+ mc_io->portal_phys_addr,
+ (unsigned int)
+@@ -426,7 +426,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
+ goto common_exit;
+
+ if (status != MC_CMD_STATUS_OK) {
+- dev_dbg(&mc_io->dev,
++ dev_dbg(mc_io->dev,
+ "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n",
+ mc_io->portal_phys_addr,
+ (unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0001-staging-fsl-mc-read-version-of-root-dprc-from-mc.patch b/patches.arch/arm64-0001-staging-fsl-mc-read-version-of-root-dprc-from-mc.patch
new file mode 100644
index 0000000000..db8561320e
--- /dev/null
+++ b/patches.arch/arm64-0001-staging-fsl-mc-read-version-of-root-dprc-from-mc.patch
@@ -0,0 +1,112 @@
+From 46cac6991c8bd1802802c59756aa9365847a4b9a Mon Sep 17 00:00:00 2001
+From: Itai Katz <itai.katz@freescale.com>
+Date: Wed, 21 Oct 2015 15:57:56 +0300
+Subject: [PATCH 1/4] staging: fsl-mc: read version of root dprc from mc
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 46cac6991c8bd1802802c59756aa9365847a4b9a
+References: fate#319900
+
+
+Before this patch, probe function of root dprc used hard coded
+values from header file as the version numbers (major & minor) of
+the root dprc.
+In this patch the values are read from the root dprc object in mc.
+
+Signed-off-by: Itai Katz <itai.katz@freescale.com>
+(Stuart: resolved merge conflict)
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 48 +++++++++++++++++++++++++++++-------
+ 1 file changed, 39 insertions(+), 9 deletions(-)
+
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -305,11 +305,10 @@ static void fsl_mc_get_root_dprc(struct
+ }
+ }
+
+-static int get_dprc_icid(struct fsl_mc_io *mc_io,
+- int container_id, u16 *icid)
++static int get_dprc_attr(struct fsl_mc_io *mc_io,
++ int container_id, struct dprc_attributes *attr)
+ {
+- u16 dprc_handle;
+- struct dprc_attributes attr;
++ uint16_t dprc_handle;
+ int error;
+
+ error = dprc_open(mc_io, 0, container_id, &dprc_handle);
+@@ -318,15 +317,14 @@ static int get_dprc_icid(struct fsl_mc_i
+ return error;
+ }
+
+- memset(&attr, 0, sizeof(attr));
+- error = dprc_get_attributes(mc_io, 0, dprc_handle, &attr);
++ memset(attr, 0, sizeof(struct dprc_attributes));
++ error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
+ if (error < 0) {
+ dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
+ error);
+ goto common_cleanup;
+ }
+
+- *icid = attr.icid;
+ error = 0;
+
+ common_cleanup:
+@@ -334,6 +332,35 @@ common_cleanup:
+ return error;
+ }
+
++static int get_dprc_icid(struct fsl_mc_io *mc_io,
++ int container_id, uint16_t *icid)
++{
++ struct dprc_attributes attr;
++ int error;
++
++ error = get_dprc_attr(mc_io, container_id, &attr);
++ if (error == 0)
++ *icid = attr.icid;
++
++ return error;
++}
++
++static int get_dprc_version(struct fsl_mc_io *mc_io,
++ int container_id, uint16_t *major, uint16_t *minor)
++{
++ struct dprc_attributes attr;
++ int error;
++
++ error = get_dprc_attr(mc_io, container_id, &attr);
++ if (error == 0) {
++ *major = attr.version.major;
++ *minor = attr.version.minor;
++ }
++
++ return error;
++}
++
++
+ static int translate_mc_addr(struct fsl_mc_device *mc_dev,
+ enum dprc_region_type mc_region_type,
+ u64 mc_offset, phys_addr_t *phys_addr)
+@@ -795,11 +822,14 @@ static int fsl_mc_bus_probe(struct platf
+ goto error_cleanup_mc_io;
+ }
+
++ error = get_dprc_version(mc_io, container_id,
++ &obj_desc.ver_major, &obj_desc.ver_minor);
++ if (error < 0)
++ goto error_cleanup_mc_io;
++
+ obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
+ strcpy(obj_desc.type, "dprc");
+ obj_desc.id = container_id;
+- obj_desc.ver_major = DPRC_VER_MAJOR;
+- obj_desc.ver_minor = DPRC_VER_MINOR;
+ obj_desc.irq_count = 1;
+ obj_desc.region_count = 0;
+
diff --git a/patches.arch/arm64-0001-staging-fsl-mc-update-dpmcp-binary-interface-to-v3.0.patch b/patches.arch/arm64-0001-staging-fsl-mc-update-dpmcp-binary-interface-to-v3.0.patch
new file mode 100644
index 0000000000..756c79876b
--- /dev/null
+++ b/patches.arch/arm64-0001-staging-fsl-mc-update-dpmcp-binary-interface-to-v3.0.patch
@@ -0,0 +1,134 @@
+From ffd8342a64a29ff4541e3f2efb9302b5f3184622 Mon Sep 17 00:00:00 2001
+From: Stuart Yoder <stuart.yoder@nxp.com>
+Date: Wed, 2 Mar 2016 10:08:35 -0600
+Subject: [PATCH 01/12] staging: fsl-mc: update dpmcp binary interface to v3.0
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: ffd8342a64a29ff4541e3f2efb9302b5f3184622
+References: fate#319900
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 5 ++---
+ drivers/staging/fsl-mc/bus/dpmcp.c | 35 ++--------------------------------
+ drivers/staging/fsl-mc/bus/dpmcp.h | 10 ++--------
+ 3 files changed, 6 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
+index a87e9f8..c6f4ec0 100644
+--- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
++++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
+@@ -33,8 +33,8 @@
+ #define _FSL_DPMCP_CMD_H
+
+ /* DPMCP Version */
+-#define DPMCP_VER_MAJOR 2
+-#define DPMCP_VER_MINOR 1
++#define DPMCP_VER_MAJOR 3
++#define DPMCP_VER_MINOR 0
+
+ /* Command IDs */
+ #define DPMCP_CMDID_CLOSE 0x800
+@@ -52,6 +52,5 @@
+ #define DPMCP_CMDID_SET_IRQ_MASK 0x014
+ #define DPMCP_CMDID_GET_IRQ_MASK 0x015
+ #define DPMCP_CMDID_GET_IRQ_STATUS 0x016
+-#define DPMCP_CMDID_CLEAR_IRQ_STATUS 0x017
+
+ #endif /* _FSL_DPMCP_CMD_H */
+diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c
+index b0248f5..fd6dd4e 100644
+--- a/drivers/staging/fsl-mc/bus/dpmcp.c
++++ b/drivers/staging/fsl-mc/bus/dpmcp.c
+@@ -213,7 +213,7 @@ int dpmcp_set_irq(struct fsl_mc_io *mc_io,
+ cmd.params[0] |= mc_enc(0, 8, irq_index);
+ cmd.params[0] |= mc_enc(32, 32, irq_cfg->val);
+ cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr);
+- cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id);
++ cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+@@ -254,7 +254,7 @@ int dpmcp_get_irq(struct fsl_mc_io *mc_io,
+ /* retrieve response parameters */
+ irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32);
+ irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64);
+- irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
++ irq_cfg->irq_num = (int)mc_dec(cmd.params[2], 0, 32);
+ *type = (int)mc_dec(cmd.params[2], 32, 32);
+ return 0;
+ }
+@@ -435,37 +435,6 @@ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
+ }
+
+ /**
+- * dpmcp_clear_irq_status() - Clear a pending interrupt's status
+- *
+- * @mc_io: Pointer to MC portal's I/O object
+- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+- * @token: Token of DPMCP object
+- * @irq_index: The interrupt index to configure
+- * @status: Bits to clear (W1C) - one bit per cause:
+- * 0 = don't change
+- * 1 = clear status bit
+- *
+- * Return: '0' on Success; Error code otherwise.
+- */
+-int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io,
+- u32 cmd_flags,
+- u16 token,
+- u8 irq_index,
+- u32 status)
+-{
+- struct mc_command cmd = { 0 };
+-
+- /* prepare command */
+- cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLEAR_IRQ_STATUS,
+- cmd_flags, token);
+- cmd.params[0] |= mc_enc(0, 32, status);
+- cmd.params[0] |= mc_enc(32, 8, irq_index);
+-
+- /* send command to mc*/
+- return mc_send_command(mc_io, &cmd);
+-}
+-
+-/**
+ * dpmcp_get_attributes - Retrieve DPMCP attributes.
+ *
+ * @mc_io: Pointer to MC portal's I/O object
+diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h
+index 6df351f..fe79d4d 100644
+--- a/drivers/staging/fsl-mc/bus/dpmcp.h
++++ b/drivers/staging/fsl-mc/bus/dpmcp.h
+@@ -82,12 +82,12 @@ int dpmcp_reset(struct fsl_mc_io *mc_io,
+ * struct dpmcp_irq_cfg - IRQ configuration
+ * @paddr: Address that must be written to signal a message-based interrupt
+ * @val: Value to write into irq_addr address
+- * @user_irq_id: A user defined number associated with this IRQ
++ * @irq_num: A user defined number associated with this IRQ
+ */
+ struct dpmcp_irq_cfg {
+ uint64_t paddr;
+ uint32_t val;
+- int user_irq_id;
++ int irq_num;
+ };
+
+ int dpmcp_set_irq(struct fsl_mc_io *mc_io,
+@@ -133,12 +133,6 @@ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
+ uint8_t irq_index,
+ uint32_t *status);
+
+-int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io,
+- uint32_t cmd_flags,
+- uint16_t token,
+- uint8_t irq_index,
+- uint32_t status);
+-
+ /**
+ * struct dpmcp_attr - Structure representing DPMCP attributes
+ * @id: DPMCP object ID
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0001-v6-dt-bindings-Add-bindings-for-Layerscape-SCFG-MSI.patch b/patches.arch/arm64-0001-v6-dt-bindings-Add-bindings-for-Layerscape-SCFG-MSI.patch
new file mode 100644
index 0000000000..3f6faaa712
--- /dev/null
+++ b/patches.arch/arm64-0001-v6-dt-bindings-Add-bindings-for-Layerscape-SCFG-MSI.patch
@@ -0,0 +1,74 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [1/2,v6] dt/bindings: Add bindings for Layerscape SCFG MSI
+From: Minghuan Lian <Minghuan.Lian@nxp.com>
+X-Patchwork-Id: 8649091
+Message-Id: <1458731300-13648-1-git-send-email-Minghuan.Lian@nxp.com>
+To: <linux-arm-kernel@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
+ <devicetree@vger.kernel.org>
+Cc: Roy Zang <roy.zang@nxp.com>, Jason Cooper <jason@lakedaemon.net>,
+ Marc Zyngier <marc.zyngier@arm.com>,
+ Stuart Yoder <stuart.yoder@nxp.com>, Yang-Leo Li <leoyang.li@nxp.com>,
+ Minghuan Lian <Minghuan.Lian@nxp.com>,
+ Thomas Gleixner <tglx@linutronix.de>, Scott Wood <scott.wood@nxp.com>,
+ Mingkai Hu <mingkai.hu@nxp.com>
+Date: Wed, 23 Mar 2016 19:08:19 +0800
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8649091
+References: fate#320030 fate#319900
+
+Some Layerscape SoCs use a simple MSI controller implementation.
+It contains only two SCFG register to trigger and describe a
+group 32 MSI interrupts. The patch adds bindings to describe
+the controller.
+
+Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+change log:
+v6-v4: no change
+v4: add interrupt-parent description
+v3-v1: no change
+
+ .../interrupt-controller/fsl,ls-scfg-msi.txt | 30 ++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+
+diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+new file mode 100644
+index 0000000..9e38949
+--- /dev/null
++++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+@@ -0,0 +1,30 @@
++* Freescale Layerscape SCFG PCIe MSI controller
++
++Required properties:
++
++- compatible: should be "fsl,<soc-name>-msi" to identify
++ Layerscape PCIe MSI controller block such as:
++ "fsl,1s1021a-msi"
++ "fsl,1s1043a-msi"
++- msi-controller: indicates that this is a PCIe MSI controller node
++- reg: physical base address of the controller and length of memory mapped.
++- interrupts: an interrupt to the parent interrupt controller.
++
++Optional properties:
++- interrupt-parent: the phandle to the parent interrupt controller.
++
++This interrupt controller hardware is a second level interrupt controller that
++is hooked to a parent interrupt controller: e.g: ARM GIC for ARM-based
++platforms. If interrupt-parent is not provided, the default parent interrupt
++controller will be used.
++Each PCIe node needs to have property msi-parent that points to
++MSI controller node
++
++Examples:
++
++ msi1: msi-controller@1571000 {
++ compatible = "fsl,1s1043a-msi";
++ reg = <0x0 0x1571000 0x0 0x8>,
++ msi-controller;
++ interrupts = <0 116 0x4>;
++ };
diff --git a/patches.arch/arm64-0002-Documentation-mailbox-Add-APM-X-Gene-SLIMpro-mailbox.patch b/patches.arch/arm64-0002-Documentation-mailbox-Add-APM-X-Gene-SLIMpro-mailbox.patch
new file mode 100644
index 0000000000..8e8cc6b603
--- /dev/null
+++ b/patches.arch/arm64-0002-Documentation-mailbox-Add-APM-X-Gene-SLIMpro-mailbox.patch
@@ -0,0 +1,65 @@
+From: Duc Dang <dhdang@apm.com>
+Date: Fri, 12 Feb 2016 19:39:27 -0800
+Subject: Documentation: mailbox: Add APM X-Gene SLIMpro mailbox dts
+ documentation
+Git-commit: 9b2396dd1e41657c095d480802020c283ba1a43e
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+This adds the APM X-Gene SLIMpro mailbox device tree
+node documentation.
+
+Signed-off-by: Feng Kan <fkan@apm.com>
+Signed-off-by: Duc Dang <dhdang@apm.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ .../bindings/mailbox/xgene-slimpro-mailbox.txt | 35 ++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mailbox/xgene-slimpro-mailbox.txt
+
+diff --git a/Documentation/devicetree/bindings/mailbox/xgene-slimpro-mailbox.txt b/Documentation/devicetree/bindings/mailbox/xgene-slimpro-mailbox.txt
+new file mode 100644
+index 0000000..e46451b
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mailbox/xgene-slimpro-mailbox.txt
+@@ -0,0 +1,35 @@
++The APM X-Gene SLIMpro mailbox is used to communicate messages between
++the ARM64 processors and the Cortex M3 (dubbed SLIMpro). It uses a simple
++interrupt based door bell mechanism and can exchange simple messages using the
++internal registers.
++
++There are total of 8 interrupts in this mailbox. Each used for an individual
++door bell (or mailbox channel).
++
++Required properties:
++- compatible: Should be as "apm,xgene-slimpro-mbox".
++
++- reg: Contains the mailbox register address range.
++
++- interrupts: 8 interrupts must be from 0 to 7, interrupt 0 define the
++ the interrupt for mailbox channel 0 and interrupt 1 for
++ mailbox channel 1 and so likewise for the reminder.
++
++- #mbox-cells: only one to specify the mailbox channel number.
++
++Example:
++
++Mailbox Node:
++ mailbox: mailbox@10540000 {
++ compatible = "apm,xgene-slimpro-mbox";
++ reg = <0x0 0x10540000 0x0 0xa000>;
++ #mbox-cells = <1>;
++ interrupts = <0x0 0x0 0x4>,
++ <0x0 0x1 0x4>,
++ <0x0 0x2 0x4>,
++ <0x0 0x3 0x4>,
++ <0x0 0x4 0x4>,
++ <0x0 0x5 0x4>,
++ <0x0 0x6 0x4>,
++ <0x0 0x7 0x4>,
++ };
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0002-PCI-layerscape-Fix-MSG-TLP-drop-setting.patch b/patches.arch/arm64-0002-PCI-layerscape-Fix-MSG-TLP-drop-setting.patch
new file mode 100644
index 0000000000..91815b2182
--- /dev/null
+++ b/patches.arch/arm64-0002-PCI-layerscape-Fix-MSG-TLP-drop-setting.patch
@@ -0,0 +1,75 @@
+From 1195c103f6c98d9ff381cac3a8760d4f8a133627 Mon Sep 17 00:00:00 2001
+From: Minghuan Lian <Minghuan.Lian@nxp.com>
+Date: Mon, 29 Feb 2016 17:24:15 -0600
+Subject: [PATCH] PCI: layerscape: Fix MSG TLP drop setting
+Patch-mainline: v4.5
+Git-commit: 1195c103f6c98d9ff381cac3a8760d4f8a133627
+References: fate#319900 fate#320030
+
+Some kinds of Layerscape PCIe controllers will forward the received message
+TLPs to system application address space, which could corrupt system memory
+or lead to a system hang. Enable MSG_DROP to fix this issue.
+
+Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/pci/host/pci-layerscape.c | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
+index 3923bed..f39961b 100644
+--- a/drivers/pci/host/pci-layerscape.c
++++ b/drivers/pci/host/pci-layerscape.c
+@@ -77,6 +77,16 @@ static void ls_pcie_fix_class(struct ls_pcie *pcie)
+ iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
+ }
+
++/* Drop MSG TLP except for Vendor MSG */
++static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
++{
++ u32 val;
++
++ val = ioread32(pcie->dbi + PCIE_STRFMR1);
++ val &= 0xDFFFFFFF;
++ iowrite32(val, pcie->dbi + PCIE_STRFMR1);
++}
++
+ static int ls1021_pcie_link_up(struct pcie_port *pp)
+ {
+ u32 state;
+@@ -97,7 +107,7 @@ static int ls1021_pcie_link_up(struct pcie_port *pp)
+ static void ls1021_pcie_host_init(struct pcie_port *pp)
+ {
+ struct ls_pcie *pcie = to_ls_pcie(pp);
+- u32 val, index[2];
++ u32 index[2];
+
+ pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node,
+ "fsl,pcie-scfg");
+@@ -116,13 +126,7 @@ static void ls1021_pcie_host_init(struct pcie_port *pp)
+
+ dw_pcie_setup_rc(pp);
+
+- /*
+- * LS1021A Workaround for internal TKT228622
+- * to fix the INTx hang issue
+- */
+- val = ioread32(pcie->dbi + PCIE_STRFMR1);
+- val &= 0xffff;
+- iowrite32(val, pcie->dbi + PCIE_STRFMR1);
++ ls_pcie_drop_msg_tlp(pcie);
+ }
+
+ static int ls_pcie_link_up(struct pcie_port *pp)
+@@ -147,6 +151,7 @@ static void ls_pcie_host_init(struct pcie_port *pp)
+ iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
+ ls_pcie_fix_class(pcie);
+ ls_pcie_clear_multifunction(pcie);
++ ls_pcie_drop_msg_tlp(pcie);
+ iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
+ }
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-ahci-qoriq-Update-the-default-Rx-watermark-value.patch b/patches.arch/arm64-0002-ahci-qoriq-Update-the-default-Rx-watermark-value.patch
new file mode 100644
index 0000000000..333996cf07
--- /dev/null
+++ b/patches.arch/arm64-0002-ahci-qoriq-Update-the-default-Rx-watermark-value.patch
@@ -0,0 +1,46 @@
+From e3a6dadc6dca64f464238f8a36876c610400eef9 Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Wed, 16 Dec 2015 13:43:50 +0800
+Subject: [PATCH 2/3] ahci: qoriq: Update the default Rx watermark value
+Patch-mainline: v4.5-rc1
+Git-commit: e3a6dadc6dca64f464238f8a36876c610400eef9
+References: fate#319900
+
+The PTC[RXWM] sets the watermark value for Rx FIFO. The default
+value 0x20 might be insufficient for some hard drives. If the
+watermark value is too small, a single-cycle overflow may occur
+and is reported as a CRC or internal error in the PxSERR register.
+Updated the value to 0x29 according to the validation test.
+All LS platforms are affected.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/ata/ahci_qoriq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+index 4d613f8..256d911 100644
+--- a/drivers/ata/ahci_qoriq.c
++++ b/drivers/ata/ahci_qoriq.c
+@@ -38,7 +38,7 @@
+ #define AHCI_PORT_PHY_3_CFG 0x0e081004
+ #define AHCI_PORT_PHY_4_CFG 0x00480811
+ #define AHCI_PORT_PHY_5_CFG 0x192c96a4
+-#define AHCI_PORT_TRANS_CFG 0x08000025
++#define AHCI_PORT_TRANS_CFG 0x08000029
+ #define LS1043A_PORT_PHY2 0x28184d1f
+ #define LS1043A_PORT_PHY3 0x0e081509
+
+@@ -169,6 +169,7 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
+
+ case AHCI_LS2080A:
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
++ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+ break;
+ }
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-amd-xgbe-Change-from-napi_complete-to-napi_complete_.patch b/patches.arch/arm64-0002-amd-xgbe-Change-from-napi_complete-to-napi_complete_.patch
new file mode 100644
index 0000000000..a91e07f4d1
--- /dev/null
+++ b/patches.arch/arm64-0002-amd-xgbe-Change-from-napi_complete-to-napi_complete_.patch
@@ -0,0 +1,60 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:48:19 -0600
+Subject: amd-xgbe: Change from napi_complete to napi_complete_done
+Git-commit: 491aefb38a31bb163e1e4393ba42abf68ce4c6eb
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+Change from using napi_complete to napi_complete_done to allow for the
+use of gro_flush_timeout in tuning network processing.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+index cfd3f7e..5a4d9ca 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+@@ -6,7 +6,7 @@
+ *
+ * License 1: GPLv2
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -56,7 +56,7 @@
+ *
+ * License 2: Modified BSD
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -2068,7 +2068,7 @@ static int xgbe_one_poll(struct napi_struct *napi, int budget)
+ /* If we processed everything, we are done */
+ if (processed < budget) {
+ /* Turn off polling */
+- napi_complete(napi);
++ napi_complete_done(napi, processed);
+
+ /* Enable Tx and Rx interrupts */
+ enable_irq(channel->dma_irq);
+@@ -2110,7 +2110,7 @@ static int xgbe_all_poll(struct napi_struct *napi, int budget)
+ /* If we processed everything, we are done */
+ if (processed < budget) {
+ /* Turn off polling */
+- napi_complete(napi);
++ napi_complete_done(napi, processed);
+
+ /* Enable Tx and Rx interrupts */
+ xgbe_enable_rx_tx_ints(pdata);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0002-arm64-Broadcom-Vulcan-support.patch b/patches.arch/arm64-0002-arm64-Broadcom-Vulcan-support.patch
new file mode 100644
index 0000000000..61d9cf380f
--- /dev/null
+++ b/patches.arch/arm64-0002-arm64-Broadcom-Vulcan-support.patch
@@ -0,0 +1,237 @@
+From 5bfb3889878756a7f6b673df1738c473424e169f Mon Sep 17 00:00:00 2001
+From: Zi Shen Lim <zlim@broadcom.com>
+Date: Sat, 20 Feb 2016 19:49:20 +0530
+Subject: [PATCH 2/3] arm64: Broadcom Vulcan support
+Patch-mainline: v4.6-rc1
+Git-commit: 5bfb3889878756a7f6b673df1738c473424e169f
+References: fate#319481
+
+Add a configuration option and a device tree for Broadcom's Vulcan
+ARM64 processor. vulcan.dtsi has the on-chip blocks like the PCIe
+controller, GICv3 with ITS, PMU, system timer and the pl011 UART.
+vulcan-eval.dts has definitions for a basic evaluation board.
+
+Vulcan's processor cores support the ARMv8.1 instruction set and
+will use "brcm,vulcan" as the compatible property. The firmware
+has PSCI 0.2 support for cpu wakeup.
+
+Signed-off-by: Zi Shen Lim <zlim@broadcom.com>
+[ updated and split dts - jchandra@broadcom.com ]
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ arch/arm64/Kconfig.platforms | 5
+ arch/arm64/boot/dts/broadcom/Makefile | 1
+ arch/arm64/boot/dts/broadcom/vulcan-eval.dts | 33 ++++++
+ arch/arm64/boot/dts/broadcom/vulcan.dtsi | 144 +++++++++++++++++++++++++++
+ 4 files changed, 183 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/broadcom/vulcan-eval.dts
+ create mode 100644 arch/arm64/boot/dts/broadcom/vulcan.dtsi
+
+--- a/arch/arm64/Kconfig.platforms
++++ b/arch/arm64/Kconfig.platforms
+@@ -118,6 +118,11 @@ config ARCH_VEXPRESS
+ This enables support for the ARMv8 software model (Versatile
+ Express).
+
++config ARCH_VULCAN
++ bool "Broadcom Vulcan SOC Family"
++ help
++ This enables support for Broadcom Vulcan SoC Family
++
+ config ARCH_XGENE
+ bool "AppliedMicro X-Gene SOC Family"
+ select MFD_SYSCON
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -1,4 +1,5 @@
+ dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb
++dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb
+
+ always := $(dtb-y)
+ subdir-y := $(dts-dirs)
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/vulcan-eval.dts
+@@ -0,0 +1,33 @@
++/*
++ * dts file for Broadcom (BRCM) Vulcan Evaluation Platform
++ *
++ * Copyright (c) 2013-2016 Broadcom
++ *
++ * 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.
++ */
++
++/dts-v1/;
++
++#include "vulcan.dtsi"
++
++/ {
++ model = "Broadcom Vulcan Eval Platform";
++ compatible = "brcm,vulcan-eval", "brcm,vulcan-soc";
++
++ memory {
++ device_type = "memory";
++ reg = <0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */
++ <0x00000008 0x80000000 0x0 0x80000000>; /* 2G @ 34G */
++ };
++
++ aliases {
++ serial0 = &uart0;
++ };
++
++ chosen {
++ stdout-path = "serial0:115200n8";
++ };
++};
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/vulcan.dtsi
+@@ -0,0 +1,144 @@
++/*
++ * dtsi file for Broadcom (BRCM) Vulcan processor
++ *
++ * Copyright (c) 2013-2016 Broadcom
++ * Author: Zi Shen Lim <zlim@broadcom.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.
++ */
++
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++
++/ {
++ model = "Broadcom Vulcan";
++ compatible = "brcm,vulcan-soc";
++ interrupt-parent = <&gic>;
++ #address-cells = <2>;
++ #size-cells = <2>;
++
++ /* just 4 cpus now, 128 needed in full config */
++ cpus {
++ #address-cells = <0x2>;
++ #size-cells = <0x0>;
++
++ cpu@0 {
++ device_type = "cpu";
++ compatible = "brcm,vulcan", "arm,armv8";
++ reg = <0x0 0x0>;
++ enable-method = "psci";
++ };
++
++ cpu@1 {
++ device_type = "cpu";
++ compatible = "brcm,vulcan", "arm,armv8";
++ reg = <0x0 0x1>;
++ enable-method = "psci";
++ };
++
++ cpu@2 {
++ device_type = "cpu";
++ compatible = "brcm,vulcan", "arm,armv8";
++ reg = <0x0 0x2>;
++ enable-method = "psci";
++ };
++
++ cpu@3 {
++ device_type = "cpu";
++ compatible = "brcm,vulcan", "arm,armv8";
++ reg = <0x0 0x3>;
++ enable-method = "psci";
++ };
++ };
++
++ psci {
++ compatible = "arm,psci-0.2";
++ method = "smc";
++ };
++
++ gic: interrupt-controller@400080000 {
++ compatible = "arm,gic-v3";
++ #interrupt-cells = <3>;
++ #address-cells = <2>;
++ #size-cells = <2>;
++ ranges;
++ interrupt-controller;
++ #redistributor-regions = <1>;
++ reg = <0x04 0x00080000 0x0 0x20000>, /* GICD */
++ <0x04 0x01000000 0x0 0x1000000>; /* GICR */
++ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
++
++ gicits: gic-its@40010000 {
++ compatible = "arm,gic-v3-its";
++ msi-controller;
++ reg = <0x04 0x00100000 0x0 0x20000>; /* GIC ITS */
++ };
++ };
++
++ timer {
++ compatible = "arm,armv8-timer";
++ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ pmu {
++ compatible = "arm,armv8-pmuv3";
++ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; /* PMU overflow */
++ };
++
++ clk125mhz: uart_clk125mhz {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <125000000>;
++ clock-output-names = "clk125mhz";
++ };
++
++ pci {
++ compatible = "pci-host-ecam-generic";
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++
++ /* ECAM at 0x3000_0000 - 0x4000_0000 */
++ reg = <0x0 0x30000000 0x0 0x10000000>;
++ reg-names = "PCI ECAM";
++
++ /* IO 0x4000_0000 - 0x4001_0000 */
++ ranges = <0x01000000 0 0x40000000 0 0x40000000 0 0x00010000
++ /* MEM 0x4800_0000 - 0x5000_0000 */
++ 0x02000000 0 0x48000000 0 0x48000000 0 0x08000000
++ /* MEM64 pref 0x6_0000_0000 - 0x7_0000_0000 */
++ 0x43000000 6 0x00000000 6 0x00000000 1 0x00000000>;
++ interrupt-map-mask = <0 0 0 7>;
++ interrupt-map =
++ /* addr pin ic icaddr icintr */
++ <0 0 0 1 &gic 0 0 GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH
++ 0 0 0 2 &gic 0 0 GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH
++ 0 0 0 3 &gic 0 0 GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH
++ 0 0 0 4 &gic 0 0 GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
++ msi-parent = <&gicits>;
++ dma-coherent;
++ };
++
++ soc {
++ compatible = "simple-bus";
++ #address-cells = <2>;
++ #size-cells = <2>;
++ ranges;
++
++ uart0: serial@402020000 {
++ compatible = "arm,pl011", "arm,primecell";
++ reg = <0x04 0x02020000 0x0 0x1000>;
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&clk125mhz>;
++ clock-names = "apb_pclk";
++ };
++ };
++
++};
diff --git a/patches.arch/arm64-0002-fsl-mc-msi-Added-FSL-MC-specific-member-to-the-msi_d.patch b/patches.arch/arm64-0002-fsl-mc-msi-Added-FSL-MC-specific-member-to-the-msi_d.patch
new file mode 100644
index 0000000000..74f81cd37c
--- /dev/null
+++ b/patches.arch/arm64-0002-fsl-mc-msi-Added-FSL-MC-specific-member-to-the-msi_d.patch
@@ -0,0 +1,49 @@
+From 550308e48cddbc2aa74f7236941b17b55b2e78e9 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:20 -0600
+Subject: [PATCH 02/11] fsl-mc: msi: Added FSL-MC-specific member to the
+ msi_desc's union
+Patch-mainline: v4.6-rc1
+Git-commit: 550308e48cddbc2aa74f7236941b17b55b2e78e9
+References: fate#319900
+
+FSL-MC is a bus type different from PCI and platform, so it needs
+its own member in the msi_desc's union.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ include/linux/msi.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/include/linux/msi.h b/include/linux/msi.h
+index a2a0068..8b425c6 100644
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -33,6 +33,14 @@ struct platform_msi_desc {
+ };
+
+ /**
++ * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data
++ * @msi_index: The index of the MSI descriptor
++ */
++struct fsl_mc_msi_desc {
++ u16 msi_index;
++};
++
++/**
+ * struct msi_desc - Descriptor structure for MSI based interrupts
+ * @list: List head for management
+ * @irq: The base interrupt number
+@@ -87,6 +95,7 @@ struct msi_desc {
+ * tree wide cleanup.
+ */
+ struct platform_msi_desc platform;
++ struct fsl_mc_msi_desc fsl_mc;
+ };
+ };
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-staging-fsl-mc-Avoid-section-mismatch.patch b/patches.arch/arm64-0002-staging-fsl-mc-Avoid-section-mismatch.patch
new file mode 100644
index 0000000000..255710df78
--- /dev/null
+++ b/patches.arch/arm64-0002-staging-fsl-mc-Avoid-section-mismatch.patch
@@ -0,0 +1,54 @@
+From 533606073710ad649108689d0eaf4abd8aeb1d15 Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding@nvidia.com>
+Date: Mon, 15 Feb 2016 14:22:23 +0100
+Subject: [PATCH 2/2] staging: fsl-mc: Avoid section mismatch
+Patch-mainline: v4.6-rc1
+Git-commit: 533606073710ad649108689d0eaf4abd8aeb1d15
+References: fate#319900
+
+The fsl_mc_allocator_driver_exit() function is marked __exit, but is
+called by the error handling code in fsl_mc_allocator_driver_init().
+This results in a section mismatch, which in turn could lead to
+executing random code.
+
+Remove the __exit annotation to fix this.
+
+Cc: J. German Rivera <German.Rivera@freescale.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-allocator.c | 2 +-
+ drivers/staging/fsl-mc/include/mc-private.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
+index c5fa628..86f8543 100644
+--- a/drivers/staging/fsl-mc/bus/mc-allocator.c
++++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
+@@ -756,7 +756,7 @@ int __init fsl_mc_allocator_driver_init(void)
+ return fsl_mc_driver_register(&fsl_mc_allocator_driver);
+ }
+
+-void __exit fsl_mc_allocator_driver_exit(void)
++void fsl_mc_allocator_driver_exit(void)
+ {
+ fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
+ }
+diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
+index be72a44..ee5f1d2 100644
+--- a/drivers/staging/fsl-mc/include/mc-private.h
++++ b/drivers/staging/fsl-mc/include/mc-private.h
+@@ -123,7 +123,7 @@ void dprc_driver_exit(void);
+
+ int __init fsl_mc_allocator_driver_init(void);
+
+-void __exit fsl_mc_allocator_driver_exit(void);
++void fsl_mc_allocator_driver_exit(void);
+
+ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
+ enum fsl_mc_pool_type pool_type,
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-staging-fsl-mc-Remove-unneeded-else-following-a-retu.patch b/patches.arch/arm64-0002-staging-fsl-mc-Remove-unneeded-else-following-a-retu.patch
new file mode 100644
index 0000000000..87172bce0c
--- /dev/null
+++ b/patches.arch/arm64-0002-staging-fsl-mc-Remove-unneeded-else-following-a-retu.patch
@@ -0,0 +1,53 @@
+From 9397ce2104d70feb6798690921a296c6ccf22564 Mon Sep 17 00:00:00 2001
+From: Janani Ravichandran <janani.rvchndrn@gmail.com>
+Date: Thu, 18 Feb 2016 17:22:50 -0500
+Subject: [PATCH 2/2] staging: fsl-mc: Remove unneeded else following a return
+Patch-mainline: v4.6-rc1
+Git-commit: 9397ce2104d70feb6798690921a296c6ccf22564
+References: fate#319900
+
+Remove unnecessary else when there is a return statement in the
+corresponding if block. Coccinelle patch used:
+
+@rule1@
+expression e1;
+@@
+
+ if (e1) { ... return ...; }
+- else{
+ ...
+- }
+
+@rule2@
+expression e2;
+statement s1;
+@@
+
+ if(e2) { ... return ...; }
+- else
+ s1
+
+Signed-off-by: Janani Ravichandran <janani.rvchndrn@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index c42bfac..5958e0f 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -248,8 +248,7 @@ static bool fsl_mc_is_root_dprc(struct device *dev)
+ fsl_mc_get_root_dprc(dev, &root_dprc_dev);
+ if (!root_dprc_dev)
+ return false;
+- else
+- return dev == root_dprc_dev;
++ return dev == root_dprc_dev;
+ }
+
+ static int get_dprc_icid(struct fsl_mc_io *mc_io,
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-staging-fsl-mc-add-dprc-version-check.patch b/patches.arch/arm64-0002-staging-fsl-mc-add-dprc-version-check.patch
new file mode 100644
index 0000000000..b148a2fe37
--- /dev/null
+++ b/patches.arch/arm64-0002-staging-fsl-mc-add-dprc-version-check.patch
@@ -0,0 +1,112 @@
+From 5839635ce1ad51ecbbca5abdfe00342f0670c9b4 Mon Sep 17 00:00:00 2001
+From: Itai Katz <itai.katz@freescale.com>
+Date: Mon, 21 Dec 2015 14:39:46 +0200
+Subject: [PATCH 2/4] staging: fsl-mc: add dprc version check
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 5839635ce1ad51ecbbca5abdfe00342f0670c9b4
+References: fate#319900
+
+The dprc driver supports dprc version 5.0 and above.
+This patch adds the code to check the version.
+
+Signed-off-by: Itai Katz <itai.katz@freescale.com>
+(Stuart: resolved merge conflicts)
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-cmd.h | 6 ++---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 30 ++++++++++++++++++++++++++++
+ drivers/staging/fsl-mc/bus/mc-bus.c | 1
+ drivers/staging/fsl-mc/include/mc-private.h | 2 +
+ 4 files changed, 36 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
++++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h
+@@ -40,9 +40,9 @@
+ #ifndef _FSL_DPRC_CMD_H
+ #define _FSL_DPRC_CMD_H
+
+-/* DPRC Version */
+-#define DPRC_VER_MAJOR 5
+-#define DPRC_VER_MINOR 1
++/* Minimal supported DPRC Version */
++#define DPRC_MIN_VER_MAJOR 5
++#define DPRC_MIN_VER_MINOR 0
+
+ /* Command IDs */
+ #define DPRC_CMDID_CLOSE 0x800
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -312,6 +312,17 @@ int dprc_scan_objects(struct fsl_mc_devi
+ continue;
+ }
+
++ /*
++ * for DPRC versions that do not support the
++ * shareability attribute, make simplifying assumption
++ * that only SEC is not shareable.
++ */
++ if ((mc_bus_dev->obj_desc.ver_major == 5) &&
++ (mc_bus_dev->obj_desc.ver_minor == 0) &&
++ (strcmp(obj_desc->type, "dpseci") == 0))
++ obj_desc->flags |=
++ DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY;
++
+ irq_count += obj_desc->irq_count;
+ dev_dbg(&mc_bus_dev->dev,
+ "Discovered object: type %s, id %d\n",
+@@ -693,6 +704,25 @@ static int dprc_probe(struct fsl_mc_devi
+ goto error_cleanup_msi_domain;
+ }
+
++ error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
++ &mc_bus->dprc_attr);
++ if (error < 0) {
++ dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
++ error);
++ goto error_cleanup_open;
++ }
++
++ if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR ||
++ (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR &&
++ mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) {
++ dev_err(&mc_dev->dev,
++ "ERROR: DPRC version %d.%d not supported\n",
++ mc_bus->dprc_attr.version.major,
++ mc_bus->dprc_attr.version.minor);
++ error = -ENOTSUPP;
++ goto error_cleanup_open;
++ }
++
+ mutex_init(&mc_bus->scan_mutex);
+
+ /*
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -822,6 +822,7 @@ static int fsl_mc_bus_probe(struct platf
+ goto error_cleanup_mc_io;
+ }
+
++ memset(&obj_desc, 0, sizeof(struct dprc_obj_desc));
+ error = get_dprc_version(mc_io, container_id,
+ &obj_desc.ver_major, &obj_desc.ver_minor);
+ if (error < 0)
+--- a/drivers/staging/fsl-mc/include/mc-private.h
++++ b/drivers/staging/fsl-mc/include/mc-private.h
+@@ -94,12 +94,14 @@ struct fsl_mc_resource_pool {
+ * from the physical DPRC.
+ * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
+ * @scan_mutex: Serializes bus scanning
++ * @dprc_attr: DPRC attributes
+ */
+ struct fsl_mc_bus {
+ struct fsl_mc_device mc_dev;
+ struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
+ struct fsl_mc_device_irq *irq_resources;
+ struct mutex scan_mutex; /* serializes bus scanning */
++ struct dprc_attributes dprc_attr;
+ };
+
+ #define to_fsl_mc_bus(_mc_dev) \
diff --git a/patches.arch/arm64-0002-staging-fsl-mc-bus-Eliminate-double-function-call.patch b/patches.arch/arm64-0002-staging-fsl-mc-bus-Eliminate-double-function-call.patch
new file mode 100644
index 0000000000..7639927012
--- /dev/null
+++ b/patches.arch/arm64-0002-staging-fsl-mc-bus-Eliminate-double-function-call.patch
@@ -0,0 +1,82 @@
+From eb66b2d301033e33c29fedffc6a317003d1e632c Mon Sep 17 00:00:00 2001
+From: Bhaktipriya Shridhar <bhaktipriya96@gmail.com>
+Date: Sun, 28 Feb 2016 23:58:05 +0530
+Subject: [PATCH 2/4] staging: fsl-mc: bus: Eliminate double function call
+Patch-mainline: v4.6-rc1
+Git-commit: eb66b2d301033e33c29fedffc6a317003d1e632c
+References: fate#319900
+
+A call to irq_find_matching_host was already made and the result
+has been stored in mc_msi_domain. mc_msi_domain is again reassigned
+using the same function call which is redundant.
+
+irq_find_matching_host returns/locates a domain for a given fwnode.
+The domain is identified using device node and bus_token(if several
+domains have same device node but different purposes they can be
+distinguished using bus-specific token).
+http://www.bricktou.com/include/linux/irqdomain_irq_find_matching_host_en.html
+
+Also, of_property_read_bool finds and reads a boolean from a property
+device node from which the property value is to be read. It doesn't
+alter the device node.
+http://lists.infradead.org/pipermail/linux-arm-kernel/2012-February/083698.html
+
+Since, both the function calls have the same device node and bus_token,
+the return values shall be the same. Hence, the second call has been
+removed.
+
+This was done using Coccinelle:
+
+@r@
+idexpression *x;
+identifier f;
+position p1,p2;
+@@
+
+x@p1 = f(...)
+... when != x
+(
+x@p2 = f(...)
+)
+
+@script:python@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+if (p1[0].line == p2[0].line):
+ cocci.include_match(False)
+
+@@
+idexpression *x;
+identifier f;
+position r.p1,r.p2;
+@@
+
+*x@p1 = f(...)
+...
+*x@p2 = f(...)
+
+Signed-off-by: Bhaktipriya Shridhar <bhaktipriya96@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+index 4e8e822..720e2b0 100644
+--- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
++++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+@@ -118,8 +118,6 @@ void its_fsl_mc_msi_cleanup(void)
+ if (!of_property_read_bool(np, "msi-controller"))
+ continue;
+
+- mc_msi_domain = irq_find_matching_host(np,
+- DOMAIN_BUS_FSL_MC_MSI);
+ if (mc_msi_domain &&
+ mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info)
+ irq_domain_remove(mc_msi_domain);
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-staging-fsl-mc-fix-incorrect-type-passed-to-dev_err-.patch b/patches.arch/arm64-0002-staging-fsl-mc-fix-incorrect-type-passed-to-dev_err-.patch
new file mode 100644
index 0000000000..2ff5e9c4b1
--- /dev/null
+++ b/patches.arch/arm64-0002-staging-fsl-mc-fix-incorrect-type-passed-to-dev_err-.patch
@@ -0,0 +1,47 @@
+From 2e11590171683c6b12193fe4b0ede1e6201b7f45 Mon Sep 17 00:00:00 2001
+From: Cihangir Akturk <cakturk@gmail.com>
+Date: Mon, 14 Mar 2016 18:14:07 +0200
+Subject: [PATCH 2/2] staging: fsl-mc: fix incorrect type passed to dev_err
+ macros
+Patch-mainline: v4.6-rc1
+Git-commit: 2e11590171683c6b12193fe4b0ede1e6201b7f45
+References: fate#319900
+
+dev_err macros expect const struct device ** as its second
+argument, but here the argument we are passing is of typ
+struct device **. This patch fixes this error.
+
+Fixes: 454b0ec8bf99 ("Staging: fsl-mc: Replace pr_err with dev_err")
+Cc: Bhumika Goyal <bhumirks@gmail.com>
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Cihangir Akturk <cakturk@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 9f77c37b..b594556 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -260,14 +260,14 @@ static int get_dprc_icid(struct fsl_mc_io *mc_io,
+
+ error = dprc_open(mc_io, 0, container_id, &dprc_handle);
+ if (error < 0) {
+- dev_err(&mc_io->dev, "dprc_open() failed: %d\n", error);
++ dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
+ return error;
+ }
+
+ memset(&attr, 0, sizeof(attr));
+ error = dprc_get_attributes(mc_io, 0, dprc_handle, &attr);
+ if (error < 0) {
+- dev_err(&mc_io->dev, "dprc_get_attributes() failed: %d\n",
++ dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
+ error);
+ goto common_cleanup;
+ }
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0002-staging-fsl-mc-update-dpbp-binary-interface-to-v2.2.patch b/patches.arch/arm64-0002-staging-fsl-mc-update-dpbp-binary-interface-to-v2.2.patch
new file mode 100644
index 0000000000..7ae2a33581
--- /dev/null
+++ b/patches.arch/arm64-0002-staging-fsl-mc-update-dpbp-binary-interface-to-v2.2.patch
@@ -0,0 +1,219 @@
+From 84d84ccbb8bb198478ac46e55d1b34ea73fcbc76 Mon Sep 17 00:00:00 2001
+From: Stuart Yoder <stuart.yoder@nxp.com>
+Date: Wed, 2 Mar 2016 10:44:39 -0600
+Subject: [PATCH 02/12] staging: fsl-mc: update dpbp binary interface to v2.2
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 84d84ccbb8bb198478ac46e55d1b34ea73fcbc76
+References: fate#319900
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dpbp.c | 77 ++++++++++++++++++++++++++++++-
+ drivers/staging/fsl-mc/include/dpbp-cmd.h | 4 +-
+ drivers/staging/fsl-mc/include/dpbp.h | 51 +++++++++++++++++++-
+ 3 files changed, 127 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c
+index 2d97173..c31fe1b 100644
+--- a/drivers/staging/fsl-mc/bus/dpbp.c
++++ b/drivers/staging/fsl-mc/bus/dpbp.c
+@@ -293,7 +293,7 @@ int dpbp_set_irq(struct fsl_mc_io *mc_io,
+ cmd.params[0] |= mc_enc(0, 8, irq_index);
+ cmd.params[0] |= mc_enc(32, 32, irq_cfg->val);
+ cmd.params[1] |= mc_enc(0, 64, irq_cfg->addr);
+- cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id);
++ cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+@@ -334,7 +334,7 @@ int dpbp_get_irq(struct fsl_mc_io *mc_io,
+ /* retrieve response parameters */
+ irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32);
+ irq_cfg->addr = (u64)mc_dec(cmd.params[1], 0, 64);
+- irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
++ irq_cfg->irq_num = (int)mc_dec(cmd.params[2], 0, 32);
+ *type = (int)mc_dec(cmd.params[2], 32, 32);
+ return 0;
+ }
+@@ -502,6 +502,7 @@ int dpbp_get_irq_status(struct fsl_mc_io *mc_io,
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS,
+ cmd_flags, token);
++ cmd.params[0] |= mc_enc(0, 32, *status);
+ cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+ /* send command to mc*/
+@@ -580,3 +581,75 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io,
+ return 0;
+ }
+ EXPORT_SYMBOL(dpbp_get_attributes);
++
++/**
++ * dpbp_set_notifications() - Set notifications towards software
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPBP object
++ * @cfg: notifications configuration
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpbp_set_notifications(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ struct dpbp_notification_cfg *cfg)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS,
++ cmd_flags,
++ token);
++
++ cmd.params[0] |= mc_enc(0, 32, cfg->depletion_entry);
++ cmd.params[0] |= mc_enc(32, 32, cfg->depletion_exit);
++ cmd.params[1] |= mc_enc(0, 32, cfg->surplus_entry);
++ cmd.params[1] |= mc_enc(32, 32, cfg->surplus_exit);
++ cmd.params[2] |= mc_enc(0, 16, cfg->options);
++ cmd.params[3] |= mc_enc(0, 64, cfg->message_ctx);
++ cmd.params[4] |= mc_enc(0, 64, cfg->message_iova);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++/**
++ * dpbp_get_notifications() - Get the notifications configuration
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPBP object
++ * @cfg: notifications configuration
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpbp_get_notifications(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ struct dpbp_notification_cfg *cfg)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ cfg->depletion_entry = (u32)mc_dec(cmd.params[0], 0, 32);
++ cfg->depletion_exit = (u32)mc_dec(cmd.params[0], 32, 32);
++ cfg->surplus_entry = (u32)mc_dec(cmd.params[1], 0, 32);
++ cfg->surplus_exit = (u32)mc_dec(cmd.params[1], 32, 32);
++ cfg->options = (u16)mc_dec(cmd.params[2], 0, 16);
++ cfg->message_ctx = (u64)mc_dec(cmd.params[3], 0, 64);
++ cfg->message_iova = (u64)mc_dec(cmd.params[4], 0, 64);
++
++ return 0;
++}
+diff --git a/drivers/staging/fsl-mc/include/dpbp-cmd.h b/drivers/staging/fsl-mc/include/dpbp-cmd.h
+index efa9bf3..c57b454 100644
+--- a/drivers/staging/fsl-mc/include/dpbp-cmd.h
++++ b/drivers/staging/fsl-mc/include/dpbp-cmd.h
+@@ -34,7 +34,7 @@
+
+ /* DPBP Version */
+ #define DPBP_VER_MAJOR 2
+-#define DPBP_VER_MINOR 1
++#define DPBP_VER_MINOR 2
+
+ /* Command IDs */
+ #define DPBP_CMDID_CLOSE 0x800
+@@ -57,4 +57,6 @@
+ #define DPBP_CMDID_GET_IRQ_STATUS 0x016
+ #define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017
+
++#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0
++#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1
+ #endif /* _FSL_DPBP_CMD_H */
+diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h
+index 37ed951..ed03ca2 100644
+--- a/drivers/staging/fsl-mc/include/dpbp.h
++++ b/drivers/staging/fsl-mc/include/dpbp.h
+@@ -85,12 +85,12 @@ int dpbp_reset(struct fsl_mc_io *mc_io,
+ * struct dpbp_irq_cfg - IRQ configuration
+ * @addr: Address that must be written to signal a message-based interrupt
+ * @val: Value to write into irq_addr address
+- * @user_irq_id: A user defined number associated with this IRQ
++ * @irq_num: A user defined number associated with this IRQ
+ */
+ struct dpbp_irq_cfg {
+ u64 addr;
+ u32 val;
+- int user_irq_id;
++ int irq_num;
+ };
+
+ int dpbp_set_irq(struct fsl_mc_io *mc_io,
+@@ -168,6 +168,53 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io,
+ u16 token,
+ struct dpbp_attr *attr);
+
++/**
++ * DPBP notifications options
++ */
++
++/**
++ * BPSCN write will attempt to allocate into a cache (coherent write)
++ */
++#define DPBP_NOTIF_OPT_COHERENT_WRITE 0x00000001
++
++/**
++ * struct dpbp_notification_cfg - Structure representing DPBP notifications
++ * towards software
++ * @depletion_entry: below this threshold the pool is "depleted";
++ * set it to '0' to disable it
++ * @depletion_exit: greater than or equal to this threshold the pool exit its
++ * "depleted" state
++ * @surplus_entry: above this threshold the pool is in "surplus" state;
++ * set it to '0' to disable it
++ * @surplus_exit: less than or equal to this threshold the pool exit its
++ * "surplus" state
++ * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry'
++ * is not '0' (enable); I/O virtual address (must be in DMA-able memory),
++ * must be 16B aligned.
++ * @message_ctx: The context that will be part of the BPSCN message and will
++ * be written to 'message_iova'
++ * @options: Mask of available options; use 'DPBP_NOTIF_OPT_<X>' values
++ */
++struct dpbp_notification_cfg {
++ uint32_t depletion_entry;
++ uint32_t depletion_exit;
++ uint32_t surplus_entry;
++ uint32_t surplus_exit;
++ uint64_t message_iova;
++ uint64_t message_ctx;
++ uint16_t options;
++};
++
++int dpbp_set_notifications(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ struct dpbp_notification_cfg *cfg);
++
++int dpbp_get_notifications(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ struct dpbp_notification_cfg *cfg);
++
+ /** @} */
+
+ #endif /* __FSL_DPBP_H */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0002-v6-irqchip-Layerscape-Add-SCFG-MSI-controller-support.patch b/patches.arch/arm64-0002-v6-irqchip-Layerscape-Add-SCFG-MSI-controller-support.patch
new file mode 100644
index 0000000000..3cdba8d4ec
--- /dev/null
+++ b/patches.arch/arm64-0002-v6-irqchip-Layerscape-Add-SCFG-MSI-controller-support.patch
@@ -0,0 +1,312 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [2/2,v6] irqchip/Layerscape: Add SCFG MSI controller support
+From: Minghuan Lian <Minghuan.Lian@nxp.com>
+X-Patchwork-Id: 8649101
+Message-Id: <1458731300-13648-2-git-send-email-Minghuan.Lian@nxp.com>
+To: <linux-arm-kernel@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
+ <devicetree@vger.kernel.org>
+Cc: Roy Zang <roy.zang@nxp.com>, Jason Cooper <jason@lakedaemon.net>,
+ Marc Zyngier <marc.zyngier@arm.com>,
+ Stuart Yoder <stuart.yoder@nxp.com>, Yang-Leo Li <leoyang.li@nxp.com>,
+ Minghuan Lian <Minghuan.Lian@nxp.com>,
+ Thomas Gleixner <tglx@linutronix.de>, Scott Wood <scott.wood@nxp.com>,
+ Mingkai Hu <mingkai.hu@nxp.com>
+Date: Wed, 23 Mar 2016 19:08:20 +0800
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8649101
+References: fate#320030 fate#319900
+
+Some kind of Freescale Layerscape SoC provides a MSI
+implementation which uses two SCFG registers MSIIR and
+MSIR to support 32 MSI interrupts for each PCIe controller.
+The patch is to support it.
+
+Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
+Tested-by: Alexander Stein <alexander.stein@systec-electronic.com>
+Acked-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+Change log
+v6:
+1. Change copyright - use "Freescale" instead of "NXP"
+v5:
+1. drop nr_irqs from struct ls_scfg_msi
+v4:
+1. do not register irq_enable irq_disable
+2. shorten the chip name to "SCFG"
+v3:
+1. call of_node_to_fwnode()
+v2:
+1. rename ls1-msi to ls-scfg-msi
+2. remove reg-names MSIIR MSIR
+3. remove calling set_irq_flags()
+
+ drivers/irqchip/Kconfig | 5
+ drivers/irqchip/Makefile | 1
+ drivers/irqchip/irq-ls-scfg-msi.c | 240 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 246 insertions(+)
+ create mode 100644 drivers/irqchip/irq-ls-scfg-msi.c
+
+--- a/drivers/irqchip/Kconfig
++++ b/drivers/irqchip/Kconfig
+@@ -193,3 +193,8 @@ config IRQ_MXS
+ def_bool y if MACH_ASM9260 || ARCH_MXS
+ select IRQ_DOMAIN
+ select STMP_DEVICE
++
++config LS_SCFG_MSI
++ def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE
++ depends on PCI && PCI_MSI
++ select PCI_MSI_IRQ_DOMAIN
+--- a/drivers/irqchip/Makefile
++++ b/drivers/irqchip/Makefile
+@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC) += irq-r
+ obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
+ obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
+ obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
++obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
+--- /dev/null
++++ b/drivers/irqchip/irq-ls-scfg-msi.c
+@@ -0,0 +1,240 @@
++/*
++ * Freescale SCFG MSI(-X) support
++ *
++ * Copyright (C) 2016 Freescale Semiconductor.
++ *
++ * Author: Minghuan Lian <Minghuan.Lian@nxp.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/kernel.h>
++#include <linux/module.h>
++#include <linux/msi.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/irqchip/chained_irq.h>
++#include <linux/irqdomain.h>
++#include <linux/of_pci.h>
++#include <linux/of_platform.h>
++#include <linux/spinlock.h>
++
++#define MSI_MAX_IRQS 32
++#define MSI_IBS_SHIFT 3
++#define MSIR 4
++
++struct ls_scfg_msi {
++ spinlock_t lock;
++ struct platform_device *pdev;
++ struct irq_domain *parent;
++ struct irq_domain *msi_domain;
++ void __iomem *regs;
++ phys_addr_t msiir_addr;
++ int irq;
++ DECLARE_BITMAP(used, MSI_MAX_IRQS);
++};
++
++static struct irq_chip ls_scfg_msi_irq_chip = {
++ .name = "MSI",
++ .irq_mask = pci_msi_mask_irq,
++ .irq_unmask = pci_msi_unmask_irq,
++};
++
++static struct msi_domain_info ls_scfg_msi_domain_info = {
++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS |
++ MSI_FLAG_USE_DEF_CHIP_OPS |
++ MSI_FLAG_PCI_MSIX),
++ .chip = &ls_scfg_msi_irq_chip,
++};
++
++static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
++{
++ struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(data);
++
++ msg->address_hi = upper_32_bits(msi_data->msiir_addr);
++ msg->address_lo = lower_32_bits(msi_data->msiir_addr);
++ msg->data = data->hwirq << MSI_IBS_SHIFT;
++}
++
++static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
++ const struct cpumask *mask, bool force)
++{
++ return -EINVAL;
++}
++
++static struct irq_chip ls_scfg_msi_parent_chip = {
++ .name = "SCFG",
++ .irq_compose_msi_msg = ls_scfg_msi_compose_msg,
++ .irq_set_affinity = ls_scfg_msi_set_affinity,
++};
++
++static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
++ unsigned int virq,
++ unsigned int nr_irqs,
++ void *args)
++{
++ struct ls_scfg_msi *msi_data = domain->host_data;
++ int pos, err = 0;
++
++ WARN_ON(nr_irqs != 1);
++
++ spin_lock(&msi_data->lock);
++ pos = find_first_zero_bit(msi_data->used, MSI_MAX_IRQS);
++ if (pos < MSI_MAX_IRQS)
++ __set_bit(pos, msi_data->used);
++ else
++ err = -ENOSPC;
++ spin_unlock(&msi_data->lock);
++
++ if (err)
++ return err;
++
++ irq_domain_set_info(domain, virq, pos,
++ &ls_scfg_msi_parent_chip, msi_data,
++ handle_simple_irq, NULL, NULL);
++
++ return 0;
++}
++
++static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain,
++ unsigned int virq, unsigned int nr_irqs)
++{
++ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
++ struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(d);
++ int pos;
++
++ pos = d->hwirq;
++ if (pos < 0 || pos >= MSI_MAX_IRQS) {
++ pr_err("failed to teardown msi. Invalid hwirq %d\n", pos);
++ return;
++ }
++
++ spin_lock(&msi_data->lock);
++ __clear_bit(pos, msi_data->used);
++ spin_unlock(&msi_data->lock);
++}
++
++static const struct irq_domain_ops ls_scfg_msi_domain_ops = {
++ .alloc = ls_scfg_msi_domain_irq_alloc,
++ .free = ls_scfg_msi_domain_irq_free,
++};
++
++static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
++{
++ struct ls_scfg_msi *msi_data = irq_desc_get_handler_data(desc);
++ unsigned long val;
++ int pos, virq;
++
++ chained_irq_enter(irq_desc_get_chip(desc), desc);
++
++ val = ioread32be(msi_data->regs + MSIR);
++ for_each_set_bit(pos, &val, MSI_MAX_IRQS) {
++ virq = irq_find_mapping(msi_data->parent, (31 - pos));
++ if (virq)
++ generic_handle_irq(virq);
++ }
++
++ chained_irq_exit(irq_desc_get_chip(desc), desc);
++}
++
++static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data)
++{
++ /* Initialize MSI domain parent */
++ msi_data->parent = irq_domain_add_linear(NULL,
++ MSI_MAX_IRQS,
++ &ls_scfg_msi_domain_ops,
++ msi_data);
++ if (!msi_data->parent) {
++ dev_err(&msi_data->pdev->dev, "failed to create IRQ domain\n");
++ return -ENOMEM;
++ }
++
++ msi_data->msi_domain = pci_msi_create_irq_domain(
++ of_node_to_fwnode(msi_data->pdev->dev.of_node),
++ &ls_scfg_msi_domain_info,
++ msi_data->parent);
++ if (!msi_data->msi_domain) {
++ dev_err(&msi_data->pdev->dev, "failed to create MSI domain\n");
++ irq_domain_remove(msi_data->parent);
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++static int ls_scfg_msi_probe(struct platform_device *pdev)
++{
++ struct ls_scfg_msi *msi_data;
++ struct resource *res;
++ int ret;
++
++ msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL);
++ if (!msi_data)
++ return -ENOMEM;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ msi_data->regs = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(msi_data->regs)) {
++ dev_err(&pdev->dev, "failed to initialize 'regs'\n");
++ return PTR_ERR(msi_data->regs);
++ }
++ msi_data->msiir_addr = res->start;
++
++ msi_data->irq = platform_get_irq(pdev, 0);
++ if (msi_data->irq <= 0) {
++ dev_err(&pdev->dev, "failed to get MSI irq\n");
++ return -ENODEV;
++ }
++
++ msi_data->pdev = pdev;
++ spin_lock_init(&msi_data->lock);
++
++ ret = ls_scfg_msi_domains_init(msi_data);
++ if (ret)
++ return ret;
++
++ irq_set_chained_handler_and_data(msi_data->irq,
++ ls_scfg_msi_irq_handler,
++ msi_data);
++
++ platform_set_drvdata(pdev, msi_data);
++
++ return 0;
++}
++
++static int ls_scfg_msi_remove(struct platform_device *pdev)
++{
++ struct ls_scfg_msi *msi_data = platform_get_drvdata(pdev);
++
++ irq_set_chained_handler_and_data(msi_data->irq, NULL, NULL);
++
++ irq_domain_remove(msi_data->msi_domain);
++ irq_domain_remove(msi_data->parent);
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++static const struct of_device_id ls_scfg_msi_id[] = {
++ { .compatible = "fsl,1s1021a-msi", },
++ { .compatible = "fsl,1s1043a-msi", },
++ {},
++};
++
++static struct platform_driver ls_scfg_msi_driver = {
++ .driver = {
++ .name = "ls-scfg-msi",
++ .of_match_table = ls_scfg_msi_id,
++ },
++ .probe = ls_scfg_msi_probe,
++ .remove = ls_scfg_msi_remove,
++};
++
++module_platform_driver(ls_scfg_msi_driver);
++
++MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@nxp.com>");
++MODULE_DESCRIPTION("Freescale Layerscape SCFG MSI controller driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.arch/arm64-0003-Staging-fsl-mc-Replace-pr_debug-with-dev_dbg.patch b/patches.arch/arm64-0003-Staging-fsl-mc-Replace-pr_debug-with-dev_dbg.patch
new file mode 100644
index 0000000000..19a290f241
--- /dev/null
+++ b/patches.arch/arm64-0003-Staging-fsl-mc-Replace-pr_debug-with-dev_dbg.patch
@@ -0,0 +1,105 @@
+From de71daf5c839b3b3cc8a5b09b4a00107817868de Mon Sep 17 00:00:00 2001
+From: Bhumika Goyal <bhumirks@gmail.com>
+Date: Fri, 4 Mar 2016 19:14:52 +0530
+Subject: [PATCH 3/4] Staging: fsl-mc: Replace pr_debug with dev_dbg
+Patch-mainline: v4.6-rc1
+Git-commit: de71daf5c839b3b3cc8a5b09b4a00107817868de
+References: fate#319900
+
+This patch replaces pr_debug calls with dev_dbg when the device structure
+is available as dev_* prints identifying information about the struct
+device.
+Done using coccinelle:
+
+@r exists@
+identifier f, s;
+identifier x;
+position p;
+@@
+f(...,struct s *x,...) {
+<+...
+when != x == NULL
+\(pr_err@p\|pr_debug@p\|pr_info\)(...);
+...+>
+}
+
+@r2@
+identifier fld2;
+identifier r.s;
+@@
+
+struct s {
+ ...
+ struct device *fld2;
+ ...
+};
+
+@@
+identifier r.x,r2.fld2;
+position r.p;
+@@
+
+(
+-pr_err@p
++dev_err
+ (
++ &x->fld2,
+...)
+|
+- pr_debug@p
++ dev_dbg
+ (
++ &x->fld2,
+...)
+|
+- pr_info@p
++ dev_info
+ (
++ &x->fld2,
+...)
+)
+
+Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-sys.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/staging/fsl-mc/bus/mc-sys.c
+index 6e14892..8101c46 100644
+--- a/drivers/staging/fsl-mc/bus/mc-sys.c
++++ b/drivers/staging/fsl-mc/bus/mc-sys.c
+@@ -328,7 +328,8 @@ static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
+ MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+
+ if (time_after_eq(jiffies, jiffies_until_timeout)) {
+- pr_debug("MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
++ dev_dbg(&mc_io->dev,
++ "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
+ mc_io->portal_phys_addr,
+ (unsigned int)
+ MC_CMD_HDR_READ_TOKEN(cmd->header),
+@@ -369,7 +370,8 @@ static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
+ udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
+ timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
+ if (timeout_usecs == 0) {
+- pr_debug("MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
++ dev_dbg(&mc_io->dev,
++ "MC command timed out (portal: %#llx, obj handle: %#x, command: %#x)\n",
+ mc_io->portal_phys_addr,
+ (unsigned int)
+ MC_CMD_HDR_READ_TOKEN(cmd->header),
+@@ -424,7 +426,8 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
+ goto common_exit;
+
+ if (status != MC_CMD_STATUS_OK) {
+- pr_debug("MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n",
++ dev_dbg(&mc_io->dev,
++ "MC command failed: portal: %#llx, obj handle: %#x, command: %#x, status: %s (%#x)\n",
+ mc_io->portal_phys_addr,
+ (unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
+ (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0003-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch b/patches.arch/arm64-0003-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch
new file mode 100644
index 0000000000..4769c8eafd
--- /dev/null
+++ b/patches.arch/arm64-0003-ahci-qoriq-Adjust-the-default-register-values-on-ls1.patch
@@ -0,0 +1,68 @@
+From dfcdc5fe0379d5650c9306ecc6fcc5cb6cb8982a Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Wed, 16 Dec 2015 14:00:35 +0800
+Subject: [PATCH 3/3] ahci: qoriq: Adjust the default register values on
+ ls1021a
+Patch-mainline: v4.5-rc1
+Git-commit: dfcdc5fe0379d5650c9306ecc6fcc5cb6cb8982a
+References: fate#320030
+
+Updated the registers' values to enhance SATA performance and
+reliability on ls1021a soc.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/ata/ahci_qoriq.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+index 256d911..7bdee9b 100644
+--- a/drivers/ata/ahci_qoriq.c
++++ b/drivers/ata/ahci_qoriq.c
+@@ -34,16 +34,20 @@
+
+ /* port register default value */
+ #define AHCI_PORT_PHY_1_CFG 0xa003fffe
+-#define AHCI_PORT_PHY_2_CFG 0x28183411
+-#define AHCI_PORT_PHY_3_CFG 0x0e081004
+-#define AHCI_PORT_PHY_4_CFG 0x00480811
+-#define AHCI_PORT_PHY_5_CFG 0x192c96a4
+ #define AHCI_PORT_TRANS_CFG 0x08000029
+-#define LS1043A_PORT_PHY2 0x28184d1f
+-#define LS1043A_PORT_PHY3 0x0e081509
++
++/* for ls1021a */
++#define LS1021A_PORT_PHY2 0x28183414
++#define LS1021A_PORT_PHY3 0x0e080e06
++#define LS1021A_PORT_PHY4 0x064a080b
++#define LS1021A_PORT_PHY5 0x2aa86470
+
+ #define SATA_ECC_DISABLE 0x00020000
+
++/* for ls1043a */
++#define LS1043A_PORT_PHY2 0x28184d1f
++#define LS1043A_PORT_PHY3 0x0e081509
++
+ enum ahci_qoriq_type {
+ AHCI_LS1021A,
+ AHCI_LS1043A,
+@@ -153,10 +157,10 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
+ case AHCI_LS1021A:
+ writel(SATA_ECC_DISABLE, qpriv->ecc_addr);
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+- writel(AHCI_PORT_PHY_2_CFG, reg_base + PORT_PHY2);
+- writel(AHCI_PORT_PHY_3_CFG, reg_base + PORT_PHY3);
+- writel(AHCI_PORT_PHY_4_CFG, reg_base + PORT_PHY4);
+- writel(AHCI_PORT_PHY_5_CFG, reg_base + PORT_PHY5);
++ writel(LS1021A_PORT_PHY2, reg_base + PORT_PHY2);
++ writel(LS1021A_PORT_PHY3, reg_base + PORT_PHY3);
++ writel(LS1021A_PORT_PHY4, reg_base + PORT_PHY4);
++ writel(LS1021A_PORT_PHY5, reg_base + PORT_PHY5);
+ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+ break;
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0003-amd-xgbe-Use-__napi_schedule_irqoff.patch b/patches.arch/arm64-0003-amd-xgbe-Use-__napi_schedule_irqoff.patch
new file mode 100644
index 0000000000..04ab903a26
--- /dev/null
+++ b/patches.arch/arm64-0003-amd-xgbe-Use-__napi_schedule_irqoff.patch
@@ -0,0 +1,43 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:48:29 -0600
+Subject: amd-xgbe: Use __napi_schedule_irqoff
+Git-commit: 793494228fdf15acb252063f9f6dcccd3d1d497e
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+Change from calling __napi_schedule to __napi_schedule_irqoff when running
+in interrupt context or when called by netpoll with interrupts already
+disabled. The Tx timer function will continue to use __napi_schedule.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+index 5a4d9ca..80ef404 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+@@ -356,7 +356,7 @@ static irqreturn_t xgbe_isr(int irq, void *data)
+ xgbe_disable_rx_tx_ints(pdata);
+
+ /* Turn on polling */
+- __napi_schedule(&pdata->napi);
++ __napi_schedule_irqoff(&pdata->napi);
+ }
+ }
+
+@@ -409,7 +409,7 @@ static irqreturn_t xgbe_dma_isr(int irq, void *data)
+ disable_irq_nosync(channel->dma_irq);
+
+ /* Turn on polling */
+- __napi_schedule(&channel->napi);
++ __napi_schedule_irqoff(&channel->napi);
+ }
+
+ return IRQ_HANDLED;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0003-arm64-cputype-info-for-Broadcom-Vulcan.patch b/patches.arch/arm64-0003-arm64-cputype-info-for-Broadcom-Vulcan.patch
new file mode 100644
index 0000000000..9ee10dd972
--- /dev/null
+++ b/patches.arch/arm64-0003-arm64-cputype-info-for-Broadcom-Vulcan.patch
@@ -0,0 +1,39 @@
+From 9eb8a2cdf65ce47c3aa68f1297c84d8bcf5a7b3a Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Sat, 20 Feb 2016 19:49:23 +0530
+Subject: [PATCH 3/3] arm64: cputype info for Broadcom Vulcan
+Patch-mainline: v4.6-rc1
+Git-commit: 9eb8a2cdf65ce47c3aa68f1297c84d8bcf5a7b3a
+References: fate#319481
+
+Add Broadcom Vulcan implementor ID and part ID in cputype.h. This is
+to document the values.
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Acked-by: Will Deacon <will.deacon@arm.com>
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ arch/arm64/include/asm/cputype.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm64/include/asm/cputype.h
++++ b/arch/arm64/include/asm/cputype.h
+@@ -76,6 +76,7 @@
+ #define ARM_CPU_IMP_ARM 0x41
+ #define ARM_CPU_IMP_APM 0x50
+ #define ARM_CPU_IMP_CAVIUM 0x43
++#define ARM_CPU_IMP_BRCM 0x42
+
+ #define ARM_CPU_PART_AEM_V8 0xD0F
+ #define ARM_CPU_PART_FOUNDATION 0xD00
+@@ -90,6 +91,8 @@
+ #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
+ #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
+
++#define BRCM_CPU_PART_VULCAN 0x516
++
+ #ifndef __ASSEMBLY__
+
+ /*
diff --git a/patches.arch/arm64-0003-staging-fsl-mc-Added-generic-MSI-support-for-FSL-MC-.patch b/patches.arch/arm64-0003-staging-fsl-mc-Added-generic-MSI-support-for-FSL-MC-.patch
new file mode 100644
index 0000000000..4511627dd7
--- /dev/null
+++ b/patches.arch/arm64-0003-staging-fsl-mc-Added-generic-MSI-support-for-FSL-MC-.patch
@@ -0,0 +1,420 @@
+From 679c2c758c501c833a271a08aa4adbb601c42f63 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:21 -0600
+Subject: [PATCH 03/11] staging: fsl-mc: Added generic MSI support for FSL-MC
+ devices
+Patch-mainline: v4.6-rc1
+Git-commit: 679c2c758c501c833a271a08aa4adbb601c42f63
+References: fate#319900
+
+Created an MSI domain for the fsl-mc bus-- including functions
+to create a domain, find a domain, alloc/free domain irqs, and
+bus specific overrides for domain and irq_chip ops.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/Kconfig | 1 +
+ drivers/staging/fsl-mc/bus/Makefile | 1 +
+ drivers/staging/fsl-mc/bus/mc-msi.c | 276 ++++++++++++++++++++++++++++
+ drivers/staging/fsl-mc/include/dprc.h | 2 +-
+ drivers/staging/fsl-mc/include/mc-private.h | 17 ++
+ drivers/staging/fsl-mc/include/mc.h | 17 ++
+ 6 files changed, 313 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/staging/fsl-mc/bus/mc-msi.c
+
+diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig
+index 0d779d9..c498ac6 100644
+--- a/drivers/staging/fsl-mc/bus/Kconfig
++++ b/drivers/staging/fsl-mc/bus/Kconfig
+@@ -9,6 +9,7 @@
+ config FSL_MC_BUS
+ tristate "Freescale Management Complex (MC) bus driver"
+ depends on OF && ARM64
++ select GENERIC_MSI_IRQ_DOMAIN
+ help
+ Driver to enable the bus infrastructure for the Freescale
+ QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware
+diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
+index 25433a9..a5f2ba4 100644
+--- a/drivers/staging/fsl-mc/bus/Makefile
++++ b/drivers/staging/fsl-mc/bus/Makefile
+@@ -13,5 +13,6 @@ mc-bus-driver-objs := mc-bus.o \
+ dpmng.o \
+ dprc-driver.o \
+ mc-allocator.o \
++ mc-msi.o \
+ dpmcp.o \
+ dpbp.o
+diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c
+new file mode 100644
+index 0000000..3a8258f
+--- /dev/null
++++ b/drivers/staging/fsl-mc/bus/mc-msi.c
+@@ -0,0 +1,276 @@
++/*
++ * Freescale Management Complex (MC) bus driver MSI support
++ *
++ * Copyright (C) 2015 Freescale Semiconductor, Inc.
++ * Author: German Rivera <German.Rivera@freescale.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include "../include/mc-private.h"
++#include <linux/of_device.h>
++#include <linux/of_address.h>
++#include <linux/irqchip/arm-gic-v3.h>
++#include <linux/of_irq.h>
++#include <linux/irq.h>
++#include <linux/irqdomain.h>
++#include <linux/msi.h>
++#include "../include/mc-sys.h"
++#include "dprc-cmd.h"
++
++static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
++ struct msi_desc *desc)
++{
++ arg->desc = desc;
++ arg->hwirq = (irq_hw_number_t)desc->fsl_mc.msi_index;
++}
++
++static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
++{
++ struct msi_domain_ops *ops = info->ops;
++
++ if (WARN_ON(!ops))
++ return;
++
++ /*
++ * set_desc should not be set by the caller
++ */
++ if (WARN_ON(ops->set_desc))
++ return;
++
++ ops->set_desc = fsl_mc_msi_set_desc;
++}
++
++static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
++ struct fsl_mc_device_irq *mc_dev_irq)
++{
++ int error;
++ struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
++ struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
++ struct dprc_irq_cfg irq_cfg;
++
++ /*
++ * msi_desc->msg.address is 0x0 when this function is invoked in
++ * the free_irq() code path. In this case, for the MC, we don't
++ * really need to "unprogram" the MSI, so we just return.
++ */
++ if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
++ return;
++
++ if (WARN_ON(!owner_mc_dev))
++ return;
++
++ irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
++ msi_desc->msg.address_lo;
++ irq_cfg.val = msi_desc->msg.data;
++ irq_cfg.user_irq_id = msi_desc->irq;
++
++ if (owner_mc_dev == mc_bus_dev) {
++ /*
++ * IRQ is for the mc_bus_dev's DPRC itself
++ */
++ error = dprc_set_irq(mc_bus_dev->mc_io,
++ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
++ mc_bus_dev->mc_handle,
++ mc_dev_irq->dev_irq_index,
++ &irq_cfg);
++ if (error < 0) {
++ dev_err(&owner_mc_dev->dev,
++ "dprc_set_irq() failed: %d\n", error);
++ }
++ } else {
++ /*
++ * IRQ is for for a child device of mc_bus_dev
++ */
++ error = dprc_set_obj_irq(mc_bus_dev->mc_io,
++ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
++ mc_bus_dev->mc_handle,
++ owner_mc_dev->obj_desc.type,
++ owner_mc_dev->obj_desc.id,
++ mc_dev_irq->dev_irq_index,
++ &irq_cfg);
++ if (error < 0) {
++ dev_err(&owner_mc_dev->dev,
++ "dprc_obj_set_irq() failed: %d\n", error);
++ }
++ }
++}
++
++/*
++ * NOTE: This function is invoked with interrupts disabled
++ */
++static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
++ struct msi_msg *msg)
++{
++ struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
++ struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
++ struct fsl_mc_device_irq *mc_dev_irq =
++ &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
++
++ WARN_ON(mc_dev_irq->msi_desc != msi_desc);
++ msi_desc->msg = *msg;
++
++ /*
++ * Program the MSI (paddr, value) pair in the device:
++ */
++ __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
++}
++
++static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
++{
++ struct irq_chip *chip = info->chip;
++
++ if (WARN_ON((!chip)))
++ return;
++
++ /*
++ * irq_write_msi_msg should not be set by the caller
++ */
++ if (WARN_ON(chip->irq_write_msi_msg))
++ return;
++
++ chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
++}
++
++/**
++ * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
++ * @np: Optional device-tree node of the interrupt controller
++ * @info: MSI domain info
++ * @parent: Parent irq domain
++ *
++ * Updates the domain and chip ops and creates a fsl-mc MSI
++ * interrupt domain.
++ *
++ * Returns:
++ * A domain pointer or NULL in case of failure.
++ */
++struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
++ struct msi_domain_info *info,
++ struct irq_domain *parent)
++{
++ struct irq_domain *domain;
++
++ if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
++ fsl_mc_msi_update_dom_ops(info);
++ if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
++ fsl_mc_msi_update_chip_ops(info);
++
++ domain = msi_create_irq_domain(fwnode, info, parent);
++ if (domain)
++ domain->bus_token = DOMAIN_BUS_FSL_MC_MSI;
++
++ return domain;
++}
++
++int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
++ struct irq_domain **mc_msi_domain)
++{
++ struct irq_domain *msi_domain;
++ struct device_node *mc_of_node = mc_platform_dev->of_node;
++
++ msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
++ DOMAIN_BUS_FSL_MC_MSI);
++ if (!msi_domain) {
++ pr_err("Unable to find fsl-mc MSI domain for %s\n",
++ mc_of_node->full_name);
++
++ return -ENOENT;
++ }
++
++ *mc_msi_domain = msi_domain;
++ return 0;
++}
++
++static void fsl_mc_msi_free_descs(struct device *dev)
++{
++ struct msi_desc *desc, *tmp;
++
++ list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
++ list_del(&desc->list);
++ free_msi_entry(desc);
++ }
++}
++
++static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
++
++{
++ unsigned int i;
++ int error;
++ struct msi_desc *msi_desc;
++
++ for (i = 0; i < irq_count; i++) {
++ msi_desc = alloc_msi_entry(dev);
++ if (!msi_desc) {
++ dev_err(dev, "Failed to allocate msi entry\n");
++ error = -ENOMEM;
++ goto cleanup_msi_descs;
++ }
++
++ msi_desc->fsl_mc.msi_index = i;
++ msi_desc->nvec_used = 1;
++ INIT_LIST_HEAD(&msi_desc->list);
++ list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
++ }
++
++ return 0;
++
++cleanup_msi_descs:
++ fsl_mc_msi_free_descs(dev);
++ return error;
++}
++
++int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
++ unsigned int irq_count)
++{
++ struct irq_domain *msi_domain;
++ int error;
++
++ if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
++ return -EINVAL;
++
++ error = fsl_mc_msi_alloc_descs(dev, irq_count);
++ if (error < 0)
++ return error;
++
++ msi_domain = dev_get_msi_domain(dev);
++ if (WARN_ON(!msi_domain)) {
++ error = -EINVAL;
++ goto cleanup_msi_descs;
++ }
++
++ /*
++ * NOTE: Calling this function will trigger the invocation of the
++ * its_fsl_mc_msi_prepare() callback
++ */
++ error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
++
++ if (error) {
++ dev_err(dev, "Failed to allocate IRQs\n");
++ goto cleanup_msi_descs;
++ }
++
++ return 0;
++
++cleanup_msi_descs:
++ fsl_mc_msi_free_descs(dev);
++ return error;
++}
++
++void fsl_mc_msi_domain_free_irqs(struct device *dev)
++{
++ struct irq_domain *msi_domain;
++
++ msi_domain = dev_get_msi_domain(dev);
++ if (WARN_ON(!msi_domain))
++ return;
++
++ msi_domain_free_irqs(msi_domain, dev);
++
++ if (WARN_ON(list_empty(dev_to_msi_list(dev))))
++ return;
++
++ fsl_mc_msi_free_descs(dev);
++}
+diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h
+index c3152f6..94c4927 100644
+--- a/drivers/staging/fsl-mc/include/dprc.h
++++ b/drivers/staging/fsl-mc/include/dprc.h
+@@ -176,7 +176,7 @@ int dprc_reset_container(struct fsl_mc_io *mc_io,
+ * @user_irq_id: A user defined number associated with this IRQ
+ */
+ struct dprc_irq_cfg {
+- u64 paddr;
++ phys_addr_t paddr;
+ u32 val;
+ int user_irq_id;
+ };
+diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
+index c706f77..36b418c 100644
+--- a/drivers/staging/fsl-mc/include/mc-private.h
++++ b/drivers/staging/fsl-mc/include/mc-private.h
+@@ -26,6 +26,9 @@
+ strcmp(_obj_type, "dpmcp") == 0 || \
+ strcmp(_obj_type, "dpcon") == 0)
+
++struct irq_domain;
++struct msi_domain_info;
++
+ /**
+ * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
+ * @root_mc_bus_dev: MC object device representing the root DPRC
+@@ -79,11 +82,13 @@ struct fsl_mc_resource_pool {
+ * @resource_pools: array of resource pools (one pool per resource type)
+ * for this MC bus. These resources represent allocatable entities
+ * from the physical DPRC.
++ * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
+ * @scan_mutex: Serializes bus scanning
+ */
+ struct fsl_mc_bus {
+ struct fsl_mc_device mc_dev;
+ struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
++ struct fsl_mc_device_irq *irq_resources;
+ struct mutex scan_mutex; /* serializes bus scanning */
+ };
+
+@@ -116,4 +121,16 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
+
+ void fsl_mc_resource_free(struct fsl_mc_resource *resource);
+
++struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
++ struct msi_domain_info *info,
++ struct irq_domain *parent);
++
++int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
++ struct irq_domain **mc_msi_domain);
++
++int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
++ unsigned int irq_count);
++
++void fsl_mc_msi_domain_free_irqs(struct device *dev);
++
+ #endif /* _FSL_MC_PRIVATE_H_ */
+diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
+index a933291..1c1d6ae 100644
+--- a/drivers/staging/fsl-mc/include/mc.h
++++ b/drivers/staging/fsl-mc/include/mc.h
+@@ -104,6 +104,23 @@ struct fsl_mc_resource {
+ };
+
+ /**
++ * struct fsl_mc_device_irq - MC object device message-based interrupt
++ * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs()
++ * @mc_dev: MC object device that owns this interrupt
++ * @dev_irq_index: device-relative IRQ index
++ * @resource: MC generic resource associated with the interrupt
++ */
++struct fsl_mc_device_irq {
++ struct msi_desc *msi_desc;
++ struct fsl_mc_device *mc_dev;
++ u8 dev_irq_index;
++ struct fsl_mc_resource resource;
++};
++
++#define to_fsl_mc_irq(_mc_resource) \
++ container_of(_mc_resource, struct fsl_mc_device_irq, resource)
++
++/**
+ * Bit masks for a MC object device (struct fsl_mc_device) flags
+ */
+ #define FSL_MC_IS_DPRC 0x0001
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0003-staging-fsl-mc-add-dpmcp-version-check.patch b/patches.arch/arm64-0003-staging-fsl-mc-add-dpmcp-version-check.patch
new file mode 100644
index 0000000000..350850e98d
--- /dev/null
+++ b/patches.arch/arm64-0003-staging-fsl-mc-add-dpmcp-version-check.patch
@@ -0,0 +1,61 @@
+From 8b6865e53ced19dcfa90bf9ba12f918d3a6a2f15 Mon Sep 17 00:00:00 2001
+From: Itai Katz <itai.katz@freescale.com>
+Date: Sun, 3 Jan 2016 15:21:39 +0200
+Subject: [PATCH 3/4] staging: fsl-mc: add dpmcp version check
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 8b6865e53ced19dcfa90bf9ba12f918d3a6a2f15
+References: fate#319900
+
+The dpmcp driver supports dpmcp version 3.0 and above.
+This patch adds the code to check the version.
+
+Signed-off-by: Itai Katz <itai.katz@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 6 +++---
+ drivers/staging/fsl-mc/bus/mc-allocator.c | 11 +++++++++++
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
+index c6f4ec0..c9b52dd 100644
+--- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
++++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
+@@ -32,9 +32,9 @@
+ #ifndef _FSL_DPMCP_CMD_H
+ #define _FSL_DPMCP_CMD_H
+
+-/* DPMCP Version */
+-#define DPMCP_VER_MAJOR 3
+-#define DPMCP_VER_MINOR 0
++/* Minimal supported DPMCP Version */
++#define DPMCP_MIN_VER_MAJOR 3
++#define DPMCP_MIN_VER_MINOR 0
+
+ /* Command IDs */
+ #define DPMCP_CMDID_CLOSE 0x800
+diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
+index 52b16f7..4676ba1 100644
+--- a/drivers/staging/fsl-mc/bus/mc-allocator.c
++++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
+@@ -310,6 +310,17 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
+ if (WARN_ON(!dpmcp_dev))
+ goto error_cleanup_resource;
+
++ if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
++ (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
++ dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
++ dev_err(&dpmcp_dev->dev,
++ "ERROR: Version %d.%d of DPMCP not supported.\n",
++ dpmcp_dev->obj_desc.ver_major,
++ dpmcp_dev->obj_desc.ver_minor);
++ error = -ENOTSUPP;
++ goto error_cleanup_resource;
++ }
++
+ if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
+ goto error_cleanup_resource;
+
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0003-staging-fsl-mc-update-dprc-binary-interface-to-v5.1.patch b/patches.arch/arm64-0003-staging-fsl-mc-update-dprc-binary-interface-to-v5.1.patch
new file mode 100644
index 0000000000..fc3dcfee2f
--- /dev/null
+++ b/patches.arch/arm64-0003-staging-fsl-mc-update-dprc-binary-interface-to-v5.1.patch
@@ -0,0 +1,221 @@
+From eba9e0525429b3cd0b7e1173c02e4b50042423fc Mon Sep 17 00:00:00 2001
+From: Stuart Yoder <stuart.yoder@nxp.com>
+Date: Wed, 2 Mar 2016 10:54:15 -0600
+Subject: [PATCH 03/12] staging: fsl-mc: update dprc binary interface to v5.1
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: eba9e0525429b3cd0b7e1173c02e4b50042423fc
+References: fate#319900
+
+The meaning of the "status" parameter in dprc_get_irq_status
+has changed, and this patch updates the flib and caller
+of the API.
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-cmd.h | 4 ++--
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 1 +
+ drivers/staging/fsl-mc/bus/dprc.c | 26 +++++++++++++-------------
+ drivers/staging/fsl-mc/bus/mc-msi.c | 2 +-
+ drivers/staging/fsl-mc/include/dprc.h | 19 ++++++++++++-------
+ 5 files changed, 29 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h
+index 6552c20..d0198f5 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
++++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h
+@@ -41,8 +41,8 @@
+ #define _FSL_DPRC_CMD_H
+
+ /* DPRC Version */
+-#define DPRC_VER_MAJOR 4
+-#define DPRC_VER_MINOR 0
++#define DPRC_VER_MAJOR 5
++#define DPRC_VER_MINOR 1
+
+ /* Command IDs */
+ #define DPRC_CMDID_CLOSE 0x800
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 9380ebc..2932924 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -423,6 +423,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
+ if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
+ goto out;
+
++ status = 0;
+ error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
+ &status);
+ if (error < 0) {
+diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c
+index 381b9a9..b19f1a3 100644
+--- a/drivers/staging/fsl-mc/bus/dprc.c
++++ b/drivers/staging/fsl-mc/bus/dprc.c
+@@ -265,7 +265,7 @@ int dprc_get_irq(struct fsl_mc_io *mc_io,
+ /* retrieve response parameters */
+ irq_cfg->val = mc_dec(cmd.params[0], 0, 32);
+ irq_cfg->paddr = mc_dec(cmd.params[1], 0, 64);
+- irq_cfg->user_irq_id = mc_dec(cmd.params[2], 0, 32);
++ irq_cfg->irq_num = mc_dec(cmd.params[2], 0, 32);
+ *type = mc_dec(cmd.params[2], 32, 32);
+
+ return 0;
+@@ -296,7 +296,7 @@ int dprc_set_irq(struct fsl_mc_io *mc_io,
+ cmd.params[0] |= mc_enc(32, 8, irq_index);
+ cmd.params[0] |= mc_enc(0, 32, irq_cfg->val);
+ cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr);
+- cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id);
++ cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+@@ -466,6 +466,7 @@ int dprc_get_irq_status(struct fsl_mc_io *mc_io,
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
+ cmd_flags, token);
++ cmd.params[0] |= mc_enc(0, 32, *status);
+ cmd.params[0] |= mc_enc(32, 8, irq_index);
+
+ /* send command to mc*/
+@@ -948,6 +949,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io,
+ obj_desc->state = mc_dec(cmd.params[1], 32, 32);
+ obj_desc->ver_major = mc_dec(cmd.params[2], 0, 16);
+ obj_desc->ver_minor = mc_dec(cmd.params[2], 16, 16);
++ obj_desc->flags = mc_dec(cmd.params[2], 32, 16);
+ obj_desc->type[0] = mc_dec(cmd.params[3], 0, 8);
+ obj_desc->type[1] = mc_dec(cmd.params[3], 8, 8);
+ obj_desc->type[2] = mc_dec(cmd.params[3], 16, 8);
+@@ -1042,6 +1044,7 @@ int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
+ obj_desc->state = (u32)mc_dec(cmd.params[1], 32, 32);
+ obj_desc->ver_major = (u16)mc_dec(cmd.params[2], 0, 16);
+ obj_desc->ver_minor = (u16)mc_dec(cmd.params[2], 16, 16);
++ obj_desc->flags = mc_dec(cmd.params[2], 32, 16);
+ obj_desc->type[0] = (char)mc_dec(cmd.params[3], 0, 8);
+ obj_desc->type[1] = (char)mc_dec(cmd.params[3], 8, 8);
+ obj_desc->type[2] = (char)mc_dec(cmd.params[3], 16, 8);
+@@ -1108,7 +1111,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
+ cmd.params[0] |= mc_enc(32, 8, irq_index);
+ cmd.params[0] |= mc_enc(0, 32, irq_cfg->val);
+ cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr);
+- cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id);
++ cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num);
+ cmd.params[2] |= mc_enc(32, 32, obj_id);
+ cmd.params[3] |= mc_enc(0, 8, obj_type[0]);
+ cmd.params[3] |= mc_enc(8, 8, obj_type[1]);
+@@ -1189,7 +1192,7 @@ int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
+ /* retrieve response parameters */
+ irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32);
+ irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64);
+- irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
++ irq_cfg->irq_num = (int)mc_dec(cmd.params[2], 0, 32);
+ *type = (int)mc_dec(cmd.params[2], 32, 32);
+
+ return 0;
+@@ -1437,14 +1440,8 @@ EXPORT_SYMBOL(dprc_set_obj_label);
+ * @endpoint1: Endpoint 1 configuration parameters
+ * @endpoint2: Endpoint 2 configuration parameters
+ * @cfg: Connection configuration. The connection configuration is ignored for
+- * connections made to DPMAC objects, where rate is set according to
+- * MAC configuration.
+- * The committed rate is the guaranteed rate for the connection.
+- * The maximum rate is an upper limit allowed for the connection; it is
+- * expected to be equal or higher than the committed rate.
+- * When committed and maximum rates are both zero, the connection is set
+- * to "best effort" mode, having lower priority compared to connections
+- * with committed or maximum rates.
++ * connections made to DPMAC objects, where rate is retrieved from the
++ * MAC configuration.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+@@ -1555,7 +1552,10 @@ int dprc_disconnect(struct fsl_mc_io *mc_io,
+ * @token: Token of DPRC object
+ * @endpoint1: Endpoint 1 configuration parameters
+ * @endpoint2: Returned endpoint 2 configuration parameters
+-* @state: Returned link state: 1 - link is up, 0 - link is down
++* @state: Returned link state:
++* 1 - link is up;
++* 0 - link is down;
++* -1 - no connection (endpoint2 information is irrelevant)
+ *
+ * Return: '0' on Success; -ENAVAIL if connection does not exist.
+ */
+diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c
+index 3a8258f..ba48add 100644
+--- a/drivers/staging/fsl-mc/bus/mc-msi.c
++++ b/drivers/staging/fsl-mc/bus/mc-msi.c
+@@ -65,7 +65,7 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
+ irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
+ msi_desc->msg.address_lo;
+ irq_cfg.val = msi_desc->msg.data;
+- irq_cfg.user_irq_id = msi_desc->irq;
++ irq_cfg.irq_num = msi_desc->irq;
+
+ if (owner_mc_dev == mc_bus_dev) {
+ /*
+diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h
+index 94c4927..2c819f6 100644
+--- a/drivers/staging/fsl-mc/include/dprc.h
++++ b/drivers/staging/fsl-mc/include/dprc.h
+@@ -94,11 +94,6 @@ int dprc_close(struct fsl_mc_io *mc_io,
+ */
+ #define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008
+
+-/* IOMMU bypass - indicates whether objects of this container are permitted
+- * to bypass the IOMMU.
+- */
+-#define DPRC_CFG_OPT_IOMMU_BYPASS 0x00000010
+-
+ /* AIOP - Indicates that container belongs to AIOP. */
+ #define DPRC_CFG_OPT_AIOP 0x00000020
+
+@@ -173,12 +168,12 @@ int dprc_reset_container(struct fsl_mc_io *mc_io,
+ * struct dprc_irq_cfg - IRQ configuration
+ * @paddr: Address that must be written to signal a message-based interrupt
+ * @val: Value to write into irq_addr address
+- * @user_irq_id: A user defined number associated with this IRQ
++ * @irq_num: A user defined number associated with this IRQ
+ */
+ struct dprc_irq_cfg {
+ phys_addr_t paddr;
+ u32 val;
+- int user_irq_id;
++ int irq_num;
+ };
+
+ int dprc_set_irq(struct fsl_mc_io *mc_io,
+@@ -353,6 +348,14 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io,
+ #define DPRC_OBJ_STATE_PLUGGED 0x00000002
+
+ /**
++ * Shareability flag - Object flag indicating no memory shareability.
++ * the object generates memory accesses that are non coherent with other
++ * masters;
++ * user is responsible for proper memory handling through IOMMU configuration.
++ */
++#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
++
++/**
+ * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj()
+ * @type: Type of object: NULL terminated string
+ * @id: ID of logical object resource
+@@ -363,6 +366,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io,
+ * @region_count: Number of mappable regions supported by the object
+ * @state: Object state: combination of DPRC_OBJ_STATE_ states
+ * @label: Object label
++ * @flags: Object's flags
+ */
+ struct dprc_obj_desc {
+ char type[16];
+@@ -374,6 +378,7 @@ struct dprc_obj_desc {
+ u8 region_count;
+ u32 state;
+ char label[16];
++ uint16_t flags;
+ };
+
+ int dprc_get_obj(struct fsl_mc_io *mc_io,
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0004-Staging-fsl-mc-Replace-pr_err-with-dev_err.patch b/patches.arch/arm64-0004-Staging-fsl-mc-Replace-pr_err-with-dev_err.patch
new file mode 100644
index 0000000000..bd1c02979e
--- /dev/null
+++ b/patches.arch/arm64-0004-Staging-fsl-mc-Replace-pr_err-with-dev_err.patch
@@ -0,0 +1,92 @@
+From 454b0ec8bf992b35895eb86a4b62ec3ba7be190c Mon Sep 17 00:00:00 2001
+From: Bhumika Goyal <bhumirks@gmail.com>
+Date: Fri, 4 Mar 2016 19:15:55 +0530
+Subject: [PATCH 4/4] Staging: fsl-mc: Replace pr_err with dev_err
+Patch-mainline: v4.6-rc1
+Git-commit: 454b0ec8bf992b35895eb86a4b62ec3ba7be190c
+References: fate#319900
+
+This patch replaces pr_err calls with dev_err when the device structure
+is available as dev_* prints identifying information about the struct device.
+Done using coccinelle:
+
+@r exists@
+identifier f, s;
+identifier x;
+position p;
+@@
+f(...,struct s *x,...) {
+<+...
+when != x == NULL
+\(pr_err@p\|pr_debug@p\|pr_info\)(...);
+...+>
+}
+
+@r2@
+identifier fld2;
+identifier r.s;
+@@
+
+struct s {
+ ...
+ struct device *fld2;
+ ...
+};
+
+@@
+identifier r.x,r2.fld2;
+position r.p;
+@@
+
+(
+-pr_err@p
++dev_err
+ (
++ &x->fld2,
+...)
+|
+- pr_debug@p
++ dev_dbg
+ (
++ &x->fld2,
+...)
+|
+- pr_info@p
++ dev_info
+ (
++ &x->fld2,
+...)
+)
+
+Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 5958e0f..9f77c37b 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -260,14 +260,15 @@ static int get_dprc_icid(struct fsl_mc_io *mc_io,
+
+ error = dprc_open(mc_io, 0, container_id, &dprc_handle);
+ if (error < 0) {
+- pr_err("dprc_open() failed: %d\n", error);
++ dev_err(&mc_io->dev, "dprc_open() failed: %d\n", error);
+ return error;
+ }
+
+ memset(&attr, 0, sizeof(attr));
+ error = dprc_get_attributes(mc_io, 0, dprc_handle, &attr);
+ if (error < 0) {
+- pr_err("dprc_get_attributes() failed: %d\n", error);
++ dev_err(&mc_io->dev, "dprc_get_attributes() failed: %d\n",
++ error);
+ goto common_cleanup;
+ }
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0004-amd-xgbe-Verify-forced-speed-matches-the-active-spee.patch b/patches.arch/arm64-0004-amd-xgbe-Verify-forced-speed-matches-the-active-spee.patch
new file mode 100644
index 0000000000..001ce0ab17
--- /dev/null
+++ b/patches.arch/arm64-0004-amd-xgbe-Verify-forced-speed-matches-the-active-spee.patch
@@ -0,0 +1,63 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:48:39 -0600
+Subject: amd-xgbe: Verify forced speed matches the active speedset
+Git-commit: 757e6aa34ca9529786877d3045684e7c9f686075
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+When using ethtool to set the speed for the device, verify that the
+specified speed is valid within the active speedset.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+index 6040293..11d9f0c 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+@@ -6,7 +6,7 @@
+ *
+ * License 1: GPLv2
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -56,7 +56,7 @@
+ *
+ * License 2: Modified BSD
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -318,8 +318,20 @@ static int xgbe_set_settings(struct net_device *netdev,
+ if (cmd->autoneg == AUTONEG_DISABLE) {
+ switch (speed) {
+ case SPEED_10000:
++ break;
+ case SPEED_2500:
++ if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) {
++ netdev_err(netdev, "unsupported speed %u\n",
++ speed);
++ return -EINVAL;
++ }
++ break;
+ case SPEED_1000:
++ if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) {
++ netdev_err(netdev, "unsupported speed %u\n",
++ speed);
++ return -EINVAL;
++ }
+ break;
+ default:
+ netdev_err(netdev, "unsupported speed %u\n", speed);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0004-staging-fsl-mc-Added-GICv3-ITS-support-for-FSL-MC-MS.patch b/patches.arch/arm64-0004-staging-fsl-mc-Added-GICv3-ITS-support-for-FSL-MC-MS.patch
new file mode 100644
index 0000000000..d4ee70b9e1
--- /dev/null
+++ b/patches.arch/arm64-0004-staging-fsl-mc-Added-GICv3-ITS-support-for-FSL-MC-MS.patch
@@ -0,0 +1,181 @@
+From 3a288fd51b41a2998195c321d8dd4a229176e6f7 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:22 -0600
+Subject: [PATCH 04/11] staging: fsl-mc: Added GICv3-ITS support for FSL-MC
+ MSIs
+Patch-mainline: v4.6-rc1
+Git-commit: 3a288fd51b41a2998195c321d8dd4a229176e6f7
+References: fate#319900
+
+Added platform-specific MSI support layer for FSL-MC devices.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/Makefile | 1 +
+ .../staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 127 +++++++++++++++++++++
+ drivers/staging/fsl-mc/include/mc-private.h | 4 +
+ 3 files changed, 132 insertions(+)
+ create mode 100644 drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+
+diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
+index a5f2ba4..e731517 100644
+--- a/drivers/staging/fsl-mc/bus/Makefile
++++ b/drivers/staging/fsl-mc/bus/Makefile
+@@ -14,5 +14,6 @@ mc-bus-driver-objs := mc-bus.o \
+ dprc-driver.o \
+ mc-allocator.o \
+ mc-msi.o \
++ irq-gic-v3-its-fsl-mc-msi.o \
+ dpmcp.o \
+ dpbp.o
+diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+new file mode 100644
+index 0000000..4e8e822
+--- /dev/null
++++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+@@ -0,0 +1,127 @@
++/*
++ * Freescale Management Complex (MC) bus driver MSI support
++ *
++ * Copyright (C) 2015 Freescale Semiconductor, Inc.
++ * Author: German Rivera <German.Rivera@freescale.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include "../include/mc-private.h"
++#include <linux/of_device.h>
++#include <linux/of_address.h>
++#include <linux/irqchip/arm-gic-v3.h>
++#include <linux/irq.h>
++#include <linux/msi.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include "../include/mc-sys.h"
++#include "dprc-cmd.h"
++
++static struct irq_chip its_msi_irq_chip = {
++ .name = "fsl-mc-bus-msi",
++ .irq_mask = irq_chip_mask_parent,
++ .irq_unmask = irq_chip_unmask_parent,
++ .irq_eoi = irq_chip_eoi_parent,
++ .irq_set_affinity = msi_domain_set_affinity
++};
++
++static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
++ struct device *dev,
++ int nvec, msi_alloc_info_t *info)
++{
++ struct fsl_mc_device *mc_bus_dev;
++ struct msi_domain_info *msi_info;
++
++ if (WARN_ON(dev->bus != &fsl_mc_bus_type))
++ return -EINVAL;
++
++ mc_bus_dev = to_fsl_mc_device(dev);
++ if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC)))
++ return -EINVAL;
++
++ /*
++ * Set the device Id to be passed to the GIC-ITS:
++ *
++ * NOTE: This device id corresponds to the IOMMU stream ID
++ * associated with the DPRC object (ICID).
++ */
++ info->scratchpad[0].ul = mc_bus_dev->icid;
++ msi_info = msi_get_domain_info(msi_domain->parent);
++ return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
++}
++
++static struct msi_domain_ops its_fsl_mc_msi_ops = {
++ .msi_prepare = its_fsl_mc_msi_prepare,
++};
++
++static struct msi_domain_info its_fsl_mc_msi_domain_info = {
++ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
++ .ops = &its_fsl_mc_msi_ops,
++ .chip = &its_msi_irq_chip,
++};
++
++static const struct of_device_id its_device_id[] = {
++ { .compatible = "arm,gic-v3-its", },
++ {},
++};
++
++int __init its_fsl_mc_msi_init(void)
++{
++ struct device_node *np;
++ struct irq_domain *parent;
++ struct irq_domain *mc_msi_domain;
++
++ for (np = of_find_matching_node(NULL, its_device_id); np;
++ np = of_find_matching_node(np, its_device_id)) {
++ if (!of_property_read_bool(np, "msi-controller"))
++ continue;
++
++ parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
++ if (!parent || !msi_get_domain_info(parent)) {
++ pr_err("%s: unable to locate ITS domain\n",
++ np->full_name);
++ continue;
++ }
++
++ mc_msi_domain = fsl_mc_msi_create_irq_domain(
++ of_node_to_fwnode(np),
++ &its_fsl_mc_msi_domain_info,
++ parent);
++ if (!mc_msi_domain) {
++ pr_err("%s: unable to create fsl-mc domain\n",
++ np->full_name);
++ continue;
++ }
++
++ WARN_ON(mc_msi_domain->
++ host_data != &its_fsl_mc_msi_domain_info);
++
++ pr_info("fsl-mc MSI: %s domain created\n", np->full_name);
++ }
++
++ return 0;
++}
++
++void its_fsl_mc_msi_cleanup(void)
++{
++ struct device_node *np;
++
++ for (np = of_find_matching_node(NULL, its_device_id); np;
++ np = of_find_matching_node(np, its_device_id)) {
++ struct irq_domain *mc_msi_domain = irq_find_matching_host(
++ np,
++ DOMAIN_BUS_FSL_MC_MSI);
++
++ if (!of_property_read_bool(np, "msi-controller"))
++ continue;
++
++ mc_msi_domain = irq_find_matching_host(np,
++ DOMAIN_BUS_FSL_MC_MSI);
++ if (mc_msi_domain &&
++ mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info)
++ irq_domain_remove(mc_msi_domain);
++ }
++}
+diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
+index 36b418c..28c8d32 100644
+--- a/drivers/staging/fsl-mc/include/mc-private.h
++++ b/drivers/staging/fsl-mc/include/mc-private.h
+@@ -133,4 +133,8 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
+
+ void fsl_mc_msi_domain_free_irqs(struct device *dev);
+
++int __init its_fsl_mc_msi_init(void);
++
++void its_fsl_mc_msi_cleanup(void);
++
+ #endif /* _FSL_MC_PRIVATE_H_ */
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0004-staging-fsl-mc-change-binding-rules.patch b/patches.arch/arm64-0004-staging-fsl-mc-change-binding-rules.patch
new file mode 100644
index 0000000000..c0b17cf818
--- /dev/null
+++ b/patches.arch/arm64-0004-staging-fsl-mc-change-binding-rules.patch
@@ -0,0 +1,140 @@
+From b39b268558aaa40d50feaf6d3b1b2e4d8203880e Mon Sep 17 00:00:00 2001
+From: Itai Katz <itai.katz@freescale.com>
+Date: Tue, 13 Oct 2015 14:42:54 +0300
+Subject: [PATCH 04/12] staging: fsl-mc: change binding rules
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: b39b268558aaa40d50feaf6d3b1b2e4d8203880e
+References: fate#319900
+
+Overall version of MC is informational like a release number.
+This patch removes the check of MC version number (and consequent actions).
+Print of overall MC version remains for informational purposes.
+
+The patch also removes the reference to major and minor version fields in
+fsl_mc_device_match_id from the drivers of following MC objects:
+- DPRC
+- DPBP
+- DPMCP
+- DPCON
+
+Signed-off-by: Itai Katz <itai.katz@freescale.com>
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 4 +---
+ drivers/staging/fsl-mc/bus/mc-allocator.c | 6 -----
+ drivers/staging/fsl-mc/bus/mc-bus.c | 38 +------------------------------
+ 3 files changed, 2 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 2932924..344ddfd 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -780,9 +780,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
+ static const struct fsl_mc_device_match_id match_id_table[] = {
+ {
+ .vendor = FSL_MC_VENDOR_FREESCALE,
+- .obj_type = "dprc",
+- .ver_major = DPRC_VER_MAJOR,
+- .ver_minor = DPRC_VER_MINOR},
++ .obj_type = "dprc"},
+ {.vendor = 0x0},
+ };
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
+index 86f8543..52b16f7 100644
+--- a/drivers/staging/fsl-mc/bus/mc-allocator.c
++++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
+@@ -722,20 +722,14 @@ static const struct fsl_mc_device_match_id match_id_table[] = {
+ {
+ .vendor = FSL_MC_VENDOR_FREESCALE,
+ .obj_type = "dpbp",
+- .ver_major = DPBP_VER_MAJOR,
+- .ver_minor = DPBP_VER_MINOR
+ },
+ {
+ .vendor = FSL_MC_VENDOR_FREESCALE,
+ .obj_type = "dpmcp",
+- .ver_major = DPMCP_VER_MAJOR,
+- .ver_minor = DPMCP_VER_MINOR
+ },
+ {
+ .vendor = FSL_MC_VENDOR_FREESCALE,
+ .obj_type = "dpcon",
+- .ver_major = DPCON_VER_MAJOR,
+- .ver_minor = DPCON_VER_MINOR
+ },
+ {.vendor = 0x0},
+ };
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 5958e0f..45de8b1 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -40,8 +40,6 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+ struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
+ bool found = false;
+- bool major_version_mismatch = false;
+- bool minor_version_mismatch = false;
+
+ if (WARN_ON(!fsl_mc_bus_exists()))
+ goto out;
+@@ -64,32 +62,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
+ for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
+ if (id->vendor == mc_dev->obj_desc.vendor &&
+ strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
+- if (id->ver_major == mc_dev->obj_desc.ver_major) {
+- found = true;
+- if (id->ver_minor != mc_dev->obj_desc.ver_minor)
+- minor_version_mismatch = true;
+- } else {
+- major_version_mismatch = true;
+- }
++ found = true;
+
+ break;
+ }
+ }
+
+- if (major_version_mismatch) {
+- dev_warn(dev,
+- "Major version mismatch: driver version %u.%u, MC object version %u.%u\n",
+- id->ver_major, id->ver_minor,
+- mc_dev->obj_desc.ver_major,
+- mc_dev->obj_desc.ver_minor);
+- } else if (minor_version_mismatch) {
+- dev_warn(dev,
+- "Minor version mismatch: driver version %u.%u, MC object version %u.%u\n",
+- id->ver_major, id->ver_minor,
+- mc_dev->obj_desc.ver_major,
+- mc_dev->obj_desc.ver_minor);
+- }
+-
+ out:
+ dev_dbg(dev, "%smatched\n", found ? "" : "not ");
+ return found;
+@@ -721,20 +699,6 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
+ "Freescale Management Complex Firmware version: %u.%u.%u\n",
+ mc_version.major, mc_version.minor, mc_version.revision);
+
+- if (mc_version.major < MC_VER_MAJOR) {
+- dev_err(&pdev->dev,
+- "ERROR: MC firmware version not supported by driver (driver version: %u.%u)\n",
+- MC_VER_MAJOR, MC_VER_MINOR);
+- error = -ENOTSUPP;
+- goto error_cleanup_mc_io;
+- }
+-
+- if (mc_version.major > MC_VER_MAJOR) {
+- dev_warn(&pdev->dev,
+- "WARNING: driver may not support newer MC firmware features (driver version: %u.%u)\n",
+- MC_VER_MAJOR, MC_VER_MINOR);
+- }
+-
+ error = get_mc_addr_translation_ranges(&pdev->dev,
+ &mc->translation_ranges,
+ &mc->num_translation_ranges);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0004-staging-fsl-mc-return-EINVAL-for-all-fsl_mc_portal_a.patch b/patches.arch/arm64-0004-staging-fsl-mc-return-EINVAL-for-all-fsl_mc_portal_a.patch
new file mode 100644
index 0000000000..b09e390311
--- /dev/null
+++ b/patches.arch/arm64-0004-staging-fsl-mc-return-EINVAL-for-all-fsl_mc_portal_a.patch
@@ -0,0 +1,37 @@
+From b0cad6b291d1ee602127736f5d473614698cde95 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Horia=20Geant=C4=83?= <horia.geanta@freescale.com>
+Date: Fri, 11 Dec 2015 15:34:20 +0200
+Subject: [PATCH 4/4] staging: fsl-mc: return -EINVAL for all
+ fsl_mc_portal_allocate() failures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: b0cad6b291d1ee602127736f5d473614698cde95
+References: fate#319900
+
+There are some error paths that allow for a NULL new_mc_io and err = 0
+return code. Return -EINVAL instead.
+
+Signed-off-by: Horia Geantă <horia.geanta@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-allocator.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
+index 4676ba1..7ee71e7 100644
+--- a/drivers/staging/fsl-mc/bus/mc-allocator.c
++++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
+@@ -306,6 +306,7 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
+ if (error < 0)
+ return error;
+
++ error = -EINVAL;
+ dpmcp_dev = resource->data;
+ if (WARN_ON(!dpmcp_dev))
+ goto error_cleanup_resource;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0005-amd-xgbe-Enable-disable-PFC-per-traffic-class.patch b/patches.arch/arm64-0005-amd-xgbe-Enable-disable-PFC-per-traffic-class.patch
new file mode 100644
index 0000000000..6fb2be340f
--- /dev/null
+++ b/patches.arch/arm64-0005-amd-xgbe-Enable-disable-PFC-per-traffic-class.patch
@@ -0,0 +1,74 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:48:48 -0600
+Subject: amd-xgbe: Enable/disable PFC per traffic class
+Git-commit: 8dba2a2a88397dec6bdcae8bf7ceeefd62fd39fc
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+Currently the PFC flow control is enabled on all traffic classes if
+one or more traffic classes request it. The PFC enable setting of the
+traffic class should be used to determine whether to enable or disable
+flow control for the traffic class.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 36 ++++++++++++++++++++++++++++++--
+ 1 file changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index 931e374..6b98a99 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -518,13 +518,45 @@ static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
+
+ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
+ {
++ struct ieee_pfc *pfc = pdata->pfc;
++ struct ieee_ets *ets = pdata->ets;
+ unsigned int max_q_count, q_count;
+ unsigned int reg, reg_val;
+ unsigned int i;
+
+ /* Set MTL flow control */
+- for (i = 0; i < pdata->rx_q_count; i++)
+- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 1);
++ for (i = 0; i < pdata->rx_q_count; i++) {
++ unsigned int ehfc = 0;
++
++ if (pfc && ets) {
++ unsigned int prio;
++
++ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
++ unsigned int tc;
++
++ /* Does this queue handle the priority? */
++ if (pdata->prio2q_map[prio] != i)
++ continue;
++
++ /* Get the Traffic Class for this priority */
++ tc = ets->prio_tc[prio];
++
++ /* Check if flow control should be enabled */
++ if (pfc->pfc_en & (1 << tc)) {
++ ehfc = 1;
++ break;
++ }
++ }
++ } else {
++ ehfc = 1;
++ }
++
++ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, ehfc);
++
++ netif_dbg(pdata, drv, pdata->netdev,
++ "flow control %s for RXq%u\n",
++ ehfc ? "enabled" : "disabled", i);
++ }
+
+ /* Set MAC flow control */
+ max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0005-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch b/patches.arch/arm64-0005-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch
new file mode 100644
index 0000000000..4bed214fdc
--- /dev/null
+++ b/patches.arch/arm64-0005-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch
@@ -0,0 +1,339 @@
+From 89f067df928b9bfc53430b09aa4ac894f34f7340 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:23 -0600
+Subject: [PATCH 05/11] staging: fsl-mc: Extended MC bus allocator to include
+ IRQs
+Patch-mainline: v4.6-rc1
+Git-commit: 89f067df928b9bfc53430b09aa4ac894f34f7340
+References: fate#319900
+
+All the IRQs for DPAA2 objects in the same DPRC must use
+the ICID of that DPRC, as their device Id in the GIC-ITS.
+Thus, all these IRQs must share the same ITT table in the GIC.
+As a result, a pool of IRQs with the same device Id must be
+preallocated per DPRC (fsl-mc bus instance). So, the fsl-mc
+bus object allocator is extended to also provide services
+to allocate IRQs to DPAA2 devices, from their parent fsl-mc bus
+IRQ pool.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-allocator.c | 199 ++++++++++++++++++++++++++++
+ drivers/staging/fsl-mc/include/mc-private.h | 15 +++
+ drivers/staging/fsl-mc/include/mc.h | 9 ++
+ 3 files changed, 223 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c
+index 88d1857..c5fa628 100644
+--- a/drivers/staging/fsl-mc/bus/mc-allocator.c
++++ b/drivers/staging/fsl-mc/bus/mc-allocator.c
+@@ -15,6 +15,7 @@
+ #include "../include/dpcon-cmd.h"
+ #include "dpmcp-cmd.h"
+ #include "dpmcp.h"
++#include <linux/msi.h>
+
+ /**
+ * fsl_mc_resource_pool_add_device - add allocatable device to a resource
+@@ -160,6 +161,7 @@ static const char *const fsl_mc_pool_type_strings[] = {
+ [FSL_MC_POOL_DPMCP] = "dpmcp",
+ [FSL_MC_POOL_DPBP] = "dpbp",
+ [FSL_MC_POOL_DPCON] = "dpcon",
++ [FSL_MC_POOL_IRQ] = "irq",
+ };
+
+ static int __must_check object_type_to_pool_type(const char *object_type,
+@@ -465,6 +467,203 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
+ }
+ EXPORT_SYMBOL_GPL(fsl_mc_object_free);
+
++/*
++ * Initialize the interrupt pool associated with a MC bus.
++ * It allocates a block of IRQs from the GIC-ITS
++ */
++int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
++ unsigned int irq_count)
++{
++ unsigned int i;
++ struct msi_desc *msi_desc;
++ struct fsl_mc_device_irq *irq_resources;
++ struct fsl_mc_device_irq *mc_dev_irq;
++ int error;
++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
++ struct fsl_mc_resource_pool *res_pool =
++ &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
++
++ if (WARN_ON(irq_count == 0 ||
++ irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
++ return -EINVAL;
++
++ error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
++ if (error < 0)
++ return error;
++
++ irq_resources = devm_kzalloc(&mc_bus_dev->dev,
++ sizeof(*irq_resources) * irq_count,
++ GFP_KERNEL);
++ if (!irq_resources) {
++ error = -ENOMEM;
++ goto cleanup_msi_irqs;
++ }
++
++ for (i = 0; i < irq_count; i++) {
++ mc_dev_irq = &irq_resources[i];
++
++ /*
++ * NOTE: This mc_dev_irq's MSI addr/value pair will be set
++ * by the fsl_mc_msi_write_msg() callback
++ */
++ mc_dev_irq->resource.type = res_pool->type;
++ mc_dev_irq->resource.data = mc_dev_irq;
++ mc_dev_irq->resource.parent_pool = res_pool;
++ INIT_LIST_HEAD(&mc_dev_irq->resource.node);
++ list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
++ }
++
++ for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
++ mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
++ mc_dev_irq->msi_desc = msi_desc;
++ mc_dev_irq->resource.id = msi_desc->irq;
++ }
++
++ res_pool->max_count = irq_count;
++ res_pool->free_count = irq_count;
++ mc_bus->irq_resources = irq_resources;
++ return 0;
++
++cleanup_msi_irqs:
++ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
++ return error;
++}
++EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
++
++/**
++ * Teardown the interrupt pool associated with an MC bus.
++ * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
++ */
++void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
++{
++ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
++ struct fsl_mc_resource_pool *res_pool =
++ &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
++
++ if (WARN_ON(!mc_bus->irq_resources))
++ return;
++
++ if (WARN_ON(res_pool->max_count == 0))
++ return;
++
++ if (WARN_ON(res_pool->free_count != res_pool->max_count))
++ return;
++
++ INIT_LIST_HEAD(&res_pool->free_list);
++ res_pool->max_count = 0;
++ res_pool->free_count = 0;
++ mc_bus->irq_resources = NULL;
++ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
++}
++EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
++
++/**
++ * It allocates the IRQs required by a given MC object device. The
++ * IRQs are allocated from the interrupt pool associated with the
++ * MC bus that contains the device, if the device is not a DPRC device.
++ * Otherwise, the IRQs are allocated from the interrupt pool associated
++ * with the MC bus that represents the DPRC device itself.
++ */
++int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
++{
++ int i;
++ int irq_count;
++ int res_allocated_count = 0;
++ int error = -EINVAL;
++ struct fsl_mc_device_irq **irqs = NULL;
++ struct fsl_mc_bus *mc_bus;
++ struct fsl_mc_resource_pool *res_pool;
++
++ if (WARN_ON(mc_dev->irqs))
++ return -EINVAL;
++
++ irq_count = mc_dev->obj_desc.irq_count;
++ if (WARN_ON(irq_count == 0))
++ return -EINVAL;
++
++ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
++ mc_bus = to_fsl_mc_bus(mc_dev);
++ else
++ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
++
++ if (WARN_ON(!mc_bus->irq_resources))
++ return -EINVAL;
++
++ res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
++ if (res_pool->free_count < irq_count) {
++ dev_err(&mc_dev->dev,
++ "Not able to allocate %u irqs for device\n", irq_count);
++ return -ENOSPC;
++ }
++
++ irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
++ GFP_KERNEL);
++ if (!irqs)
++ return -ENOMEM;
++
++ for (i = 0; i < irq_count; i++) {
++ struct fsl_mc_resource *resource;
++
++ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
++ &resource);
++ if (error < 0)
++ goto error_resource_alloc;
++
++ irqs[i] = to_fsl_mc_irq(resource);
++ res_allocated_count++;
++
++ WARN_ON(irqs[i]->mc_dev);
++ irqs[i]->mc_dev = mc_dev;
++ irqs[i]->dev_irq_index = i;
++ }
++
++ mc_dev->irqs = irqs;
++ return 0;
++
++error_resource_alloc:
++ for (i = 0; i < res_allocated_count; i++) {
++ irqs[i]->mc_dev = NULL;
++ fsl_mc_resource_free(&irqs[i]->resource);
++ }
++
++ return error;
++}
++EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
++
++/*
++ * It frees the IRQs that were allocated for a MC object device, by
++ * returning them to the corresponding interrupt pool.
++ */
++void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
++{
++ int i;
++ int irq_count;
++ struct fsl_mc_bus *mc_bus;
++ struct fsl_mc_device_irq **irqs = mc_dev->irqs;
++
++ if (WARN_ON(!irqs))
++ return;
++
++ irq_count = mc_dev->obj_desc.irq_count;
++
++ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
++ mc_bus = to_fsl_mc_bus(mc_dev);
++ else
++ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
++
++ if (WARN_ON(!mc_bus->irq_resources))
++ return;
++
++ for (i = 0; i < irq_count; i++) {
++ WARN_ON(!irqs[i]->mc_dev);
++ irqs[i]->mc_dev = NULL;
++ fsl_mc_resource_free(&irqs[i]->resource);
++ }
++
++ mc_dev->irqs = NULL;
++}
++EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
++
+ /**
+ * fsl_mc_allocator_probe - callback invoked when an allocatable device is
+ * being added to the system
+diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
+index 28c8d32..3babe92 100644
+--- a/drivers/staging/fsl-mc/include/mc-private.h
++++ b/drivers/staging/fsl-mc/include/mc-private.h
+@@ -30,6 +30,16 @@ struct irq_domain;
+ struct msi_domain_info;
+
+ /**
++ * Maximum number of total IRQs that can be pre-allocated for an MC bus'
++ * IRQ pool
++ */
++#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
++
++struct device_node;
++struct irq_domain;
++struct msi_domain_info;
++
++/**
+ * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
+ * @root_mc_bus_dev: MC object device representing the root DPRC
+ * @num_translation_ranges: number of entries in addr_translation_ranges
+@@ -137,4 +147,9 @@ int __init its_fsl_mc_msi_init(void);
+
+ void its_fsl_mc_msi_cleanup(void);
+
++int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
++ unsigned int irq_count);
++
++void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
++
+ #endif /* _FSL_MC_PRIVATE_H_ */
+diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
+index 1c1d6ae..ac7c1ce 100644
+--- a/drivers/staging/fsl-mc/include/mc.h
++++ b/drivers/staging/fsl-mc/include/mc.h
+@@ -14,12 +14,14 @@
+ #include <linux/device.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/list.h>
++#include <linux/interrupt.h>
+ #include "../include/dprc.h"
+
+ #define FSL_MC_VENDOR_FREESCALE 0x1957
+
+ struct fsl_mc_device;
+ struct fsl_mc_io;
++struct fsl_mc_bus;
+
+ /**
+ * struct fsl_mc_driver - MC object device driver object
+@@ -75,6 +77,7 @@ enum fsl_mc_pool_type {
+ FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
+ FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
+ FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
++ FSL_MC_POOL_IRQ,
+
+ /*
+ * NOTE: New resource pool types must be added before this entry
+@@ -141,6 +144,7 @@ struct fsl_mc_device_irq {
+ * NULL if none.
+ * @obj_desc: MC description of the DPAA device
+ * @regions: pointer to array of MMIO region entries
++ * @irqs: pointer to array of pointers to interrupts allocated to this device
+ * @resource: generic resource associated with this MC object device, if any.
+ *
+ * Generic device object for MC object devices that are "attached" to a
+@@ -172,6 +176,7 @@ struct fsl_mc_device {
+ struct fsl_mc_io *mc_io;
+ struct dprc_obj_desc obj_desc;
+ struct resource *regions;
++ struct fsl_mc_device_irq **irqs;
+ struct fsl_mc_resource *resource;
+ };
+
+@@ -215,6 +220,10 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
+
+ void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
+
++int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
++
++void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
++
+ extern struct bus_type fsl_mc_bus_type;
+
+ #endif /* _FSL_MC_H_ */
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0005-staging-fsl-mc-set-up-coherent-dma-ops-for-added-dev.patch b/patches.arch/arm64-0005-staging-fsl-mc-set-up-coherent-dma-ops-for-added-dev.patch
new file mode 100644
index 0000000000..193ecf6649
--- /dev/null
+++ b/patches.arch/arm64-0005-staging-fsl-mc-set-up-coherent-dma-ops-for-added-dev.patch
@@ -0,0 +1,37 @@
+From 663f6fefb9eb226826a9d6ac35f622a581e631a1 Mon Sep 17 00:00:00 2001
+From: Stuart Yoder <stuart.yoder@nxp.com>
+Date: Mon, 7 Mar 2016 09:01:05 -0600
+Subject: [PATCH 05/12] staging: fsl-mc: set up coherent dma ops for added
+ devices
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 663f6fefb9eb226826a9d6ac35f622a581e631a1
+References: fate#319900
+
+Unless discovered devices have the no shareability flag set,
+set up coherent dma ops for them.
+
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 45de8b1..3a55d61 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -468,6 +468,10 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
+ goto error_cleanup_dev;
+ }
+
++ /* Objects are coherent, unless 'no shareability' flag set. */
++ if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY))
++ arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
++
+ /*
+ * The device-specific probe callback will get invoked by device_add()
+ */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0006-amd-xgbe-Fix-the-mapping-of-priorities-to-traffic-cl.patch b/patches.arch/arm64-0006-amd-xgbe-Fix-the-mapping-of-priorities-to-traffic-cl.patch
new file mode 100644
index 0000000000..ff8e59ff0a
--- /dev/null
+++ b/patches.arch/arm64-0006-amd-xgbe-Fix-the-mapping-of-priorities-to-traffic-cl.patch
@@ -0,0 +1,103 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:48:57 -0600
+Subject: amd-xgbe: Fix the mapping of priorities to traffic classes
+Git-commit: 6a49ee4e1b9eb8747ff79c5438a42c0726aaa03b
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+The driver is checking the pfc_en field of the ieee_pfc structure to
+determine whether to associate a priority with a traffic class. This is
+incorrect since the pfc_en field is for determining if PFC is enabled
+for a traffic class.
+
+The association of priority to traffic class does not depend on whether
+the traffic class is enabled for PFC, so remove that check. Also, the
+mapping of priorities to traffic classes should be done when configuring
+the traffic classes and not the PFC support so move the priority to traffic
+class association from xgbe_config_dcb_pfc to xgbe_config_dcb_tc.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 50 ++++++++++++++------------------
+ 1 file changed, 21 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index 6b98a99..67d234e 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -1329,7 +1329,8 @@ static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
+ {
+ struct ieee_ets *ets = pdata->ets;
+ unsigned int total_weight, min_weight, weight;
+- unsigned int i;
++ unsigned int mask, reg, reg_val;
++ unsigned int i, prio;
+
+ if (!ets)
+ return;
+@@ -1346,6 +1347,25 @@ static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
+ min_weight = 1;
+
+ for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
++ /* Map the priorities to the traffic class */
++ mask = 0;
++ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
++ if (ets->prio_tc[prio] == i)
++ mask |= (1 << prio);
++ }
++ mask &= 0xff;
++
++ netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n",
++ i, mask);
++ reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG));
++ reg_val = XGMAC_IOREAD(pdata, reg);
++
++ reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3));
++ reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3));
++
++ XGMAC_IOWRITE(pdata, reg, reg_val);
++
++ /* Set the traffic class algorithm */
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ netif_dbg(pdata, drv, pdata->netdev,
+@@ -1370,34 +1390,6 @@ static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
+
+ static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
+ {
+- struct ieee_pfc *pfc = pdata->pfc;
+- struct ieee_ets *ets = pdata->ets;
+- unsigned int mask, reg, reg_val;
+- unsigned int tc, prio;
+-
+- if (!pfc || !ets)
+- return;
+-
+- for (tc = 0; tc < pdata->hw_feat.tc_cnt; tc++) {
+- mask = 0;
+- for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+- if ((pfc->pfc_en & (1 << prio)) &&
+- (ets->prio_tc[prio] == tc))
+- mask |= (1 << prio);
+- }
+- mask &= 0xff;
+-
+- netif_dbg(pdata, drv, pdata->netdev, "TC%u PFC mask=%#x\n",
+- tc, mask);
+- reg = MTL_TCPM0R + (MTL_TCPM_INC * (tc / MTL_TCPM_TC_PER_REG));
+- reg_val = XGMAC_IOREAD(pdata, reg);
+-
+- reg_val &= ~(0xff << ((tc % MTL_TCPM_TC_PER_REG) << 3));
+- reg_val |= (mask << ((tc % MTL_TCPM_TC_PER_REG) << 3));
+-
+- XGMAC_IOWRITE(pdata, reg, reg_val);
+- }
+-
+ xgbe_config_flow_control(pdata);
+ }
+
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0006-staging-fsl-mc-Changed-DPRC-built-in-portal-s-mc_io-.patch b/patches.arch/arm64-0006-staging-fsl-mc-Changed-DPRC-built-in-portal-s-mc_io-.patch
new file mode 100644
index 0000000000..ac070fbfbe
--- /dev/null
+++ b/patches.arch/arm64-0006-staging-fsl-mc-Changed-DPRC-built-in-portal-s-mc_io-.patch
@@ -0,0 +1,55 @@
+From 1129cde59d08afd91fb2baed66824eb2dbd079aa Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:24 -0600
+Subject: [PATCH 06/11] staging: fsl-mc: Changed DPRC built-in portal's mc_io
+ to be atomic
+Patch-mainline: v4.6-rc1
+Git-commit: 1129cde59d08afd91fb2baed66824eb2dbd079aa
+References: fate#319900
+
+The DPRC built-in portal's mc_io is used to send commands to the MC
+to program MSIs for MC objects. This is done by the
+fsl_mc_msi_write_msg() callback, which is invoked by the generic MSI
+layer with interrupts disabled. As a result, the mc_io used in
+fsl_mc_msi_write_msg needs to be an atomic mc_io.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 4 +++-
+ drivers/staging/fsl-mc/bus/mc-bus.c | 3 ++-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 2c4cd70..767d437 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -396,7 +396,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ error = fsl_create_mc_io(&mc_dev->dev,
+ mc_dev->regions[0].start,
+ region_size,
+- NULL, 0, &mc_dev->mc_io);
++ NULL,
++ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
++ &mc_dev->mc_io);
+ if (error < 0)
+ return error;
+ }
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 84db55b..d34f1af 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -702,7 +702,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
+ mc_portal_phys_addr = res.start;
+ mc_portal_size = resource_size(&res);
+ error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
+- mc_portal_size, NULL, 0, &mc_io);
++ mc_portal_size, NULL,
++ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
+ if (error < 0)
+ return error;
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0006-staging-fsl-mc-set-cacheable-flag-for-added-devices-.patch b/patches.arch/arm64-0006-staging-fsl-mc-set-cacheable-flag-for-added-devices-.patch
new file mode 100644
index 0000000000..b814eeedbf
--- /dev/null
+++ b/patches.arch/arm64-0006-staging-fsl-mc-set-cacheable-flag-for-added-devices-.patch
@@ -0,0 +1,39 @@
+From 08ca497af53b939242da028f2846044709cf8d93 Mon Sep 17 00:00:00 2001
+From: Itai Katz <itai.katz@freescale.com>
+Date: Tue, 1 Dec 2015 09:44:11 +0200
+Subject: [PATCH 06/12] staging: fsl-mc: set cacheable flag for added devices
+ if applicable
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 08ca497af53b939242da028f2846044709cf8d93
+References: fate#319900
+
+Some DPAA2 devices have mmio regions that should be mapped as
+cacheable by drivers. Set IORESOURCE_CACHEABLE in the region's
+flags if applicable.
+
+Signed-off-by: Itai Katz <itai.katz@freescale.com>
+[Stuart: update subject and commit message]
+Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
+
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 3a55d61..dda074d 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -353,6 +353,8 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
+ regions[i].end = regions[i].start + region_desc.size - 1;
+ regions[i].name = "fsl-mc object MMIO region";
+ regions[i].flags = IORESOURCE_IO;
++ if (region_desc.flags & DPRC_REGION_CACHEABLE)
++ regions[i].flags |= IORESOURCE_CACHEABLE;
+ }
+
+ mc_dev->regions = regions;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0007-staging-fsl-mc-Populate-the-IRQ-pool-for-an-MC-bus-i.patch b/patches.arch/arm64-0007-staging-fsl-mc-Populate-the-IRQ-pool-for-an-MC-bus-i.patch
new file mode 100644
index 0000000000..b9d65b3f26
--- /dev/null
+++ b/patches.arch/arm64-0007-staging-fsl-mc-Populate-the-IRQ-pool-for-an-MC-bus-i.patch
@@ -0,0 +1,120 @@
+From 1e4aa42aa9a16d3ec2bbbf7e7d946603b52217de Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:25 -0600
+Subject: [PATCH 07/11] staging: fsl-mc: Populate the IRQ pool for an MC bus
+ instance
+Patch-mainline: v4.6-rc1
+Git-commit: 1e4aa42aa9a16d3ec2bbbf7e7d946603b52217de
+References: fate#319900
+
+Scan the corresponding DPRC container to get total count
+of IRQs needed by all its child DPAA2 objects. Then,
+preallocate a set of MSI IRQs with the DPRC's ICID
+(GIT-ITS device Id) to populate the the DPRC's IRQ pool.
+Each child DPAA2 object in the DPRC and the DPRC object itself
+will allocate their necessary MSI IRQs from the DPRC's IRQ pool,
+in their driver probe function.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 24 ++++++++++++++++++++++--
+ drivers/staging/fsl-mc/include/mc-private.h | 3 ++-
+ 2 files changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 767d437..ef1bb93 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -241,6 +241,7 @@ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
+ * dprc_scan_objects - Discover objects in a DPRC
+ *
+ * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
++ * @total_irq_count: total number of IRQs needed by objects in the DPRC.
+ *
+ * Detects objects added and removed from a DPRC and synchronizes the
+ * state of the Linux bus driver, MC by adding and removing
+@@ -254,11 +255,13 @@ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
+ * populated before they can get allocation requests from probe callbacks
+ * of the device drivers for the non-allocatable devices.
+ */
+-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
++int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
++ unsigned int *total_irq_count)
+ {
+ int num_child_objects;
+ int dprc_get_obj_failures;
+ int error;
++ unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
+ struct dprc_obj_desc *child_obj_desc_array = NULL;
+
+ error = dprc_get_obj_count(mc_bus_dev->mc_io,
+@@ -307,6 +310,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
+ continue;
+ }
+
++ irq_count += obj_desc->irq_count;
+ dev_dbg(&mc_bus_dev->dev,
+ "Discovered object: type %s, id %d\n",
+ obj_desc->type, obj_desc->id);
+@@ -319,6 +323,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
+ }
+ }
+
++ *total_irq_count = irq_count;
+ dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
+ num_child_objects);
+
+@@ -344,6 +349,7 @@ EXPORT_SYMBOL_GPL(dprc_scan_objects);
+ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
+ {
+ int error;
++ unsigned int irq_count;
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+
+ dprc_init_all_resource_pools(mc_bus_dev);
+@@ -352,11 +358,25 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
+ * Discover objects in the DPRC:
+ */
+ mutex_lock(&mc_bus->scan_mutex);
+- error = dprc_scan_objects(mc_bus_dev);
++ error = dprc_scan_objects(mc_bus_dev, &irq_count);
+ mutex_unlock(&mc_bus->scan_mutex);
+ if (error < 0)
+ goto error;
+
++ if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
++ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
++ dev_warn(&mc_bus_dev->dev,
++ "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
++ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
++ }
++
++ error = fsl_mc_populate_irq_pool(
++ mc_bus,
++ FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
++ if (error < 0)
++ goto error;
++ }
++
+ return 0;
+ error:
+ dprc_cleanup_all_resource_pools(mc_bus_dev);
+diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h
+index 3babe92..be72a44 100644
+--- a/drivers/staging/fsl-mc/include/mc-private.h
++++ b/drivers/staging/fsl-mc/include/mc-private.h
+@@ -114,7 +114,8 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
+
+ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev);
+
+-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev);
++int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
++ unsigned int *total_irq_count);
+
+ int __init dprc_driver_init(void);
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0007-staging-fsl-mc-update-dpcon-binary-interface-to-v2.2.patch b/patches.arch/arm64-0007-staging-fsl-mc-update-dpcon-binary-interface-to-v2.2.patch
new file mode 100644
index 0000000000..ee66002da1
--- /dev/null
+++ b/patches.arch/arm64-0007-staging-fsl-mc-update-dpcon-binary-interface-to-v2.2.patch
@@ -0,0 +1,981 @@
+From 8930c369e096386887838a46d0b1d7105c32d307 Mon Sep 17 00:00:00 2001
+From: Ioana Radulescu <ruxandra.radulescu@freescale.com>
+Date: Fri, 3 Jul 2015 19:02:45 +0300
+Subject: [PATCH 07/12] staging: fsl-mc: update dpcon binary interface to v2.2
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 8930c369e096386887838a46d0b1d7105c32d307
+References: fate#319900
+
+-this includes adding the command building/parsing
+ wrapper functions
+
+Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/Makefile | 3 +-
+ drivers/staging/fsl-mc/bus/dpcon.c | 407 +++++++++++++++++++++++++++++
+ drivers/staging/fsl-mc/include/dpcon-cmd.h | 102 +++++++-
+ drivers/staging/fsl-mc/include/dpcon.h | 407 +++++++++++++++++++++++++++++
+ 4 files changed, 917 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/staging/fsl-mc/bus/dpcon.c
+ create mode 100644 drivers/staging/fsl-mc/include/dpcon.h
+
+diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
+index e731517..1a050e1 100644
+--- a/drivers/staging/fsl-mc/bus/Makefile
++++ b/drivers/staging/fsl-mc/bus/Makefile
+@@ -16,4 +16,5 @@ mc-bus-driver-objs := mc-bus.o \
+ mc-msi.o \
+ irq-gic-v3-its-fsl-mc-msi.o \
+ dpmcp.o \
+- dpbp.o
++ dpbp.o \
++ dpcon.o
+diff --git a/drivers/staging/fsl-mc/bus/dpcon.c b/drivers/staging/fsl-mc/bus/dpcon.c
+new file mode 100644
+index 0000000..7965284
+--- /dev/null
++++ b/drivers/staging/fsl-mc/bus/dpcon.c
+@@ -0,0 +1,407 @@
++/* Copyright 2013-2015 Freescale Semiconductor Inc.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * * Neither the name of the above-listed copyright holders nor the
++ * names of any contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++#include "../include/mc-sys.h"
++#include "../include/mc-cmd.h"
++#include "../include/dpcon.h"
++#include "../include/dpcon-cmd.h"
++
++int dpcon_open(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ int dpcon_id,
++ uint16_t *token)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
++ cmd_flags,
++ 0);
++ DPCON_CMD_OPEN(cmd, dpcon_id);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
++
++ return 0;
++}
++EXPORT_SYMBOL(dpcon_open);
++
++int dpcon_close(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++EXPORT_SYMBOL(dpcon_close);
++
++int dpcon_create(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ const struct dpcon_cfg *cfg,
++ uint16_t *token)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CREATE,
++ cmd_flags,
++ 0);
++ DPCON_CMD_CREATE(cmd, cfg);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
++
++ return 0;
++}
++
++int dpcon_destroy(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DESTROY,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++int dpcon_enable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++EXPORT_SYMBOL(dpcon_enable);
++
++int dpcon_disable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++EXPORT_SYMBOL(dpcon_disable);
++
++int dpcon_is_enabled(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ int *en)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ DPCON_RSP_IS_ENABLED(cmd, *en);
++
++ return 0;
++}
++
++int dpcon_reset(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
++ cmd_flags, token);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++int dpcon_set_irq(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ struct dpcon_irq_cfg *irq_cfg)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ,
++ cmd_flags,
++ token);
++ DPCON_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++int dpcon_get_irq(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ int *type,
++ struct dpcon_irq_cfg *irq_cfg)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ,
++ cmd_flags,
++ token);
++ DPCON_CMD_GET_IRQ(cmd, irq_index);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ DPCON_RSP_GET_IRQ(cmd, *type, irq_cfg);
++
++ return 0;
++}
++
++int dpcon_set_irq_enable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint8_t en)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ_ENABLE,
++ cmd_flags,
++ token);
++ DPCON_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++int dpcon_get_irq_enable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint8_t *en)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_ENABLE,
++ cmd_flags,
++ token);
++ DPCON_CMD_GET_IRQ_ENABLE(cmd, irq_index);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ DPCON_RSP_GET_IRQ_ENABLE(cmd, *en);
++
++ return 0;
++}
++
++int dpcon_set_irq_mask(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t mask)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ_MASK,
++ cmd_flags,
++ token);
++ DPCON_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++int dpcon_get_irq_mask(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t *mask)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_MASK,
++ cmd_flags,
++ token);
++ DPCON_CMD_GET_IRQ_MASK(cmd, irq_index);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ DPCON_RSP_GET_IRQ_MASK(cmd, *mask);
++
++ return 0;
++}
++
++int dpcon_get_irq_status(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t *status)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_STATUS,
++ cmd_flags,
++ token);
++ DPCON_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ DPCON_RSP_GET_IRQ_STATUS(cmd, *status);
++
++ return 0;
++}
++
++int dpcon_clear_irq_status(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t status)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLEAR_IRQ_STATUS,
++ cmd_flags,
++ token);
++ DPCON_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++int dpcon_get_attributes(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ struct dpcon_attr *attr)
++{
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
++ cmd_flags,
++ token);
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ /* retrieve response parameters */
++ DPCON_RSP_GET_ATTR(cmd, attr);
++
++ return 0;
++}
++EXPORT_SYMBOL(dpcon_get_attributes);
++
++int dpcon_set_notification(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ struct dpcon_notification_cfg *cfg)
++{
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
++ cmd_flags,
++ token);
++ DPCON_CMD_SET_NOTIFICATION(cmd, cfg);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++EXPORT_SYMBOL(dpcon_set_notification);
++
+diff --git a/drivers/staging/fsl-mc/include/dpcon-cmd.h b/drivers/staging/fsl-mc/include/dpcon-cmd.h
+index 536b2ef..ecb40d0 100644
+--- a/drivers/staging/fsl-mc/include/dpcon-cmd.h
++++ b/drivers/staging/fsl-mc/include/dpcon-cmd.h
+@@ -34,7 +34,7 @@
+
+ /* DPCON Version */
+ #define DPCON_VER_MAJOR 2
+-#define DPCON_VER_MINOR 1
++#define DPCON_VER_MINOR 2
+
+ /* Command IDs */
+ #define DPCON_CMDID_CLOSE 0x800
+@@ -59,4 +59,104 @@
+
+ #define DPCON_CMDID_SET_NOTIFICATION 0x100
+
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_OPEN(cmd, dpcon_id) \
++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_CREATE(cmd, cfg) \
++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_priorities)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_RSP_IS_ENABLED(cmd, en) \
++ MC_RSP_OP(cmd, 0, 0, 1, int, en)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
++do { \
++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\
++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\
++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_GET_IRQ(cmd, irq_index) \
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_RSP_GET_IRQ(cmd, type, irq_cfg) \
++do { \
++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val);\
++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\
++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
++ MC_RSP_OP(cmd, 2, 32, 32, int, type);\
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
++do { \
++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_RSP_GET_IRQ_ENABLE(cmd, en) \
++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
++do { \
++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_GET_IRQ_MASK(cmd, irq_index) \
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_RSP_GET_IRQ_MASK(cmd, mask) \
++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
++do { \
++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_RSP_GET_IRQ_STATUS(cmd, status) \
++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
++do { \
++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_RSP_GET_ATTR(cmd, attr) \
++do { \
++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\
++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_ch_id);\
++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\
++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\
++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\
++} while (0)
++
++/* cmd, param, offset, width, type, arg_name */
++#define DPCON_CMD_SET_NOTIFICATION(cmd, cfg) \
++do { \
++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dpio_id);\
++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->priority);\
++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx);\
++} while (0)
++
+ #endif /* _FSL_DPCON_CMD_H */
+diff --git a/drivers/staging/fsl-mc/include/dpcon.h b/drivers/staging/fsl-mc/include/dpcon.h
+new file mode 100644
+index 0000000..2555be5
+--- /dev/null
++++ b/drivers/staging/fsl-mc/include/dpcon.h
+@@ -0,0 +1,407 @@
++/* Copyright 2013-2015 Freescale Semiconductor Inc.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * * Neither the name of the above-listed copyright holders nor the
++ * names of any contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ *
++ * ALTERNATIVELY, this software may be distributed under the terms of the
++ * GNU General Public License ("GPL") as published by the Free Software
++ * Foundation, either version 2 of that License or (at your option) any
++ * later version.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ */
++#ifndef __FSL_DPCON_H
++#define __FSL_DPCON_H
++
++/* Data Path Concentrator API
++ * Contains initialization APIs and runtime control APIs for DPCON
++ */
++
++struct fsl_mc_io;
++
++/** General DPCON macros */
++
++/**
++ * Use it to disable notifications; see dpcon_set_notification()
++ */
++#define DPCON_INVALID_DPIO_ID (int)(-1)
++
++/**
++ * dpcon_open() - Open a control session for the specified object
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @dpcon_id: DPCON unique ID
++ * @token: Returned token; use in subsequent API calls
++ *
++ * This function can be used to open a control session for an
++ * already created object; an object may have been declared in
++ * the DPL or by calling the dpcon_create() function.
++ * This function returns a unique authentication token,
++ * associated with the specific object ID and the specific MC
++ * portal; this token must be used in all subsequent commands for
++ * this specific object.
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_open(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ int dpcon_id,
++ uint16_t *token);
++
++/**
++ * dpcon_close() - Close the control session of the object
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ *
++ * After this function is called, no further operations are
++ * allowed on the object without opening a new control session.
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_close(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token);
++
++/**
++ * struct dpcon_cfg - Structure representing DPCON configuration
++ * @num_priorities: Number of priorities for the DPCON channel (1-8)
++ */
++struct dpcon_cfg {
++ uint8_t num_priorities;
++};
++
++/**
++ * dpcon_create() - Create the DPCON object.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @cfg: Configuration structure
++ * @token: Returned token; use in subsequent API calls
++ *
++ * Create the DPCON object, allocate required resources and
++ * perform required initialization.
++ *
++ * The object can be created either by declaring it in the
++ * DPL file, or by calling this function.
++ *
++ * This function returns a unique authentication token,
++ * associated with the specific object ID and the specific MC
++ * portal; this token must be used in all subsequent calls to
++ * this specific object. For objects that are created using the
++ * DPL file, call dpcon_open() function to get an authentication
++ * token first.
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_create(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ const struct dpcon_cfg *cfg,
++ uint16_t *token);
++
++/**
++ * dpcon_destroy() - Destroy the DPCON object and release all its resources.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ *
++ * Return: '0' on Success; error code otherwise.
++ */
++int dpcon_destroy(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token);
++
++/**
++ * dpcon_enable() - Enable the DPCON
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ *
++ * Return: '0' on Success; Error code otherwise
++ */
++int dpcon_enable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token);
++
++/**
++ * dpcon_disable() - Disable the DPCON
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ *
++ * Return: '0' on Success; Error code otherwise
++ */
++int dpcon_disable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token);
++
++/**
++ * dpcon_is_enabled() - Check if the DPCON is enabled.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @en: Returns '1' if object is enabled; '0' otherwise
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_is_enabled(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ int *en);
++
++/**
++ * dpcon_reset() - Reset the DPCON, returns the object to initial state.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_reset(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token);
++
++/**
++ * struct dpcon_irq_cfg - IRQ configuration
++ * @addr: Address that must be written to signal a message-based interrupt
++ * @val: Value to write into irq_addr address
++ * @irq_num: A user defined number associated with this IRQ
++ */
++struct dpcon_irq_cfg {
++ uint64_t addr;
++ uint32_t val;
++ int irq_num;
++};
++
++/**
++ * dpcon_set_irq() - Set IRQ information for the DPCON to trigger an interrupt.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: Identifies the interrupt index to configure
++ * @irq_cfg: IRQ configuration
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_set_irq(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ struct dpcon_irq_cfg *irq_cfg);
++
++/**
++ * dpcon_get_irq() - Get IRQ information from the DPCON.
++ *
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @type: Interrupt type: 0 represents message interrupt
++ * type (both irq_addr and irq_val are valid)
++ * @irq_cfg: IRQ attributes
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_get_irq(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ int *type,
++ struct dpcon_irq_cfg *irq_cfg);
++
++/**
++ * dpcon_set_irq_enable() - Set overall interrupt state.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @en: Interrupt state - enable = 1, disable = 0
++ *
++ * Allows GPP software to control when interrupts are generated.
++ * Each interrupt can have up to 32 causes. The enable/disable control's the
++ * overall interrupt state. if the interrupt is disabled no causes will cause
++ * an interrupt.
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_set_irq_enable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint8_t en);
++
++/**
++ * dpcon_get_irq_enable() - Get overall interrupt state.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @en: Returned interrupt state - enable = 1, disable = 0
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_get_irq_enable(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint8_t *en);
++
++/**
++ * dpcon_set_irq_mask() - Set interrupt mask.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @mask: Event mask to trigger interrupt;
++ * each bit:
++ * 0 = ignore event
++ * 1 = consider event for asserting IRQ
++ *
++ * Every interrupt can have up to 32 causes and the interrupt model supports
++ * masking/unmasking each cause independently
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_set_irq_mask(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t mask);
++
++/**
++ * dpcon_get_irq_mask() - Get interrupt mask.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @mask: Returned event mask to trigger interrupt
++ *
++ * Every interrupt can have up to 32 causes and the interrupt model supports
++ * masking/unmasking each cause independently
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_get_irq_mask(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t *mask);
++
++/**
++ * dpcon_get_irq_status() - Get the current status of any pending interrupts.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @status: interrupts status - one bit per cause:
++ * 0 = no interrupt pending
++ * 1 = interrupt pending
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_get_irq_status(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t *status);
++
++/**
++ * dpcon_clear_irq_status() - Clear a pending interrupt's status
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @irq_index: The interrupt index to configure
++ * @status: bits to clear (W1C) - one bit per cause:
++ * 0 = don't change
++ * 1 = clear status bit
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_clear_irq_status(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ uint8_t irq_index,
++ uint32_t status);
++
++/**
++ * struct dpcon_attr - Structure representing DPCON attributes
++ * @id: DPCON object ID
++ * @version: DPCON version
++ * @qbman_ch_id: Channel ID to be used by dequeue operation
++ * @num_priorities: Number of priorities for the DPCON channel (1-8)
++ */
++struct dpcon_attr {
++ int id;
++ /**
++ * struct version - DPCON version
++ * @major: DPCON major version
++ * @minor: DPCON minor version
++ */
++ struct {
++ uint16_t major;
++ uint16_t minor;
++ } version;
++ uint16_t qbman_ch_id;
++ uint8_t num_priorities;
++};
++
++/**
++ * dpcon_get_attributes() - Retrieve DPCON attributes.
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @attr: Object's attributes
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpcon_get_attributes(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ struct dpcon_attr *attr);
++
++/**
++ * struct dpcon_notification_cfg - Structure representing notification parameters
++ * @dpio_id: DPIO object ID; must be configured with a notification channel;
++ * to disable notifications set it to 'DPCON_INVALID_DPIO_ID';
++ * @priority: Priority selection within the DPIO channel; valid values
++ * are 0-7, depending on the number of priorities in that channel
++ * @user_ctx: User context value provided with each CDAN message
++ */
++struct dpcon_notification_cfg {
++ int dpio_id;
++ uint8_t priority;
++ uint64_t user_ctx;
++};
++
++/**
++ * dpcon_set_notification() - Set DPCON notification destination
++ * @mc_io: Pointer to MC portal's I/O object
++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token: Token of DPCON object
++ * @cfg: Notification parameters
++ *
++ * Return: '0' on Success; Error code otherwise
++ */
++int dpcon_set_notification(struct fsl_mc_io *mc_io,
++ uint32_t cmd_flags,
++ uint16_t token,
++ struct dpcon_notification_cfg *cfg);
++
++#endif /* __FSL_DPCON_H */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0008-amd-xgbe-Check-Rx-queue-fifos-before-stopping-Rx-DMA.patch b/patches.arch/arm64-0008-amd-xgbe-Check-Rx-queue-fifos-before-stopping-Rx-DMA.patch
new file mode 100644
index 0000000000..aec4594449
--- /dev/null
+++ b/patches.arch/arm64-0008-amd-xgbe-Check-Rx-queue-fifos-before-stopping-Rx-DMA.patch
@@ -0,0 +1,109 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:49:16 -0600
+Subject: amd-xgbe: Check Rx queue fifos before stopping Rx DMA
+Git-commit: c3727d61ea73a1df60bacd0b416e01282a94240b
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+Check to be sure that the Rx queue fifos are empty before stopping the
+Rx DMA channels.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-common.h | 10 +++++++---
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 30 +++++++++++++++++++++++++++++
+ 2 files changed, 37 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+index b6fa891..bbef959 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+@@ -6,7 +6,7 @@
+ *
+ * License 1: GPLv2
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -56,7 +56,7 @@
+ *
+ * License 2: Modified BSD
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -768,12 +768,16 @@
+ #define MTL_Q_TQDR 0x08
+ #define MTL_Q_RQOMR 0x40
+ #define MTL_Q_RQMPOCR 0x44
+-#define MTL_Q_RQDR 0x4c
++#define MTL_Q_RQDR 0x48
+ #define MTL_Q_RQFCR 0x50
+ #define MTL_Q_IER 0x70
+ #define MTL_Q_ISR 0x74
+
+ /* MTL queue register entry bit positions and sizes */
++#define MTL_Q_RQDR_PRXQ_INDEX 16
++#define MTL_Q_RQDR_PRXQ_WIDTH 14
++#define MTL_Q_RQDR_RXQSTS_INDEX 4
++#define MTL_Q_RQDR_RXQSTS_WIDTH 2
+ #define MTL_Q_RQFCR_RFA_INDEX 1
+ #define MTL_Q_RQFCR_RFA_WIDTH 6
+ #define MTL_Q_RQFCR_RFD_INDEX 17
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index 43273c98..b48c6ec 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -2656,6 +2656,32 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
+ }
+ }
+
++static void xgbe_prepare_rx_stop(struct xgbe_prv_data *pdata,
++ unsigned int queue)
++{
++ unsigned int rx_status;
++ unsigned long rx_timeout;
++
++ /* The Rx engine cannot be stopped if it is actively processing
++ * packets. Wait for the Rx queue to empty the Rx fifo. Don't
++ * wait forever though...
++ */
++ rx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
++ while (time_before(jiffies, rx_timeout)) {
++ rx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_RQDR);
++ if ((XGMAC_GET_BITS(rx_status, MTL_Q_RQDR, PRXQ) == 0) &&
++ (XGMAC_GET_BITS(rx_status, MTL_Q_RQDR, RXQSTS) == 0))
++ break;
++
++ usleep_range(500, 1000);
++ }
++
++ if (!time_before(jiffies, rx_timeout))
++ netdev_info(pdata->netdev,
++ "timed out waiting for Rx queue %u to empty\n",
++ queue);
++}
++
+ static void xgbe_enable_rx(struct xgbe_prv_data *pdata)
+ {
+ struct xgbe_channel *channel;
+@@ -2694,6 +2720,10 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata)
+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0);
+ XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0);
+
++ /* Prepare for Rx DMA channel stop */
++ for (i = 0; i < pdata->rx_q_count; i++)
++ xgbe_prepare_rx_stop(pdata, i);
++
+ /* Disable each Rx queue */
+ XGMAC_IOWRITE(pdata, MAC_RQC0R, 0);
+
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0008-staging-fsl-mc-set-MSI-domain-for-DPRC-objects.patch b/patches.arch/arm64-0008-staging-fsl-mc-set-MSI-domain-for-DPRC-objects.patch
new file mode 100644
index 0000000000..9dfa2c10c7
--- /dev/null
+++ b/patches.arch/arm64-0008-staging-fsl-mc-set-MSI-domain-for-DPRC-objects.patch
@@ -0,0 +1,112 @@
+From 232ae8f2494e3ba445e7f07705f5c3296102bb4c Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:26 -0600
+Subject: [PATCH 08/11] staging: fsl-mc: set MSI domain for DPRC objects
+Patch-mainline: v4.6-rc1
+Git-commit: 232ae8f2494e3ba445e7f07705f5c3296102bb4c
+References: fate#319900
+
+THE MSI domain associated with a root DPRC object is
+obtained form the device tree. Child DPRCs inherit
+the parent DPRC MSI domain.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 39 ++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index ef1bb93..38fc404 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -13,6 +13,7 @@
+ #include "../include/mc-sys.h"
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/interrupt.h>
+ #include "dprc-cmd.h"
+
+ struct dprc_child_objs {
+@@ -398,11 +399,16 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ {
+ int error;
+ size_t region_size;
++ struct device *parent_dev = mc_dev->dev.parent;
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
++ bool msi_domain_set = false;
+
+ if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+ return -EINVAL;
+
++ if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
++ return -EINVAL;
++
+ if (!mc_dev->mc_io) {
+ /*
+ * This is a child DPRC:
+@@ -421,6 +427,30 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ &mc_dev->mc_io);
+ if (error < 0)
+ return error;
++ /*
++ * Inherit parent MSI domain:
++ */
++ dev_set_msi_domain(&mc_dev->dev,
++ dev_get_msi_domain(parent_dev));
++ msi_domain_set = true;
++ } else {
++ /*
++ * This is a root DPRC
++ */
++ struct irq_domain *mc_msi_domain;
++
++ if (WARN_ON(parent_dev->bus == &fsl_mc_bus_type))
++ return -EINVAL;
++
++ error = fsl_mc_find_msi_domain(parent_dev,
++ &mc_msi_domain);
++ if (error < 0) {
++ dev_warn(&mc_dev->dev,
++ "WARNING: MC bus without interrupt support\n");
++ } else {
++ dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
++ msi_domain_set = true;
++ }
+ }
+
+ error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
+@@ -446,6 +476,9 @@ error_cleanup_open:
+ (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
+
+ error_cleanup_mc_io:
++ if (msi_domain_set)
++ dev_set_msi_domain(&mc_dev->dev, NULL);
++
+ fsl_destroy_mc_io(mc_dev->mc_io);
+ return error;
+ }
+@@ -463,6 +496,7 @@ error_cleanup_mc_io:
+ static int dprc_remove(struct fsl_mc_device *mc_dev)
+ {
+ int error;
++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
+
+ if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+ return -EINVAL;
+@@ -475,6 +509,11 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
+ if (error < 0)
+ dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
+
++ if (dev_get_msi_domain(&mc_dev->dev)) {
++ fsl_mc_cleanup_irq_pool(mc_bus);
++ dev_set_msi_domain(&mc_dev->dev, NULL);
++ }
++
+ dev_info(&mc_dev->dev, "DPRC device unbound from driver");
+ return 0;
+ }
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0008-staging-fsl-mc-static-inline-function-to-differentia.patch b/patches.arch/arm64-0008-staging-fsl-mc-static-inline-function-to-differentia.patch
new file mode 100644
index 0000000000..f967b0b2d7
--- /dev/null
+++ b/patches.arch/arm64-0008-staging-fsl-mc-static-inline-function-to-differentia.patch
@@ -0,0 +1,115 @@
+From f5f615afe89424729b1da48deeae2a95a1384759 Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Mon, 8 Feb 2016 17:40:11 -0600
+Subject: [PATCH 08/12] staging: fsl-mc: static inline function to
+ differentiate root dprc
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: f5f615afe89424729b1da48deeae2a95a1384759
+References: fate#319900
+
+Define a static inline function is_root_dprc(dev) to tell whether
+a device is root dprc or not via platform_bus_type.
+Remove fsl_mc_is_root_dprc() because is_root_dprc() is simpler
+and easier to understand.
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 21 +++------------------
+ drivers/staging/fsl-mc/include/mc.h | 14 ++++++++++++++
+ 2 files changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index dda074d..f288f4a 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -24,8 +24,6 @@
+
+ static struct kmem_cache *mc_dev_cache;
+
+-static bool fsl_mc_is_root_dprc(struct device *dev);
+-
+ /**
+ * fsl_mc_bus_match - device to driver matching callback
+ * @dev: the MC object device structure to match against
+@@ -52,7 +50,7 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
+ * Only exception is the root DPRC, which is a special case.
+ */
+ if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 &&
+- !fsl_mc_is_root_dprc(&mc_dev->dev))
++ !is_root_dprc(&mc_dev->dev))
+ goto out;
+
+ /*
+@@ -216,19 +214,6 @@ static void fsl_mc_get_root_dprc(struct device *dev,
+ }
+ }
+
+-/**
+- * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
+- */
+-static bool fsl_mc_is_root_dprc(struct device *dev)
+-{
+- struct device *root_dprc_dev;
+-
+- fsl_mc_get_root_dprc(dev, &root_dprc_dev);
+- if (!root_dprc_dev)
+- return false;
+- return dev == root_dprc_dev;
+-}
+-
+ static int get_dprc_icid(struct fsl_mc_io *mc_io,
+ int container_id, u16 *icid)
+ {
+@@ -528,7 +513,7 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
+ mc_dev->mc_io = NULL;
+ }
+
+- if (fsl_mc_is_root_dprc(&mc_dev->dev)) {
++ if (is_root_dprc(&mc_dev->dev)) {
+ if (atomic_read(&root_dprc_count) > 0)
+ atomic_dec(&root_dprc_count);
+ else
+@@ -746,7 +731,7 @@ static int fsl_mc_bus_remove(struct platform_device *pdev)
+ {
+ struct fsl_mc *mc = platform_get_drvdata(pdev);
+
+- if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
++ if (WARN_ON(!is_root_dprc(&mc->root_mc_bus_dev->dev)))
+ return -EINVAL;
+
+ fsl_mc_device_remove(mc->root_mc_bus_dev);
+diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
+index ac7c1ce..6dffa29 100644
+--- a/drivers/staging/fsl-mc/include/mc.h
++++ b/drivers/staging/fsl-mc/include/mc.h
+@@ -15,6 +15,7 @@
+ #include <linux/mod_devicetable.h>
+ #include <linux/list.h>
+ #include <linux/interrupt.h>
++#include <linux/platform_device.h>
+ #include "../include/dprc.h"
+
+ #define FSL_MC_VENDOR_FREESCALE 0x1957
+@@ -226,4 +227,17 @@ void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
+
+ extern struct bus_type fsl_mc_bus_type;
+
++/**
++ * is_root_dprc - tell whether dev is root dprc or not.
++ * root dprc's parent is a platform device,
++ * that platform device's bus type is platform_bus_type.
++ * @dev: MC object device
++ * return 1 on root dprc, 0 otherwise
++ */
++static inline bool is_root_dprc(struct device *dev)
++{
++ return ((to_fsl_mc_device(dev)->flags & FSL_MC_IS_DPRC) &&
++ ((dev)->bus == &fsl_mc_bus_type) &&
++ ((dev)->parent->bus == &platform_bus_type));
++}
+ #endif /* _FSL_MC_H_ */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0009-amd-xgbe-Mask-auto-negotiation-interrupts-in-ISR.patch b/patches.arch/arm64-0009-amd-xgbe-Mask-auto-negotiation-interrupts-in-ISR.patch
new file mode 100644
index 0000000000..2b38f8c10b
--- /dev/null
+++ b/patches.arch/arm64-0009-amd-xgbe-Mask-auto-negotiation-interrupts-in-ISR.patch
@@ -0,0 +1,251 @@
+From: "Lendacky, Thomas" <Thomas.Lendacky@amd.com>
+Date: Wed, 17 Feb 2016 11:49:28 -0600
+Subject: amd-xgbe: Mask auto-negotiation interrupts in ISR
+Git-commit: ced3fcae693b563b20ee8d2dba966760e6b771d4
+Patch-mainline: v4.6-rc1
+References: fate#320554
+
+Currently the auto-negotiation interrupt handling disables the irq
+instead of masking off the interrupts. This was done because the phy
+library was originally used to read and write the PCS registers, which
+could not be performed in interrupt context. Now that the phy library is
+no longer used to read and write the PCS registers the interrupts can be
+masked off in the interrupt service routine eliminating the need to call
+disable_irq/enable_irq. This also requires changing the protection mutex
+to a spinlock.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 10 +++---
+ drivers/net/ethernet/amd/xgbe/xgbe-main.c | 6 ++--
+ drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 53 +++++++++++++++++--------------
+ drivers/net/ethernet/amd/xgbe/xgbe.h | 5 +--
+ 4 files changed, 41 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index b48c6ec..1babcc1 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -1022,6 +1022,7 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata)
+ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg)
+ {
++ unsigned long flags;
+ unsigned int mmd_address;
+ int mmd_data;
+
+@@ -1039,10 +1040,10 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ * register offsets must therefore be adjusted by left shifting the
+ * offset 2 bits and reading 32 bits of data.
+ */
+- mutex_lock(&pdata->xpcs_mutex);
++ spin_lock_irqsave(&pdata->xpcs_lock, flags);
+ XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
+ mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2);
+- mutex_unlock(&pdata->xpcs_mutex);
++ spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
+
+ return mmd_data;
+ }
+@@ -1051,6 +1052,7 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ int mmd_reg, int mmd_data)
+ {
+ unsigned int mmd_address;
++ unsigned long flags;
+
+ if (mmd_reg & MII_ADDR_C45)
+ mmd_address = mmd_reg & ~MII_ADDR_C45;
+@@ -1066,10 +1068,10 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+ * register offsets must therefore be adjusted by left shifting the
+ * offset 2 bits and reading 32 bits of data.
+ */
+- mutex_lock(&pdata->xpcs_mutex);
++ spin_lock_irqsave(&pdata->xpcs_lock, flags);
+ XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
+ XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
+- mutex_unlock(&pdata->xpcs_mutex);
++ spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
+ }
+
+ static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc)
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+index 618d952..3eee320 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+@@ -6,7 +6,7 @@
+ *
+ * License 1: GPLv2
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -56,7 +56,7 @@
+ *
+ * License 2: Modified BSD
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -363,7 +363,7 @@ static int xgbe_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, netdev);
+
+ spin_lock_init(&pdata->lock);
+- mutex_init(&pdata->xpcs_mutex);
++ spin_lock_init(&pdata->xpcs_lock);
+ mutex_init(&pdata->rss_mutex);
+ spin_lock_init(&pdata->tstamp_lock);
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+index 4460580..84c5d29 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+@@ -6,7 +6,7 @@
+ *
+ * License 1: GPLv2
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -56,7 +56,7 @@
+ *
+ * License 2: Modified BSD
+ *
+- * Copyright (c) 2014 Advanced Micro Devices, Inc.
++ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -626,10 +626,22 @@ static irqreturn_t xgbe_an_isr(int irq, void *data)
+
+ netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
+
+- /* Interrupt reason must be read and cleared outside of IRQ context */
+- disable_irq_nosync(pdata->an_irq);
++ /* Disable AN interrupts */
++ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
++
++ /* Save the interrupt(s) that fired */
++ pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
+
+- queue_work(pdata->an_workqueue, &pdata->an_irq_work);
++ if (pdata->an_int) {
++ /* Clear the interrupt(s) that fired and process them */
++ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
++
++ queue_work(pdata->an_workqueue, &pdata->an_irq_work);
++ } else {
++ /* Enable AN interrupts */
++ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK,
++ XGBE_AN_INT_MASK);
++ }
+
+ return IRQ_HANDLED;
+ }
+@@ -673,34 +685,26 @@ static void xgbe_an_state_machine(struct work_struct *work)
+ struct xgbe_prv_data,
+ an_work);
+ enum xgbe_an cur_state = pdata->an_state;
+- unsigned int int_reg, int_mask;
+
+ mutex_lock(&pdata->an_mutex);
+
+- /* Read the interrupt */
+- int_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
+- if (!int_reg)
++ if (!pdata->an_int)
+ goto out;
+
+ next_int:
+- if (int_reg & XGBE_AN_PG_RCV) {
++ if (pdata->an_int & XGBE_AN_PG_RCV) {
+ pdata->an_state = XGBE_AN_PAGE_RECEIVED;
+- int_mask = XGBE_AN_PG_RCV;
+- } else if (int_reg & XGBE_AN_INC_LINK) {
++ pdata->an_int &= ~XGBE_AN_PG_RCV;
++ } else if (pdata->an_int & XGBE_AN_INC_LINK) {
+ pdata->an_state = XGBE_AN_INCOMPAT_LINK;
+- int_mask = XGBE_AN_INC_LINK;
+- } else if (int_reg & XGBE_AN_INT_CMPLT) {
++ pdata->an_int &= ~XGBE_AN_INC_LINK;
++ } else if (pdata->an_int & XGBE_AN_INT_CMPLT) {
+ pdata->an_state = XGBE_AN_COMPLETE;
+- int_mask = XGBE_AN_INT_CMPLT;
++ pdata->an_int &= ~XGBE_AN_INT_CMPLT;
+ } else {
+ pdata->an_state = XGBE_AN_ERROR;
+- int_mask = 0;
+ }
+
+- /* Clear the interrupt to be processed */
+- int_reg &= ~int_mask;
+- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, int_reg);
+-
+ pdata->an_result = pdata->an_state;
+
+ again:
+@@ -740,14 +744,14 @@ again:
+ }
+
+ if (pdata->an_state == XGBE_AN_NO_LINK) {
+- int_reg = 0;
++ pdata->an_int = 0;
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ } else if (pdata->an_state == XGBE_AN_ERROR) {
+ netdev_err(pdata->netdev,
+ "error during auto-negotiation, state=%u\n",
+ cur_state);
+
+- int_reg = 0;
++ pdata->an_int = 0;
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+ }
+
+@@ -765,11 +769,12 @@ again:
+ if (cur_state != pdata->an_state)
+ goto again;
+
+- if (int_reg)
++ if (pdata->an_int)
+ goto next_int;
+
+ out:
+- enable_irq(pdata->an_irq);
++ /* Enable AN interrupts on the way out */
++ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK);
+
+ mutex_unlock(&pdata->an_mutex);
+ }
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
+index ca28354..98d9d63 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
+@@ -774,8 +774,8 @@ struct xgbe_prv_data {
+ /* Overall device lock */
+ spinlock_t lock;
+
+- /* XPCS indirect addressing mutex */
+- struct mutex xpcs_mutex;
++ /* XPCS indirect addressing lock */
++ spinlock_t xpcs_lock;
+
+ /* RSS addressing mutex */
+ struct mutex rss_mutex;
+@@ -927,6 +927,7 @@ struct xgbe_prv_data {
+ u32 serdes_dfe_tap_ena[XGBE_SPEEDS];
+
+ /* Auto-negotiation state machine support */
++ unsigned int an_int;
+ struct mutex an_mutex;
+ enum xgbe_an an_result;
+ enum xgbe_an an_state;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0009-staging-fsl-mc-Fixed-bug-in-dprc_probe-error-path.patch b/patches.arch/arm64-0009-staging-fsl-mc-Fixed-bug-in-dprc_probe-error-path.patch
new file mode 100644
index 0000000000..deb901566b
--- /dev/null
+++ b/patches.arch/arm64-0009-staging-fsl-mc-Fixed-bug-in-dprc_probe-error-path.patch
@@ -0,0 +1,80 @@
+From 8804f9fc5cf38c29c56f041341685edfc623f427 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:27 -0600
+Subject: [PATCH 09/11] staging: fsl-mc: Fixed bug in dprc_probe() error path
+Patch-mainline: v4.6-rc1
+Git-commit: 8804f9fc5cf38c29c56f041341685edfc623f427
+References: fate#319900
+
+Destroy mc_io in error path in dprc_probe() only if the mc_io was
+created in this function.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 38fc404..42b2494 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -401,6 +401,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ size_t region_size;
+ struct device *parent_dev = mc_dev->dev.parent;
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
++ bool mc_io_created = false;
+ bool msi_domain_set = false;
+
+ if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
+@@ -413,6 +414,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ /*
+ * This is a child DPRC:
+ */
++ if (WARN_ON(parent_dev->bus != &fsl_mc_bus_type))
++ return -EINVAL;
++
+ if (WARN_ON(mc_dev->obj_desc.region_count == 0))
+ return -EINVAL;
+
+@@ -427,6 +431,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ &mc_dev->mc_io);
+ if (error < 0)
+ return error;
++
++ mc_io_created = true;
++
+ /*
+ * Inherit parent MSI domain:
+ */
+@@ -457,7 +464,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ &mc_dev->mc_handle);
+ if (error < 0) {
+ dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
+- goto error_cleanup_mc_io;
++ goto error_cleanup_msi_domain;
+ }
+
+ mutex_init(&mc_bus->scan_mutex);
+@@ -475,11 +482,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ error_cleanup_open:
+ (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
+
+-error_cleanup_mc_io:
++error_cleanup_msi_domain:
+ if (msi_domain_set)
+ dev_set_msi_domain(&mc_dev->dev, NULL);
+
+- fsl_destroy_mc_io(mc_dev->mc_io);
++ if (mc_io_created) {
++ fsl_destroy_mc_io(mc_dev->mc_io);
++ mc_dev->mc_io = NULL;
++ }
++
+ return error;
+ }
+
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0009-staging-fsl-mc-dprc-device-s-sysfs-rescan-documentat.patch b/patches.arch/arm64-0009-staging-fsl-mc-dprc-device-s-sysfs-rescan-documentat.patch
new file mode 100644
index 0000000000..c57c0eef86
--- /dev/null
+++ b/patches.arch/arm64-0009-staging-fsl-mc-dprc-device-s-sysfs-rescan-documentat.patch
@@ -0,0 +1,42 @@
+From 0fbd8684578ee5366484678b9b090d00a2030416 Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Mon, 8 Feb 2016 17:40:13 -0600
+Subject: [PATCH 09/12] staging: fsl-mc: dprc device's sysfs rescan
+ documentation
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 0fbd8684578ee5366484678b9b090d00a2030416
+References: fate#319900
+
+Add the sysfs documentation for the rescan attribute of
+dprc devices.
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ Documentation/ABI/testing/sysfs-devices-dprc | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-devices-dprc
+
+diff --git a/Documentation/ABI/testing/sysfs-devices-dprc b/Documentation/ABI/testing/sysfs-devices-dprc
+new file mode 100644
+index 0000000..3c5d725
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-devices-dprc
+@@ -0,0 +1,13 @@
++What: /sys/devices/.../dprc.X/rescan
++Date: October 2015
++Contact: Lijun Pan <Lijun.Pan@freescale.com>
++Description:
++ Writing a non-zero value to this attribute will
++ force a rescan of dprc.X container in the system, and
++ add/remove previously added/removed objects in
++ Management Complex firmwarer, i.e., synchronize
++ the objects under dprc.X and Management Complex
++ firmware. For example:
++ # echo 1 > /sys/devices/platform/80c000000.fsl-mc/dprc.1/rescan
++
++
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0010-staging-fsl-mc-Added-DPRC-interrupt-handler.patch b/patches.arch/arm64-0010-staging-fsl-mc-Added-DPRC-interrupt-handler.patch
new file mode 100644
index 0000000000..8b71b8ac83
--- /dev/null
+++ b/patches.arch/arm64-0010-staging-fsl-mc-Added-DPRC-interrupt-handler.patch
@@ -0,0 +1,310 @@
+From f52dee5ccdf57364299448c88787ff92656d1ed2 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:28 -0600
+Subject: [PATCH 10/11] staging: fsl-mc: Added DPRC interrupt handler
+Patch-mainline: v4.6-rc1
+Git-commit: f52dee5ccdf57364299448c88787ff92656d1ed2
+References: fate#319900
+
+The interrupt handler for DPRC IRQs is added. DPRC IRQs are
+generated for hot plug events related to DPAA2 objects in a given
+DPRC. These events include, creating/destroying DPAA2 objects in
+the DPRC, changing the "plugged" state of DPAA2 objects and moving
+objects between DPRCs.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/dprc-driver.c | 247 +++++++++++++++++++++++++++++++
+ 1 file changed, 247 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c
+index 42b2494..52c6fce 100644
+--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
++++ b/drivers/staging/fsl-mc/bus/dprc-driver.c
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
++#include <linux/msi.h>
+ #include "dprc-cmd.h"
+
+ struct dprc_child_objs {
+@@ -386,6 +387,230 @@ error:
+ EXPORT_SYMBOL_GPL(dprc_scan_container);
+
+ /**
++ * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
++ *
++ * @irq: IRQ number of the interrupt being handled
++ * @arg: Pointer to device structure
++ */
++static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
++{
++ return IRQ_WAKE_THREAD;
++}
++
++/**
++ * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
++ *
++ * @irq: IRQ number of the interrupt being handled
++ * @arg: Pointer to device structure
++ */
++static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
++{
++ int error;
++ u32 status;
++ struct device *dev = (struct device *)arg;
++ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
++ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
++ struct fsl_mc_io *mc_io = mc_dev->mc_io;
++ struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
++
++ dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
++ irq_num, smp_processor_id());
++
++ if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
++ return IRQ_HANDLED;
++
++ mutex_lock(&mc_bus->scan_mutex);
++ if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
++ goto out;
++
++ error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
++ &status);
++ if (error < 0) {
++ dev_err(dev,
++ "dprc_get_irq_status() failed: %d\n", error);
++ goto out;
++ }
++
++ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
++ status);
++ if (error < 0) {
++ dev_err(dev,
++ "dprc_clear_irq_status() failed: %d\n", error);
++ goto out;
++ }
++
++ if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
++ DPRC_IRQ_EVENT_OBJ_REMOVED |
++ DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
++ DPRC_IRQ_EVENT_OBJ_DESTROYED |
++ DPRC_IRQ_EVENT_OBJ_CREATED)) {
++ unsigned int irq_count;
++
++ error = dprc_scan_objects(mc_dev, &irq_count);
++ if (error < 0) {
++ /*
++ * If the error is -ENXIO, we ignore it, as it indicates
++ * that the object scan was aborted, as we detected that
++ * an object was removed from the DPRC in the MC, while
++ * we were scanning the DPRC.
++ */
++ if (error != -ENXIO) {
++ dev_err(dev, "dprc_scan_objects() failed: %d\n",
++ error);
++ }
++
++ goto out;
++ }
++
++ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
++ dev_warn(dev,
++ "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
++ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
++ }
++ }
++
++out:
++ mutex_unlock(&mc_bus->scan_mutex);
++ return IRQ_HANDLED;
++}
++
++/*
++ * Disable and clear interrupt for a given DPRC object
++ */
++static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
++{
++ int error;
++ struct fsl_mc_io *mc_io = mc_dev->mc_io;
++
++ WARN_ON(mc_dev->obj_desc.irq_count != 1);
++
++ /*
++ * Disable generation of interrupt, while we configure it:
++ */
++ error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
++ if (error < 0) {
++ dev_err(&mc_dev->dev,
++ "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
++ error);
++ return error;
++ }
++
++ /*
++ * Disable all interrupt causes for the interrupt:
++ */
++ error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
++ if (error < 0) {
++ dev_err(&mc_dev->dev,
++ "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
++ error);
++ return error;
++ }
++
++ /*
++ * Clear any leftover interrupts:
++ */
++ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
++ if (error < 0) {
++ dev_err(&mc_dev->dev,
++ "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
++ error);
++ return error;
++ }
++
++ return 0;
++}
++
++static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
++{
++ int error;
++ struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
++
++ WARN_ON(mc_dev->obj_desc.irq_count != 1);
++
++ /*
++ * NOTE: devm_request_threaded_irq() invokes the device-specific
++ * function that programs the MSI physically in the device
++ */
++ error = devm_request_threaded_irq(&mc_dev->dev,
++ irq->msi_desc->irq,
++ dprc_irq0_handler,
++ dprc_irq0_handler_thread,
++ IRQF_NO_SUSPEND | IRQF_ONESHOT,
++ "FSL MC DPRC irq0",
++ &mc_dev->dev);
++ if (error < 0) {
++ dev_err(&mc_dev->dev,
++ "devm_request_threaded_irq() failed: %d\n",
++ error);
++ return error;
++ }
++
++ return 0;
++}
++
++static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
++{
++ int error;
++
++ /*
++ * Enable all interrupt causes for the interrupt:
++ */
++ error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
++ ~0x0u);
++ if (error < 0) {
++ dev_err(&mc_dev->dev,
++ "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
++ error);
++
++ return error;
++ }
++
++ /*
++ * Enable generation of the interrupt:
++ */
++ error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
++ if (error < 0) {
++ dev_err(&mc_dev->dev,
++ "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
++ error);
++
++ return error;
++ }
++
++ return 0;
++}
++
++/*
++ * Setup interrupt for a given DPRC device
++ */
++static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
++{
++ int error;
++
++ error = fsl_mc_allocate_irqs(mc_dev);
++ if (error < 0)
++ return error;
++
++ error = disable_dprc_irq(mc_dev);
++ if (error < 0)
++ goto error_free_irqs;
++
++ error = register_dprc_irq_handler(mc_dev);
++ if (error < 0)
++ goto error_free_irqs;
++
++ error = enable_dprc_irq(mc_dev);
++ if (error < 0)
++ goto error_free_irqs;
++
++ return 0;
++
++error_free_irqs:
++ fsl_mc_free_irqs(mc_dev);
++ return error;
++}
++
++/**
+ * dprc_probe - callback invoked when a DPRC is being bound to this driver
+ *
+ * @mc_dev: Pointer to fsl-mc device representing a DPRC
+@@ -476,6 +701,13 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
+ if (error < 0)
+ goto error_cleanup_open;
+
++ /*
++ * Configure interrupt for the DPRC object associated with this MC bus:
++ */
++ error = dprc_setup_irq(mc_dev);
++ if (error < 0)
++ goto error_cleanup_open;
++
+ dev_info(&mc_dev->dev, "DPRC device bound to driver");
+ return 0;
+
+@@ -494,6 +726,15 @@ error_cleanup_msi_domain:
+ return error;
+ }
+
++/*
++ * Tear down interrupt for a given DPRC object
++ */
++static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
++{
++ (void)disable_dprc_irq(mc_dev);
++ fsl_mc_free_irqs(mc_dev);
++}
++
+ /**
+ * dprc_remove - callback invoked when a DPRC is being unbound from this driver
+ *
+@@ -514,6 +755,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
+ if (WARN_ON(!mc_dev->mc_io))
+ return -EINVAL;
+
++ if (WARN_ON(!mc_bus->irq_resources))
++ return -EINVAL;
++
++ if (dev_get_msi_domain(&mc_dev->dev))
++ dprc_teardown_irq(mc_dev);
++
+ device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
+ dprc_cleanup_all_resource_pools(mc_dev);
+ error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0010-staging-fsl-mc-root-dprc-rescan-attribute-to-sync-ke.patch b/patches.arch/arm64-0010-staging-fsl-mc-root-dprc-rescan-attribute-to-sync-ke.patch
new file mode 100644
index 0000000000..64671e7b9d
--- /dev/null
+++ b/patches.arch/arm64-0010-staging-fsl-mc-root-dprc-rescan-attribute-to-sync-ke.patch
@@ -0,0 +1,84 @@
+From bc8a00bbcef2f6f4f0d08ce3052e9f1767e3492d Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Mon, 8 Feb 2016 17:40:14 -0600
+Subject: [PATCH 10/12] staging: fsl-mc: root dprc rescan attribute to sync
+ kernel with MC
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: bc8a00bbcef2f6f4f0d08ce3052e9f1767e3492d
+References: fate#319900
+
+Introduce the rescan attribute as a device attribute to
+synchronize the fsl-mc bus objects and the MC firmware.
+
+To rescan the root dprc only, e.g.
+echo 1 > /sys/bus/fsl-mc/devices/dprc.1/rescan
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 44 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index f288f4a..00150a0 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -80,10 +80,54 @@ static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+ return 0;
+ }
+
++static ssize_t rescan_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long val;
++ unsigned int irq_count;
++ struct fsl_mc_device *root_mc_dev;
++ struct fsl_mc_bus *root_mc_bus;
++
++ if (!is_root_dprc(dev))
++ return -EINVAL;
++
++ root_mc_dev = to_fsl_mc_device(dev);
++ root_mc_bus = to_fsl_mc_bus(root_mc_dev);
++
++ if (kstrtoul(buf, 0, &val) < 0)
++ return -EINVAL;
++
++ if (val) {
++ mutex_lock(&root_mc_bus->scan_mutex);
++ dprc_scan_objects(root_mc_dev, &irq_count);
++ mutex_unlock(&root_mc_bus->scan_mutex);
++ }
++
++ return count;
++}
++
++static DEVICE_ATTR_WO(rescan);
++
++static struct attribute *fsl_mc_dev_attrs[] = {
++ &dev_attr_rescan.attr,
++ NULL,
++};
++
++static const struct attribute_group fsl_mc_dev_group = {
++ .attrs = fsl_mc_dev_attrs,
++};
++
++static const struct attribute_group *fsl_mc_dev_groups[] = {
++ &fsl_mc_dev_group,
++ NULL,
++};
++
+ struct bus_type fsl_mc_bus_type = {
+ .name = "fsl-mc",
+ .match = fsl_mc_bus_match,
+ .uevent = fsl_mc_bus_uevent,
++ .dev_groups = fsl_mc_dev_groups,
+ };
+ EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
+
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0011-staging-fsl-mc-Added-MSI-support-to-the-MC-bus-drive.patch b/patches.arch/arm64-0011-staging-fsl-mc-Added-MSI-support-to-the-MC-bus-drive.patch
new file mode 100644
index 0000000000..923d5e05f1
--- /dev/null
+++ b/patches.arch/arm64-0011-staging-fsl-mc-Added-MSI-support-to-the-MC-bus-drive.patch
@@ -0,0 +1,67 @@
+From 660a24bf60821ce9f5799b0772a0a82c922c72c1 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Wed, 6 Jan 2016 16:03:29 -0600
+Subject: [PATCH 11/11] staging: fsl-mc: Added MSI support to the MC bus driver
+Patch-mainline: v4.6-rc1
+Git-commit: 660a24bf60821ce9f5799b0772a0a82c922c72c1
+References: fate#319900
+
+Initialize/Cleanup ITS-MSI support for the MC bus driver at driver
+init/exit time. Associate an MSI domain with each DPAA2 child device.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index d34f1af..9317561 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -16,6 +16,8 @@
+ #include <linux/ioport.h>
+ #include <linux/slab.h>
+ #include <linux/limits.h>
++#include <linux/bitops.h>
++#include <linux/msi.h>
+ #include "../include/dpmng.h"
+ #include "../include/mc-sys.h"
+ #include "dprc-cmd.h"
+@@ -472,6 +474,8 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
+ mc_dev->icid = parent_mc_dev->icid;
+ mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
+ mc_dev->dev.dma_mask = &mc_dev->dma_mask;
++ dev_set_msi_domain(&mc_dev->dev,
++ dev_get_msi_domain(&parent_mc_dev->dev));
+ }
+
+ /*
+@@ -833,8 +837,15 @@ static int __init fsl_mc_bus_driver_init(void)
+ if (error < 0)
+ goto error_cleanup_dprc_driver;
+
++ error = its_fsl_mc_msi_init();
++ if (error < 0)
++ goto error_cleanup_mc_allocator;
++
+ return 0;
+
++error_cleanup_mc_allocator:
++ fsl_mc_allocator_driver_exit();
++
+ error_cleanup_dprc_driver:
+ dprc_driver_exit();
+
+@@ -856,6 +867,7 @@ static void __exit fsl_mc_bus_driver_exit(void)
+ if (WARN_ON(!mc_dev_cache))
+ return;
+
++ its_fsl_mc_msi_cleanup();
+ fsl_mc_allocator_driver_exit();
+ dprc_driver_exit();
+ platform_driver_unregister(&fsl_mc_bus_driver);
+--
+2.6.2
+
diff --git a/patches.arch/arm64-0011-staging-fsl-mc-fsl-mc-bus-s-sysfs-rescan-documentati.patch b/patches.arch/arm64-0011-staging-fsl-mc-fsl-mc-bus-s-sysfs-rescan-documentati.patch
new file mode 100644
index 0000000000..661521c478
--- /dev/null
+++ b/patches.arch/arm64-0011-staging-fsl-mc-fsl-mc-bus-s-sysfs-rescan-documentati.patch
@@ -0,0 +1,40 @@
+From 02a9f17fe8af026a370460e9160d36a8fa3a715d Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Mon, 8 Feb 2016 17:40:15 -0600
+Subject: [PATCH 11/12] staging: fsl-mc: fsl-mc bus's sysfs rescan
+ documentation
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 02a9f17fe8af026a370460e9160d36a8fa3a715d
+References: fate#319900
+
+Add the sysfs documentation for the rescan attribute of
+fsl-mc bus.
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ Documentation/ABI/testing/sysfs-bus-fsl-mc | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-fsl-mc
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-fsl-mc b/Documentation/ABI/testing/sysfs-bus-fsl-mc
+new file mode 100644
+index 0000000..3fa747c
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-fsl-mc
+@@ -0,0 +1,11 @@
++What: /sys/bus/fsl-mc/rescan
++Date: October 2015
++Contact: Lijun Pan <Lijun.Pan@freescale.com>
++Description:
++ Writing a non-zero value to this attribute will
++ force a rescan of fsl-mc bus in the system, and
++ add/remove previously added/removed objects in
++ Management Complex firmwarer, i.e., synchronize
++ the objects under fsl-mc bus and Management Complex
++ firmware. For example:
++ # echo 1 > /sys/bus/fsl-mc/rescan
+--
+2.6.6
+
diff --git a/patches.arch/arm64-0012-staging-fsl-mc-bus-rescan-attribute-to-sync-kernel-w.patch b/patches.arch/arm64-0012-staging-fsl-mc-bus-rescan-attribute-to-sync-kernel-w.patch
new file mode 100644
index 0000000000..5a9caa7b52
--- /dev/null
+++ b/patches.arch/arm64-0012-staging-fsl-mc-bus-rescan-attribute-to-sync-kernel-w.patch
@@ -0,0 +1,88 @@
+From 59a6830a0788110395f57a73f9784e296f3fcf73 Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Mon, 8 Feb 2016 17:40:16 -0600
+Subject: [PATCH 12/12] staging: fsl-mc: bus rescan attribute to sync kernel
+ with MC
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: https://github.com/qoriq-open-source/linux.git nxp/linux-v4.5
+Git-commit: 59a6830a0788110395f57a73f9784e296f3fcf73
+References: fate#319900
+
+Introduce the rescan attribute as a bus attribute to
+synchronize the fsl-mc bus objects and the MC firmware.
+
+To rescan the fsl-mc bus, e.g.,
+echo 1 > /sys/bus/fsl-mc/rescan
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/staging/fsl-mc/bus/mc-bus.c | 47 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c
+index 00150a0..e9ce8ce 100644
+--- a/drivers/staging/fsl-mc/bus/mc-bus.c
++++ b/drivers/staging/fsl-mc/bus/mc-bus.c
+@@ -123,11 +123,58 @@ static const struct attribute_group *fsl_mc_dev_groups[] = {
+ NULL,
+ };
+
++static int scan_fsl_mc_bus(struct device *dev, void *data)
++{
++ unsigned int irq_count;
++ struct fsl_mc_device *root_mc_dev;
++ struct fsl_mc_bus *root_mc_bus;
++
++ if (is_root_dprc(dev)) {
++ root_mc_dev = to_fsl_mc_device(dev);
++ root_mc_bus = to_fsl_mc_bus(root_mc_dev);
++ mutex_lock(&root_mc_bus->scan_mutex);
++ dprc_scan_objects(root_mc_dev, &irq_count);
++ mutex_unlock(&root_mc_bus->scan_mutex);
++ }
++
++ return 0;
++}
++
++static ssize_t bus_rescan_store(struct bus_type *bus,
++ const char *buf, size_t count)
++{
++ unsigned long val;
++
++ if (kstrtoul(buf, 0, &val) < 0)
++ return -EINVAL;
++
++ if (val)
++ bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus);
++
++ return count;
++}
++static BUS_ATTR(rescan, (S_IWUSR | S_IWGRP), NULL, bus_rescan_store);
++
++static struct attribute *fsl_mc_bus_attrs[] = {
++ &bus_attr_rescan.attr,
++ NULL,
++};
++
++static const struct attribute_group fsl_mc_bus_group = {
++ .attrs = fsl_mc_bus_attrs,
++};
++
++static const struct attribute_group *fsl_mc_bus_groups[] = {
++ &fsl_mc_bus_group,
++ NULL,
++};
++
+ struct bus_type fsl_mc_bus_type = {
+ .name = "fsl-mc",
+ .match = fsl_mc_bus_match,
+ .uevent = fsl_mc_bus_uevent,
+ .dev_groups = fsl_mc_dev_groups,
++ .bus_groups = fsl_mc_bus_groups,
+ };
+ EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
+
+--
+2.6.6
+
diff --git a/patches.arch/arm64-1-2-ARM-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-008585.patch b/patches.arch/arm64-1-2-ARM-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-008585.patch
new file mode 100644
index 0000000000..5fd46483f4
--- /dev/null
+++ b/patches.arch/arm64-1-2-ARM-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-008585.patch
@@ -0,0 +1,381 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [RFC,1/2] ARM/ARM64: arch_timer: Work around QorIQ Erratum A-008585
+From: Scott Wood <oss@buserror.net>
+X-Patchwork-Id: 8796041
+Message-Id: <1460341353-15619-2-git-send-email-oss@buserror.net>
+To: Shawn Guo <shawnguo@kernel.org>, Russell King <linux@arm.linux.org.uk>,
+ Catalin Marinas <catalin.marinas@arm.com>,
+ Will Deacon <will.deacon@arm.com>
+Cc: Scott Wood <oss@buserror.net>, mbrugger@suse.com, stuart.yoder@nxp.com,
+ linux-arm-kernel@lists.infradead.org
+Date: Sun, 10 Apr 2016 21:22:32 -0500
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8796041
+
+Erratum A-008585 says that the ARM generic timer "has the potential to
+contain an erroneous value for a small number of core clock cycles
+every time the timer value changes" and that the workaround is to
+reread TVAL and count registers until successive reads return the same
+value.
+
+This erratum can be found on LS1021A (32-bit), LS1043A (64-bit), and
+LS2080A (64-bit).
+
+This patch is loosely based on work by Priyanka Jain and Bhupesh
+Sharma.
+
+Signed-off-by: Scott Wood <oss@buserror.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+.../devicetree/bindings/arm/arch_timer.txt | 4 ++
+ Documentation/devicetree/bindings/arm/arch_timer.txt | 4 +
+ arch/arm/boot/dts/ls1021a.dtsi | 1
+ arch/arm/include/asm/arch_timer.h | 71 ++++++++++++++++---
+ arch/arm/include/asm/vdso_datapage.h | 1
+ arch/arm/kernel/vdso.c | 1
+ arch/arm/vdso/vgettimeofday.c | 2
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 1
+ arch/arm64/include/asm/arch_timer.h | 35 +++++++--
+ arch/arm64/include/asm/vdso_datapage.h | 1
+ arch/arm64/kernel/asm-offsets.c | 1
+ arch/arm64/kernel/vdso.c | 2
+ arch/arm64/kernel/vdso/gettimeofday.S | 14 +++
+ drivers/clocksource/arm_arch_timer.c | 5 +
+ 13 files changed, 120 insertions(+), 19 deletions(-)
+
+--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
++++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
+@@ -25,6 +25,10 @@ to deliver its interrupts via SPIs.
+ - always-on : a boolean property. If present, the timer is powered through an
+ always-on power domain, therefore it never loses context.
+
++- fsl,erratum-a008585 : A boolean property. Indicates the presence of
++ QorIQ erratum A-008585, which says reading the timer is unreliable
++ unless the same value is returned by back-to-back reads.
++
+ ** Optional properties:
+
+ - arm,cpu-registers-not-fw-configured : Firmware does not initialize
+--- a/arch/arm/boot/dts/ls1021a.dtsi
++++ b/arch/arm/boot/dts/ls1021a.dtsi
+@@ -91,6 +91,7 @@
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
++ fsl,erratum-a008585;
+ };
+
+ pmu {
+--- a/arch/arm/include/asm/arch_timer.h
++++ b/arch/arm/include/asm/arch_timer.h
+@@ -12,6 +12,8 @@
+ #ifdef CONFIG_ARM_ARCH_TIMER
+ int arch_timer_arch_init(void);
+
++extern bool arm_arch_timer_reread;
++
+ /*
+ * These register accessors are marked inline so the compiler can
+ * nicely work out which register we want, and chuck away the rest of
+@@ -44,7 +46,7 @@ void arch_timer_reg_write_cp15(int acces
+ }
+
+ static __always_inline
+-u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
++u32 arch_timer_reg_read_cp15_raw(int access, enum arch_timer_reg reg)
+ {
+ u32 val = 0;
+
+@@ -71,6 +73,38 @@ u32 arch_timer_reg_read_cp15(int access,
+ return val;
+ }
+
++static __always_inline
++u32 arch_timer_reg_tval_reread(int access, enum arch_timer_reg reg)
++{
++ u32 val, val_new;
++ int timeout = 200;
++
++ do {
++ if (access == ARCH_TIMER_PHYS_ACCESS) {
++ asm volatile("mrc p15, 0, %0, c14, c2, 0;"
++ "mrc p15, 0, %1, c14, c2, 0"
++ : "=r" (val), "=r" (val_new));
++ } else if (access == ARCH_TIMER_VIRT_ACCESS) {
++ asm volatile("mrc p15, 0, %0, c14, c3, 0;"
++ "mrc p15, 0, %1, c14, c3, 0"
++ : "=r" (val), "=r" (val_new));
++ }
++ timeout--;
++ } while (val != val_new && timeout);
++
++ WARN_ON_ONCE(!timeout);
++ return val;
++}
++
++static __always_inline
++u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
++{
++ if (arm_arch_timer_reread && reg == ARCH_TIMER_REG_TVAL)
++ return arch_timer_reg_tval_reread(access, reg);
++
++ return arch_timer_reg_read_cp15_raw(access, reg);
++}
++
+ static inline u32 arch_timer_get_cntfrq(void)
+ {
+ u32 val;
+@@ -78,22 +112,39 @@ static inline u32 arch_timer_get_cntfrq(
+ return val;
+ }
+
+-static inline u64 arch_counter_get_cntpct(void)
++static __always_inline u64 arch_counter_get_cnt(int opcode, bool reread)
+ {
+- u64 cval;
++ u64 val, val_new;
++ int timeout = 200;
+
+ isb();
+- asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
+- return cval;
++
++ if (reread) {
++ do {
++ asm volatile("mrrc p15, %2, %Q0, %R0, c14;"
++ "mrrc p15, %2, %Q1, %R1, c14"
++ : "=r" (val), "=r" (val_new)
++ : "i" (opcode));
++ timeout--;
++ } while (val != val_new && timeout);
++
++ BUG_ON(!timeout);
++ } else {
++ asm volatile("mrrc p15, %1, %Q0, %R0, c14" : "=r" (val)
++ : "i" (opcode));
++ }
++
++ return val;
+ }
+
+-static inline u64 arch_counter_get_cntvct(void)
++static inline u64 arch_counter_get_cntpct(void)
+ {
+- u64 cval;
++ return arch_counter_get_cnt(0, arm_arch_timer_reread);
++}
+
+- isb();
+- asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
+- return cval;
++static inline u64 arch_counter_get_cntvct(void)
++{
++ return arch_counter_get_cnt(1, arm_arch_timer_reread);
+ }
+
+ static inline u32 arch_timer_get_cntkctl(void)
+--- a/arch/arm/include/asm/vdso_datapage.h
++++ b/arch/arm/include/asm/vdso_datapage.h
+@@ -46,6 +46,7 @@ struct vdso_data {
+ u64 xtime_clock_snsec; /* CLOCK_REALTIME sub-ns base */
+ u32 tz_minuteswest; /* timezone info for gettimeofday(2) */
+ u32 tz_dsttime;
++ u32 timer_reread; /* Erratum requires two equal timer reads */
+ };
+
+ union vdso_data_store {
+--- a/arch/arm/kernel/vdso.c
++++ b/arch/arm/kernel/vdso.c
+@@ -307,6 +307,7 @@ void update_vsyscall(struct timekeeper *
+
+ vdso_write_begin(vdso_data);
+
++ vdso_data->timer_reread = arm_arch_timer_reread;
+ vdso_data->tk_is_cntvct = tk_is_cntvct(tk);
+ vdso_data->xtime_coarse_sec = tk->xtime_sec;
+ vdso_data->xtime_coarse_nsec = (u32)(tk->tkr_mono.xtime_nsec >>
+--- a/arch/arm/vdso/vgettimeofday.c
++++ b/arch/arm/vdso/vgettimeofday.c
+@@ -123,7 +123,7 @@ static notrace u64 get_ns(struct vdso_da
+ u64 cycle_now;
+ u64 nsec;
+
+- cycle_now = arch_counter_get_cntvct();
++ cycle_now = arch_counter_get_cnt(1, vdata->timer_reread);
+
+ cycle_delta = (cycle_now - vdata->cs_cycle_last) & vdata->cs_mask;
+
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -159,6 +159,7 @@
+ <1 14 0x8>, /* Physical Non-Secure PPI, active-low */
+ <1 11 0x8>, /* Virtual PPI, active-low */
+ <1 10 0x8>; /* Hypervisor PPI, active-low */
++ fsl,erratum-a008585;
+ };
+
+ pmu {
+--- a/arch/arm64/include/asm/arch_timer.h
++++ b/arch/arm64/include/asm/arch_timer.h
+@@ -27,6 +27,31 @@
+
+ #include <clocksource/arm_arch_timer.h>
+
++extern bool arm_arch_timer_reread;
++
++/* QorIQ errata workarounds */
++#define ARCH_TIMER_REREAD(reg) ({ \
++ u64 _val_old, _val_new; \
++ int _timeout = 200; \
++ do { \
++ asm volatile("mrs %0, " reg ";" \
++ "mrs %1, " reg \
++ : "=r" (_val_old), "=r" (_val_new)); \
++ _timeout--; \
++ } while (_val_old != _val_new && _timeout); \
++ WARN_ON_ONCE(!_timeout); \
++ _val_old; \
++})
++
++#define ARCH_TIMER_READ(reg) ({ \
++ u64 _val; \
++ if (arm_arch_timer_reread) \
++ _val = ARCH_TIMER_REREAD(reg); \
++ else \
++ asm volatile("mrs %0, " reg : "=r" (_val)); \
++ _val; \
++})
++
+ /*
+ * These register accessors are marked inline so the compiler can
+ * nicely work out which register we want, and chuck away the rest of
+@@ -69,7 +94,7 @@ u32 arch_timer_reg_read_cp15(int access,
+ asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+- asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
++ val = ARCH_TIMER_READ("cntp_tval_el0");
+ break;
+ }
+ } else if (access == ARCH_TIMER_VIRT_ACCESS) {
+@@ -78,7 +103,7 @@ u32 arch_timer_reg_read_cp15(int access,
+ asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+- asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
++ val = ARCH_TIMER_READ("cntv_tval_el0");
+ break;
+ }
+ }
+@@ -116,12 +141,8 @@ static inline u64 arch_counter_get_cntpc
+
+ static inline u64 arch_counter_get_cntvct(void)
+ {
+- u64 cval;
+-
+ isb();
+- asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
+-
+- return cval;
++ return ARCH_TIMER_READ("cntvct_el0");
+ }
+
+ static inline int arch_timer_arch_init(void)
+--- a/arch/arm64/include/asm/vdso_datapage.h
++++ b/arch/arm64/include/asm/vdso_datapage.h
+@@ -34,6 +34,7 @@ struct vdso_data {
+ __u32 tz_minuteswest; /* Whacky timezone stuff */
+ __u32 tz_dsttime;
+ __u32 use_syscall;
++ __u32 timer_reread; /* Erratum requires two equal timer reads */
+ };
+
+ #endif /* !__ASSEMBLY__ */
+--- a/arch/arm64/kernel/asm-offsets.c
++++ b/arch/arm64/kernel/asm-offsets.c
+@@ -94,6 +94,7 @@ int main(void)
+ DEFINE(VDSO_TZ_MINWEST, offsetof(struct vdso_data, tz_minuteswest));
+ DEFINE(VDSO_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime));
+ DEFINE(VDSO_USE_SYSCALL, offsetof(struct vdso_data, use_syscall));
++ DEFINE(VDSO_TIMER_REREAD, offsetof(struct vdso_data, timer_reread));
+ BLANK();
+ DEFINE(TVAL_TV_SEC, offsetof(struct timeval, tv_sec));
+ DEFINE(TVAL_TV_USEC, offsetof(struct timeval, tv_usec));
+--- a/arch/arm64/kernel/vdso.c
++++ b/arch/arm64/kernel/vdso.c
+@@ -31,6 +31,7 @@
+ #include <linux/timekeeper_internal.h>
+ #include <linux/vmalloc.h>
+
++#include <asm/arch_timer.h>
+ #include <asm/cacheflush.h>
+ #include <asm/signal32.h>
+ #include <asm/vdso.h>
+@@ -204,6 +205,7 @@ void update_vsyscall(struct timekeeper *
+ ++vdso_data->tb_seq_count;
+ smp_wmb();
+
++ vdso_data->timer_reread = arm_arch_timer_reread;
+ vdso_data->use_syscall = use_syscall;
+ vdso_data->xtime_coarse_sec = tk->xtime_sec;
+ vdso_data->xtime_coarse_nsec = tk->tkr_mono.xtime_nsec >>
+--- a/arch/arm64/kernel/vdso/gettimeofday.S
++++ b/arch/arm64/kernel/vdso/gettimeofday.S
+@@ -207,7 +207,7 @@ ENDPROC(__kernel_clock_getres)
+ /*
+ * Read the current time from the architected counter.
+ * Expects vdso_data to be initialised.
+- * Clobbers the temporary registers (x9 - x15).
++ * Clobbers the temporary registers (x9 - x17).
+ * Returns:
+ * - w9 = vDSO sequence counter
+ * - (x10, x11) = (ts->tv_sec, shifted ts->tv_nsec)
+@@ -217,6 +217,7 @@ ENTRY(__do_get_tspec)
+ .cfi_startproc
+
+ /* Read from the vDSO data page. */
++ ldr w17, [vdso_data, #VDSO_TIMER_REREAD]
+ ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+ ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+ ldp w11, w12, [vdso_data, #VDSO_CS_MULT]
+@@ -225,6 +226,17 @@ ENTRY(__do_get_tspec)
+ /* Read the virtual counter. */
+ isb
+ mrs x15, cntvct_el0
++ /*
++ * Erratum A-008585 requires back-to-back reads to be identical
++ * in order to avoid glitches.
++ */
++ cmp w17, #0
++ b.eq 2f
++1: mrs x15, cntvct_el0
++ mrs x16, cntvct_el0
++ cmp x16, x15
++ b.ne 1b
++2:
+
+ /* Calculate cycle delta and convert to ns. */
+ sub x10, x15, x10
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -71,6 +71,9 @@ static bool arch_timer_use_virtual = tru
+ static bool arch_timer_c3stop;
+ static bool arch_timer_mem_use_virtual;
+
++bool arm_arch_timer_reread; /* QorIQ erratum A-008585 */
++EXPORT_SYMBOL(arm_arch_timer_reread);
++
+ /*
+ * Architected system timer support.
+ */
+@@ -728,6 +731,8 @@ static void __init arch_timer_of_init(st
+ arch_timer_detect_rate(NULL, np);
+
+ arch_timer_c3stop = !of_property_read_bool(np, "always-on");
++ arm_arch_timer_reread =
++ of_property_read_bool(np, "fsl,erratum-a008585");
+
+ /*
+ * If we cannot rely on firmware initializing the timer registers then
diff --git a/patches.arch/arm64-1-4-MAINTAINERS-Add-entry-for-APM-X-Gene-SoC-PMU-driver.patch b/patches.arch/arm64-1-4-MAINTAINERS-Add-entry-for-APM-X-Gene-SoC-PMU-driver.patch
new file mode 100644
index 0000000000..d0b754fc78
--- /dev/null
+++ b/patches.arch/arm64-1-4-MAINTAINERS-Add-entry-for-APM-X-Gene-SoC-PMU-driver.patch
@@ -0,0 +1,42 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,1/4] MAINTAINERS: Add entry for APM X-Gene SoC PMU driver
+From: Tai Nguyen <ttnguyen@apm.com>
+X-Patchwork-Id: 8817871
+Message-Id: <1460510547-17611-2-git-send-email-ttnguyen@apm.com>
+To: mark.rutland@arm.com,
+ will.deacon@arm.com,
+ catalin.marinas@arm.com
+Cc: devicetree@vger.kernel.org, patches@apm.com, linux-kernel@vger.kernel.org,
+ linux-arm-kernel@lists.infradead.org, Tai Nguyen <ttnguyen@apm.com>
+Date: Tue, 12 Apr 2016 18:22:24 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8817871
+
+MAINTAINERS: Add entry for APM X-Gene SoC PMU driver
+
+Signed-off-by: Tai Nguyen <ttnguyen@apm.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+MAINTAINERS | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 4978dc1..e2da90c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -8593,6 +8593,13 @@ L: linux-scsi@vger.kernel.org
+ S: Supported
+ F: drivers/scsi/pm8001/
+
++PMU-XGENE
++APPLIED MICRO (APM) X-GENE SOC PMU
++M: Tai Nguyen <ttnguyen@apm.com>
++S: Supported
++F: drivers/perf/xgene_pmu.c
++F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
++
+ POSIX CLOCKS and TIMERS
+ M: Thomas Gleixner <tglx@linutronix.de>
+ L: linux-kernel@vger.kernel.org
diff --git a/patches.arch/arm64-1-6-Documentation-arm64-pmu-Add-Broadcom-Vulcan-PMU-binding.patch b/patches.arch/arm64-1-6-Documentation-arm64-pmu-Add-Broadcom-Vulcan-PMU-binding.patch
new file mode 100644
index 0000000000..65820a16aa
--- /dev/null
+++ b/patches.arch/arm64-1-6-Documentation-arm64-pmu-Add-Broadcom-Vulcan-PMU-binding.patch
@@ -0,0 +1,43 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,1/6] Documentation: arm64: pmu: Add Broadcom Vulcan PMU binding
+From: Ashok Kumar <ashoks@broadcom.com>
+X-Patchwork-Id: 8800891
+Message-Id: <1460379741-1181-2-git-send-email-ashoks@broadcom.com>
+To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+ mark.rutland@arm.com, will.deacon@arm.com, Suzuki.Poulose@arm.com,
+ robh+dt@kernel.org, catalin.marinas@arm.com
+Cc: jchandra@broadcom.com, Ashok Kumar <ashoks@broadcom.com>,
+ jglauber@cavium.com
+Date: Mon, 11 Apr 2016 06:02:16 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8800891
+
+Document the compatible string for Broadcom Vulcan PMU.
+Also arranged the list in alphabetical order.
+
+Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+Documentation/devicetree/bindings/arm/pmu.txt | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
+index 6eb73be..74d5417 100644
+--- a/Documentation/devicetree/bindings/arm/pmu.txt
++++ b/Documentation/devicetree/bindings/arm/pmu.txt
+@@ -22,10 +22,11 @@ Required properties:
+ "arm,arm11mpcore-pmu"
+ "arm,arm1176-pmu"
+ "arm,arm1136-pmu"
++ "brcm,vulcan-pmu"
++ "cavium,thunder-pmu"
+ "qcom,scorpion-pmu"
+ "qcom,scorpion-mp-pmu"
+ "qcom,krait-pmu"
+- "cavium,thunder-pmu"
+ - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a per-cpu
+ interrupt (PPI) then 1 interrupt should be specified.
+
diff --git a/patches.arch/arm64-2-2-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-009971.patch b/patches.arch/arm64-2-2-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-009971.patch
new file mode 100644
index 0000000000..f0259fe0e8
--- /dev/null
+++ b/patches.arch/arm64-2-2-ARM64-arch_timer-Work-around-QorIQ-Erratum-A-009971.patch
@@ -0,0 +1,139 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [RFC,2/2] ARM64: arch_timer: Work around QorIQ Erratum A-009971
+From: Scott Wood <oss@buserror.net>
+X-Patchwork-Id: 8796031
+Message-Id: <1460341353-15619-3-git-send-email-oss@buserror.net>
+To: Shawn Guo <shawnguo@kernel.org>, Russell King <linux@arm.linux.org.uk>,
+ Catalin Marinas <catalin.marinas@arm.com>,
+ Will Deacon <will.deacon@arm.com>
+Cc: Scott Wood <oss@buserror.net>, Priyanka Jain <priyanka.jain@nxp.com>,
+ mbrugger@suse.com, stuart.yoder@nxp.com,
+ linux-arm-kernel@lists.infradead.org
+Date: Sun, 10 Apr 2016 21:22:33 -0500
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8796031
+
+From: Priyanka Jain <priyanka.jain@nxp.com>
+
+Erratum A-009971 says that it is possible for the timer value register
+to be written incorrectly, resulting in "an incorrect and potentially
+very long timeout". The workaround is to read the timer count
+immediately before and after writing the timer value register, and
+repeat if the counter reads don't match.
+
+This erratum can be found on LS2080A.
+
+Signed-off-by: Priyanka Jain <priyanka.jain@nxp.com>
+[scottwood: cleanup and fixes]
+Signed-off-by: Scott Wood <oss@buserror.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+.../devicetree/bindings/arm/arch_timer.txt | 5 ++++
+ Documentation/devicetree/bindings/arm/arch_timer.txt | 5 +++
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 1
+ arch/arm64/include/asm/arch_timer.h | 27 +++++++++++++++++--
+ drivers/clocksource/arm_arch_timer.c | 3 ++
+ 4 files changed, 34 insertions(+), 2 deletions(-)
+
+--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
++++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
+@@ -29,6 +29,11 @@ to deliver its interrupts via SPIs.
+ QorIQ erratum A-008585, which says reading the timer is unreliable
+ unless the same value is returned by back-to-back reads.
+
++- fsl,erratum-a009971 : A boolean property. Indicates the presence of
++ QorIQ erratum A-009971, which says writing the timer value register
++ is unreliable unless timer count reads before and after the timer write
++ return the same value.
++
+ ** Optional properties:
+
+ - arm,cpu-registers-not-fw-configured : Firmware does not initialize
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -160,6 +160,7 @@
+ <1 11 0x8>, /* Virtual PPI, active-low */
+ <1 10 0x8>; /* Hypervisor PPI, active-low */
+ fsl,erratum-a008585;
++ fsl,erratum-a009971;
+ };
+
+ pmu {
+--- a/arch/arm64/include/asm/arch_timer.h
++++ b/arch/arm64/include/asm/arch_timer.h
+@@ -28,6 +28,7 @@
+ #include <clocksource/arm_arch_timer.h>
+
+ extern bool arm_arch_timer_reread;
++extern bool arm_arch_timer_rewrite;
+
+ /* QorIQ errata workarounds */
+ #define ARCH_TIMER_REREAD(reg) ({ \
+@@ -52,6 +53,20 @@ extern bool arm_arch_timer_reread;
+ _val; \
+ })
+
++#define ARCH_TIMER_TVAL_REWRITE(pv, val) do { \
++ u64 _cnt_old, _cnt_new; \
++ int _timeout = 200; \
++ do { \
++ asm volatile("mrs %0, cntvct_el0;" \
++ "msr cnt" pv "_tval_el0, %2;" \
++ "mrs %1, cntvct_el0" \
++ : "=&r" (_cnt_old), "=r" (_cnt_new) \
++ : "r" (val)); \
++ _timeout--; \
++ } while (_cnt_old != _cnt_new && _timeout); \
++ WARN_ON_ONCE(!_timeout); \
++} while (0)
++
+ /*
+ * These register accessors are marked inline so the compiler can
+ * nicely work out which register we want, and chuck away the rest of
+@@ -66,7 +81,11 @@ void arch_timer_reg_write_cp15(int acces
+ asm volatile("msr cntp_ctl_el0, %0" : : "r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+- asm volatile("msr cntp_tval_el0, %0" : : "r" (val));
++ if (arm_arch_timer_rewrite)
++ ARCH_TIMER_TVAL_REWRITE("p", val);
++ else
++ asm volatile("msr cntp_tval_el0, %0" : :
++ "r" (val));
+ break;
+ }
+ } else if (access == ARCH_TIMER_VIRT_ACCESS) {
+@@ -75,7 +94,11 @@ void arch_timer_reg_write_cp15(int acces
+ asm volatile("msr cntv_ctl_el0, %0" : : "r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+- asm volatile("msr cntv_tval_el0, %0" : : "r" (val));
++ if (arm_arch_timer_rewrite)
++ ARCH_TIMER_TVAL_REWRITE("v", val);
++ else
++ asm volatile("msr cntv_tval_el0, %0" : :
++ "r" (val));
+ break;
+ }
+ }
+--- a/drivers/clocksource/arm_arch_timer.c
++++ b/drivers/clocksource/arm_arch_timer.c
+@@ -73,6 +73,7 @@ static bool arch_timer_mem_use_virtual;
+
+ bool arm_arch_timer_reread; /* QorIQ erratum A-008585 */
+ EXPORT_SYMBOL(arm_arch_timer_reread);
++bool arm_arch_timer_rewrite; /* QorIQ erratum A-009971 */
+
+ /*
+ * Architected system timer support.
+@@ -733,6 +734,8 @@ static void __init arch_timer_of_init(st
+ arch_timer_c3stop = !of_property_read_bool(np, "always-on");
+ arm_arch_timer_reread =
+ of_property_read_bool(np, "fsl,erratum-a008585");
++ arm_arch_timer_rewrite =
++ of_property_read_bool(np, "fsl,erratum-a009971");
+
+ /*
+ * If we cannot rely on firmware initializing the timer registers then
diff --git a/patches.arch/arm64-2-4-Documentation-Add-documentation-for-APM-X-Gene-SoC-PMU-DTS-binding.patch b/patches.arch/arm64-2-4-Documentation-Add-documentation-for-APM-X-Gene-SoC-PMU-DTS-binding.patch
new file mode 100644
index 0000000000..615a1bd44e
--- /dev/null
+++ b/patches.arch/arm64-2-4-Documentation-Add-documentation-for-APM-X-Gene-SoC-PMU-DTS-binding.patch
@@ -0,0 +1,148 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2, 2/4] Documentation: Add documentation for APM X-Gene SoC PMU DTS
+ binding
+From: Tai Nguyen <ttnguyen@apm.com>
+X-Patchwork-Id: 8817881
+Message-Id: <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
+To: mark.rutland@arm.com,
+ will.deacon@arm.com,
+ catalin.marinas@arm.com
+Cc: devicetree@vger.kernel.org, patches@apm.com, linux-kernel@vger.kernel.org,
+ linux-arm-kernel@lists.infradead.org, Tai Nguyen <ttnguyen@apm.com>
+Date: Tue, 12 Apr 2016 18:22:25 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8817881
+
+Documentation: Add documentation for APM X-Gene SoC PMU DTS binding
+
+Signed-off-by: Tai Nguyen <ttnguyen@apm.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+.../devicetree/bindings/perf/apm-xgene-pmu.txt | 116 +++++++++++++++++++++
+ 1 file changed, 116 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
+
+diff --git a/Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt b/Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
+new file mode 100644
+index 0000000..40dfd4e
+--- /dev/null
++++ b/Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
+@@ -0,0 +1,116 @@
++* APM X-Gene SoC PMU bindings
++
++This is APM X-Gene SoC PMU (Performance Monitoring Unit) module.
++The following PMU devices are supported:
++
++ L3C - L3 cache controller
++ IOB - IO bridge
++ MCB - Memory controller bridge
++ MC - Memory controller
++
++The following section describes the SoC PMU DT node binding.
++
++Required properties:
++- compatible : Shall be "apm,xgene-pmu" for revision 1 or
++ "apm,xgene-pmu-v2" for revision 2.
++- regmap-csw : Regmap of the CPU switch fabric (CSW) resource.
++- regmap-mcba : Regmap of the MCB-A (memory bridge) resource.
++- regmap-mcbb : Regmap of the MCB-B (memory bridge) resource.
++- reg : First resource shall be the CPU bus PMU resource.
++- interrupts : Interrupt-specifier for PMU IRQ.
++
++Required properties for L3C subnode:
++- compatible : Shall be "apm,xgene-pmu-l3c".
++- reg : First resource shall be the L3C PMU resource.
++- index : Instance number of the L3C PMU.
++
++Required properties for IOB subnode:
++- compatible : Shall be "apm,xgene-pmu-iob".
++- reg : First resource shall be the IOB PMU resource.
++- index : Instance number of the IOB PMU.
++
++Required properties for MCB subnode:
++- compatible : Shall be "apm,xgene-pmu-mcb".
++- reg : First resource shall be the MCB PMU resource.
++- index : Instance number of the MCB PMU.
++
++Required properties for MC subnode:
++- compatible : Shall be "apm,xgene-pmu-mc".
++- reg : First resource shall be the MC PMU resource.
++- index : Instance number of the MC PMU.
++
++Example:
++ csw: csw@7e200000 {
++ compatible = "apm,xgene-csw", "syscon";
++ reg = <0x0 0x7e200000 0x0 0x1000>;
++ };
++
++ mcba: mcba@7e700000 {
++ compatible = "apm,xgene-mcb", "syscon";
++ reg = <0x0 0x7e700000 0x0 0x1000>;
++ };
++
++ mcbb: mcbb@7e720000 {
++ compatible = "apm,xgene-mcb", "syscon";
++ reg = <0x0 0x7e720000 0x0 0x1000>;
++ };
++
++ pmu: pmu@78810000 {
++ compatible = "apm,xgene-pmu-v2";
++ #address-cells = <2>;
++ #size-cells = <2>;
++ ranges;
++ regmap-csw = <&csw>;
++ regmap-mcba = <&mcba>;
++ regmap-mcbb = <&mcbb>;
++ reg = <0x0 0x78810000 0x0 0x1000>;
++ interrupts = <0x0 0x22 0x4>;
++
++ pmul3c@7e610000 {
++ compatible = "apm,xgene-pmu-l3c";
++ reg = <0x0 0x7e610000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmuiob@7e940000 {
++ compatible = "apm,xgene-pmu-iob";
++ reg = <0x0 0x7e940000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmucmcb@7e710000 {
++ compatible = "apm,xgene-pmu-mcb";
++ reg = <0x0 0x7e710000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmucmcb@7e730000 {
++ compatible = "apm,xgene-pmu-mcb";
++ reg = <0x0 0x7e730000 0x0 0x1000>;
++ index = <1>;
++ };
++
++ pmucmc@7e810000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e810000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmucmc@7e850000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e850000 0x0 0x1000>;
++ index = <1>;
++ };
++
++ pmucmc@7e890000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e890000 0x0 0x1000>;
++ index = <2>;
++ };
++
++ pmucmc@7e8d0000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e8d0000 0x0 0x1000>;
++ index = <3>;
++ };
++ };
diff --git a/patches.arch/arm64-2-6-arm64-dts-Add-Broadcom-Vulcan-PMU-in-dts.patch b/patches.arch/arm64-2-6-arm64-dts-Add-Broadcom-Vulcan-PMU-in-dts.patch
new file mode 100644
index 0000000000..91a9cc9419
--- /dev/null
+++ b/patches.arch/arm64-2-6-arm64-dts-Add-Broadcom-Vulcan-PMU-in-dts.patch
@@ -0,0 +1,37 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,2/6] arm64: dts: Add Broadcom Vulcan PMU in dts
+From: Ashok Kumar <ashoks@broadcom.com>
+X-Patchwork-Id: 8800911
+Message-Id: <1460379741-1181-3-git-send-email-ashoks@broadcom.com>
+To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+ mark.rutland@arm.com, will.deacon@arm.com, Suzuki.Poulose@arm.com,
+ robh+dt@kernel.org, catalin.marinas@arm.com
+Cc: jchandra@broadcom.com, Ashok Kumar <ashoks@broadcom.com>,
+ jglauber@cavium.com
+Date: Mon, 11 Apr 2016 06:02:17 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8800911
+
+Add "brcm,vulcan-pmu" compatible string for Broadcom Vulcan PMU.
+
+Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+arch/arm64/boot/dts/broadcom/vulcan.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/broadcom/vulcan.dtsi b/arch/arm64/boot/dts/broadcom/vulcan.dtsi
+index c49b5a8..03dd845 100644
+--- a/arch/arm64/boot/dts/broadcom/vulcan.dtsi
++++ b/arch/arm64/boot/dts/broadcom/vulcan.dtsi
+@@ -86,7 +86,7 @@
+ };
+
+ pmu {
+- compatible = "arm,armv8-pmuv3";
++ compatible = "brcm,vulcan-pmu", "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; /* PMU overflow */
+ };
+
diff --git a/patches.arch/arm64-3-4-perf-xgene-Add-APM-X-Gene-SoC-Performance-Monitoring-Unit-driver.patch b/patches.arch/arm64-3-4-perf-xgene-Add-APM-X-Gene-SoC-Performance-Monitoring-Unit-driver.patch
new file mode 100644
index 0000000000..96e70c2fee
--- /dev/null
+++ b/patches.arch/arm64-3-4-perf-xgene-Add-APM-X-Gene-SoC-Performance-Monitoring-Unit-driver.patch
@@ -0,0 +1,1517 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2, 3/4] perf: xgene: Add APM X-Gene SoC Performance Monitoring Unit
+ driver
+From: Tai Nguyen <ttnguyen@apm.com>
+X-Patchwork-Id: 8817901
+Message-Id: <1460510547-17611-4-git-send-email-ttnguyen@apm.com>
+To: mark.rutland@arm.com,
+ will.deacon@arm.com,
+ catalin.marinas@arm.com
+Cc: devicetree@vger.kernel.org, patches@apm.com, linux-kernel@vger.kernel.org,
+ linux-arm-kernel@lists.infradead.org, Tai Nguyen <ttnguyen@apm.com>
+Date: Tue, 12 Apr 2016 18:22:26 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8817901
+
+Signed-off-by: Tai Nguyen <ttnguyen@apm.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+Documentation/perf/xgene-pmu.txt | 48 ++
+ Documentation/perf/xgene-pmu.txt | 48 +
+ drivers/perf/Kconfig | 7
+ drivers/perf/Makefile | 1
+ drivers/perf/xgene_pmu.c | 1414 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 1470 insertions(+)
+ create mode 100644 Documentation/perf/xgene-pmu.txt
+ create mode 100644 drivers/perf/xgene_pmu.c
+
+--- /dev/null
++++ b/Documentation/perf/xgene-pmu.txt
+@@ -0,0 +1,48 @@
++APM X-Gene SoC Performance Monitoring Unit (PMU)
++================================================
++
++X-Gene SoC PMU consists of various independent system device PMUs such as
++L3 cache(s), I/O bridge(s), memory controller bridge(s) and memory
++controller(s). These PMU devices are loosely architected to follow the
++same model as the PMU for ARM cores. The PMUs share the same top level
++interrupt and status CSR region.
++
++PMU (perf) driver
++-----------------
++
++The xgene-pmu driver registers several perf PMU drivers. Each of the perf
++driver provides description of its available events and configuration options
++in sysfs, see /sys/devices/<l3cX/iobX/mcbX/mcX>/.
++
++The "format" directory describes format of the config (event ID),
++config1 (agent ID) fields of the perf_event_attr structure. The "events"
++directory provides configuration templates for all supported event types that
++can be used with perf tool. For example, "l3c0/bank-fifo-full/" is an
++equivalent of "l3c0/config=0x0b/".
++
++Most of the SoC PMU has a specific list of agent ID used for monitoring
++performance of a specific datapath. For example, agents of a L3 cache can be
++a specific CPU or an I/O bridge. Each PMU has a set of 2 registers capable of
++masking the agents from which the request come from. If the bit with
++the bit number corresponding to the agent is set, the event is counted only if
++it is caused by a request from that agent. Each agent ID bit is mapping to a
++corresponding bit in "config1" fields. By default, the event will be counted
++for all agent requests (config1 = 0xffffffffffffffffULL). For all the supported
++agents of each PMU, please refer to APM X-Gene User Manual.
++
++Each perf driver also provides a "cpumask" sysfs attribute, which contains a
++single CPU ID of the processor which will be used to handle all the PMU events.
++
++Example for perf tool use:
++
++ / # perf list | grep -e l3c -e iob -e mcb -e mc
++ l3c0/ackq-full/ [Kernel PMU event]
++ <...>
++ mcb1/mcb-csw-stall/ [Kernel PMU event]
++
++ / # perf stat -a -e l3c0/read-miss/,mcb1/csw-write-request/ sleep 1
++
++ / # perf stat -a -e l3c0/read-miss,config1=0x01/ sleep 1
++
++The driver does not support sampling, therefore "perf record" will
++not work. Per-task (without "-a") perf sessions are not supported.
+--- a/drivers/perf/Kconfig
++++ b/drivers/perf/Kconfig
+@@ -12,4 +12,11 @@ config ARM_PMU
+ Say y if you want to use CPU performance monitors on ARM-based
+ systems.
+
++config XGENE_PMU
++ depends on PERF_EVENTS && ARCH_XGENE
++ bool "APM SoC X-Gene PMU"
++ default n
++ help
++ Say y if you want to use APM X-Gene SOC performance monitors.
++
+ endmenu
+--- a/drivers/perf/Makefile
++++ b/drivers/perf/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_ARM_PMU) += arm_pmu.o
++obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o
+ obj-$(CONFIG_ARCH_THUNDER) += uncore/
+--- /dev/null
++++ b/drivers/perf/xgene_pmu.c
+@@ -0,0 +1,1414 @@
++/*
++ * APM X-Gene SoC PMU (Performance Monitor Unit)
++ *
++ * Copyright (c) 2016, Applied Micro Circuits Corporation
++ * Author: Hoan Tran <hotran@apm.com>
++ * Tai Nguyen <ttnguyen@apm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/acpi.h>
++#include <linux/efi.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/of_platform.h>
++#include <linux/of_address.h>
++#include <linux/of_fdt.h>
++#include <linux/of_irq.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/perf_event.h>
++#include <linux/module.h>
++#include <linux/cpumask.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++#include <linux/regmap.h>
++
++#define CSW_CSWCR 0x0000
++#define CSW_CSWCR_DUALMCB_MASK BIT(0)
++#define MCBADDRMR 0x0000
++#define MCBADDRMR_DUALMCU_MODE_MASK BIT(2)
++
++#define PCPPMU_INTSTATUS_REG 0x000
++#define PCPPMU_INTMASK_REG 0x004
++#define PCPPMU_INTMASK 0x0000000F
++#define PCPPMU_INTENMASK 0xFFFFFFFF
++#define PCPPMU_INTCLRMASK 0xFFFFFFF0
++#define PCPPMU_INT_MCU BIT(0)
++#define PCPPMU_INT_MCB BIT(1)
++#define PCPPMU_INT_L3C BIT(2)
++#define PCPPMU_INT_IOB BIT(3)
++
++#define PMU_MAX_COUNTERS 4
++#define PMU_CNT_MAX_VAL 0x100000000ULL
++#define PMU_OVERFLOW_MASK 0xF
++#define PMU_PMCR_E BIT(0)
++#define PMU_PMCR_P BIT(1)
++
++#define PMU_PMEVCNTR0 0x000
++#define PMU_PMEVCNTR1 0x004
++#define PMU_PMEVCNTR2 0x008
++#define PMU_PMEVCNTR3 0x00C
++#define PMU_PMEVTYPER0 0x400
++#define PMU_PMEVTYPER1 0x404
++#define PMU_PMEVTYPER2 0x408
++#define PMU_PMEVTYPER3 0x40C
++#define PMU_PMAMR0 0xA00
++#define PMU_PMAMR1 0xA04
++#define PMU_PMCNTENSET 0xC00
++#define PMU_PMCNTENCLR 0xC20
++#define PMU_PMINTENSET 0xC40
++#define PMU_PMINTENCLR 0xC60
++#define PMU_PMOVSR 0xC80
++#define PMU_PMCR 0xE04
++
++#define to_pmu_dev(p) container_of(p, struct xgene_pmu_dev, pmu)
++#define _GET_CNTR(ev) (ev->hw.extra_reg.reg)
++#define _GET_EVENTID(ev) (ev->hw.config & 0xFFULL)
++#define _GET_AGENTID(ev) (ev->hw.extra_reg.config & 0xFFFFFFFFULL)
++#define _GET_AGENT1ID(ev) ((ev->hw.extra_reg.config >> 32) & 0xFFFFFFFFULL)
++
++struct hw_pmu_info {
++ u32 id;
++ u32 type;
++ void __iomem *csr;
++};
++
++struct xgene_pmu_dev {
++ struct hw_pmu_info *inf;
++ struct xgene_pmu *parent;
++ struct pmu pmu;
++ u8 max_counters;
++ DECLARE_BITMAP(cntr_assign_mask, PMU_MAX_COUNTERS);
++ raw_spinlock_t lock;
++ u64 max_period;
++ const struct attribute_group **attr_groups;
++ u32 nformat_attrs;
++ u32 nevents_attrs;
++ struct dev_ext_attribute *format_attr;
++ struct dev_ext_attribute *events_attr;
++ struct perf_event *pmu_counter_event[4];
++};
++
++struct xgene_pmu {
++ struct device *dev;
++ int version;
++ void __iomem *pcppmu_csr;
++ u32 mcb_active_mask;
++ u32 mc_active_mask;
++ cpumask_t cpu;
++ struct list_head l3cpmus;
++ struct list_head iobpmus;
++ struct list_head mcbpmus;
++ struct list_head mcpmus;
++};
++
++struct xgene_pmu_dev_ctx {
++ struct list_head next;
++ struct xgene_pmu_dev *pmu_dev;
++ struct hw_pmu_info inf;
++};
++
++struct xgene_pmu_data {
++ int id;
++ u32 data;
++};
++
++enum xgene_pmu_version {
++ PCP_PMU_V1 = 1,
++ PCP_PMU_V2,
++};
++
++enum xgene_pmu_dev_type {
++ PMU_TYPE_L3C = 0,
++ PMU_TYPE_IOB,
++ PMU_TYPE_MCB,
++ PMU_TYPE_MC,
++};
++
++#define PMU_EXT_ATTR(_name, _func, _config) \
++ { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config }
++/*
++ * sysfs format attributes
++ */
++static ssize_t _xgene_pmu_format_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dev_ext_attribute *eattr;
++
++ eattr = container_of(attr, struct dev_ext_attribute, attr);
++ return sprintf(buf, "%s\n", (char *) eattr->var);
++}
++
++#define PMU_FORMAT_EXT_ATTR(_name, _config) \
++ PMU_EXT_ATTR(_name, _xgene_pmu_format_show, (char *)_config)
++
++static struct dev_ext_attribute l3c_pmu_format_attrs[] = {
++ PMU_FORMAT_EXT_ATTR(l3c_eventid, "config:0-7"),
++ PMU_FORMAT_EXT_ATTR(l3c_agentid, "config1:0-9"),
++};
++
++static struct dev_ext_attribute iob_pmu_format_attrs[] = {
++ PMU_FORMAT_EXT_ATTR(iob_eventid, "config:0-7"),
++ PMU_FORMAT_EXT_ATTR(iob_agentid, "config1:0-63"),
++};
++
++static struct dev_ext_attribute mcb_pmu_format_attrs[] = {
++ PMU_FORMAT_EXT_ATTR(mcb_eventid, "config:0-5"),
++ PMU_FORMAT_EXT_ATTR(mcb_agentid, "config1:0-9"),
++};
++
++static struct dev_ext_attribute mc_pmu_format_attrs[] = {
++ PMU_FORMAT_EXT_ATTR(mc_eventid, "config:0-28"),
++};
++
++static struct attribute_group pmu_format_attr_group = {
++ .name = "format",
++ .attrs = NULL, /* Filled in xgene_pmu_alloc_attrs */
++};
++
++/*
++ * sysfs event attributes
++ */
++static ssize_t _xgene_pmu_event_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dev_ext_attribute *eattr;
++
++ eattr = container_of(attr, struct dev_ext_attribute, attr);
++ return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var);
++}
++
++#define PMU_EVENT_EXT_ATTR(_name, _config) \
++ PMU_EXT_ATTR(_name, _xgene_pmu_event_show, (unsigned long)_config)
++
++static struct dev_ext_attribute l3c_pmu_events_attrs[] = {
++ PMU_EVENT_EXT_ATTR(cycle-count, 0x00),
++ PMU_EVENT_EXT_ATTR(cycle-count-div-64, 0x01),
++ PMU_EVENT_EXT_ATTR(read-hit, 0x02),
++ PMU_EVENT_EXT_ATTR(read-miss, 0x03),
++ PMU_EVENT_EXT_ATTR(write-need-replacement, 0x06),
++ PMU_EVENT_EXT_ATTR(write-not-need-replacement, 0x07),
++ PMU_EVENT_EXT_ATTR(tq-full, 0x08),
++ PMU_EVENT_EXT_ATTR(ackq-full, 0x09),
++ PMU_EVENT_EXT_ATTR(wdb-full, 0x0a),
++ PMU_EVENT_EXT_ATTR(bank-fifo-full, 0x0b),
++ PMU_EVENT_EXT_ATTR(odb-full, 0x0c),
++ PMU_EVENT_EXT_ATTR(wbq-full, 0x0d),
++ PMU_EVENT_EXT_ATTR(bank-conflict-fifo-issue, 0x0e),
++ PMU_EVENT_EXT_ATTR(bank-fifo-issue, 0x0f),
++};
++
++static struct dev_ext_attribute iob_pmu_events_attrs[] = {
++ PMU_EVENT_EXT_ATTR(cycle-count, 0x00),
++ PMU_EVENT_EXT_ATTR(cycle-count-div-64, 0x01),
++ PMU_EVENT_EXT_ATTR(axi0-read, 0x02),
++ PMU_EVENT_EXT_ATTR(axi0-read-partial, 0x03),
++ PMU_EVENT_EXT_ATTR(axi1-read, 0x04),
++ PMU_EVENT_EXT_ATTR(axi1-read-partial, 0x05),
++ PMU_EVENT_EXT_ATTR(csw-read-block, 0x06),
++ PMU_EVENT_EXT_ATTR(csw-read-partial, 0x07),
++ PMU_EVENT_EXT_ATTR(axi0-write, 0x10),
++ PMU_EVENT_EXT_ATTR(axi0-write-partial, 0x11),
++ PMU_EVENT_EXT_ATTR(axi1-write, 0x13),
++ PMU_EVENT_EXT_ATTR(axi1-write-partial, 0x14),
++ PMU_EVENT_EXT_ATTR(csw-inbound-dirty, 0x16),
++};
++
++static struct dev_ext_attribute mcb_pmu_events_attrs[] = {
++ PMU_EVENT_EXT_ATTR(cycle-count, 0x00),
++ PMU_EVENT_EXT_ATTR(cycle-count-div-64, 0x01),
++ PMU_EVENT_EXT_ATTR(csw-read, 0x02),
++ PMU_EVENT_EXT_ATTR(csw-write-request, 0x03),
++ PMU_EVENT_EXT_ATTR(mcb-csw-stall, 0x04),
++ PMU_EVENT_EXT_ATTR(cancel-read-gack, 0x05),
++};
++
++static struct dev_ext_attribute mc_pmu_events_attrs[] = {
++ PMU_EVENT_EXT_ATTR(cycle-count, 0x00),
++ PMU_EVENT_EXT_ATTR(cycle-count-div-64, 0x01),
++ PMU_EVENT_EXT_ATTR(act-cmd-sent, 0x02),
++ PMU_EVENT_EXT_ATTR(pre-cmd-sent, 0x03),
++ PMU_EVENT_EXT_ATTR(rd-cmd-sent, 0x04),
++ PMU_EVENT_EXT_ATTR(rda-cmd-sent, 0x05),
++ PMU_EVENT_EXT_ATTR(wr-cmd-sent, 0x06),
++ PMU_EVENT_EXT_ATTR(wra-cmd-sent, 0x07),
++ PMU_EVENT_EXT_ATTR(pde-cmd-sent, 0x08),
++ PMU_EVENT_EXT_ATTR(sre-cmd-sent, 0x09),
++ PMU_EVENT_EXT_ATTR(prea-cmd-sent, 0x0a),
++ PMU_EVENT_EXT_ATTR(ref-cmd-sent, 0x0b),
++ PMU_EVENT_EXT_ATTR(rd-rda-cmd-sent, 0x0c),
++ PMU_EVENT_EXT_ATTR(wr-wra-cmd-sent, 0x0d),
++ PMU_EVENT_EXT_ATTR(in-rd-collision, 0x0e),
++ PMU_EVENT_EXT_ATTR(in-wr-collision, 0x0f),
++ PMU_EVENT_EXT_ATTR(collision-queue-not-empty, 0x10),
++ PMU_EVENT_EXT_ATTR(collision-queue-full, 0x11),
++ PMU_EVENT_EXT_ATTR(mcu-request, 0x12),
++ PMU_EVENT_EXT_ATTR(mcu-rd-request, 0x13),
++ PMU_EVENT_EXT_ATTR(mcu-hp-rd-request, 0x14),
++ PMU_EVENT_EXT_ATTR(mcu-wr-request, 0x15),
++ PMU_EVENT_EXT_ATTR(mcu-rd-proceed-all, 0x16),
++ PMU_EVENT_EXT_ATTR(mcu-rd-proceed-cancel, 0x17),
++ PMU_EVENT_EXT_ATTR(mcu-rd-response, 0x18),
++ PMU_EVENT_EXT_ATTR(mcu-rd-proceed-speculative-all, 0x19),
++ PMU_EVENT_EXT_ATTR(mcu-rd-proceed-speculative-cancel, 0x1a),
++ PMU_EVENT_EXT_ATTR(mcu-wr-proceed-all, 0x1b),
++ PMU_EVENT_EXT_ATTR(mcu-wr-proceed-cancel, 0x1c),
++};
++
++static struct attribute_group pmu_events_attr_group = {
++ .name = "events",
++ .attrs = NULL, /* Filled in xgene_pmu_alloc_attrs */
++};
++
++/*
++ * sysfs cpumask attributes
++ */
++static ssize_t xgene_pmu_cpumask_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(dev_get_drvdata(dev));
++
++ return cpumap_print_to_pagebuf(true, buf, &pmu_dev->parent->cpu);
++}
++static DEVICE_ATTR(cpumask, S_IRUGO, xgene_pmu_cpumask_show, NULL);
++
++static struct attribute *xgene_pmu_cpumask_attrs[] = {
++ &dev_attr_cpumask.attr,
++ NULL,
++};
++
++static struct attribute_group pmu_cpumask_attr_group = {
++ .attrs = xgene_pmu_cpumask_attrs,
++};
++
++static const struct attribute_group *pmu_attr_groups[] = {
++ &pmu_format_attr_group,
++ &pmu_cpumask_attr_group,
++ &pmu_events_attr_group,
++ NULL
++};
++
++static int get_next_avail_cntr(struct xgene_pmu_dev *pmu_dev)
++{
++ int cntr;
++
++ cntr = find_first_zero_bit(pmu_dev->cntr_assign_mask,
++ pmu_dev->max_counters);
++ if (cntr == pmu_dev->max_counters)
++ return -ENOSPC;
++ set_bit(cntr, pmu_dev->cntr_assign_mask);
++
++ return cntr;
++}
++
++static void clear_avail_cntr(struct xgene_pmu_dev *pmu_dev, int cntr)
++{
++ clear_bit(cntr, pmu_dev->cntr_assign_mask);
++}
++
++static inline void xgene_pmu_mask_int(struct xgene_pmu *xgene_pmu)
++{
++ writel(PCPPMU_INTENMASK, xgene_pmu->pcppmu_csr + PCPPMU_INTMASK_REG);
++}
++
++static inline void xgene_pmu_unmask_int(struct xgene_pmu *xgene_pmu)
++{
++ writel(PCPPMU_INTCLRMASK, xgene_pmu->pcppmu_csr + PCPPMU_INTMASK_REG);
++}
++
++static inline u32 xgene_pmu_read_counter(struct xgene_pmu_dev *pmu_dev, int idx)
++{
++ return readl(pmu_dev->inf->csr + PMU_PMEVCNTR0 + (4 * idx));
++}
++
++static inline void
++xgene_pmu_write_counter(struct xgene_pmu_dev *pmu_dev, int idx, u32 val)
++{
++ writel(val, pmu_dev->inf->csr + PMU_PMEVCNTR0 + (4 * idx));
++}
++
++static inline void
++xgene_pmu_write_evttype(struct xgene_pmu_dev *pmu_dev, int idx, u32 val)
++{
++ writel(val, pmu_dev->inf->csr + PMU_PMEVTYPER0 + (4 * idx));
++}
++
++static inline void
++xgene_pmu_write_agenttype(struct xgene_pmu_dev *pmu_dev, u32 val)
++{
++ writel(val, pmu_dev->inf->csr + PMU_PMAMR0);
++}
++
++static inline void
++xgene_pmu_write_agent1type(struct xgene_pmu_dev *pmu_dev, u32 val)
++{
++ writel(val, pmu_dev->inf->csr + PMU_PMAMR1);
++}
++
++static inline void
++xgene_pmu_enable_counter(struct xgene_pmu_dev *pmu_dev, int idx)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMCNTENSET);
++ val |= 1 << idx;
++ writel(val, pmu_dev->inf->csr + PMU_PMCNTENSET);
++}
++
++static inline void
++xgene_pmu_disable_counter(struct xgene_pmu_dev *pmu_dev, int idx)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMCNTENCLR);
++ val |= 1 << idx;
++ writel(val, pmu_dev->inf->csr + PMU_PMCNTENCLR);
++}
++
++static inline void
++xgene_pmu_enable_counter_int(struct xgene_pmu_dev *pmu_dev, int idx)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMINTENSET);
++ val |= 1 << idx;
++ writel(val, pmu_dev->inf->csr + PMU_PMINTENSET);
++}
++
++static inline void
++xgene_pmu_disable_counter_int(struct xgene_pmu_dev *pmu_dev, int idx)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMINTENCLR);
++ val |= 1 << idx;
++ writel(val, pmu_dev->inf->csr + PMU_PMINTENCLR);
++}
++
++static inline void xgene_pmu_reset_counters(struct xgene_pmu_dev *pmu_dev)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMCR);
++ val |= PMU_PMCR_P;
++ writel(val, pmu_dev->inf->csr + PMU_PMCR);
++}
++
++static inline void xgene_pmu_start_counters(struct xgene_pmu_dev *pmu_dev)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMCR);
++ val |= PMU_PMCR_E;
++ writel(val, pmu_dev->inf->csr + PMU_PMCR);
++}
++
++static inline void xgene_pmu_stop_counters(struct xgene_pmu_dev *pmu_dev)
++{
++ u32 val;
++
++ val = readl(pmu_dev->inf->csr + PMU_PMCR);
++ val &= ~PMU_PMCR_E;
++ writel(val, pmu_dev->inf->csr + PMU_PMCR);
++}
++
++static int xgene_perf_event_init(struct perf_event *event)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++ struct hw_perf_event *hwc = &event->hw;
++ u64 config, config1;
++
++ /* Test the event attr type check for PMU enumeration */
++ if (event->attr.type != event->pmu->type)
++ return -ENOENT;
++
++ /*
++ * SOC PMU counters are shared across all cores.
++ * Therefore, it does not support per-process mode.
++ * Also, it does not support event sampling mode.
++ */
++ if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
++ return -EINVAL;
++
++ /* SOC counters do not have usr/os/guest/host bits */
++ if (event->attr.exclude_user || event->attr.exclude_kernel ||
++ event->attr.exclude_host || event->attr.exclude_guest)
++ return -EINVAL;
++
++ if (event->cpu < 0)
++ return -EINVAL;
++ /*
++ * Many perf core operations (eg. events rotation) operate on a
++ * single CPU context. This is obvious for CPU PMUs, where one
++ * expects the same sets of events being observed on all CPUs,
++ * but can lead to issues for off-core PMUs, where each
++ * event could be theoretically assigned to a different CPU. To
++ * mitigate this, we enforce CPU assignment to one, selected
++ * processor (the one described in the "cpumask" attribute).
++ */
++ event->cpu = cpumask_first(&pmu_dev->parent->cpu);
++
++ config = event->attr.config;
++ config1 = event->attr.config1;
++
++ hwc->config = config;
++ /*
++ * Each bit of the config1 field represents an agent from which the
++ * request of the event come. The event is counted only if it's caused
++ * by a request of an agent has the bit set.
++ * By default, the event is counted for all agents.
++ */
++ if (config1)
++ hwc->extra_reg.config = config1;
++ else
++ hwc->extra_reg.config = 0xFFFFFFFFFFFFFFFFULL;
++
++ return 0;
++}
++
++static void xgene_perf_enable_event(struct perf_event *event)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++
++ xgene_pmu_write_evttype(pmu_dev, _GET_CNTR(event), _GET_EVENTID(event));
++ xgene_pmu_write_agenttype(pmu_dev, _GET_AGENTID(event));
++ if (pmu_dev->inf->type == PMU_TYPE_IOB)
++ xgene_pmu_write_agent1type(pmu_dev, _GET_AGENT1ID(event));
++
++ xgene_pmu_start_counters(pmu_dev);
++ xgene_pmu_enable_counter(pmu_dev, _GET_CNTR(event));
++ xgene_pmu_enable_counter_int(pmu_dev, _GET_CNTR(event));
++}
++
++static void xgene_perf_disable_event(struct perf_event *event)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++
++ xgene_pmu_disable_counter(pmu_dev, _GET_CNTR(event));
++ xgene_pmu_disable_counter_int(pmu_dev, _GET_CNTR(event));
++}
++
++static void xgene_perf_start(struct perf_event *event, int flags)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++ struct hw_perf_event *hwc = &event->hw;
++
++ if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
++ return;
++
++ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
++ hwc->state = 0;
++
++ if (flags & PERF_EF_RELOAD) {
++ u64 prev_raw_count = local64_read(&hwc->prev_count);
++
++ xgene_pmu_write_counter(pmu_dev, _GET_CNTR(event),
++ (u32) prev_raw_count);
++ }
++
++ xgene_perf_enable_event(event);
++ perf_event_update_userpage(event);
++}
++
++static void xgene_perf_read(struct perf_event *event)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++ struct hw_perf_event *hwc = &event->hw;
++ u64 prev_raw_count;
++ u64 count;
++ u64 delta;
++
++ count = xgene_pmu_read_counter(pmu_dev, _GET_CNTR(event))
++ & pmu_dev->max_period;
++
++ prev_raw_count = local64_read(&hwc->prev_count);
++ if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, count)
++ != prev_raw_count)
++ return;
++
++ delta = (count - prev_raw_count) & pmu_dev->max_period;
++
++ local64_add(delta, &event->count);
++}
++
++static void xgene_perf_stop(struct perf_event *event, int flags)
++{
++ struct hw_perf_event *hwc = &event->hw;
++ u64 config;
++
++ if (hwc->state & PERF_HES_UPTODATE)
++ return;
++
++ xgene_perf_disable_event(event);
++ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
++ hwc->state |= PERF_HES_STOPPED;
++
++ if (hwc->state & PERF_HES_UPTODATE)
++ return;
++
++ config = hwc->config;
++ xgene_perf_read(event);
++ hwc->state |= PERF_HES_UPTODATE;
++}
++
++static int xgene_perf_add(struct perf_event *event, int flags)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++ int retval;
++
++ event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
++
++ retval = get_next_avail_cntr(pmu_dev);
++ if (retval != -ENOSPC)
++ event->hw.extra_reg.reg = (u16) retval;
++ else
++ return retval;
++
++ if (flags & PERF_EF_START)
++ xgene_perf_start(event, PERF_EF_RELOAD);
++
++ /* Update counter event pointer for Interrupt handler */
++ pmu_dev->pmu_counter_event[retval] = event;
++
++ return 0;
++}
++
++static void xgene_perf_del(struct perf_event *event, int flags)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++
++ xgene_perf_stop(event, PERF_EF_UPDATE);
++
++ /* clear the assigned counter */
++ clear_avail_cntr(pmu_dev, _GET_CNTR(event));
++
++ perf_event_update_userpage(event);
++}
++
++static struct attribute **alloc_attrs(struct device *dev, u32 n,
++ struct dev_ext_attribute *dev_attr)
++{
++ struct attribute **attrs;
++ int i;
++
++ /* Alloc n + 1 (for terminating NULL) */
++ attrs = devm_kcalloc(dev, n + 1, sizeof(struct attribute *),
++ GFP_KERNEL);
++ if (!attrs)
++ return attrs;
++
++ for (i = 0; i < n; i++)
++ attrs[i] = &dev_attr[i].attr.attr;
++ return attrs;
++}
++
++static int
++xgene_pmu_alloc_attrs(struct device *dev, struct xgene_pmu_dev *pmu_dev)
++{
++ struct attribute **attrs;
++
++ if (pmu_dev->nformat_attrs) {
++ attrs = alloc_attrs(dev, pmu_dev->nformat_attrs,
++ pmu_dev->format_attr);
++ if (!attrs)
++ return -ENOMEM;
++ pmu_format_attr_group.attrs = attrs;
++ }
++
++ if (pmu_dev->nevents_attrs) {
++ attrs = alloc_attrs(dev, pmu_dev->nevents_attrs,
++ pmu_dev->events_attr);
++ if (!attrs)
++ return -ENOMEM;
++ pmu_events_attr_group.attrs = attrs;
++ }
++
++ pmu_dev->attr_groups = pmu_attr_groups;
++
++ return 0;
++}
++
++static void deallocate_attrs(struct device *dev, struct xgene_pmu_dev *pmu_dev)
++{
++ if (pmu_events_attr_group.attrs)
++ devm_kfree(dev, pmu_events_attr_group.attrs);
++
++ if (pmu_format_attr_group.attrs)
++ devm_kfree(dev, pmu_format_attr_group.attrs);
++
++ /* Reset pmu format/events attribute pointers for next device */
++ pmu_events_attr_group.attrs = NULL;
++ pmu_format_attr_group.attrs = NULL;
++}
++
++static u64 xgene_perf_event_update(struct perf_event *event,
++ struct hw_perf_event *hwc, int idx)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++ u64 delta, prev_raw_count, new_raw_count;
++
++again:
++ prev_raw_count = local64_read(&hwc->prev_count);
++ new_raw_count = pmu_dev->max_period;
++
++ if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
++ new_raw_count) != prev_raw_count)
++ goto again;
++
++ delta = (new_raw_count - prev_raw_count) & pmu_dev->max_period;
++
++ local64_add(delta, &event->count);
++ local64_sub(delta, &hwc->period_left);
++
++ return new_raw_count;
++}
++
++static int xgene_perf_event_set_period(struct perf_event *event,
++ struct hw_perf_event *hwc, int idx)
++{
++ struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
++ s64 left = local64_read(&hwc->period_left);
++ s64 period = hwc->sample_period;
++ int ret = 0;
++
++ if (unlikely(left <= -period)) {
++ left = period;
++ local64_set(&hwc->period_left, left);
++ hwc->last_period = period;
++ ret = 1;
++ }
++
++ if (unlikely(left <= 0)) {
++ left += period;
++ local64_set(&hwc->period_left, left);
++ hwc->last_period = period;
++ ret = 1;
++ }
++
++ /*
++ * Limit the maximum period to prevent the counter value
++ * from overtaking the one we are about to program. In
++ * effect we are reducing max_period to account for
++ * interrupt latency (and we are being very conservative).
++ */
++ if (left > (pmu_dev->max_period >> 1))
++ left = pmu_dev->max_period >> 1;
++
++ local64_set(&hwc->prev_count, (u64) -left);
++
++ xgene_pmu_write_counter(pmu_dev, idx, (u64)(-left) & 0xffffffff);
++
++ perf_event_update_userpage(event);
++
++ return ret;
++}
++
++static int xgene_init_perf(struct xgene_pmu_dev *pmu_dev, char *name)
++{
++ struct xgene_pmu *xgene_pmu;
++
++ raw_spin_lock_init(&pmu_dev->lock);
++
++ pmu_dev->max_period = PMU_CNT_MAX_VAL - 1;
++ /* First PMU version supports only single event counter */
++ xgene_pmu = pmu_dev->parent;
++ if (xgene_pmu->version == 1)
++ pmu_dev->max_counters = 1;
++ else
++ pmu_dev->max_counters = PMU_MAX_COUNTERS;
++
++ /* Perf driver registration */
++ pmu_dev->pmu = (struct pmu) {
++ .attr_groups = pmu_dev->attr_groups,
++ .task_ctx_nr = perf_invalid_context,
++ .event_init = xgene_perf_event_init,
++ .add = xgene_perf_add,
++ .del = xgene_perf_del,
++ .start = xgene_perf_start,
++ .stop = xgene_perf_stop,
++ .read = xgene_perf_read,
++ };
++
++ /* Hardware counter init */
++ xgene_pmu_stop_counters(pmu_dev);
++ xgene_pmu_reset_counters(pmu_dev);
++
++ return perf_pmu_register(&pmu_dev->pmu, name, -1);
++}
++
++static int
++xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
++{
++ struct device *dev = xgene_pmu->dev;
++ struct xgene_pmu_dev *pmu;
++ char name[10];
++ int rc;
++
++ pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
++ if (!pmu)
++ return -ENOMEM;
++ pmu->parent = xgene_pmu;
++ pmu->inf = &ctx->inf;
++ ctx->pmu_dev = pmu;
++
++ switch (pmu->inf->type) {
++ case PMU_TYPE_L3C:
++ pmu->format_attr = l3c_pmu_format_attrs;
++ pmu->nformat_attrs = ARRAY_SIZE(l3c_pmu_format_attrs);
++ pmu->events_attr = l3c_pmu_events_attrs;
++ pmu->nevents_attrs = ARRAY_SIZE(l3c_pmu_events_attrs);
++ sprintf(name, "l3c%d", pmu->inf->id);
++ break;
++ case PMU_TYPE_IOB:
++ pmu->format_attr = iob_pmu_format_attrs;
++ pmu->nformat_attrs = ARRAY_SIZE(iob_pmu_format_attrs);
++ pmu->events_attr = iob_pmu_events_attrs;
++ pmu->nevents_attrs = ARRAY_SIZE(iob_pmu_events_attrs);
++ sprintf(name, "iob%d", pmu->inf->id);
++ break;
++ case PMU_TYPE_MCB:
++ if (!(xgene_pmu->mcb_active_mask & (1 << pmu->inf->id)))
++ goto dev_err;
++ pmu->format_attr = mcb_pmu_format_attrs;
++ pmu->nformat_attrs = ARRAY_SIZE(mcb_pmu_format_attrs);
++ pmu->events_attr = mcb_pmu_events_attrs;
++ pmu->nevents_attrs = ARRAY_SIZE(mcb_pmu_events_attrs);
++ sprintf(name, "mcb%d", pmu->inf->id);
++ break;
++ case PMU_TYPE_MC:
++ if (!(xgene_pmu->mc_active_mask & (1 << pmu->inf->id)))
++ goto dev_err;
++ pmu->format_attr = mc_pmu_format_attrs;
++ pmu->nformat_attrs = ARRAY_SIZE(mc_pmu_format_attrs);
++ pmu->events_attr = mc_pmu_events_attrs;
++ pmu->nevents_attrs = ARRAY_SIZE(mc_pmu_events_attrs);
++ sprintf(name, "mc%d", pmu->inf->id);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ rc = xgene_pmu_alloc_attrs(dev, pmu);
++ if (rc) {
++ dev_err(dev, "%s PMU: Failed to alloc attributes\n", name);
++ goto dev_err;
++ }
++
++ rc = xgene_init_perf(pmu, name);
++ if (rc) {
++ dev_err(dev, "%s PMU: Failed to init perf driver\n", name);
++ goto dev_err;
++ }
++
++ dev_info(dev, "%s PMU registered\n", name);
++
++ /* All attribute allocations can be free'd after perf_register_pmu */
++ deallocate_attrs(dev, pmu);
++ return rc;
++
++dev_err:
++ deallocate_attrs(dev, pmu);
++ devm_kfree(dev, pmu);
++ return -ENODEV;
++}
++
++static irqreturn_t _xgene_pmu_isr(int irq, struct xgene_pmu_dev *pmu_dev)
++{
++ struct perf_event *event = NULL;
++ struct perf_sample_data data;
++ struct xgene_pmu *xgene_pmu;
++ struct hw_perf_event *hwc;
++ int idx;
++ u32 val;
++
++ /* Get interrupt counter source */
++ val = readl(pmu_dev->inf->csr + PMU_PMOVSR);
++ idx = ffs(val) - 1;
++ if (!(val & PMU_OVERFLOW_MASK))
++ goto out;
++ event = pmu_dev->pmu_counter_event[idx];
++
++ /* Ignore if we don't have an event. */
++ if (!event)
++ goto out;
++
++ hwc = &event->hw;
++
++ xgene_perf_event_update(event, hwc, idx);
++ perf_sample_data_init(&data, 0, hwc->last_period);
++ if (!xgene_perf_event_set_period(event, hwc, idx))
++ goto out;
++
++out:
++ /* Clear interrupt flag */
++ xgene_pmu = pmu_dev->parent;
++ if (xgene_pmu->version == 1)
++ writel(0x0, pmu_dev->inf->csr + PMU_PMOVSR);
++ else
++ writel(val, pmu_dev->inf->csr + PMU_PMOVSR);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t xgene_pmu_isr(int irq, void *dev_id)
++{
++ struct xgene_pmu_dev_ctx *ctx, *temp_ctx;
++ struct xgene_pmu *xgene_pmu = dev_id;
++ u32 val;
++
++ xgene_pmu_mask_int(xgene_pmu);
++
++ /* Get Interrupt PMU source */
++ val = readl(xgene_pmu->pcppmu_csr + PCPPMU_INTSTATUS_REG)
++ & PCPPMU_INTMASK;
++ if (val & PCPPMU_INT_MCU) {
++ list_for_each_entry_safe(ctx, temp_ctx,
++ &xgene_pmu->mcpmus, next) {
++ _xgene_pmu_isr(irq, ctx->pmu_dev);
++ }
++ }
++ if (val & PCPPMU_INT_MCB) {
++ list_for_each_entry_safe(ctx, temp_ctx,
++ &xgene_pmu->mcbpmus, next) {
++ _xgene_pmu_isr(irq, ctx->pmu_dev);
++ }
++ }
++ if (val & PCPPMU_INT_L3C) {
++ list_for_each_entry_safe(ctx, temp_ctx,
++ &xgene_pmu->l3cpmus, next) {
++ _xgene_pmu_isr(irq, ctx->pmu_dev);
++ }
++ }
++ if (val & PCPPMU_INT_IOB) {
++ list_for_each_entry_safe(ctx, temp_ctx,
++ &xgene_pmu->iobpmus, next) {
++ _xgene_pmu_isr(irq, ctx->pmu_dev);
++ }
++ }
++
++ xgene_pmu_unmask_int(xgene_pmu);
++
++ return IRQ_HANDLED;
++}
++
++static int acpi_pmu_probe_active_mcb_mcu(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ void __iomem *csw_csr, *mcba_csr, *mcbb_csr;
++ struct resource *res;
++ unsigned int reg;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ csw_csr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(csw_csr)) {
++ dev_err(&pdev->dev, "ioremap failed for CSW CSR resource\n");
++ return PTR_ERR(csw_csr);
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
++ mcba_csr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(mcba_csr)) {
++ dev_err(&pdev->dev, "ioremap failed for MCBA CSR resource\n");
++ return PTR_ERR(mcba_csr);
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
++ mcbb_csr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(mcbb_csr)) {
++ dev_err(&pdev->dev, "ioremap failed for MCBB CSR resource\n");
++ return PTR_ERR(mcbb_csr);
++ }
++
++ reg = readl(csw_csr + CSW_CSWCR);
++ if (reg & CSW_CSWCR_DUALMCB_MASK) {
++ /* Dual MCB active */
++ xgene_pmu->mcb_active_mask = 0x3;
++ /* Probe all active MC(s) */
++ reg = readl(mcbb_csr + CSW_CSWCR);
++ xgene_pmu->mc_active_mask =
++ (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0xF : 0x5;
++ } else {
++ /* Single MCB active */
++ xgene_pmu->mcb_active_mask = 0x1;
++ /* Probe all active MC(s) */
++ reg = readl(mcba_csr + CSW_CSWCR);
++ xgene_pmu->mc_active_mask =
++ (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0x3 : 0x1;
++ }
++
++ return 0;
++}
++
++static int fdt_pmu_probe_active_mcb_mcu(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ struct regmap *csw_map, *mcba_map, *mcbb_map;
++ struct device_node *np = pdev->dev.of_node;
++ unsigned int reg;
++
++ csw_map = syscon_regmap_lookup_by_phandle(np, "regmap-csw");
++ if (IS_ERR(csw_map)) {
++ dev_err(&pdev->dev, "unable to get syscon regmap csw\n");
++ return PTR_ERR(csw_map);
++ }
++
++ mcba_map = syscon_regmap_lookup_by_phandle(np, "regmap-mcba");
++ if (IS_ERR(mcba_map)) {
++ dev_err(&pdev->dev, "unable to get syscon regmap mcba\n");
++ return PTR_ERR(mcba_map);
++ }
++
++ mcbb_map = syscon_regmap_lookup_by_phandle(np, "regmap-mcbb");
++ if (IS_ERR(mcbb_map)) {
++ dev_err(&pdev->dev, "unable to get syscon regmap mcbb\n");
++ return PTR_ERR(mcbb_map);
++ }
++
++ if (regmap_read(csw_map, CSW_CSWCR, &reg))
++ return -EINVAL;
++
++ if (reg & CSW_CSWCR_DUALMCB_MASK) {
++ /* Dual MCB active */
++ xgene_pmu->mcb_active_mask = 0x3;
++ /* Probe all active MC(s) */
++ if (regmap_read(mcbb_map, MCBADDRMR, &reg))
++ return 0;
++ xgene_pmu->mc_active_mask =
++ (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0xF : 0x5;
++ } else {
++ /* Single MCB active */
++ xgene_pmu->mcb_active_mask = 0x1;
++ /* Probe all active MC(s) */
++ if (regmap_read(mcba_map, MCBADDRMR, &reg))
++ return 0;
++ xgene_pmu->mc_active_mask =
++ (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0x3 : 0x1;
++ }
++
++ return 0;
++}
++
++static int xgene_pmu_probe_active_mcb_mcu(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ if (has_acpi_companion(&pdev->dev))
++ return acpi_pmu_probe_active_mcb_mcu(xgene_pmu, pdev);
++ return fdt_pmu_probe_active_mcb_mcu(xgene_pmu, pdev);
++}
++
++#if defined(CONFIG_ACPI)
++static int acpi_pmu_dev_add_resource(struct acpi_resource *ares, void *data)
++{
++ struct resource *res = data;
++
++ if (ares->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32)
++ acpi_dev_resource_memory(ares, res);
++
++ /* Always tell the ACPI core to skip this resource */
++ return 1;
++}
++
++static struct
++xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
++ struct acpi_device *adev, u32 type)
++{
++ struct device *dev = xgene_pmu->dev;
++ struct list_head resource_list;
++ struct xgene_pmu_dev_ctx *ctx;
++ const union acpi_object *obj;
++ struct hw_pmu_info *inf;
++ void __iomem *dev_csr;
++ struct resource res;
++ u32 id;
++ int rc;
++
++ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
++ if (!ctx)
++ return NULL;
++
++ INIT_LIST_HEAD(&resource_list);
++ rc = acpi_dev_get_resources(adev, &resource_list,
++ acpi_pmu_dev_add_resource, &res);
++ acpi_dev_free_resource_list(&resource_list);
++ if (rc < 0 || IS_ERR(&res)) {
++ dev_err(dev, "PMU type %d: No resource address found\n", type);
++ goto err;
++ }
++
++ dev_csr = devm_ioremap_resource(dev, &res);
++ if (IS_ERR(dev_csr)) {
++ dev_err(dev, "PMU type %d: Fail to map resource\n", type);
++ rc = PTR_ERR(dev_csr);
++ goto err;
++ }
++
++ rc = acpi_dev_get_property(adev, "index", ACPI_TYPE_INTEGER, &obj);
++ if (rc < 0) {
++ dev_err(&adev->dev, "No index property found\n");
++ id = 0;
++ } else {
++ id = (u32) obj->integer.value;
++ }
++
++ inf = &ctx->inf;
++ inf->type = type;
++ inf->csr = dev_csr;
++ inf->id = id;
++
++ return ctx;
++err:
++ devm_kfree(dev, ctx);
++ return NULL;
++}
++
++static acpi_status acpi_pmu_dev_add(acpi_handle handle, u32 level,
++ void *data, void **return_value)
++{
++ struct xgene_pmu *xgene_pmu = data;
++ struct xgene_pmu_dev_ctx *ctx;
++ struct acpi_device *adev;
++
++ if (acpi_bus_get_device(handle, &adev))
++ return AE_OK;
++ if (acpi_bus_get_status(adev) || !adev->status.present)
++ return AE_OK;
++
++ if (!strcmp(acpi_device_hid(adev), "APMC0D5D"))
++ ctx = acpi_get_pmu_hw_inf(xgene_pmu, adev, PMU_TYPE_L3C);
++ else if (!strcmp(acpi_device_hid(adev), "APMC0D5E"))
++ ctx = acpi_get_pmu_hw_inf(xgene_pmu, adev, PMU_TYPE_IOB);
++ else if (!strcmp(acpi_device_hid(adev), "APMC0D5F"))
++ ctx = acpi_get_pmu_hw_inf(xgene_pmu, adev, PMU_TYPE_MCB);
++ else if (!strcmp(acpi_device_hid(adev), "APMC0D60"))
++ ctx = acpi_get_pmu_hw_inf(xgene_pmu, adev, PMU_TYPE_MC);
++ else
++ ctx = NULL;
++
++ if (!ctx)
++ return AE_OK;
++
++ if (xgene_pmu_dev_add(xgene_pmu, ctx))
++ return AE_OK;
++
++ switch (ctx->inf.type) {
++ case PMU_TYPE_L3C:
++ list_add(&ctx->next, &xgene_pmu->l3cpmus);
++ break;
++ case PMU_TYPE_IOB:
++ list_add(&ctx->next, &xgene_pmu->iobpmus);
++ break;
++ case PMU_TYPE_MCB:
++ list_add(&ctx->next, &xgene_pmu->mcbpmus);
++ break;
++ case PMU_TYPE_MC:
++ list_add(&ctx->next, &xgene_pmu->mcpmus);
++ break;
++ }
++ return AE_OK;
++}
++
++static int acpi_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ struct device *dev = xgene_pmu->dev;
++ acpi_handle handle;
++ acpi_status status;
++
++ handle = ACPI_HANDLE(dev);
++ if (!handle)
++ return -EINVAL;
++
++ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
++ acpi_pmu_dev_add, NULL, xgene_pmu, NULL);
++ if (ACPI_FAILURE(status))
++ dev_err(dev, "failed to probe PMU devices\n");
++ return 0;
++}
++#else
++static int acpi_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ return 0;
++}
++#endif
++
++static struct
++xgene_pmu_dev_ctx *fdt_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
++ struct device_node *np, u32 type)
++{
++ struct device *dev = xgene_pmu->dev;
++ struct xgene_pmu_dev_ctx *ctx;
++ struct hw_pmu_info *inf;
++ void __iomem *dev_csr;
++ struct resource res;
++ u32 id;
++ int rc;
++
++ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
++ if (!ctx)
++ return NULL;
++ rc = of_address_to_resource(np, 0, &res);
++ if (rc < 0) {
++ dev_err(dev, "PMU type %d: No resource address found\n", type);
++ goto err;
++ }
++ dev_csr = devm_ioremap_resource(dev, &res);
++ if (IS_ERR(dev_csr)) {
++ dev_err(dev, "PMU type %d: Fail to map resource\n", type);
++ rc = PTR_ERR(dev_csr);
++ goto err;
++ }
++
++ if (of_property_read_u32(np, "index", &id)) {
++ dev_err(dev, "PMU type %d: No index property found\n", type);
++ id = 0;
++ }
++
++ inf = &ctx->inf;
++ inf->type = type;
++ inf->csr = dev_csr;
++ inf->id = id;
++
++ return ctx;
++err:
++ devm_kfree(dev, ctx);
++ return NULL;
++}
++
++static int fdt_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ struct xgene_pmu_dev_ctx *ctx;
++ struct device_node *np;
++
++ for_each_child_of_node(pdev->dev.of_node, np) {
++ if (!of_device_is_available(np))
++ continue;
++
++ if (of_device_is_compatible(np, "apm,xgene-pmu-l3c"))
++ ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_L3C);
++ else if (of_device_is_compatible(np, "apm,xgene-pmu-iob"))
++ ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_IOB);
++ else if (of_device_is_compatible(np, "apm,xgene-pmu-mcb"))
++ ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_MCB);
++ else if (of_device_is_compatible(np, "apm,xgene-pmu-mc"))
++ ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_MC);
++ else
++ ctx = NULL;
++
++ if (!ctx)
++ continue;
++
++ if (xgene_pmu_dev_add(xgene_pmu, ctx))
++ continue;
++
++ switch (ctx->inf.type) {
++ case PMU_TYPE_L3C:
++ list_add(&ctx->next, &xgene_pmu->l3cpmus);
++ break;
++ case PMU_TYPE_IOB:
++ list_add(&ctx->next, &xgene_pmu->iobpmus);
++ break;
++ case PMU_TYPE_MCB:
++ list_add(&ctx->next, &xgene_pmu->mcbpmus);
++ break;
++ case PMU_TYPE_MC:
++ list_add(&ctx->next, &xgene_pmu->mcpmus);
++ break;
++ }
++ }
++
++ return 0;
++}
++
++static int xgene_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
++ struct platform_device *pdev)
++{
++ if (has_acpi_companion(&pdev->dev))
++ return acpi_pmu_probe_pmu_dev(xgene_pmu, pdev);
++ return fdt_pmu_probe_pmu_dev(xgene_pmu, pdev);
++}
++
++static const struct xgene_pmu_data xgene_pmu_data = {
++ .id = PCP_PMU_V1,
++ .data = 0,
++};
++
++static const struct xgene_pmu_data xgene_pmu_v2_data = {
++ .id = PCP_PMU_V2,
++ .data = 0,
++};
++
++static const struct of_device_id xgene_pmu_of_match[] = {
++ { .compatible = "apm,xgene-pmu", .data = &xgene_pmu_data },
++ { .compatible = "apm,xgene-pmu-v2", .data = &xgene_pmu_v2_data },
++ {},
++};
++MODULE_DEVICE_TABLE(of, xgene_pmu_of_match);
++#ifdef CONFIG_ACPI
++static const struct acpi_device_id xgene_pmu_acpi_match[] = {
++ {"APMC0D5B", PCP_PMU_V1},
++ {"APMC0D5C", PCP_PMU_V2},
++ {},
++};
++MODULE_DEVICE_TABLE(acpi, xgene_pmu_acpi_match);
++#endif
++
++static int xgene_pmu_probe(struct platform_device *pdev)
++{
++ const struct xgene_pmu_data *dev_data;
++ const struct of_device_id *of_id;
++ struct xgene_pmu *xgene_pmu;
++ struct resource *res;
++ int version, dev_id;
++ int irq, rc;
++
++ xgene_pmu = devm_kzalloc(&pdev->dev, sizeof(*xgene_pmu), GFP_KERNEL);
++ if (!xgene_pmu)
++ return -ENOMEM;
++ xgene_pmu->dev = &pdev->dev;
++ platform_set_drvdata(pdev, xgene_pmu);
++
++ dev_id = -EINVAL;
++ of_id = of_match_device(xgene_pmu_of_match, &pdev->dev);
++ if (of_id) {
++ dev_data = (const struct xgene_pmu_data *) of_id->data;
++ dev_id = dev_data->id;
++ }
++
++#ifdef CONFIG_ACPI
++ if (ACPI_COMPANION(&pdev->dev)) {
++ const struct acpi_device_id *acpi_id;
++
++ acpi_id = acpi_match_device(xgene_pmu_acpi_match, &pdev->dev);
++ if (acpi_id)
++ dev_id = (int) acpi_id->driver_data;
++ }
++#endif
++ if (dev_id < 0)
++ return -ENODEV;
++
++ version = (dev_id == PCP_PMU_V1) ? 1 : 2;
++
++ INIT_LIST_HEAD(&xgene_pmu->l3cpmus);
++ INIT_LIST_HEAD(&xgene_pmu->iobpmus);
++ INIT_LIST_HEAD(&xgene_pmu->mcbpmus);
++ INIT_LIST_HEAD(&xgene_pmu->mcpmus);
++
++ xgene_pmu->version = version;
++ dev_info(&pdev->dev, "X-Gene PMU version %d\n", xgene_pmu->version);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ xgene_pmu->pcppmu_csr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(xgene_pmu->pcppmu_csr)) {
++ dev_err(&pdev->dev, "ioremap failed for PCP PMU resource\n");
++ rc = PTR_ERR(xgene_pmu->pcppmu_csr);
++ goto err;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "No IRQ resource\n");
++ rc = -EINVAL;
++ goto err;
++ }
++ rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr, IRQF_SHARED,
++ dev_name(&pdev->dev), xgene_pmu);
++ if (rc) {
++ dev_err(&pdev->dev, "Could not request IRQ %d\n", irq);
++ goto err;
++ }
++
++ /* Check for active MCBs and MCUs */
++ rc = xgene_pmu_probe_active_mcb_mcu(xgene_pmu, pdev);
++ if (rc) {
++ dev_warn(&pdev->dev, "Unknown MCB/MCU active status\n");
++ xgene_pmu->mcb_active_mask = 0x1;
++ xgene_pmu->mc_active_mask = 0x1;
++ }
++
++ /* Pick one core to use for cpumask attributes */
++ cpumask_set_cpu(smp_processor_id(), &xgene_pmu->cpu);
++
++ /* Enable interrupt */
++ xgene_pmu_unmask_int(xgene_pmu);
++
++ /* Walk through the tree for all PMU perf devices */
++ rc = xgene_pmu_probe_pmu_dev(xgene_pmu, pdev);
++ if (rc) {
++ dev_err(&pdev->dev, "No PMU perf devices found!\n");
++ goto err;
++ }
++
++ return 0;
++
++err:
++ if (xgene_pmu->pcppmu_csr)
++ devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr);
++ devm_kfree(&pdev->dev, xgene_pmu);
++
++ return rc;
++}
++
++static void
++xgene_pmu_dev_cleanup(struct xgene_pmu *xgene_pmu, struct list_head *pmus)
++{
++ struct xgene_pmu_dev_ctx *ctx, *temp_ctx;
++ struct device *dev = xgene_pmu->dev;
++ struct xgene_pmu_dev *pmu_dev;
++
++ list_for_each_entry_safe(ctx, temp_ctx, pmus, next) {
++ pmu_dev = ctx->pmu_dev;
++ if (pmu_dev->inf->csr)
++ devm_iounmap(dev, pmu_dev->inf->csr);
++ devm_kfree(dev, ctx);
++ devm_kfree(dev, pmu_dev);
++ }
++}
++
++static int xgene_pmu_remove(struct platform_device *pdev)
++{
++ struct xgene_pmu *xgene_pmu = dev_get_drvdata(&pdev->dev);
++
++ xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->l3cpmus);
++ xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->iobpmus);
++ xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcbpmus);
++ xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcpmus);
++
++ if (xgene_pmu->pcppmu_csr)
++ devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr);
++ devm_kfree(&pdev->dev, xgene_pmu);
++
++ return 0;
++}
++
++static struct platform_driver xgene_pmu_driver = {
++ .probe = xgene_pmu_probe,
++ .remove = xgene_pmu_remove,
++ .driver = {
++ .name = "xgene-pmu",
++ .of_match_table = xgene_pmu_of_match,
++ .acpi_match_table = ACPI_PTR(xgene_pmu_acpi_match),
++ },
++};
++
++module_platform_driver(xgene_pmu_driver);
++
++MODULE_DESCRIPTION("APM X-Gene SoC PMU driver");
++MODULE_AUTHOR("Hoan Tran <hotran@apm.com>");
++MODULE_AUTHOR("Tai Nguyen <ttnguyen@apm.com>");
++MODULE_LICENSE("GPL");
diff --git a/patches.arch/arm64-3-6-arm64-perf-Changed-events-naming-as-per-ARM-ARM.patch b/patches.arch/arm64-3-6-arm64-perf-Changed-events-naming-as-per-ARM-ARM.patch
new file mode 100644
index 0000000000..5b30ab5289
--- /dev/null
+++ b/patches.arch/arm64-3-6-arm64-perf-Changed-events-naming-as-per-ARM-ARM.patch
@@ -0,0 +1,456 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,3/6] arm64/perf: Changed events naming as per ARM ARM
+From: Ashok Kumar <ashoks@broadcom.com>
+X-Patchwork-Id: 8800921
+Message-Id: <1460379741-1181-4-git-send-email-ashoks@broadcom.com>
+To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+ mark.rutland@arm.com, will.deacon@arm.com, Suzuki.Poulose@arm.com,
+ robh+dt@kernel.org, catalin.marinas@arm.com
+Cc: jchandra@broadcom.com, Ashok Kumar <ashoks@broadcom.com>,
+ jglauber@cavium.com
+Date: Mon, 11 Apr 2016 06:02:18 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8800921
+
+changed all the events name definition as per ARM ARM
+naming convention.
+
+Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+arch/arm64/kernel/perf_event.c | 302 ++++++++++++++++++++---------------------
+ arch/arm64/kernel/perf_event.c | 301 ++++++++++++++++++++---------------------
+ 1 file changed, 150 insertions(+), 151 deletions(-)
+
+--- a/arch/arm64/kernel/perf_event.c
++++ b/arch/arm64/kernel/perf_event.c
+@@ -33,43 +33,43 @@
+ */
+
+ /* Required events. */
+-#define ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR 0x00
+-#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL 0x03
+-#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS 0x04
+-#define ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED 0x10
+-#define ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES 0x11
+-#define ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED 0x12
++#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00
++#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
++#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04
++#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10
++#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11
++#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12
+
+ /* At least one of the following is required. */
+-#define ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED 0x08
+-#define ARMV8_PMUV3_PERFCTR_OP_SPEC 0x1B
++#define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x08
++#define ARMV8_PMUV3_PERFCTR_INST_SPEC 0x1B
+
+ /* Common architectural events. */
+-#define ARMV8_PMUV3_PERFCTR_MEM_READ 0x06
+-#define ARMV8_PMUV3_PERFCTR_MEM_WRITE 0x07
++#define ARMV8_PMUV3_PERFCTR_LD_RETIRED 0x06
++#define ARMV8_PMUV3_PERFCTR_ST_RETIRED 0x07
+ #define ARMV8_PMUV3_PERFCTR_EXC_TAKEN 0x09
+-#define ARMV8_PMUV3_PERFCTR_EXC_EXECUTED 0x0A
+-#define ARMV8_PMUV3_PERFCTR_CID_WRITE 0x0B
+-#define ARMV8_PMUV3_PERFCTR_PC_WRITE 0x0C
+-#define ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH 0x0D
+-#define ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN 0x0E
+-#define ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS 0x0F
+-#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE 0x1C
++#define ARMV8_PMUV3_PERFCTR_EXC_RETURN 0x0A
++#define ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED 0x0B
++#define ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED 0x0C
++#define ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED 0x0D
++#define ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED 0x0E
++#define ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED 0x0F
++#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED 0x1C
+ #define ARMV8_PMUV3_PERFCTR_CHAIN 0x1E
+ #define ARMV8_PMUV3_PERFCTR_BR_RETIRED 0x21
+
+ /* Common microarchitectural events. */
+-#define ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL 0x01
+-#define ARMV8_PMUV3_PERFCTR_ITLB_REFILL 0x02
+-#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL 0x05
++#define ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL 0x01
++#define ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL 0x02
++#define ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL 0x05
+ #define ARMV8_PMUV3_PERFCTR_MEM_ACCESS 0x13
+-#define ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS 0x14
+-#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB 0x15
+-#define ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS 0x16
+-#define ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL 0x17
+-#define ARMV8_PMUV3_PERFCTR_L2_CACHE_WB 0x18
++#define ARMV8_PMUV3_PERFCTR_L1I_CACHE 0x14
++#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB 0x15
++#define ARMV8_PMUV3_PERFCTR_L2D_CACHE 0x16
++#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL 0x17
++#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB 0x18
+ #define ARMV8_PMUV3_PERFCTR_BUS_ACCESS 0x19
+-#define ARMV8_PMUV3_PERFCTR_MEM_ERROR 0x1A
++#define ARMV8_PMUV3_PERFCTR_MEMORY_ERROR 0x1A
+ #define ARMV8_PMUV3_PERFCTR_BUS_CYCLES 0x1D
+ #define ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE 0x1F
+ #define ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE 0x20
+@@ -85,71 +85,71 @@
+ #define ARMV8_PMUV3_PERFCTR_L3D_CACHE 0x2B
+ #define ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB 0x2C
+ #define ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL 0x2D
+-#define ARMV8_PMUV3_PERFCTR_L21_TLB_REFILL 0x2E
++#define ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL 0x2E
+ #define ARMV8_PMUV3_PERFCTR_L2D_TLB 0x2F
+-#define ARMV8_PMUV3_PERFCTR_L21_TLB 0x30
+-
+-/* ARMv8 implementation defined event types. */
+-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD 0x40
+-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST 0x41
+-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD 0x42
+-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST 0x43
+-#define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD 0x4C
+-#define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST 0x4D
+-#define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD 0x4E
+-#define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST 0x4F
++#define ARMV8_PMUV3_PERFCTR_L2I_TLB 0x30
++
++/* ARMv8 recommended implementation defined event types */
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD 0x40
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x41
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD 0x42
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x43
++#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x4C
++#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x4D
++#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x4E
++#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x4F
+
+ /* ARMv8 Cortex-A53 specific event types. */
+ #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL 0xC2
+
+ /* ARMv8 Cavium ThunderX specific event types. */
+-#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST 0xE9
+-#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS 0xEA
+-#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS 0xEB
+-#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS 0xEC
+-#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS 0xED
++#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_MISS_ST 0xE9
++#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS 0xEA
++#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS 0xEB
++#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS 0xEC
++#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS 0xED
+
+ /* PMUv3 HW events mapping. */
+ static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
+- [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
+- [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+- [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+- [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
++ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
++ [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
+ /* ARM Cortex-A53 HW events mapping. */
+ static const unsigned armv8_a53_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
+- [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
+- [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+- [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+- [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE,
+- [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
++ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
++ [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
++ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
+ };
+
+ /* ARM Cortex-A57 and Cortex-A72 events mapping. */
+ static const unsigned armv8_a57_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
+- [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
+- [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+- [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+- [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
++ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
++ [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
+ };
+
+ static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
+- [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
+- [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+- [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+- [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE,
+- [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
++ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
++ [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
++ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
+ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
+ };
+@@ -158,15 +157,15 @@ static const unsigned armv8_pmuv3_perf_c
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+- [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+-
+- [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++
++ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
+ static const unsigned armv8_a53_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+@@ -175,21 +175,21 @@ static const unsigned armv8_a53_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+- [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
++ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+ [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREFETCH_LINEFILL,
+
+- [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
+- [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
++ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE,
++ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
+
+- [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
++ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
+
+- [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
+ static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+@@ -196,23 +195,23 @@ static const unsigned armv8_a57_perf_cac
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+- [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD,
+- [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST,
+-
+- [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
+- [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
+-
+- [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD,
+- [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST,
+-
+- [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+-
+- [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
++ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
++
++ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE,
++ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
++
++ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
++ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
++
++ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
++
++ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
+ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+@@ -220,29 +219,29 @@ static const unsigned armv8_thunder_perf
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+- [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD,
+- [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST,
+- [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST,
+- [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS,
+- [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS,
+-
+- [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
+- [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
+- [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS,
+- [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS,
+-
+- [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD,
+- [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD,
+- [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST,
+- [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST,
+-
+- [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+-
+- [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+- [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
++ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
++ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_MISS_ST,
++ [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS,
++ [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS,
++
++ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE,
++ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
++ [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS,
++ [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS,
++
++ [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
++ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
++ [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
++ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
++
++ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
++
++ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
+ #define ARMV8_EVENT_ATTR_RESOLVE(m) #m
+@@ -250,35 +249,35 @@ static const unsigned armv8_thunder_perf
+ PMU_EVENT_ATTR_STRING(name, armv8_event_attr_##name, \
+ "event=" ARMV8_EVENT_ATTR_RESOLVE(config))
+
+-ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR);
+-ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL);
+-ARMV8_EVENT_ATTR(l1i_tlb_refill, ARMV8_PMUV3_PERFCTR_ITLB_REFILL);
+-ARMV8_EVENT_ATTR(l1d_cache_refill, ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL);
+-ARMV8_EVENT_ATTR(l1d_cache, ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS);
+-ARMV8_EVENT_ATTR(l1d_tlb_refill, ARMV8_PMUV3_PERFCTR_DTLB_REFILL);
+-ARMV8_EVENT_ATTR(ld_retired, ARMV8_PMUV3_PERFCTR_MEM_READ);
+-ARMV8_EVENT_ATTR(st_retired, ARMV8_PMUV3_PERFCTR_MEM_WRITE);
+-ARMV8_EVENT_ATTR(inst_retired, ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED);
++ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR);
++ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL);
++ARMV8_EVENT_ATTR(l1i_tlb_refill, ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL);
++ARMV8_EVENT_ATTR(l1d_cache_refill, ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL);
++ARMV8_EVENT_ATTR(l1d_cache, ARMV8_PMUV3_PERFCTR_L1D_CACHE);
++ARMV8_EVENT_ATTR(l1d_tlb_refill, ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL);
++ARMV8_EVENT_ATTR(ld_retired, ARMV8_PMUV3_PERFCTR_LD_RETIRED);
++ARMV8_EVENT_ATTR(st_retired, ARMV8_PMUV3_PERFCTR_ST_RETIRED);
++ARMV8_EVENT_ATTR(inst_retired, ARMV8_PMUV3_PERFCTR_INST_RETIRED);
+ ARMV8_EVENT_ATTR(exc_taken, ARMV8_PMUV3_PERFCTR_EXC_TAKEN);
+-ARMV8_EVENT_ATTR(exc_return, ARMV8_PMUV3_PERFCTR_EXC_EXECUTED);
+-ARMV8_EVENT_ATTR(cid_write_retired, ARMV8_PMUV3_PERFCTR_CID_WRITE);
+-ARMV8_EVENT_ATTR(pc_write_retired, ARMV8_PMUV3_PERFCTR_PC_WRITE);
+-ARMV8_EVENT_ATTR(br_immed_retired, ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH);
+-ARMV8_EVENT_ATTR(br_return_retired, ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN);
+-ARMV8_EVENT_ATTR(unaligned_ldst_retired, ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS);
+-ARMV8_EVENT_ATTR(br_mis_pred, ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED);
+-ARMV8_EVENT_ATTR(cpu_cycles, ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES);
+-ARMV8_EVENT_ATTR(br_pred, ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED);
++ARMV8_EVENT_ATTR(exc_return, ARMV8_PMUV3_PERFCTR_EXC_RETURN);
++ARMV8_EVENT_ATTR(cid_write_retired, ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED);
++ARMV8_EVENT_ATTR(pc_write_retired, ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED);
++ARMV8_EVENT_ATTR(br_immed_retired, ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED);
++ARMV8_EVENT_ATTR(br_return_retired, ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED);
++ARMV8_EVENT_ATTR(unaligned_ldst_retired, ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED);
++ARMV8_EVENT_ATTR(br_mis_pred, ARMV8_PMUV3_PERFCTR_BR_MIS_PRED);
++ARMV8_EVENT_ATTR(cpu_cycles, ARMV8_PMUV3_PERFCTR_CPU_CYCLES);
++ARMV8_EVENT_ATTR(br_pred, ARMV8_PMUV3_PERFCTR_BR_PRED);
+ ARMV8_EVENT_ATTR(mem_access, ARMV8_PMUV3_PERFCTR_MEM_ACCESS);
+-ARMV8_EVENT_ATTR(l1i_cache, ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS);
+-ARMV8_EVENT_ATTR(l1d_cache_wb, ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB);
+-ARMV8_EVENT_ATTR(l2d_cache, ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS);
+-ARMV8_EVENT_ATTR(l2d_cache_refill, ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL);
+-ARMV8_EVENT_ATTR(l2d_cache_wb, ARMV8_PMUV3_PERFCTR_L2_CACHE_WB);
++ARMV8_EVENT_ATTR(l1i_cache, ARMV8_PMUV3_PERFCTR_L1I_CACHE);
++ARMV8_EVENT_ATTR(l1d_cache_wb, ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB);
++ARMV8_EVENT_ATTR(l2d_cache, ARMV8_PMUV3_PERFCTR_L2D_CACHE);
++ARMV8_EVENT_ATTR(l2d_cache_refill, ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL);
++ARMV8_EVENT_ATTR(l2d_cache_wb, ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB);
+ ARMV8_EVENT_ATTR(bus_access, ARMV8_PMUV3_PERFCTR_BUS_ACCESS);
+-ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEM_ERROR);
+-ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_OP_SPEC);
+-ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE);
++ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEMORY_ERROR);
++ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_INST_SPEC);
++ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED);
+ ARMV8_EVENT_ATTR(bus_cycles, ARMV8_PMUV3_PERFCTR_BUS_CYCLES);
+ ARMV8_EVENT_ATTR(chain, ARMV8_PMUV3_PERFCTR_CHAIN);
+ ARMV8_EVENT_ATTR(l1d_cache_allocate, ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE);
+@@ -296,9 +295,9 @@ ARMV8_EVENT_ATTR(l3d_cache_refill, ARMV8
+ ARMV8_EVENT_ATTR(l3d_cache, ARMV8_PMUV3_PERFCTR_L3D_CACHE);
+ ARMV8_EVENT_ATTR(l3d_cache_wb, ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB);
+ ARMV8_EVENT_ATTR(l2d_tlb_refill, ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL);
+-ARMV8_EVENT_ATTR(l21_tlb_refill, ARMV8_PMUV3_PERFCTR_L21_TLB_REFILL);
++ARMV8_EVENT_ATTR(l2i_tlb_refill, ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL);
+ ARMV8_EVENT_ATTR(l2d_tlb, ARMV8_PMUV3_PERFCTR_L2D_TLB);
+-ARMV8_EVENT_ATTR(l21_tlb, ARMV8_PMUV3_PERFCTR_L21_TLB);
++ARMV8_EVENT_ATTR(l2i_tlb, ARMV8_PMUV3_PERFCTR_L2I_TLB);
+
+ static struct attribute *armv8_pmuv3_event_attrs[] = {
+ &armv8_event_attr_sw_incr.attr.attr,
+@@ -347,9 +346,9 @@ static struct attribute *armv8_pmuv3_eve
+ &armv8_event_attr_l3d_cache.attr.attr,
+ &armv8_event_attr_l3d_cache_wb.attr.attr,
+ &armv8_event_attr_l2d_tlb_refill.attr.attr,
+- &armv8_event_attr_l21_tlb_refill.attr.attr,
++ &armv8_event_attr_l2i_tlb_refill.attr.attr,
+ &armv8_event_attr_l2d_tlb.attr.attr,
+- &armv8_event_attr_l21_tlb.attr.attr,
++ &armv8_event_attr_l2i_tlb.attr.attr,
+ NULL,
+ };
+
+@@ -720,7 +719,7 @@ static int armv8pmu_get_event_idx(struct
+ unsigned long evtype = hwc->config_base & ARMV8_EVTYPE_EVENT;
+
+ /* Always place a cycle counter into the cycle counter. */
+- if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
++ if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
+ if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
+ return -EAGAIN;
+
diff --git a/patches.arch/arm64-4-4-arm64-dts-apm-Add-APM-X-Gene-SoC-PMU-DTS-entries.patch b/patches.arch/arm64-4-4-arm64-dts-apm-Add-APM-X-Gene-SoC-PMU-DTS-entries.patch
new file mode 100644
index 0000000000..66e3d9b483
--- /dev/null
+++ b/patches.arch/arm64-4-4-arm64-dts-apm-Add-APM-X-Gene-SoC-PMU-DTS-entries.patch
@@ -0,0 +1,93 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,4/4] arm64: dts: apm: Add APM X-Gene SoC PMU DTS entries
+From: Tai Nguyen <ttnguyen@apm.com>
+X-Patchwork-Id: 8817891
+Message-Id: <1460510547-17611-5-git-send-email-ttnguyen@apm.com>
+To: mark.rutland@arm.com,
+ will.deacon@arm.com,
+ catalin.marinas@arm.com
+Cc: devicetree@vger.kernel.org, patches@apm.com, linux-kernel@vger.kernel.org,
+ linux-arm-kernel@lists.infradead.org, Tai Nguyen <ttnguyen@apm.com>
+Date: Tue, 12 Apr 2016 18:22:27 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8817891
+
+Signed-off-by: Tai Nguyen <ttnguyen@apm.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+arch/arm64/boot/dts/apm/apm-storm.dtsi | 60 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 60 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
+index fe30f76..975948d 100644
+--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
++++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
+@@ -566,6 +566,66 @@
+ };
+ };
+
++ pmu: pmu@78810000 {
++ compatible = "apm,xgene-pmu-v2";
++ #address-cells = <2>;
++ #size-cells = <2>;
++ ranges;
++ regmap-csw = <&csw>;
++ regmap-mcba = <&mcba>;
++ regmap-mcbb = <&mcbb>;
++ reg = <0x0 0x78810000 0x0 0x1000>;
++ interrupts = <0x0 0x22 0x4>;
++
++ pmul3c@7e610000 {
++ compatible = "apm,xgene-pmu-l3c";
++ reg = <0x0 0x7e610000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmuiob@7e940000 {
++ compatible = "apm,xgene-pmu-iob";
++ reg = <0x0 0x7e940000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmucmcb@7e710000 {
++ compatible = "apm,xgene-pmu-mcb";
++ reg = <0x0 0x7e710000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmucmcb@7e730000 {
++ compatible = "apm,xgene-pmu-mcb";
++ reg = <0x0 0x7e730000 0x0 0x1000>;
++ index = <1>;
++ };
++
++ pmucmc@7e810000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e810000 0x0 0x1000>;
++ index = <0>;
++ };
++
++ pmucmc@7e850000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e850000 0x0 0x1000>;
++ index = <1>;
++ };
++
++ pmucmc@7e890000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e890000 0x0 0x1000>;
++ index = <2>;
++ };
++
++ pmucmc@7e8d0000 {
++ compatible = "apm,xgene-pmu-mc";
++ reg = <0x0 0x7e8d0000 0x0 0x1000>;
++ index = <3>;
++ };
++ };
++
+ pcie0: pcie@1f2b0000 {
+ status = "disabled";
+ device_type = "pci";
diff --git a/patches.arch/arm64-4-6-arm64-perf-Define-complete-ARMv8-recommended-implementation-defined-events.patch b/patches.arch/arm64-4-6-arm64-perf-Define-complete-ARMv8-recommended-implementation-defined-events.patch
new file mode 100644
index 0000000000..5279a1b35c
--- /dev/null
+++ b/patches.arch/arm64-4-6-arm64-perf-Define-complete-ARMv8-recommended-implementation-defined-events.patch
@@ -0,0 +1,121 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4, 4/6] arm64/perf: Define complete ARMv8 recommended implementation
+ defined events
+From: Ashok Kumar <ashoks@broadcom.com>
+X-Patchwork-Id: 8801041
+Message-Id: <1460379741-1181-5-git-send-email-ashoks@broadcom.com>
+To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+ mark.rutland@arm.com, will.deacon@arm.com, Suzuki.Poulose@arm.com,
+ robh+dt@kernel.org, catalin.marinas@arm.com
+Cc: jchandra@broadcom.com, Ashok Kumar <ashoks@broadcom.com>,
+ jglauber@cavium.com
+Date: Mon, 11 Apr 2016 06:02:19 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8801041
+
+Defined all the ARMv8 recommended implementation defined events
+from J3 - "ARM recommendations for IMPLEMENTATION DEFINED event numbers"
+in ARMv8 ARM.
+
+Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+arch/arm64/kernel/perf_event.c | 79 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 79 insertions(+)
+
+diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
+index 59d5091..2ee61e8 100644
+--- a/arch/arm64/kernel/perf_event.c
++++ b/arch/arm64/kernel/perf_event.c
+@@ -94,10 +94,89 @@
+ #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR 0x41
+ #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD 0x42
+ #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR 0x43
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_INNER 0x44
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_OUTER 0x45
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_VICTIM 0x46
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_CLEAN 0x47
++#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_INVAL 0x48
++
+ #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD 0x4C
+ #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR 0x4D
+ #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD 0x4E
+ #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR 0x4F
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_RD 0x50
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WR 0x51
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_RD 0x52
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_WR 0x53
++
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_VICTIM 0x56
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_CLEAN 0x57
++#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_INVAL 0x58
++
++#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_RD 0x5C
++#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_WR 0x5D
++#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_RD 0x5E
++#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_WR 0x5F
++
++#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD 0x60
++#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR 0x61
++#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_SHARED 0x62
++#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NOT_SHARED 0x63
++#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NORMAL 0x64
++#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_PERIPH 0x65
++
++#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_RD 0x66
++#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_WR 0x67
++#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LD_SPEC 0x68
++#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_ST_SPEC 0x69
++#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LDST_SPEC 0x6A
++
++#define ARMV8_IMPDEF_PERFCTR_LDREX_SPEC 0x6C
++#define ARMV8_IMPDEF_PERFCTR_STREX_PASS_SPEC 0x6D
++#define ARMV8_IMPDEF_PERFCTR_STREX_FAIL_SPEC 0x6E
++#define ARMV8_IMPDEF_PERFCTR_STREX_SPEC 0x6F
++#define ARMV8_IMPDEF_PERFCTR_LD_SPEC 0x70
++#define ARMV8_IMPDEF_PERFCTR_ST_SPEC 0x71
++#define ARMV8_IMPDEF_PERFCTR_LDST_SPEC 0x72
++#define ARMV8_IMPDEF_PERFCTR_DP_SPEC 0x73
++#define ARMV8_IMPDEF_PERFCTR_ASE_SPEC 0x74
++#define ARMV8_IMPDEF_PERFCTR_VFP_SPEC 0x75
++#define ARMV8_IMPDEF_PERFCTR_PC_WRITE_SPEC 0x76
++#define ARMV8_IMPDEF_PERFCTR_CRYPTO_SPEC 0x77
++#define ARMV8_IMPDEF_PERFCTR_BR_IMMED_SPEC 0x78
++#define ARMV8_IMPDEF_PERFCTR_BR_RETURN_SPEC 0x79
++#define ARMV8_IMPDEF_PERFCTR_BR_INDIRECT_SPEC 0x7A
++
++#define ARMV8_IMPDEF_PERFCTR_ISB_SPEC 0x7C
++#define ARMV8_IMPDEF_PERFCTR_DSB_SPEC 0x7D
++#define ARMV8_IMPDEF_PERFCTR_DMB_SPEC 0x7E
++
++#define ARMV8_IMPDEF_PERFCTR_EXC_UNDEF 0x81
++#define ARMV8_IMPDEF_PERFCTR_EXC_SVC 0x82
++#define ARMV8_IMPDEF_PERFCTR_EXC_PABORT 0x83
++#define ARMV8_IMPDEF_PERFCTR_EXC_DABORT 0x84
++
++#define ARMV8_IMPDEF_PERFCTR_EXC_IRQ 0x86
++#define ARMV8_IMPDEF_PERFCTR_EXC_FIQ 0x87
++#define ARMV8_IMPDEF_PERFCTR_EXC_SMC 0x88
++
++#define ARMV8_IMPDEF_PERFCTR_EXC_HVC 0x8A
++#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_PABORT 0x8B
++#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_DABORT 0x8C
++#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_OTHER 0x8D
++#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_IRQ 0x8E
++#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_FIQ 0x8F
++#define ARMV8_IMPDEF_PERFCTR_RC_LD_SPEC 0x90
++#define ARMV8_IMPDEF_PERFCTR_RC_ST_SPEC 0x91
++
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_RD 0xA0
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WR 0xA1
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_RD 0xA2
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_WR 0xA3
++
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_VICTIM 0xA6
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_CLEAN 0xA7
++#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_INVAL 0xA8
+
+ /* ARMv8 Cortex-A53 specific event types. */
+ #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL 0xC2
diff --git a/patches.arch/arm64-5-6-arm64-perf-Filter-common-events-based-on-PMCEIDn_EL0.patch b/patches.arch/arm64-5-6-arm64-perf-Filter-common-events-based-on-PMCEIDn_EL0.patch
new file mode 100644
index 0000000000..7c6394d7fb
--- /dev/null
+++ b/patches.arch/arm64-5-6-arm64-perf-Filter-common-events-based-on-PMCEIDn_EL0.patch
@@ -0,0 +1,185 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,5/6] arm64/perf: Filter common events based on PMCEIDn_EL0
+From: Ashok Kumar <ashoks@broadcom.com>
+X-Patchwork-Id: 8801011
+Message-Id: <1460379741-1181-6-git-send-email-ashoks@broadcom.com>
+To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+ mark.rutland@arm.com, will.deacon@arm.com, Suzuki.Poulose@arm.com,
+ robh+dt@kernel.org, catalin.marinas@arm.com
+Cc: jchandra@broadcom.com, Ashok Kumar <ashoks@broadcom.com>,
+ jglauber@cavium.com
+Date: Mon, 11 Apr 2016 06:02:20 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8801011
+
+The complete common architectural and micro-architectural
+event number structure is filtered based on PMCEIDn_EL0 and
+exposed to /sys using is_visibile function pointer in events
+attribute_group.
+To filter the events in is_visible function, pmceid based bitmap
+is stored in arm_pmu structure and the id field from
+perf_pmu_events_attr is used to check against the bitmap.
+
+The function which derives event bitmap from PMCEIDn_EL0 is
+executed in the cpus, which has the pmu being initialized,
+for heterogeneous pmu support.
+
+Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+arch/arm64/kernel/perf_event.c | 74 +++++++++++++++++++++++++++++++++++-------
+ arch/arm64/kernel/perf_event.c | 74 ++++++++++++++++++++++++++++++++++-------
+ include/linux/perf/arm_pmu.h | 2 +
+ 2 files changed, 65 insertions(+), 11 deletions(-)
+
+--- a/arch/arm64/kernel/perf_event.c
++++ b/arch/arm64/kernel/perf_event.c
+@@ -323,10 +323,22 @@ static const unsigned armv8_thunder_perf
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
++
++static ssize_t
++armv8pmu_events_sysfs_show(struct device *dev,
++ struct device_attribute *attr, char *page)
++{
++ struct perf_pmu_events_attr *pmu_attr;
++
++ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
++
++ return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
++}
++
+ #define ARMV8_EVENT_ATTR_RESOLVE(m) #m
+ #define ARMV8_EVENT_ATTR(name, config) \
+- PMU_EVENT_ATTR_STRING(name, armv8_event_attr_##name, \
+- "event=" ARMV8_EVENT_ATTR_RESOLVE(config))
++ PMU_EVENT_ATTR(name, armv8_event_attr_##name, \
++ config, armv8pmu_events_sysfs_show)
+
+ ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR);
+ ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL);
+@@ -431,9 +443,27 @@ static struct attribute *armv8_pmuv3_eve
+ NULL,
+ };
+
++static umode_t
++armv8pmu_event_attr_is_visible(struct kobject *kobj,
++ struct attribute *attr, int unused)
++{
++ struct device *dev = kobj_to_dev(kobj);
++ struct pmu *pmu = dev_get_drvdata(dev);
++ struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu);
++ struct perf_pmu_events_attr *pmu_attr;
++
++ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
++
++ if (test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap))
++ return attr->mode;
++
++ return 0;
++}
++
+ static struct attribute_group armv8_pmuv3_events_attr_group = {
+ .name = "events",
+ .attrs = armv8_pmuv3_event_attrs,
++ .is_visible = armv8pmu_event_attr_is_visible,
+ };
+
+ PMU_FORMAT_ATTR(event, "config:0-9");
+@@ -904,11 +934,32 @@ static void armv8pmu_read_num_pmnc_event
+ *nb_cnt += 1;
+ }
+
+-static int armv8pmu_probe_num_events(struct arm_pmu *arm_pmu)
++static void armv8pmu_read_common_events_bitmap(unsigned long *bmp)
+ {
+- return smp_call_function_any(&arm_pmu->supported_cpus,
+- armv8pmu_read_num_pmnc_events,
+- &arm_pmu->num_events, 1);
++ u32 arr[2], reg;
++
++ asm volatile("mrs %0, pmceid0_el0" : "=r" (reg));
++ arr[0] = reg;
++ asm volatile("mrs %0, pmceid1_el0" : "=r" (reg));
++ arr[1] = reg;
++
++ bitmap_from_u32array(bmp, ARMV8_PMUV3_MAX_COMMON_EVENTS,
++ arr, ARRAY_SIZE(arr));
++}
++
++static void __armv8pmu_probe_pmu(void *info)
++{
++ struct arm_pmu *cpu_pmu = info;
++
++ armv8pmu_read_num_pmnc_events(&cpu_pmu->num_events);
++ armv8pmu_read_common_events_bitmap(cpu_pmu->pmceid_bitmap);
++}
++
++static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)
++{
++ return smp_call_function_any(&cpu_pmu->supported_cpus,
++ __armv8pmu_probe_pmu,
++ cpu_pmu, 1);
+ }
+
+ static void armv8_pmu_init(struct arm_pmu *cpu_pmu)
+@@ -931,7 +982,8 @@ static int armv8_pmuv3_init(struct arm_p
+ armv8_pmu_init(cpu_pmu);
+ cpu_pmu->name = "armv8_pmuv3";
+ cpu_pmu->map_event = armv8_pmuv3_map_event;
+- return armv8pmu_probe_num_events(cpu_pmu);
++ cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups;
++ return armv8pmu_probe_pmu(cpu_pmu);
+ }
+
+ static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu)
+@@ -940,7 +992,7 @@ static int armv8_a53_pmu_init(struct arm
+ cpu_pmu->name = "armv8_cortex_a53";
+ cpu_pmu->map_event = armv8_a53_map_event;
+ cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups;
+- return armv8pmu_probe_num_events(cpu_pmu);
++ return armv8pmu_probe_pmu(cpu_pmu);
+ }
+
+ static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu)
+@@ -949,7 +1001,7 @@ static int armv8_a57_pmu_init(struct arm
+ cpu_pmu->name = "armv8_cortex_a57";
+ cpu_pmu->map_event = armv8_a57_map_event;
+ cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups;
+- return armv8pmu_probe_num_events(cpu_pmu);
++ return armv8pmu_probe_pmu(cpu_pmu);
+ }
+
+ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu)
+@@ -958,7 +1010,7 @@ static int armv8_a72_pmu_init(struct arm
+ cpu_pmu->name = "armv8_cortex_a72";
+ cpu_pmu->map_event = armv8_a57_map_event;
+ cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups;
+- return armv8pmu_probe_num_events(cpu_pmu);
++ return armv8pmu_probe_pmu(cpu_pmu);
+ }
+
+ static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
+@@ -967,7 +1019,7 @@ static int armv8_thunder_pmu_init(struct
+ cpu_pmu->name = "armv8_cavium_thunder";
+ cpu_pmu->map_event = armv8_thunder_map_event;
+ cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups;
+- return armv8pmu_probe_num_events(cpu_pmu);
++ return armv8pmu_probe_pmu(cpu_pmu);
+ }
+
+ static const struct of_device_id armv8_pmu_of_device_ids[] = {
+--- a/include/linux/perf/arm_pmu.h
++++ b/include/linux/perf/arm_pmu.h
+@@ -104,6 +104,8 @@ struct arm_pmu {
+ atomic_t active_events;
+ struct mutex reserve_mutex;
+ u64 max_period;
++#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
++ DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
+ struct platform_device *plat_device;
+ struct pmu_hw_events __percpu *hw_events;
+ struct notifier_block hotplug_nb;
diff --git a/patches.arch/arm64-6-6-arm64-perf-Add-Broadcom-Vulcan-PMU-support.patch b/patches.arch/arm64-6-6-arm64-perf-Add-Broadcom-Vulcan-PMU-support.patch
new file mode 100644
index 0000000000..6ae57e2253
--- /dev/null
+++ b/patches.arch/arm64-6-6-arm64-perf-Add-Broadcom-Vulcan-PMU-support.patch
@@ -0,0 +1,124 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v4,6/6] arm64/perf: Add Broadcom Vulcan PMU support
+From: Ashok Kumar <ashoks@broadcom.com>
+X-Patchwork-Id: 8800901
+Message-Id: <1460379741-1181-7-git-send-email-ashoks@broadcom.com>
+To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+ mark.rutland@arm.com, will.deacon@arm.com, Suzuki.Poulose@arm.com,
+ robh+dt@kernel.org, catalin.marinas@arm.com
+Cc: jchandra@broadcom.com, Ashok Kumar <ashoks@broadcom.com>,
+ jglauber@cavium.com
+Date: Mon, 11 Apr 2016 06:02:21 -0700
+Patch-mainline: Submitted, https://patchwork.kernel.org/patch/8800901
+
+Broadcom Vulcan uses ARMv8 PMUv3 and supports most of
+the ARMv8 recommended implementation defined events.
+
+Added Vulcan events mapping for perf and perf_cache map.
+
+Signed-off-by: Ashok Kumar <ashoks@broadcom.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+
+---
+arch/arm64/kernel/perf_event.c | 60 ++++++++++++++++++++++++++++++++++++++++++
+ arch/arm64/kernel/perf_event.c | 60 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 60 insertions(+)
+
+--- a/arch/arm64/kernel/perf_event.c
++++ b/arch/arm64/kernel/perf_event.c
+@@ -231,6 +231,20 @@ static const unsigned armv8_thunder_perf
+ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
+ };
+
++/* Broadcom Vulcan events mapping */
++static const unsigned armv8_vulcan_perf_map[PERF_COUNT_HW_MAX] = {
++ PERF_MAP_ALL_UNSUPPORTED,
++ [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
++ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
++ [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
++ [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
++ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_BR_RETIRED,
++ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++ [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
++ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
++ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
++};
++
+ static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+@@ -323,6 +337,35 @@ static const unsigned armv8_thunder_perf
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+ };
+
++static const unsigned armv8_vulcan_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
++ [PERF_COUNT_HW_CACHE_OP_MAX]
++ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
++ PERF_CACHE_MAP_ALL_UNSUPPORTED,
++
++ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
++ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
++ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
++
++ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE,
++ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
++
++ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
++ [C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB,
++
++ [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
++ [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
++ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
++ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
++
++ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
++ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
++
++ [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
++ [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
++};
+
+ static ssize_t
+ armv8pmu_events_sysfs_show(struct device *dev,
+@@ -923,6 +966,13 @@ static int armv8_thunder_map_event(struc
+ ARMV8_EVTYPE_EVENT);
+ }
+
++static int armv8_vulcan_map_event(struct perf_event *event)
++{
++ return armpmu_map_event(event, &armv8_vulcan_perf_map,
++ &armv8_vulcan_perf_cache_map,
++ ARMV8_EVTYPE_EVENT);
++}
++
+ static void armv8pmu_read_num_pmnc_events(void *info)
+ {
+ int *nb_cnt = info;
+@@ -1022,12 +1072,22 @@ static int armv8_thunder_pmu_init(struct
+ return armv8pmu_probe_pmu(cpu_pmu);
+ }
+
++static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu)
++{
++ armv8_pmu_init(cpu_pmu);
++ cpu_pmu->name = "armv8_brcm_vulcan";
++ cpu_pmu->map_event = armv8_vulcan_map_event;
++ cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups;
++ return armv8pmu_probe_pmu(cpu_pmu);
++}
++
+ static const struct of_device_id armv8_pmu_of_device_ids[] = {
+ {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_init},
+ {.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init},
+ {.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init},
+ {.compatible = "arm,cortex-a72-pmu", .data = armv8_a72_pmu_init},
+ {.compatible = "cavium,thunder-pmu", .data = armv8_thunder_pmu_init},
++ {.compatible = "brcm,vulcan-pmu", .data = armv8_vulcan_pmu_init},
+ {},
+ };
+
diff --git a/patches.arch/arm64-clk-xgene-Add-SoC-and-PMD-PLL-clocks-with-v2-hardwar.patch b/patches.arch/arm64-clk-xgene-Add-SoC-and-PMD-PLL-clocks-with-v2-hardwar.patch
new file mode 100644
index 0000000000..1d3753636c
--- /dev/null
+++ b/patches.arch/arm64-clk-xgene-Add-SoC-and-PMD-PLL-clocks-with-v2-hardwar.patch
@@ -0,0 +1,189 @@
+From: Loc Ho <lho@apm.com>
+Date: Tue, 19 Jan 2016 19:27:42 -0700
+Subject: clk: xgene: Add SoC and PMD PLL clocks with v2 hardware
+Git-commit: 47727beb26569725f6c200cde2c38bd1e9f6f1b0
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+Add X-Gene SoC and PMD PLL clocks support for v2 hardware.
+X-Gene SoC v2 and above use an slightly different SoC
+and PMD PLL hardware logic.
+
+Signed-off-by: Loc Ho <lho@apm.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/clk/clk-xgene.c | 103 +++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 66 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
+index 10224b0..266d573 100644
+--- a/drivers/clk/clk-xgene.c
++++ b/drivers/clk/clk-xgene.c
+@@ -29,7 +29,9 @@
+ #include <linux/of_address.h>
+
+ /* Register SCU_PCPPLL bit fields */
+-#define N_DIV_RD(src) (((src) & 0x000001ff))
++#define N_DIV_RD(src) ((src) & 0x000001ff)
++#define SC_N_DIV_RD(src) ((src) & 0x0000007f)
++#define SC_OUTDIV2(src) (((src) & 0x00000100) >> 8)
+
+ /* Register SCU_SOCPLL bit fields */
+ #define CLKR_RD(src) (((src) & 0x07000000)>>24)
+@@ -63,6 +65,7 @@ struct xgene_clk_pll {
+ spinlock_t *lock;
+ u32 pll_offset;
+ enum xgene_pll_type type;
++ int version;
+ };
+
+ #define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw)
+@@ -92,27 +95,37 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
+
+ pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
+
+- if (pllclk->type == PLL_TYPE_PCP) {
+- /*
+- * PLL VCO = Reference clock * NF
+- * PCP PLL = PLL_VCO / 2
+- */
+- nout = 2;
+- fvco = parent_rate * (N_DIV_RD(pll) + 4);
++ if (pllclk->version <= 1) {
++ if (pllclk->type == PLL_TYPE_PCP) {
++ /*
++ * PLL VCO = Reference clock * NF
++ * PCP PLL = PLL_VCO / 2
++ */
++ nout = 2;
++ fvco = parent_rate * (N_DIV_RD(pll) + 4);
++ } else {
++ /*
++ * Fref = Reference Clock / NREF;
++ * Fvco = Fref * NFB;
++ * Fout = Fvco / NOUT;
++ */
++ nref = CLKR_RD(pll) + 1;
++ nout = CLKOD_RD(pll) + 1;
++ nfb = CLKF_RD(pll);
++ fref = parent_rate / nref;
++ fvco = fref * nfb;
++ }
+ } else {
+ /*
+- * Fref = Reference Clock / NREF;
+- * Fvco = Fref * NFB;
+- * Fout = Fvco / NOUT;
++ * fvco = Reference clock * FBDIVC
++ * PLL freq = fvco / NOUT
+ */
+- nref = CLKR_RD(pll) + 1;
+- nout = CLKOD_RD(pll) + 1;
+- nfb = CLKF_RD(pll);
+- fref = parent_rate / nref;
+- fvco = fref * nfb;
++ nout = SC_OUTDIV2(pll) ? 2 : 3;
++ fvco = parent_rate * SC_N_DIV_RD(pll);
+ }
+- pr_debug("%s pll recalc rate %ld parent %ld\n", clk_hw_get_name(hw),
+- fvco / nout, parent_rate);
++ pr_debug("%s pll recalc rate %ld parent %ld version %d\n",
++ clk_hw_get_name(hw), fvco / nout, parent_rate,
++ pllclk->version);
+
+ return fvco / nout;
+ }
+@@ -125,7 +138,7 @@ static const struct clk_ops xgene_clk_pll_ops = {
+ static struct clk *xgene_register_clk_pll(struct device *dev,
+ const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg, u32 pll_offset,
+- u32 type, spinlock_t *lock)
++ u32 type, spinlock_t *lock, int version)
+ {
+ struct xgene_clk_pll *apmclk;
+ struct clk *clk;
+@@ -144,6 +157,7 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
++ apmclk->version = version;
+ apmclk->reg = reg;
+ apmclk->lock = lock;
+ apmclk->pll_offset = pll_offset;
+@@ -160,26 +174,37 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
+ return clk;
+ }
+
++static int xgene_pllclk_version(struct device_node *np)
++{
++ if (of_device_is_compatible(np, "apm,xgene-socpll-clock"))
++ return 1;
++ if (of_device_is_compatible(np, "apm,xgene-pcppll-clock"))
++ return 1;
++ return 2;
++}
++
+ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type)
+ {
+- const char *clk_name = np->full_name;
+- struct clk *clk;
+- void __iomem *reg;
++ const char *clk_name = np->full_name;
++ struct clk *clk;
++ void __iomem *reg;
++ int version = xgene_pllclk_version(np);
+
+- reg = of_iomap(np, 0);
+- if (reg == NULL) {
+- pr_err("Unable to map CSR register for %s\n", np->full_name);
+- return;
+- }
+- of_property_read_string(np, "clock-output-names", &clk_name);
+- clk = xgene_register_clk_pll(NULL,
+- clk_name, of_clk_get_parent_name(np, 0),
+- CLK_IS_ROOT, reg, 0, pll_type, &clk_lock);
+- if (!IS_ERR(clk)) {
+- of_clk_add_provider(np, of_clk_src_simple_get, clk);
+- clk_register_clkdev(clk, clk_name, NULL);
+- pr_debug("Add %s clock PLL\n", clk_name);
+- }
++ reg = of_iomap(np, 0);
++ if (reg == NULL) {
++ pr_err("Unable to map CSR register for %s\n", np->full_name);
++ return;
++ }
++ of_property_read_string(np, "clock-output-names", &clk_name);
++ clk = xgene_register_clk_pll(NULL,
++ clk_name, of_clk_get_parent_name(np, 0),
++ CLK_IS_ROOT, reg, 0, pll_type, &clk_lock,
++ version);
++ if (!IS_ERR(clk)) {
++ of_clk_add_provider(np, of_clk_src_simple_get, clk);
++ clk_register_clkdev(clk, clk_name, NULL);
++ pr_debug("Add %s clock PLL\n", clk_name);
++ }
+ }
+
+ static void xgene_socpllclk_init(struct device_node *np)
+@@ -460,7 +485,7 @@ static void __init xgene_devclk_init(struct device_node *np)
+ rc = of_address_to_resource(np, i, &res);
+ if (rc != 0) {
+ if (i == 0) {
+- pr_err("no DTS register for %s\n",
++ pr_err("no DTS register for %s\n",
+ np->full_name);
+ return;
+ }
+@@ -518,4 +543,8 @@ err:
+
+ CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init);
+ CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init);
++CLK_OF_DECLARE(xgene_socpll_v2_clock, "apm,xgene-socpll-v2-clock",
++ xgene_socpllclk_init);
++CLK_OF_DECLARE(xgene_pcppll_v2_clock, "apm,xgene-pcppll-v2-clock",
++ xgene_pcppllclk_init);
+ CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-clk-xgene-Add-missing-parenthesis-when-clearing-divi.patch b/patches.arch/arm64-clk-xgene-Add-missing-parenthesis-when-clearing-divi.patch
new file mode 100644
index 0000000000..415e3be684
--- /dev/null
+++ b/patches.arch/arm64-clk-xgene-Add-missing-parenthesis-when-clearing-divi.patch
@@ -0,0 +1,38 @@
+From: Loc Ho <lho@apm.com>
+Date: Mon, 29 Feb 2016 14:15:43 -0700
+Subject: clk: xgene: Add missing parenthesis when clearing divider value
+Git-commit: 0f4c7a138dfefb0ebdbaf56e3ba2acd2958a6605
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+In the initial fix for non-zero divider shift value, the parenthesis
+was missing after the negate operation. This patch adds the required
+parenthesis. Otherwise, lower bits may be cleared unintentionally.
+
+Signed-off-by: Loc Ho <lho@apm.com>
+Acked-by: Toan Le <toanle@apm.com>
+Fixes: 1382ea631ddd ("clk: xgene: Fix divider with non-zero shift value")
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/clk/clk-xgene.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
+index bd7156b..d73450b 100644
+--- a/drivers/clk/clk-xgene.c
++++ b/drivers/clk/clk-xgene.c
+@@ -376,8 +376,8 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ /* Set new divider */
+ data = xgene_clk_read(pclk->param.divider_reg +
+ pclk->param.reg_divider_offset);
+- data &= ~((1 << pclk->param.reg_divider_width) - 1)
+- << pclk->param.reg_divider_shift;
++ data &= ~(((1 << pclk->param.reg_divider_width) - 1)
++ << pclk->param.reg_divider_shift);
+ data |= divider;
+ xgene_clk_write(data, pclk->param.divider_reg +
+ pclk->param.reg_divider_offset);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-clk-xgene-Fix-divider-with-non-zero-shift-value.patch b/patches.arch/arm64-clk-xgene-Fix-divider-with-non-zero-shift-value.patch
new file mode 100644
index 0000000000..a61d9984f5
--- /dev/null
+++ b/patches.arch/arm64-clk-xgene-Fix-divider-with-non-zero-shift-value.patch
@@ -0,0 +1,35 @@
+From: Loc Ho <lho@apm.com>
+Date: Thu, 19 Nov 2015 12:20:30 -0700
+Subject: clk: xgene: Fix divider with non-zero shift value
+Git-commit: 1382ea631ddddb634850a3795527db0feeff5aaf
+Patch-mainline: v4.5-rc1
+References: fate#319483
+
+The X-Gene clock driver missed the divider shift operation when
+set the divider value.
+
+Signed-off-by: Loc Ho <lho@apm.com>
+Fixes: 308964caeebc ("clk: Add APM X-Gene SoC clock driver")
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/clk/clk-xgene.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
+index 27c0da2..10224b0 100644
+--- a/drivers/clk/clk-xgene.c
++++ b/drivers/clk/clk-xgene.c
+@@ -351,7 +351,8 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ /* Set new divider */
+ data = xgene_clk_read(pclk->param.divider_reg +
+ pclk->param.reg_divider_offset);
+- data &= ~((1 << pclk->param.reg_divider_width) - 1);
++ data &= ~((1 << pclk->param.reg_divider_width) - 1)
++ << pclk->param.reg_divider_shift;
+ data |= divider;
+ xgene_clk_write(data, pclk->param.divider_reg +
+ pclk->param.reg_divider_offset);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-clk-xgene-Remove-return-from-void-function.patch b/patches.arch/arm64-clk-xgene-Remove-return-from-void-function.patch
new file mode 100644
index 0000000000..b5364327e6
--- /dev/null
+++ b/patches.arch/arm64-clk-xgene-Remove-return-from-void-function.patch
@@ -0,0 +1,33 @@
+From: Stephen Boyd <sboyd@codeaurora.org>
+Date: Fri, 29 Jan 2016 12:57:15 -0800
+Subject: clk: xgene: Remove return from void function
+Git-commit: f9285b54d657f433746df9232068c32ef138ebc4
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+This function doesn't return anything because it's void. Drop the
+return statement.
+
+Cc: Loc Ho <lho@apm.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/clk/clk-xgene.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
+index 266d573..bd7156b 100644
+--- a/drivers/clk/clk-xgene.c
++++ b/drivers/clk/clk-xgene.c
+@@ -50,7 +50,7 @@ static inline u32 xgene_clk_read(void __iomem *csr)
+
+ static inline void xgene_clk_write(u32 data, void __iomem *csr)
+ {
+- return writel_relaxed(data, csr);
++ writel_relaxed(data, csr);
+ }
+
+ /* PLL Clock */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-drivers-net-xgene-Add-support-for-Classifier-engine.patch b/patches.arch/arm64-drivers-net-xgene-Add-support-for-Classifier-engine.patch
new file mode 100644
index 0000000000..71ae0a6891
--- /dev/null
+++ b/patches.arch/arm64-drivers-net-xgene-Add-support-for-Classifier-engine.patch
@@ -0,0 +1,792 @@
+From: Iyappan Subramanian <isubramanian@apm.com>
+Date: Wed, 17 Feb 2016 15:00:39 -0800
+Subject: drivers: net: xgene: Add support for Classifier engine
+Git-commit: 76f94a9c77d2fe6f0f02235eea84dae19edd3161
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
+Signed-off-by: Khuong Dinh <kdinh@apm.com>
+Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
+Tested-by: Toan Le <toanle@apm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/apm/xgene/Makefile | 3 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 357 +++++++++++++++++++++++
+ drivers/net/ethernet/apm/xgene/xgene_enet_cle.h | 254 ++++++++++++++++
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 +
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 29 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 14 +
+ 6 files changed, 649 insertions(+), 9 deletions(-)
+ create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+ create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+
+diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
+index 700b5ab..f46321f 100644
+--- a/drivers/net/ethernet/apm/xgene/Makefile
++++ b/drivers/net/ethernet/apm/xgene/Makefile
+@@ -3,5 +3,6 @@
+ #
+
+ xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
+- xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o
++ xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o \
++ xgene_enet_cle.o
+ obj-$(CONFIG_NET_XGENE) += xgene-enet.o
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+new file mode 100644
+index 0000000..ff24ca9
+--- /dev/null
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+@@ -0,0 +1,357 @@
++/* Applied Micro X-Gene SoC Ethernet Classifier structures
++ *
++ * Copyright (c) 2016, Applied Micro Circuits Corporation
++ * Authors: Khuong Dinh <kdinh@apm.com>
++ * Tanmay Inamdar <tinamdar@apm.com>
++ * Iyappan Subramanian <isubramanian@apm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "xgene_enet_main.h"
++
++static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
++ struct xgene_cle_dbptr *dbptr, u32 *buf)
++{
++ buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
++ SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
++
++ buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
++ SET_VAL(CLE_PRIORITY, dbptr->cle_priority);
++}
++
++static void xgene_cle_kn_to_hw(struct xgene_cle_ptree_kn *kn, u32 *buf)
++{
++ u32 i, j = 0;
++ u32 data;
++
++ buf[j++] = SET_VAL(CLE_TYPE, kn->node_type);
++ for (i = 0; i < kn->num_keys; i++) {
++ struct xgene_cle_ptree_key *key = &kn->key[i];
++
++ if (!(i % 2)) {
++ buf[j] = SET_VAL(CLE_KN_PRIO, key->priority) |
++ SET_VAL(CLE_KN_RPTR, key->result_pointer);
++ } else {
++ data = SET_VAL(CLE_KN_PRIO, key->priority) |
++ SET_VAL(CLE_KN_RPTR, key->result_pointer);
++ buf[j++] |= (data << 16);
++ }
++ }
++}
++
++static void xgene_cle_dn_to_hw(struct xgene_cle_ptree_ewdn *dn,
++ u32 *buf, u32 jb)
++{
++ struct xgene_cle_ptree_branch *br;
++ u32 i, j = 0;
++ u32 npp;
++
++ buf[j++] = SET_VAL(CLE_DN_TYPE, dn->node_type) |
++ SET_VAL(CLE_DN_LASTN, dn->last_node) |
++ SET_VAL(CLE_DN_HLS, dn->hdr_len_store) |
++ SET_VAL(CLE_DN_EXT, dn->hdr_extn) |
++ SET_VAL(CLE_DN_BSTOR, dn->byte_store) |
++ SET_VAL(CLE_DN_SBSTOR, dn->search_byte_store) |
++ SET_VAL(CLE_DN_RPTR, dn->result_pointer);
++
++ for (i = 0; i < dn->num_branches; i++) {
++ br = &dn->branch[i];
++ npp = br->next_packet_pointer;
++
++ if ((br->jump_rel == JMP_ABS) && (npp < CLE_PKTRAM_SIZE))
++ npp += jb;
++
++ buf[j++] = SET_VAL(CLE_BR_VALID, br->valid) |
++ SET_VAL(CLE_BR_NPPTR, npp) |
++ SET_VAL(CLE_BR_JB, br->jump_bw) |
++ SET_VAL(CLE_BR_JR, br->jump_rel) |
++ SET_VAL(CLE_BR_OP, br->operation) |
++ SET_VAL(CLE_BR_NNODE, br->next_node) |
++ SET_VAL(CLE_BR_NBR, br->next_branch);
++
++ buf[j++] = SET_VAL(CLE_BR_DATA, br->data) |
++ SET_VAL(CLE_BR_MASK, br->mask);
++ }
++}
++
++static int xgene_cle_poll_cmd_done(void __iomem *base,
++ enum xgene_cle_cmd_type cmd)
++{
++ u32 status, loop = 10;
++ int ret = -EBUSY;
++
++ while (loop--) {
++ status = ioread32(base + INDCMD_STATUS);
++ if (status & cmd) {
++ ret = 0;
++ break;
++ }
++ usleep_range(1000, 2000);
++ }
++
++ return ret;
++}
++
++static int xgene_cle_dram_wr(struct xgene_enet_cle *cle, u32 *data, u8 nregs,
++ u32 index, enum xgene_cle_dram_type type,
++ enum xgene_cle_cmd_type cmd)
++{
++ enum xgene_cle_parser parser = cle->active_parser;
++ void __iomem *base = cle->base;
++ u32 i, j, ind_addr;
++ u8 port, nparsers;
++ int ret = 0;
++
++ /* PTREE_RAM onwards, DRAM regions are common for all parsers */
++ nparsers = (type >= PTREE_RAM) ? 1 : cle->parsers;
++
++ for (i = 0; i < nparsers; i++) {
++ port = i;
++ if ((type < PTREE_RAM) && (parser != PARSER_ALL))
++ port = parser;
++
++ ind_addr = XGENE_CLE_DRAM(type + (port * 4)) | index;
++ iowrite32(ind_addr, base + INDADDR);
++ for (j = 0; j < nregs; j++)
++ iowrite32(data[j], base + DATA_RAM0 + (j * 4));
++ iowrite32(cmd, base + INDCMD);
++
++ ret = xgene_cle_poll_cmd_done(base, cmd);
++ if (ret)
++ break;
++ }
++
++ return ret;
++}
++
++static void xgene_cle_enable_ptree(struct xgene_enet_pdata *pdata,
++ struct xgene_enet_cle *cle)
++{
++ struct xgene_cle_ptree *ptree = &cle->ptree;
++ void __iomem *addr, *base = cle->base;
++ u32 offset = CLE_PORT_OFFSET;
++ u32 i;
++
++ /* 1G port has to advance 4 bytes and 10G has to advance 8 bytes */
++ ptree->start_pkt += cle->jump_bytes;
++ for (i = 0; i < cle->parsers; i++) {
++ if (cle->active_parser != PARSER_ALL)
++ addr = base + cle->active_parser * offset;
++ else
++ addr = base + (i * offset);
++
++ iowrite32(ptree->start_node & 0x3fff, addr + SNPTR0);
++ iowrite32(ptree->start_pkt & 0x1ff, addr + SPPTR0);
++ }
++}
++
++static int xgene_cle_setup_dbptr(struct xgene_enet_pdata *pdata,
++ struct xgene_enet_cle *cle)
++{
++ struct xgene_cle_ptree *ptree = &cle->ptree;
++ u32 buf[CLE_DRAM_REGS];
++ u32 i;
++ int ret;
++
++ memset(buf, 0, sizeof(buf));
++ for (i = 0; i < ptree->num_dbptr; i++) {
++ xgene_cle_dbptr_to_hw(pdata, &ptree->dbptr[i], buf);
++ ret = xgene_cle_dram_wr(cle, buf, 6, i + ptree->start_dbptr,
++ DB_RAM, CLE_CMD_WR);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
++static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata,
++ struct xgene_enet_cle *cle)
++{
++ struct xgene_cle_ptree *ptree = &cle->ptree;
++ struct xgene_cle_ptree_ewdn *dn = ptree->dn;
++ struct xgene_cle_ptree_kn *kn = ptree->kn;
++ u32 buf[CLE_DRAM_REGS];
++ int i, j, ret;
++
++ memset(buf, 0, sizeof(buf));
++ for (i = 0; i < ptree->num_dn; i++) {
++ xgene_cle_dn_to_hw(&dn[i], buf, cle->jump_bytes);
++ ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node,
++ PTREE_RAM, CLE_CMD_WR);
++ if (ret)
++ return ret;
++ }
++
++ /* continue node index for key node */
++ memset(buf, 0, sizeof(buf));
++ for (j = i; j < (ptree->num_kn + ptree->num_dn); j++) {
++ xgene_cle_kn_to_hw(&kn[j - ptree->num_dn], buf);
++ ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node,
++ PTREE_RAM, CLE_CMD_WR);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
++static int xgene_cle_setup_ptree(struct xgene_enet_pdata *pdata,
++ struct xgene_enet_cle *cle)
++{
++ int ret;
++
++ ret = xgene_cle_setup_node(pdata, cle);
++ if (ret)
++ return ret;
++
++ ret = xgene_cle_setup_dbptr(pdata, cle);
++ if (ret)
++ return ret;
++
++ xgene_cle_enable_ptree(pdata, cle);
++
++ return 0;
++}
++
++static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata,
++ struct xgene_enet_cle *enet_cle,
++ struct xgene_cle_dbptr *dbptr,
++ u32 index, u8 priority)
++{
++ void __iomem *base = enet_cle->base;
++ void __iomem *base_addr;
++ u32 buf[CLE_DRAM_REGS];
++ u32 def_cls, offset;
++ u32 i, j;
++
++ memset(buf, 0, sizeof(buf));
++ xgene_cle_dbptr_to_hw(pdata, dbptr, buf);
++
++ for (i = 0; i < enet_cle->parsers; i++) {
++ if (enet_cle->active_parser != PARSER_ALL) {
++ offset = enet_cle->active_parser *
++ CLE_PORT_OFFSET;
++ } else {
++ offset = i * CLE_PORT_OFFSET;
++ }
++
++ base_addr = base + DFCLSRESDB00 + offset;
++ for (j = 0; j < 6; j++)
++ iowrite32(buf[j], base_addr + (j * 4));
++
++ def_cls = ((priority & 0x7) << 10) | (index & 0x3ff);
++ iowrite32(def_cls, base + DFCLSRESDBPTR0 + offset);
++ }
++}
++
++static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
++{
++ struct xgene_enet_cle *enet_cle = &pdata->cle;
++ struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
++ u32 def_qid, def_fpsel, pool_id;
++ struct xgene_cle_ptree *ptree;
++ struct xgene_cle_ptree_kn kn;
++ struct xgene_cle_ptree_ewdn ptree_dn[] = {
++ {
++ /* PKT_TYPE_NODE */
++ .node_type = EWDN,
++ .last_node = 0,
++ .hdr_len_store = 0,
++ .hdr_extn = NO_BYTE,
++ .byte_store = NO_BYTE,
++ .search_byte_store = NO_BYTE,
++ .result_pointer = DB_RES_DROP,
++ .num_branches = 1,
++ .branch = {
++ {
++ /* Allow all packet type */
++ .valid = 0,
++ .next_packet_pointer = 0,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = LAST_NODE,
++ .next_branch = 0,
++ .data = 0x0,
++ .mask = 0xffff
++ }
++ }
++ },
++ {
++ /* LAST NODE */
++ .node_type = EWDN,
++ .last_node = 1,
++ .hdr_len_store = 0,
++ .hdr_extn = NO_BYTE,
++ .byte_store = NO_BYTE,
++ .search_byte_store = NO_BYTE,
++ .result_pointer = DB_RES_DROP,
++ .num_branches = 1,
++ .branch = {
++ {
++ .valid = 0,
++ .next_packet_pointer = 0,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = MAX_NODES,
++ .next_branch = 0,
++ .data = 0,
++ .mask = 0xffff
++ }
++ }
++ }
++ };
++
++ ptree = &enet_cle->ptree;
++ ptree->start_pkt = 12; /* Ethertype */
++
++ def_qid = xgene_enet_dst_ring_num(pdata->rx_ring);
++ pool_id = pdata->rx_ring->buf_pool->id;
++ def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
++
++ memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
++ dbptr[DB_RES_ACCEPT].fpsel = def_fpsel;
++ dbptr[DB_RES_ACCEPT].dstqid = def_qid;
++ dbptr[DB_RES_ACCEPT].cle_priority = 1;
++
++ dbptr[DB_RES_DEF].fpsel = def_fpsel;
++ dbptr[DB_RES_DEF].dstqid = def_qid;
++ dbptr[DB_RES_DEF].cle_priority = 7;
++ xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF],
++ DB_RES_ACCEPT, 7);
++
++ dbptr[DB_RES_DROP].drop = 1;
++
++ memset(&kn, 0, sizeof(kn));
++ kn.node_type = KN;
++ kn.num_keys = 1;
++ kn.key[0].priority = 0;
++ kn.key[0].result_pointer = DB_RES_ACCEPT;
++
++ ptree->dn = ptree_dn;
++ ptree->kn = &kn;
++ ptree->dbptr = dbptr;
++ ptree->num_dn = MAX_NODES;
++ ptree->num_kn = 1;
++ ptree->num_dbptr = DB_MAX_PTRS;
++
++ return xgene_cle_setup_ptree(pdata, enet_cle);
++}
++
++struct xgene_cle_ops xgene_cle3in_ops = {
++ .cle_init = xgene_enet_cle_init,
++};
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+new file mode 100644
+index 0000000..1db2fd7
+--- /dev/null
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+@@ -0,0 +1,254 @@
++/* Applied Micro X-Gene SoC Ethernet Classifier structures
++ *
++ * Copyright (c) 2016, Applied Micro Circuits Corporation
++ * Authors: Khuong Dinh <kdinh@apm.com>
++ * Tanmay Inamdar <tinamdar@apm.com>
++ * Iyappan Subramanian <isubramanian@apm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __XGENE_ENET_CLE_H__
++#define __XGENE_ENET_CLE_H__
++
++#include <linux/io.h>
++#include <linux/random.h>
++
++/* Register offsets */
++#define INDADDR 0x04
++#define INDCMD 0x08
++#define INDCMD_STATUS 0x0c
++#define DATA_RAM0 0x10
++#define SNPTR0 0x0100
++#define SPPTR0 0x0104
++#define DFCLSRESDBPTR0 0x0108
++#define DFCLSRESDB00 0x010c
++
++#define CLE_CMD_TO 10 /* ms */
++#define CLE_PKTRAM_SIZE 256 /* bytes */
++#define CLE_PORT_OFFSET 0x200
++#define CLE_DRAM_REGS 17
++
++#define CLE_DN_TYPE_LEN 2
++#define CLE_DN_TYPE_POS 0
++#define CLE_DN_LASTN_LEN 1
++#define CLE_DN_LASTN_POS 2
++#define CLE_DN_HLS_LEN 1
++#define CLE_DN_HLS_POS 3
++#define CLE_DN_EXT_LEN 2
++#define CLE_DN_EXT_POS 4
++#define CLE_DN_BSTOR_LEN 2
++#define CLE_DN_BSTOR_POS 6
++#define CLE_DN_SBSTOR_LEN 2
++#define CLE_DN_SBSTOR_POS 8
++#define CLE_DN_RPTR_LEN 12
++#define CLE_DN_RPTR_POS 12
++
++#define CLE_BR_VALID_LEN 1
++#define CLE_BR_VALID_POS 0
++#define CLE_BR_NPPTR_LEN 9
++#define CLE_BR_NPPTR_POS 1
++#define CLE_BR_JB_LEN 1
++#define CLE_BR_JB_POS 10
++#define CLE_BR_JR_LEN 1
++#define CLE_BR_JR_POS 11
++#define CLE_BR_OP_LEN 3
++#define CLE_BR_OP_POS 12
++#define CLE_BR_NNODE_LEN 9
++#define CLE_BR_NNODE_POS 15
++#define CLE_BR_NBR_LEN 5
++#define CLE_BR_NBR_POS 24
++
++#define CLE_BR_DATA_LEN 16
++#define CLE_BR_DATA_POS 0
++#define CLE_BR_MASK_LEN 16
++#define CLE_BR_MASK_POS 16
++
++#define CLE_KN_PRIO_POS 0
++#define CLE_KN_PRIO_LEN 3
++#define CLE_KN_RPTR_POS 3
++#define CLE_KN_RPTR_LEN 10
++#define CLE_TYPE_POS 0
++#define CLE_TYPE_LEN 2
++
++#define CLE_DSTQIDL_POS 25
++#define CLE_DSTQIDL_LEN 7
++#define CLE_DSTQIDH_POS 0
++#define CLE_DSTQIDH_LEN 5
++#define CLE_FPSEL_POS 21
++#define CLE_FPSEL_LEN 4
++#define CLE_PRIORITY_POS 5
++#define CLE_PRIORITY_LEN 3
++
++#define JMP_ABS 0
++#define JMP_REL 1
++#define JMP_FW 0
++#define JMP_BW 1
++
++enum xgene_cle_ptree_nodes {
++ PKT_TYPE_NODE,
++ LAST_NODE,
++ MAX_NODES
++};
++
++enum xgene_cle_byte_store {
++ NO_BYTE,
++ FIRST_BYTE,
++ SECOND_BYTE,
++ BOTH_BYTES
++};
++
++/* Preclassification operation types */
++enum xgene_cle_node_type {
++ INV,
++ KN,
++ EWDN,
++ RES_NODE
++};
++
++/* Preclassification operation types */
++enum xgene_cle_op_type {
++ EQT,
++ NEQT,
++ LTEQT,
++ GTEQT,
++ AND,
++ NAND
++};
++
++enum xgene_cle_parser {
++ PARSER0,
++ PARSER1,
++ PARSER2,
++ PARSER_ALL
++};
++
++#define XGENE_CLE_DRAM(type) (((type) & 0xf) << 28)
++enum xgene_cle_dram_type {
++ PKT_RAM,
++ PTREE_RAM = 0xc,
++ AVL_RAM,
++ DB_RAM
++};
++
++enum xgene_cle_cmd_type {
++ CLE_CMD_WR = 1,
++ CLE_CMD_RD = 2,
++ CLE_CMD_AVL_ADD = 8,
++ CLE_CMD_AVL_DEL = 16,
++ CLE_CMD_AVL_SRCH = 32
++};
++
++enum xgene_cle_ptree_dbptrs {
++ DB_RES_DROP,
++ DB_RES_DEF,
++ DB_RES_ACCEPT,
++ DB_MAX_PTRS
++};
++
++struct xgene_cle_ptree_branch {
++ bool valid;
++ u16 next_packet_pointer;
++ bool jump_bw;
++ bool jump_rel;
++ u8 operation;
++ u16 next_node;
++ u8 next_branch;
++ u16 data;
++ u16 mask;
++};
++
++struct xgene_cle_ptree_ewdn {
++ u8 node_type;
++ bool last_node;
++ bool hdr_len_store;
++ u8 hdr_extn;
++ u8 byte_store;
++ u8 search_byte_store;
++ u16 result_pointer;
++ u8 num_branches;
++ struct xgene_cle_ptree_branch branch[6];
++};
++
++struct xgene_cle_ptree_key {
++ u8 priority;
++ u16 result_pointer;
++};
++
++struct xgene_cle_ptree_kn {
++ u8 node_type;
++ u8 num_keys;
++ struct xgene_cle_ptree_key key[32];
++};
++
++struct xgene_cle_dbptr {
++ u8 split_boundary;
++ u8 mirror_nxtfpsel;
++ u8 mirror_fpsel;
++ u16 mirror_dstqid;
++ u8 drop;
++ u8 mirror;
++ u8 hdr_data_split;
++ u64 hopinfomsbs;
++ u8 DR;
++ u8 HR;
++ u64 hopinfomlsbs;
++ u16 h0enq_num;
++ u8 h0fpsel;
++ u8 nxtfpsel;
++ u8 fpsel;
++ u16 dstqid;
++ u8 cle_priority;
++ u8 cle_flowgroup;
++ u8 cle_perflow;
++ u8 cle_insert_timestamp;
++ u8 stash;
++ u8 in;
++ u8 perprioen;
++ u8 perflowgroupen;
++ u8 perflowen;
++ u8 selhash;
++ u8 selhdrext;
++ u8 mirror_nxtfpsel_msb;
++ u8 mirror_fpsel_msb;
++ u8 hfpsel_msb;
++ u8 nxtfpsel_msb;
++ u8 fpsel_msb;
++};
++
++struct xgene_cle_ptree {
++ struct xgene_cle_ptree_ewdn *dn;
++ struct xgene_cle_ptree_kn *kn;
++ struct xgene_cle_dbptr *dbptr;
++ u32 num_dn;
++ u32 num_kn;
++ u32 num_dbptr;
++ u32 start_node;
++ u32 start_pkt;
++ u32 start_dbptr;
++};
++
++struct xgene_enet_cle {
++ void __iomem *base;
++ struct xgene_cle_ptree ptree;
++ enum xgene_cle_parser active_parser;
++ u32 parsers;
++ u32 max_nodes;
++ u32 max_dbptrs;
++ u32 jump_bytes;
++};
++
++extern struct xgene_cle_ops xgene_cle3in_ops;
++
++#endif /* __XGENE_ENET_CLE_H__ */
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+index 8a90910..45725ec 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+@@ -101,6 +101,7 @@ enum xgene_enet_rm {
+ #define MAC_OFFSET 0x30
+
+ #define BLOCK_ETH_CSR_OFFSET 0x2000
++#define BLOCK_ETH_CLE_CSR_OFFSET 0x6000
+ #define BLOCK_ETH_RING_IF_OFFSET 0x9000
+ #define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
+ #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 5eb9b20..0bf3924 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -93,13 +93,6 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
+ return 0;
+ }
+
+-static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
+-{
+- struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+-
+- return ((u16)pdata->rm << 10) | ring->num;
+-}
+-
+ static u8 xgene_enet_hdr_len(const void *data)
+ {
+ const struct ethhdr *eth = data;
+@@ -1278,6 +1271,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ else
+ base_addr = pdata->base_addr;
+ pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
++ pdata->cle.base = base_addr + BLOCK_ETH_CLE_CSR_OFFSET;
+ pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
+ pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
+@@ -1298,6 +1292,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+
+ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+ {
++ struct xgene_enet_cle *enet_cle = &pdata->cle;
+ struct net_device *ndev = pdata->ndev;
+ struct xgene_enet_desc_ring *buf_pool;
+ u16 dst_ring_num;
+@@ -1323,7 +1318,24 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+ }
+
+ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
+- pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
++ if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
++ /* Initialize and Enable PreClassifier Tree */
++ enet_cle->max_nodes = 512;
++ enet_cle->max_dbptrs = 1024;
++ enet_cle->parsers = 3;
++ enet_cle->active_parser = PARSER_ALL;
++ enet_cle->ptree.start_node = 0;
++ enet_cle->ptree.start_dbptr = 0;
++ enet_cle->jump_bytes = 8;
++ ret = pdata->cle_ops->cle_init(pdata);
++ if (ret) {
++ netdev_err(ndev, "Preclass Tree init error\n");
++ return ret;
++ }
++ } else {
++ pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
++ }
++
+ pdata->mac_ops->init(pdata);
+
+ return ret;
+@@ -1345,6 +1357,7 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
+ default:
+ pdata->mac_ops = &xgene_xgmac_ops;
+ pdata->port_ops = &xgene_xgport_ops;
++ pdata->cle_ops = &xgene_cle3in_ops;
+ pdata->rm = RM0;
+ break;
+ }
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index 248dfc4..05365c1 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -36,6 +36,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/phy.h>
+ #include "xgene_enet_hw.h"
++#include "xgene_enet_cle.h"
+ #include "xgene_enet_ring2.h"
+
+ #define XGENE_DRV_VERSION "v1.0"
+@@ -145,6 +146,10 @@ struct xgene_ring_ops {
+ u32 (*len)(struct xgene_enet_desc_ring *);
+ };
+
++struct xgene_cle_ops {
++ int (*cle_init)(struct xgene_enet_pdata *pdata);
++};
++
+ /* ethernet private data */
+ struct xgene_enet_pdata {
+ struct net_device *ndev;
+@@ -174,10 +179,12 @@ struct xgene_enet_pdata {
+ void __iomem *ring_cmd_addr;
+ int phy_mode;
+ enum xgene_enet_rm rm;
++ struct xgene_enet_cle cle;
+ struct rtnl_link_stats64 stats;
+ const struct xgene_mac_ops *mac_ops;
+ const struct xgene_port_ops *port_ops;
+ struct xgene_ring_ops *ring_ops;
++ struct xgene_cle_ops *cle_ops;
+ struct delayed_work link_work;
+ u32 port_id;
+ u8 cpu_bufnum;
+@@ -229,6 +236,13 @@ static inline struct device *ndev_to_dev(struct net_device *ndev)
+ return ndev->dev.parent;
+ }
+
++static inline u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
++{
++ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
++
++ return ((u16)pdata->rm << 10) | ring->num;
++}
++
+ void xgene_enet_set_ethtool_ops(struct net_device *netdev);
+
+ #endif /* __XGENE_ENET_MAIN_H__ */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-drivers-net-xgene-Add-support-for-RSS.patch b/patches.arch/arm64-drivers-net-xgene-Add-support-for-RSS.patch
new file mode 100644
index 0000000000..d4e31427cc
--- /dev/null
+++ b/patches.arch/arm64-drivers-net-xgene-Add-support-for-RSS.patch
@@ -0,0 +1,538 @@
+From: Iyappan Subramanian <isubramanian@apm.com>
+Date: Wed, 17 Feb 2016 15:00:40 -0800
+Subject: drivers: net: xgene: Add support for RSS
+Git-commit: fc4262d2aa9aa26ec4a29bf274bcfca569656e73
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
+Signed-off-by: Khuong Dinh <kdinh@apm.com>
+Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
+Tested-by: Toan Le <toanle@apm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 386 +++++++++++++++++++++++-
+ drivers/net/ethernet/apm/xgene/xgene_enet_cle.h | 41 +++
+ 2 files changed, 422 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+index ff24ca9..c007497 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+@@ -21,6 +21,25 @@
+
+ #include "xgene_enet_main.h"
+
++/* interfaces to convert structures to HW recognized bit formats */
++static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver,
++ enum xgene_cle_prot_type type, u32 len,
++ u32 *reg)
++{
++ *reg = SET_VAL(SB_IPFRAG, frag) |
++ SET_VAL(SB_IPPROT, type) |
++ SET_VAL(SB_IPVER, ver) |
++ SET_VAL(SB_HDRLEN, len);
++}
++
++static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel,
++ u32 nfpsel, u32 *idt_reg)
++{
++ *idt_reg = SET_VAL(IDT_DSTQID, dstqid) |
++ SET_VAL(IDT_FPSEL, fpsel) |
++ SET_VAL(IDT_NFPSEL, nfpsel);
++}
++
+ static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
+ struct xgene_cle_dbptr *dbptr, u32 *buf)
+ {
+@@ -257,29 +276,372 @@ static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata,
+ }
+ }
+
++static int xgene_cle_set_rss_sband(struct xgene_enet_cle *cle)
++{
++ u32 idx = CLE_PKTRAM_SIZE / sizeof(u32);
++ u32 mac_hdr_len = ETH_HLEN;
++ u32 sband, reg = 0;
++ u32 ipv4_ihl = 5;
++ u32 hdr_len;
++ int ret;
++
++ /* Sideband: IPV4/TCP packets */
++ hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
++ xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_TCP, hdr_len, &reg);
++ sband = reg;
++
++ /* Sideband: IPv4/UDP packets */
++ hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
++ xgene_cle_sband_to_hw(1, XGENE_CLE_IPV4, XGENE_CLE_UDP, hdr_len, &reg);
++ sband |= (reg << 16);
++
++ ret = xgene_cle_dram_wr(cle, &sband, 1, idx, PKT_RAM, CLE_CMD_WR);
++ if (ret)
++ return ret;
++
++ /* Sideband: IPv4/RAW packets */
++ hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
++ xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER,
++ hdr_len, &reg);
++ sband = reg;
++
++ /* Sideband: Ethernet II/RAW packets */
++ hdr_len = (mac_hdr_len << 5);
++ xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER,
++ hdr_len, &reg);
++ sband |= (reg << 16);
++
++ ret = xgene_cle_dram_wr(cle, &sband, 1, idx + 1, PKT_RAM, CLE_CMD_WR);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static int xgene_cle_set_rss_skeys(struct xgene_enet_cle *cle)
++{
++ u32 secret_key_ipv4[4]; /* 16 Bytes*/
++ int ret = 0;
++
++ get_random_bytes(secret_key_ipv4, 16);
++ ret = xgene_cle_dram_wr(cle, secret_key_ipv4, 4, 0,
++ RSS_IPV4_HASH_SKEY, CLE_CMD_WR);
++ return ret;
++}
++
++static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
++{
++ u32 fpsel, dstqid, nfpsel, idt_reg;
++ int i, ret = 0;
++ u16 pool_id;
++
++ for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
++ pool_id = pdata->rx_ring->buf_pool->id;
++ fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
++ dstqid = xgene_enet_dst_ring_num(pdata->rx_ring);
++ nfpsel = 0;
++ idt_reg = 0;
++
++ xgene_cle_idt_to_hw(dstqid, fpsel, nfpsel, &idt_reg);
++ ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
++ RSS_IDT, CLE_CMD_WR);
++ if (ret)
++ return ret;
++ }
++
++ ret = xgene_cle_set_rss_skeys(&pdata->cle);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata)
++{
++ struct xgene_enet_cle *cle = &pdata->cle;
++ void __iomem *base = cle->base;
++ u32 offset, val = 0;
++ int i, ret = 0;
++
++ offset = CLE_PORT_OFFSET;
++ for (i = 0; i < cle->parsers; i++) {
++ if (cle->active_parser != PARSER_ALL)
++ offset = cle->active_parser * CLE_PORT_OFFSET;
++ else
++ offset = i * CLE_PORT_OFFSET;
++
++ /* enable RSS */
++ val = (RSS_IPV4_12B << 1) | 0x1;
++ writel(val, base + RSS_CTRL0 + offset);
++ }
++
++ /* setup sideband data */
++ ret = xgene_cle_set_rss_sband(cle);
++ if (ret)
++ return ret;
++
++ /* setup indirection table */
++ ret = xgene_cle_set_rss_idt(pdata);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
+ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
+ {
+ struct xgene_enet_cle *enet_cle = &pdata->cle;
+ struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
++ struct xgene_cle_ptree_branch *br;
+ u32 def_qid, def_fpsel, pool_id;
+ struct xgene_cle_ptree *ptree;
+ struct xgene_cle_ptree_kn kn;
++ int ret;
+ struct xgene_cle_ptree_ewdn ptree_dn[] = {
+ {
+ /* PKT_TYPE_NODE */
+ .node_type = EWDN,
+ .last_node = 0,
+- .hdr_len_store = 0,
++ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = NO_BYTE,
+ .result_pointer = DB_RES_DROP,
+- .num_branches = 1,
++ .num_branches = 2,
+ .branch = {
+ {
+- /* Allow all packet type */
++ /* IPV4 */
+ .valid = 0,
+- .next_packet_pointer = 0,
++ .next_packet_pointer = 22,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = PKT_PROT_NODE,
++ .next_branch = 0,
++ .data = 0x8,
++ .mask = 0xffff
++ },
++ {
++ .valid = 0,
++ .next_packet_pointer = 262,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = LAST_NODE,
++ .next_branch = 0,
++ .data = 0x0,
++ .mask = 0xffff
++ }
++ },
++ },
++ {
++ /* PKT_PROT_NODE */
++ .node_type = EWDN,
++ .last_node = 0,
++ .hdr_len_store = 1,
++ .hdr_extn = NO_BYTE,
++ .byte_store = NO_BYTE,
++ .search_byte_store = NO_BYTE,
++ .result_pointer = DB_RES_DROP,
++ .num_branches = 3,
++ .branch = {
++ {
++ /* TCP */
++ .valid = 1,
++ .next_packet_pointer = 26,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_TCP_NODE,
++ .next_branch = 0,
++ .data = 0x0600,
++ .mask = 0xffff
++ },
++ {
++ /* UDP */
++ .valid = 1,
++ .next_packet_pointer = 26,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_UDP_NODE,
++ .next_branch = 0,
++ .data = 0x1100,
++ .mask = 0xffff
++ },
++ {
++ .valid = 0,
++ .next_packet_pointer = 260,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = LAST_NODE,
++ .next_branch = 0,
++ .data = 0x0,
++ .mask = 0xffff
++ }
++ }
++ },
++ {
++ /* RSS_IPV4_TCP_NODE */
++ .node_type = EWDN,
++ .last_node = 0,
++ .hdr_len_store = 1,
++ .hdr_extn = NO_BYTE,
++ .byte_store = NO_BYTE,
++ .search_byte_store = BOTH_BYTES,
++ .result_pointer = DB_RES_DROP,
++ .num_branches = 6,
++ .branch = {
++ {
++ /* SRC IPV4 B01 */
++ .valid = 0,
++ .next_packet_pointer = 28,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_TCP_NODE,
++ .next_branch = 1,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* SRC IPV4 B23 */
++ .valid = 0,
++ .next_packet_pointer = 30,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_TCP_NODE,
++ .next_branch = 2,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* DST IPV4 B01 */
++ .valid = 0,
++ .next_packet_pointer = 32,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_TCP_NODE,
++ .next_branch = 3,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* DST IPV4 B23 */
++ .valid = 0,
++ .next_packet_pointer = 34,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_TCP_NODE,
++ .next_branch = 4,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* TCP SRC Port */
++ .valid = 0,
++ .next_packet_pointer = 36,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_TCP_NODE,
++ .next_branch = 5,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* TCP DST Port */
++ .valid = 0,
++ .next_packet_pointer = 256,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = LAST_NODE,
++ .next_branch = 0,
++ .data = 0x0,
++ .mask = 0xffff
++ }
++ }
++ },
++ {
++ /* RSS_IPV4_UDP_NODE */
++ .node_type = EWDN,
++ .last_node = 0,
++ .hdr_len_store = 1,
++ .hdr_extn = NO_BYTE,
++ .byte_store = NO_BYTE,
++ .search_byte_store = BOTH_BYTES,
++ .result_pointer = DB_RES_DROP,
++ .num_branches = 6,
++ .branch = {
++ {
++ /* SRC IPV4 B01 */
++ .valid = 0,
++ .next_packet_pointer = 28,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_UDP_NODE,
++ .next_branch = 1,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* SRC IPV4 B23 */
++ .valid = 0,
++ .next_packet_pointer = 30,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_UDP_NODE,
++ .next_branch = 2,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* DST IPV4 B01 */
++ .valid = 0,
++ .next_packet_pointer = 32,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_UDP_NODE,
++ .next_branch = 3,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* DST IPV4 B23 */
++ .valid = 0,
++ .next_packet_pointer = 34,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_UDP_NODE,
++ .next_branch = 4,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* TCP SRC Port */
++ .valid = 0,
++ .next_packet_pointer = 36,
++ .jump_bw = JMP_FW,
++ .jump_rel = JMP_ABS,
++ .operation = EQT,
++ .next_node = RSS_IPV4_UDP_NODE,
++ .next_branch = 5,
++ .data = 0x0,
++ .mask = 0xffff
++ },
++ {
++ /* TCP DST Port */
++ .valid = 0,
++ .next_packet_pointer = 256,
+ .jump_bw = JMP_FW,
+ .jump_rel = JMP_ABS,
+ .operation = EQT,
+@@ -294,7 +656,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
+ /* LAST NODE */
+ .node_type = EWDN,
+ .last_node = 1,
+- .hdr_len_store = 0,
++ .hdr_len_store = 1,
+ .hdr_extn = NO_BYTE,
+ .byte_store = NO_BYTE,
+ .search_byte_store = NO_BYTE,
+@@ -318,6 +680,20 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
+
+ ptree = &enet_cle->ptree;
+ ptree->start_pkt = 12; /* Ethertype */
++ if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
++ ret = xgene_cle_setup_rss(pdata);
++ if (ret) {
++ netdev_err(pdata->ndev, "RSS initialization failed\n");
++ return ret;
++ }
++ } else {
++ br = &ptree_dn[PKT_PROT_NODE].branch[0];
++ br->valid = 0;
++ br->next_packet_pointer = 260;
++ br->next_node = LAST_NODE;
++ br->data = 0x0000;
++ br->mask = 0xffff;
++ }
+
+ def_qid = xgene_enet_dst_ring_num(pdata->rx_ring);
+ pool_id = pdata->rx_ring->buf_pool->id;
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+index 1db2fd7..29a17ab 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+@@ -34,6 +34,7 @@
+ #define SPPTR0 0x0104
+ #define DFCLSRESDBPTR0 0x0108
+ #define DFCLSRESDB00 0x010c
++#define RSS_CTRL0 0x0000013c
+
+ #define CLE_CMD_TO 10 /* ms */
+ #define CLE_PKTRAM_SIZE 256 /* bytes */
+@@ -98,6 +99,9 @@
+
+ enum xgene_cle_ptree_nodes {
+ PKT_TYPE_NODE,
++ PKT_PROT_NODE,
++ RSS_IPV4_TCP_NODE,
++ RSS_IPV4_UDP_NODE,
+ LAST_NODE,
+ MAX_NODES
+ };
+@@ -137,6 +141,8 @@ enum xgene_cle_parser {
+ #define XGENE_CLE_DRAM(type) (((type) & 0xf) << 28)
+ enum xgene_cle_dram_type {
+ PKT_RAM,
++ RSS_IDT,
++ RSS_IPV4_HASH_SKEY,
+ PTREE_RAM = 0xc,
+ AVL_RAM,
+ DB_RAM
+@@ -150,6 +156,22 @@ enum xgene_cle_cmd_type {
+ CLE_CMD_AVL_SRCH = 32
+ };
+
++enum xgene_cle_ipv4_rss_hashtype {
++ RSS_IPV4_8B,
++ RSS_IPV4_12B,
++};
++
++enum xgene_cle_prot_type {
++ XGENE_CLE_TCP,
++ XGENE_CLE_UDP,
++ XGENE_CLE_ESP,
++ XGENE_CLE_OTHER
++};
++
++enum xgene_cle_prot_version {
++ XGENE_CLE_IPV4,
++};
++
+ enum xgene_cle_ptree_dbptrs {
+ DB_RES_DROP,
+ DB_RES_DEF,
+@@ -157,6 +179,25 @@ enum xgene_cle_ptree_dbptrs {
+ DB_MAX_PTRS
+ };
+
++/* RSS sideband signal info */
++#define SB_IPFRAG_POS 0
++#define SB_IPFRAG_LEN 1
++#define SB_IPPROT_POS 1
++#define SB_IPPROT_LEN 2
++#define SB_IPVER_POS 3
++#define SB_IPVER_LEN 1
++#define SB_HDRLEN_POS 4
++#define SB_HDRLEN_LEN 12
++
++/* RSS indirection table */
++#define XGENE_CLE_IDT_ENTRIES 128
++#define IDT_DSTQID_POS 0
++#define IDT_DSTQID_LEN 12
++#define IDT_FPSEL_POS 12
++#define IDT_FPSEL_LEN 4
++#define IDT_NFPSEL_POS 16
++#define IDT_NFPSEL_LEN 4
++
+ struct xgene_cle_ptree_branch {
+ bool valid;
+ u16 next_packet_pointer;
+--
+2.6.6
+
diff --git a/patches.arch/arm64-drivers-net-xgene-Add-support-for-multiple-queues.patch b/patches.arch/arm64-drivers-net-xgene-Add-support-for-multiple-queues.patch
new file mode 100644
index 0000000000..ce4ef4bd71
--- /dev/null
+++ b/patches.arch/arm64-drivers-net-xgene-Add-support-for-multiple-queues.patch
@@ -0,0 +1,886 @@
+From: Iyappan Subramanian <isubramanian@apm.com>
+Date: Wed, 17 Feb 2016 15:00:41 -0800
+Subject: drivers: net: xgene: Add support for multiple queues
+Git-commit: 107dec2749fed1b4172f77c091961b15221419db
+Patch-mainline: v4.6-rc1
+References: fate#319483
+
+Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
+Signed-off-by: Khuong Dinh <kdinh@apm.com>
+Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
+Tested-by: Toan Le <toanle@apm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 11 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 12 +
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 5 +
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 453 +++++++++++++---------
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 21 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c | 12 +
+ 6 files changed, 320 insertions(+), 194 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+index c007497..b2124886 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+@@ -331,14 +331,15 @@ static int xgene_cle_set_rss_skeys(struct xgene_enet_cle *cle)
+
+ static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
+ {
+- u32 fpsel, dstqid, nfpsel, idt_reg;
++ u32 fpsel, dstqid, nfpsel, idt_reg, idx;
+ int i, ret = 0;
+ u16 pool_id;
+
+ for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
+- pool_id = pdata->rx_ring->buf_pool->id;
++ idx = i % pdata->rxq_cnt;
++ pool_id = pdata->rx_ring[idx]->buf_pool->id;
+ fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+- dstqid = xgene_enet_dst_ring_num(pdata->rx_ring);
++ dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]);
+ nfpsel = 0;
+ idt_reg = 0;
+
+@@ -695,8 +696,8 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
+ br->mask = 0xffff;
+ }
+
+- def_qid = xgene_enet_dst_ring_num(pdata->rx_ring);
+- pool_id = pdata->rx_ring->buf_pool->id;
++ def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
++ pool_id = pdata->rx_ring[0]->buf_pool->id;
+ def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+
+ memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+index db55c9f..39e081a 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+@@ -204,6 +204,17 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+ return num_msgs;
+ }
+
++static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring)
++{
++ u32 data = 0x7777;
++
++ xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data << 16);
++ xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x40);
++ xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x80);
++}
++
+ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+ struct xgene_enet_pdata *pdata,
+ enum xgene_enet_err_code status)
+@@ -892,4 +903,5 @@ struct xgene_ring_ops xgene_ring1_ops = {
+ .clear = xgene_enet_clear_ring,
+ .wr_cmd = xgene_enet_wr_cmd,
+ .len = xgene_enet_ring_len,
++ .coalesce = xgene_enet_setup_coalescing,
+ };
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+index 45725ec..ba7da98 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+@@ -54,6 +54,11 @@ enum xgene_enet_rm {
+ #define IS_BUFFER_POOL BIT(20)
+ #define PREFETCH_BUF_EN BIT(21)
+ #define CSR_RING_ID_BUF 0x000c
++#define CSR_PBM_COAL 0x0014
++#define CSR_PBM_CTICK1 0x001c
++#define CSR_PBM_CTICK2 0x0020
++#define CSR_THRESHOLD0_SET1 0x0030
++#define CSR_THRESHOLD1_SET1 0x0034
+ #define CSR_RING_NE_INT_MODE 0x017c
+ #define CSR_RING_CONFIG 0x006c
+ #define CSR_RING_WR_BASE 0x0070
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 0bf3924..8d4c1ad 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -182,7 +182,6 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ static u64 xgene_enet_work_msg(struct sk_buff *skb)
+ {
+ struct net_device *ndev = skb->dev;
+- struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct iphdr *iph;
+ u8 l3hlen = 0, l4hlen = 0;
+ u8 ethhdr, proto = 0, csum_enable = 0;
+@@ -228,10 +227,6 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb)
+ if (!mss || ((skb->len - hdr_len) <= mss))
+ goto out;
+
+- if (mss != pdata->mss) {
+- pdata->mss = mss;
+- pdata->mac_ops->set_mss(pdata);
+- }
+ hopinfo |= SET_BIT(ET);
+ }
+ } else if (iph->protocol == IPPROTO_UDP) {
+@@ -413,7 +408,7 @@ out:
+ raw_desc->m0 = cpu_to_le64(SET_VAL(LL, ll) | SET_VAL(NV, nv) |
+ SET_VAL(USERINFO, tx_ring->tail));
+ tx_ring->cp_ring->cp_skb[tx_ring->tail] = skb;
+- pdata->tx_level += count;
++ pdata->tx_level[tx_ring->cp_ring->index] += count;
+ tx_ring->tail = tail;
+
+ return count;
+@@ -423,15 +418,17 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
+ struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+- struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
+- u32 tx_level = pdata->tx_level;
++ struct xgene_enet_desc_ring *tx_ring;
++ int index = skb->queue_mapping;
++ u32 tx_level = pdata->tx_level[index];
+ int count;
+
+- if (tx_level < pdata->txc_level)
+- tx_level += ((typeof(pdata->tx_level))~0U);
++ tx_ring = pdata->tx_ring[index];
++ if (tx_level < pdata->txc_level[index])
++ tx_level += ((typeof(pdata->tx_level[index]))~0U);
+
+- if ((tx_level - pdata->txc_level) > pdata->tx_qcnt_hi) {
+- netif_stop_queue(ndev);
++ if ((tx_level - pdata->txc_level[index]) > pdata->tx_qcnt_hi) {
++ netif_stop_subqueue(ndev, index);
+ return NETDEV_TX_BUSY;
+ }
+
+@@ -529,7 +526,8 @@ static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc)
+ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
+ int budget)
+ {
+- struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
++ struct net_device *ndev = ring->ndev;
++ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_enet_raw_desc *raw_desc, *exp_desc;
+ u16 head = ring->head;
+ u16 slots = ring->slots - 1;
+@@ -573,7 +571,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
+ desc_count++;
+ processed++;
+ if (is_completion)
+- pdata->txc_level += desc_count;
++ pdata->txc_level[ring->index] += desc_count;
+
+ if (ret)
+ break;
+@@ -583,8 +581,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
+ pdata->ring_ops->wr_cmd(ring, -count);
+ ring->head = head;
+
+- if (netif_queue_stopped(ring->ndev))
+- netif_start_queue(ring->ndev);
++ if (__netif_subqueue_stopped(ndev, ring->index))
++ netif_start_subqueue(ndev, ring->index);
+ }
+
+ return processed;
+@@ -609,8 +607,16 @@ static int xgene_enet_napi(struct napi_struct *napi, const int budget)
+ static void xgene_enet_timeout(struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
++ struct netdev_queue *txq;
++ int i;
+
+ pdata->mac_ops->reset(pdata);
++
++ for (i = 0; i < pdata->txq_cnt; i++) {
++ txq = netdev_get_tx_queue(ndev, i);
++ txq->trans_start = jiffies;
++ netif_tx_start_queue(txq);
++ }
+ }
+
+ static int xgene_enet_register_irq(struct net_device *ndev)
+@@ -618,17 +624,21 @@ static int xgene_enet_register_irq(struct net_device *ndev)
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ struct xgene_enet_desc_ring *ring;
+- int ret;
++ int ret = 0, i;
+
+- ring = pdata->rx_ring;
+- irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+- ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
+- IRQF_SHARED, ring->irq_name, ring);
+- if (ret)
+- netdev_err(ndev, "Failed to request irq %s\n", ring->irq_name);
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ ring = pdata->rx_ring[i];
++ irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
++ ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
++ IRQF_SHARED, ring->irq_name, ring);
++ if (ret) {
++ netdev_err(ndev, "Failed to request irq %s\n",
++ ring->irq_name);
++ }
++ }
+
+- if (pdata->cq_cnt) {
+- ring = pdata->tx_ring->cp_ring;
++ for (i = 0; i < pdata->cq_cnt; i++) {
++ ring = pdata->tx_ring[i]->cp_ring;
+ irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+ ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
+ IRQF_SHARED, ring->irq_name, ring);
+@@ -646,15 +656,19 @@ static void xgene_enet_free_irq(struct net_device *ndev)
+ struct xgene_enet_pdata *pdata;
+ struct xgene_enet_desc_ring *ring;
+ struct device *dev;
++ int i;
+
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(ndev);
+- ring = pdata->rx_ring;
+- irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+- devm_free_irq(dev, ring->irq, ring);
+
+- if (pdata->cq_cnt) {
+- ring = pdata->tx_ring->cp_ring;
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ ring = pdata->rx_ring[i];
++ irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
++ devm_free_irq(dev, ring->irq, ring);
++ }
++
++ for (i = 0; i < pdata->cq_cnt; i++) {
++ ring = pdata->tx_ring[i]->cp_ring;
+ irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+ devm_free_irq(dev, ring->irq, ring);
+ }
+@@ -663,12 +677,15 @@ static void xgene_enet_free_irq(struct net_device *ndev)
+ static void xgene_enet_napi_enable(struct xgene_enet_pdata *pdata)
+ {
+ struct napi_struct *napi;
++ int i;
+
+- napi = &pdata->rx_ring->napi;
+- napi_enable(napi);
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ napi = &pdata->rx_ring[i]->napi;
++ napi_enable(napi);
++ }
+
+- if (pdata->cq_cnt) {
+- napi = &pdata->tx_ring->cp_ring->napi;
++ for (i = 0; i < pdata->cq_cnt; i++) {
++ napi = &pdata->tx_ring[i]->cp_ring->napi;
+ napi_enable(napi);
+ }
+ }
+@@ -676,12 +693,15 @@ static void xgene_enet_napi_enable(struct xgene_enet_pdata *pdata)
+ static void xgene_enet_napi_disable(struct xgene_enet_pdata *pdata)
+ {
+ struct napi_struct *napi;
++ int i;
+
+- napi = &pdata->rx_ring->napi;
+- napi_disable(napi);
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ napi = &pdata->rx_ring[i]->napi;
++ napi_disable(napi);
++ }
+
+- if (pdata->cq_cnt) {
+- napi = &pdata->tx_ring->cp_ring->napi;
++ for (i = 0; i < pdata->cq_cnt; i++) {
++ napi = &pdata->tx_ring[i]->cp_ring->napi;
+ napi_disable(napi);
+ }
+ }
+@@ -692,6 +712,14 @@ static int xgene_enet_open(struct net_device *ndev)
+ const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
+ int ret;
+
++ ret = netif_set_real_num_tx_queues(ndev, pdata->txq_cnt);
++ if (ret)
++ return ret;
++
++ ret = netif_set_real_num_rx_queues(ndev, pdata->rxq_cnt);
++ if (ret)
++ return ret;
++
+ mac_ops->tx_enable(pdata);
+ mac_ops->rx_enable(pdata);
+
+@@ -714,6 +742,7 @@ static int xgene_enet_close(struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
++ int i;
+
+ netif_stop_queue(ndev);
+
+@@ -727,7 +756,8 @@ static int xgene_enet_close(struct net_device *ndev)
+
+ xgene_enet_free_irq(ndev);
+ xgene_enet_napi_disable(pdata);
+- xgene_enet_process_ring(pdata->rx_ring, -1);
++ for (i = 0; i < pdata->rxq_cnt; i++)
++ xgene_enet_process_ring(pdata->rx_ring[i], -1);
+
+ return 0;
+ }
+@@ -747,18 +777,26 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
+ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
+ {
+ struct xgene_enet_desc_ring *buf_pool;
++ struct xgene_enet_desc_ring *ring;
++ int i;
+
+- if (pdata->tx_ring) {
+- xgene_enet_delete_ring(pdata->tx_ring);
+- pdata->tx_ring = NULL;
++ for (i = 0; i < pdata->txq_cnt; i++) {
++ ring = pdata->tx_ring[i];
++ if (ring) {
++ xgene_enet_delete_ring(ring);
++ pdata->tx_ring[i] = NULL;
++ }
+ }
+
+- if (pdata->rx_ring) {
+- buf_pool = pdata->rx_ring->buf_pool;
+- xgene_enet_delete_bufpool(buf_pool);
+- xgene_enet_delete_ring(buf_pool);
+- xgene_enet_delete_ring(pdata->rx_ring);
+- pdata->rx_ring = NULL;
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ ring = pdata->rx_ring[i];
++ if (ring) {
++ buf_pool = ring->buf_pool;
++ xgene_enet_delete_bufpool(buf_pool);
++ xgene_enet_delete_ring(buf_pool);
++ xgene_enet_delete_ring(ring);
++ pdata->rx_ring[i] = NULL;
++ }
+ }
+ }
+
+@@ -813,24 +851,29 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
+ {
+ struct device *dev = &pdata->pdev->dev;
+ struct xgene_enet_desc_ring *ring;
++ int i;
+
+- ring = pdata->tx_ring;
+- if (ring) {
+- if (ring->cp_ring && ring->cp_ring->cp_skb)
+- devm_kfree(dev, ring->cp_ring->cp_skb);
+- if (ring->cp_ring && pdata->cq_cnt)
+- xgene_enet_free_desc_ring(ring->cp_ring);
+- xgene_enet_free_desc_ring(ring);
+- }
+-
+- ring = pdata->rx_ring;
+- if (ring) {
+- if (ring->buf_pool) {
+- if (ring->buf_pool->rx_skb)
+- devm_kfree(dev, ring->buf_pool->rx_skb);
+- xgene_enet_free_desc_ring(ring->buf_pool);
++ for (i = 0; i < pdata->txq_cnt; i++) {
++ ring = pdata->tx_ring[i];
++ if (ring) {
++ if (ring->cp_ring && ring->cp_ring->cp_skb)
++ devm_kfree(dev, ring->cp_ring->cp_skb);
++ if (ring->cp_ring && pdata->cq_cnt)
++ xgene_enet_free_desc_ring(ring->cp_ring);
++ xgene_enet_free_desc_ring(ring);
++ }
++ }
++
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ ring = pdata->rx_ring[i];
++ if (ring) {
++ if (ring->buf_pool) {
++ if (ring->buf_pool->rx_skb)
++ devm_kfree(dev, ring->buf_pool->rx_skb);
++ xgene_enet_free_desc_ring(ring->buf_pool);
++ }
++ xgene_enet_free_desc_ring(ring);
+ }
+- xgene_enet_free_desc_ring(ring);
+ }
+ }
+
+@@ -943,104 +986,120 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
+ u8 bp_bufnum = pdata->bp_bufnum;
+ u16 ring_num = pdata->ring_num;
+ u16 ring_id;
+- int ret, size;
+-
+- /* allocate rx descriptor ring */
+- owner = xgene_derive_ring_owner(pdata);
+- ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
+- rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+- RING_CFGSIZE_16KB, ring_id);
+- if (!rx_ring) {
+- ret = -ENOMEM;
+- goto err;
+- }
+-
+- /* allocate buffer pool for receiving packets */
+- owner = xgene_derive_ring_owner(pdata);
+- ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
+- buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+- RING_CFGSIZE_2KB, ring_id);
+- if (!buf_pool) {
+- ret = -ENOMEM;
+- goto err;
+- }
++ int i, ret, size;
+
+- rx_ring->nbufpool = NUM_BUFPOOL;
+- rx_ring->buf_pool = buf_pool;
+- rx_ring->irq = pdata->rx_irq;
+- if (!pdata->cq_cnt) {
+- snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc",
+- ndev->name);
+- } else {
+- snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx", ndev->name);
+- }
+- buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
+- sizeof(struct sk_buff *), GFP_KERNEL);
+- if (!buf_pool->rx_skb) {
+- ret = -ENOMEM;
+- goto err;
+- }
+-
+- buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
+- rx_ring->buf_pool = buf_pool;
+- pdata->rx_ring = rx_ring;
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ /* allocate rx descriptor ring */
++ owner = xgene_derive_ring_owner(pdata);
++ ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
++ rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
++ RING_CFGSIZE_16KB,
++ ring_id);
++ if (!rx_ring) {
++ ret = -ENOMEM;
++ goto err;
++ }
+
+- /* allocate tx descriptor ring */
+- owner = xgene_derive_ring_owner(pdata);
+- ring_id = xgene_enet_get_ring_id(owner, eth_bufnum++);
+- tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+- RING_CFGSIZE_16KB, ring_id);
+- if (!tx_ring) {
+- ret = -ENOMEM;
+- goto err;
+- }
++ /* allocate buffer pool for receiving packets */
++ owner = xgene_derive_ring_owner(pdata);
++ ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
++ buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
++ RING_CFGSIZE_2KB,
++ ring_id);
++ if (!buf_pool) {
++ ret = -ENOMEM;
++ goto err;
++ }
+
+- size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS;
+- tx_ring->exp_bufs = dma_zalloc_coherent(dev, size, &dma_exp_bufs,
++ rx_ring->nbufpool = NUM_BUFPOOL;
++ rx_ring->buf_pool = buf_pool;
++ rx_ring->irq = pdata->irqs[i];
++ if (!pdata->cq_cnt) {
++ snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc",
++ ndev->name);
++ } else {
++ snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx%d",
++ ndev->name, i);
++ }
++ buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
++ sizeof(struct sk_buff *),
+ GFP_KERNEL);
+- if (!tx_ring->exp_bufs) {
+- ret = -ENOMEM;
+- goto err;
+- }
++ if (!buf_pool->rx_skb) {
++ ret = -ENOMEM;
++ goto err;
++ }
+
+- pdata->tx_ring = tx_ring;
++ buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
++ rx_ring->buf_pool = buf_pool;
++ pdata->rx_ring[i] = rx_ring;
++ }
+
+- if (!pdata->cq_cnt) {
+- cp_ring = pdata->rx_ring;
+- } else {
+- /* allocate tx completion descriptor ring */
+- ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
+- cp_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
++ for (i = 0; i < pdata->txq_cnt; i++) {
++ /* allocate tx descriptor ring */
++ owner = xgene_derive_ring_owner(pdata);
++ ring_id = xgene_enet_get_ring_id(owner, eth_bufnum++);
++ tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB,
+ ring_id);
+- if (!cp_ring) {
++ if (!tx_ring) {
+ ret = -ENOMEM;
+ goto err;
+ }
+- cp_ring->irq = pdata->txc_irq;
+- snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc", ndev->name);
+- }
+
+- cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
+- sizeof(struct sk_buff *), GFP_KERNEL);
+- if (!cp_ring->cp_skb) {
+- ret = -ENOMEM;
+- goto err;
+- }
++ size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS;
++ tx_ring->exp_bufs = dma_zalloc_coherent(dev, size,
++ &dma_exp_bufs,
++ GFP_KERNEL);
++ if (!tx_ring->exp_bufs) {
++ ret = -ENOMEM;
++ goto err;
++ }
+
+- size = sizeof(dma_addr_t) * MAX_SKB_FRAGS;
+- cp_ring->frag_dma_addr = devm_kcalloc(dev, tx_ring->slots,
+- size, GFP_KERNEL);
+- if (!cp_ring->frag_dma_addr) {
+- devm_kfree(dev, cp_ring->cp_skb);
+- ret = -ENOMEM;
+- goto err;
+- }
++ pdata->tx_ring[i] = tx_ring;
+
+- pdata->tx_ring->cp_ring = cp_ring;
+- pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
++ if (!pdata->cq_cnt) {
++ cp_ring = pdata->rx_ring[i];
++ } else {
++ /* allocate tx completion descriptor ring */
++ ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU,
++ cpu_bufnum++);
++ cp_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
++ RING_CFGSIZE_16KB,
++ ring_id);
++ if (!cp_ring) {
++ ret = -ENOMEM;
++ goto err;
++ }
++
++ cp_ring->irq = pdata->irqs[pdata->rxq_cnt + i];
++ cp_ring->index = i;
++ snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc%d",
++ ndev->name, i);
++ }
++
++ cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
++ sizeof(struct sk_buff *),
++ GFP_KERNEL);
++ if (!cp_ring->cp_skb) {
++ ret = -ENOMEM;
++ goto err;
++ }
+
+- pdata->tx_qcnt_hi = pdata->tx_ring->slots - 128;
++ size = sizeof(dma_addr_t) * MAX_SKB_FRAGS;
++ cp_ring->frag_dma_addr = devm_kcalloc(dev, tx_ring->slots,
++ size, GFP_KERNEL);
++ if (!cp_ring->frag_dma_addr) {
++ devm_kfree(dev, cp_ring->cp_skb);
++ ret = -ENOMEM;
++ goto err;
++ }
++
++ tx_ring->cp_ring = cp_ring;
++ tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
++ }
++
++ pdata->ring_ops->coalesce(pdata->tx_ring[0]);
++ pdata->tx_qcnt_hi = pdata->tx_ring[0]->slots - 128;
+
+ return 0;
+
+@@ -1159,6 +1218,32 @@ static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata)
+ return 0;
+ }
+
++static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
++{
++ struct platform_device *pdev = pdata->pdev;
++ struct device *dev = &pdev->dev;
++ int i, ret, max_irqs;
++
++ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
++ max_irqs = 1;
++ else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
++ max_irqs = 2;
++ else
++ max_irqs = XGENE_MAX_ENET_IRQ;
++
++ for (i = 0; i < max_irqs; i++) {
++ ret = platform_get_irq(pdev, i);
++ if (ret <= 0) {
++ dev_err(dev, "Unable to get ENET IRQ\n");
++ ret = ret ? : -ENXIO;
++ return ret;
++ }
++ pdata->irqs[i] = ret;
++ }
++
++ return 0;
++}
++
+ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ {
+ struct platform_device *pdev;
+@@ -1240,25 +1325,9 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ if (ret)
+ return ret;
+
+- ret = platform_get_irq(pdev, 0);
+- if (ret <= 0) {
+- dev_err(dev, "Unable to get ENET Rx IRQ\n");
+- ret = ret ? : -ENXIO;
++ ret = xgene_enet_get_irqs(pdata);
++ if (ret)
+ return ret;
+- }
+- pdata->rx_irq = ret;
+-
+- if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII) {
+- ret = platform_get_irq(pdev, 1);
+- if (ret <= 0) {
+- pdata->cq_cnt = 0;
+- dev_info(dev, "Unable to get Tx completion IRQ,"
+- "using Rx IRQ instead\n");
+- } else {
+- pdata->cq_cnt = XGENE_MAX_TXC_RINGS;
+- pdata->txc_irq = ret;
+- }
+- }
+
+ pdata->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pdata->clk)) {
+@@ -1296,7 +1365,7 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+ struct net_device *ndev = pdata->ndev;
+ struct xgene_enet_desc_ring *buf_pool;
+ u16 dst_ring_num;
+- int ret;
++ int i, ret;
+
+ ret = pdata->port_ops->reset(pdata);
+ if (ret)
+@@ -1309,15 +1378,18 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+ }
+
+ /* setup buffer pool */
+- buf_pool = pdata->rx_ring->buf_pool;
+- xgene_enet_init_bufpool(buf_pool);
+- ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+- if (ret) {
+- xgene_enet_delete_desc_rings(pdata);
+- return ret;
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ buf_pool = pdata->rx_ring[i]->buf_pool;
++ xgene_enet_init_bufpool(buf_pool);
++ ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
++ if (ret) {
++ xgene_enet_delete_desc_rings(pdata);
++ return ret;
++ }
+ }
+
+- dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
++ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
++ buf_pool = pdata->rx_ring[0]->buf_pool;
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+ /* Initialize and Enable PreClassifier Tree */
+ enet_cle->max_nodes = 512;
+@@ -1348,17 +1420,26 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
+ pdata->mac_ops = &xgene_gmac_ops;
+ pdata->port_ops = &xgene_gport_ops;
+ pdata->rm = RM3;
++ pdata->rxq_cnt = 1;
++ pdata->txq_cnt = 1;
++ pdata->cq_cnt = 0;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ pdata->mac_ops = &xgene_sgmac_ops;
+ pdata->port_ops = &xgene_sgport_ops;
+ pdata->rm = RM1;
++ pdata->rxq_cnt = 1;
++ pdata->txq_cnt = 1;
++ pdata->cq_cnt = 1;
+ break;
+ default:
+ pdata->mac_ops = &xgene_xgmac_ops;
+ pdata->port_ops = &xgene_xgport_ops;
+ pdata->cle_ops = &xgene_cle3in_ops;
+ pdata->rm = RM0;
++ pdata->rxq_cnt = XGENE_NUM_RX_RING;
++ pdata->txq_cnt = XGENE_NUM_TX_RING;
++ pdata->cq_cnt = XGENE_NUM_TXC_RING;
+ break;
+ }
+
+@@ -1412,12 +1493,16 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
+ static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata)
+ {
+ struct napi_struct *napi;
++ int i;
+
+- napi = &pdata->rx_ring->napi;
+- netif_napi_add(pdata->ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ napi = &pdata->rx_ring[i]->napi;
++ netif_napi_add(pdata->ndev, napi, xgene_enet_napi,
++ NAPI_POLL_WEIGHT);
++ }
+
+- if (pdata->cq_cnt) {
+- napi = &pdata->tx_ring->cp_ring->napi;
++ for (i = 0; i < pdata->cq_cnt; i++) {
++ napi = &pdata->tx_ring[i]->cp_ring->napi;
+ netif_napi_add(pdata->ndev, napi, xgene_enet_napi,
+ NAPI_POLL_WEIGHT);
+ }
+@@ -1426,12 +1511,15 @@ static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata)
+ static void xgene_enet_napi_del(struct xgene_enet_pdata *pdata)
+ {
+ struct napi_struct *napi;
++ int i;
+
+- napi = &pdata->rx_ring->napi;
+- netif_napi_del(napi);
++ for (i = 0; i < pdata->rxq_cnt; i++) {
++ napi = &pdata->rx_ring[i]->napi;
++ netif_napi_del(napi);
++ }
+
+- if (pdata->cq_cnt) {
+- napi = &pdata->tx_ring->cp_ring->napi;
++ for (i = 0; i < pdata->cq_cnt; i++) {
++ napi = &pdata->tx_ring[i]->cp_ring->napi;
+ netif_napi_del(napi);
+ }
+ }
+@@ -1445,7 +1533,8 @@ static int xgene_enet_probe(struct platform_device *pdev)
+ const struct of_device_id *of_id;
+ int ret;
+
+- ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
++ ndev = alloc_etherdev_mqs(sizeof(struct xgene_enet_pdata),
++ XGENE_NUM_RX_RING, XGENE_NUM_TX_RING);
+ if (!ndev)
+ return -ENOMEM;
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index 05365c1..175d188 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -49,6 +49,11 @@
+ #define XGENE_ENET_MSS 1448
+ #define XGENE_MIN_ENET_FRAME_SIZE 60
+
++#define XGENE_MAX_ENET_IRQ 8
++#define XGENE_NUM_RX_RING 4
++#define XGENE_NUM_TX_RING 4
++#define XGENE_NUM_TXC_RING 4
++
+ #define START_CPU_BUFNUM_0 0
+ #define START_ETH_BUFNUM_0 2
+ #define START_BP_BUFNUM_0 0x22
+@@ -73,7 +78,6 @@
+ #define X2_START_RING_NUM_1 256
+
+ #define IRQ_ID_SIZE 16
+-#define XGENE_MAX_TXC_RINGS 1
+
+ #define PHY_POLL_LINK_ON (10 * HZ)
+ #define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
+@@ -103,6 +107,7 @@ struct xgene_enet_desc_ring {
+ void *irq_mbox_addr;
+ u16 dst_ring_num;
+ u8 nbufpool;
++ u8 index;
+ struct sk_buff *(*rx_skb);
+ struct sk_buff *(*cp_skb);
+ dma_addr_t *frag_dma_addr;
+@@ -144,6 +149,7 @@ struct xgene_ring_ops {
+ void (*clear)(struct xgene_enet_desc_ring *);
+ void (*wr_cmd)(struct xgene_enet_desc_ring *, int);
+ u32 (*len)(struct xgene_enet_desc_ring *);
++ void (*coalesce)(struct xgene_enet_desc_ring *);
+ };
+
+ struct xgene_cle_ops {
+@@ -159,15 +165,16 @@ struct xgene_enet_pdata {
+ struct clk *clk;
+ struct platform_device *pdev;
+ enum xgene_enet_id enet_id;
+- struct xgene_enet_desc_ring *tx_ring;
+- struct xgene_enet_desc_ring *rx_ring;
+- u16 tx_level;
+- u16 txc_level;
++ struct xgene_enet_desc_ring *tx_ring[XGENE_NUM_TX_RING];
++ struct xgene_enet_desc_ring *rx_ring[XGENE_NUM_RX_RING];
++ u16 tx_level[XGENE_NUM_TX_RING];
++ u16 txc_level[XGENE_NUM_TX_RING];
+ char *dev_name;
+ u32 rx_buff_cnt;
+ u32 tx_qcnt_hi;
+- u32 rx_irq;
+- u32 txc_irq;
++ u32 irqs[XGENE_MAX_ENET_IRQ];
++ u8 rxq_cnt;
++ u8 txq_cnt;
+ u8 cq_cnt;
+ void __iomem *eth_csr_addr;
+ void __iomem *eth_ring_if_addr;
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
+index 0b6896b..2b76732 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
+@@ -190,6 +190,17 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+ return num_msgs;
+ }
+
++static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring)
++{
++ u32 data = 0x7777;
++
++ xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data << 16);
++ xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x40);
++ xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x80);
++}
++
+ struct xgene_ring_ops xgene_ring2_ops = {
+ .num_ring_config = X2_NUM_RING_CONFIG,
+ .num_ring_id_shift = 13,
+@@ -197,4 +208,5 @@ struct xgene_ring_ops xgene_ring2_ops = {
+ .clear = xgene_enet_clear_ring,
+ .wr_cmd = xgene_enet_wr_cmd,
+ .len = xgene_enet_ring_len,
++ .coalesce = xgene_enet_setup_coalescing,
+ };
+--
+2.6.6
+
diff --git a/patches.arch/arm64-drivers-net-xgene-constify-xgene_mac_ops-and-xgene_p.patch b/patches.arch/arm64-drivers-net-xgene-constify-xgene_mac_ops-and-xgene_p.patch
new file mode 100644
index 0000000000..709e29718e
--- /dev/null
+++ b/patches.arch/arm64-drivers-net-xgene-constify-xgene_mac_ops-and-xgene_p.patch
@@ -0,0 +1,194 @@
+From: Julia Lawall <julia.lawall@lip6.fr>
+Date: Tue, 8 Dec 2015 21:18:25 +0100
+Subject: drivers: net: xgene: constify xgene_mac_ops and xgene_port_ops
+ structures
+Git-commit: 3cdb73091767649ffd706a5caa3e75a411176f29
+Patch-mainline: v4.5-rc1
+References: fate#319483
+
+The xgene_mac_ops and xgene_port_ops structures are never modified, so
+declare them as const.
+
+Done with the help of Coccinelle.
+
+Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 8 ++++----
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h | 4 ++--
+ 8 files changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+index c31e691..db55c9f 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+@@ -869,7 +869,7 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
+ pdata->mdio_bus = NULL;
+ }
+
+-struct xgene_mac_ops xgene_gmac_ops = {
++const struct xgene_mac_ops xgene_gmac_ops = {
+ .init = xgene_gmac_init,
+ .reset = xgene_gmac_reset,
+ .rx_enable = xgene_gmac_rx_enable,
+@@ -879,7 +879,7 @@ struct xgene_mac_ops xgene_gmac_ops = {
+ .set_mac_addr = xgene_gmac_set_mac_addr,
+ };
+
+-struct xgene_port_ops xgene_gport_ops = {
++const struct xgene_port_ops xgene_gport_ops = {
+ .reset = xgene_enet_reset,
+ .cle_bypass = xgene_enet_cle_bypass,
+ .shutdown = xgene_gport_shutdown,
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+index c153a1d..8a90910 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+@@ -340,8 +340,8 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
+ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
+ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
+
+-extern struct xgene_mac_ops xgene_gmac_ops;
+-extern struct xgene_port_ops xgene_gport_ops;
++extern const struct xgene_mac_ops xgene_gmac_ops;
++extern const struct xgene_port_ops xgene_gport_ops;
+ extern struct xgene_ring_ops xgene_ring1_ops;
+
+ #endif /* __XGENE_ENET_HW_H__ */
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index d21ee87..2394191 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -682,7 +682,7 @@ static void xgene_enet_napi_disable(struct xgene_enet_pdata *pdata)
+ static int xgene_enet_open(struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+- struct xgene_mac_ops *mac_ops = pdata->mac_ops;
++ const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
+ int ret;
+
+ mac_ops->tx_enable(pdata);
+@@ -706,7 +706,7 @@ static int xgene_enet_open(struct net_device *ndev)
+ static int xgene_enet_close(struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+- struct xgene_mac_ops *mac_ops = pdata->mac_ops;
++ const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
+
+ netif_stop_queue(ndev);
+
+@@ -1416,7 +1416,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
+ struct net_device *ndev;
+ struct xgene_enet_pdata *pdata;
+ struct device *dev = &pdev->dev;
+- struct xgene_mac_ops *mac_ops;
++ const struct xgene_mac_ops *mac_ops;
+ const struct of_device_id *of_id;
+ int ret;
+
+@@ -1503,7 +1503,7 @@ err:
+ static int xgene_enet_remove(struct platform_device *pdev)
+ {
+ struct xgene_enet_pdata *pdata;
+- struct xgene_mac_ops *mac_ops;
++ const struct xgene_mac_ops *mac_ops;
+ struct net_device *ndev;
+
+ pdata = platform_get_drvdata(pdev);
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index a6e56b8..054caf0 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -174,8 +174,8 @@ struct xgene_enet_pdata {
+ int phy_mode;
+ enum xgene_enet_rm rm;
+ struct rtnl_link_stats64 stats;
+- struct xgene_mac_ops *mac_ops;
+- struct xgene_port_ops *port_ops;
++ const struct xgene_mac_ops *mac_ops;
++ const struct xgene_port_ops *port_ops;
+ struct xgene_ring_ops *ring_ops;
+ struct delayed_work link_work;
+ u32 port_id;
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+index 05b817e..7847551 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+@@ -405,7 +405,7 @@ static void xgene_enet_link_state(struct work_struct *work)
+ schedule_delayed_work(&p->link_work, poll_interval);
+ }
+
+-struct xgene_mac_ops xgene_sgmac_ops = {
++const struct xgene_mac_ops xgene_sgmac_ops = {
+ .init = xgene_sgmac_init,
+ .reset = xgene_sgmac_reset,
+ .rx_enable = xgene_sgmac_rx_enable,
+@@ -416,7 +416,7 @@ struct xgene_mac_ops xgene_sgmac_ops = {
+ .link_state = xgene_enet_link_state
+ };
+
+-struct xgene_port_ops xgene_sgport_ops = {
++const struct xgene_port_ops xgene_sgport_ops = {
+ .reset = xgene_enet_reset,
+ .cle_bypass = xgene_enet_cle_bypass,
+ .shutdown = xgene_enet_shutdown
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
+index de43246..29a71b4 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
+@@ -35,7 +35,7 @@
+ #define MPA_IDLE_WITH_QMI_EMPTY BIT(12)
+ #define SG_RX_DV_GATE_REG_0_ADDR 0x0dfc
+
+-extern struct xgene_mac_ops xgene_sgmac_ops;
+-extern struct xgene_port_ops xgene_sgport_ops;
++extern const struct xgene_mac_ops xgene_sgmac_ops;
++extern const struct xgene_port_ops xgene_sgport_ops;
+
+ #endif /* __XGENE_ENET_SGMAC_H__ */
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+index 7a28a48..ba030dc 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+@@ -326,7 +326,7 @@ static void xgene_enet_link_state(struct work_struct *work)
+ schedule_delayed_work(&pdata->link_work, poll_interval);
+ }
+
+-struct xgene_mac_ops xgene_xgmac_ops = {
++const struct xgene_mac_ops xgene_xgmac_ops = {
+ .init = xgene_xgmac_init,
+ .reset = xgene_xgmac_reset,
+ .rx_enable = xgene_xgmac_rx_enable,
+@@ -338,7 +338,7 @@ struct xgene_mac_ops xgene_xgmac_ops = {
+ .link_state = xgene_enet_link_state
+ };
+
+-struct xgene_port_ops xgene_xgport_ops = {
++const struct xgene_port_ops xgene_xgport_ops = {
+ .reset = xgene_enet_reset,
+ .cle_bypass = xgene_enet_xgcle_bypass,
+ .shutdown = xgene_enet_shutdown,
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
+index f8f908d..0a2dca8 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
+@@ -69,7 +69,7 @@
+ #define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
+ #define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
+
+-extern struct xgene_mac_ops xgene_xgmac_ops;
+-extern struct xgene_port_ops xgene_xgport_ops;
++extern const struct xgene_mac_ops xgene_xgmac_ops;
++extern const struct xgene_port_ops xgene_xgport_ops;
+
+ #endif /* __XGENE_ENET_XGMAC_H__ */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-drivers-net-xgene-fix-extra-IRQ-issue.patch b/patches.arch/arm64-drivers-net-xgene-fix-extra-IRQ-issue.patch
new file mode 100644
index 0000000000..b152553c04
--- /dev/null
+++ b/patches.arch/arm64-drivers-net-xgene-fix-extra-IRQ-issue.patch
@@ -0,0 +1,82 @@
+From: Iyappan Subramanian <isubramanian@apm.com>
+Date: Thu, 21 Jan 2016 16:07:41 -0800
+Subject: drivers: net: xgene: fix extra IRQ issue
+Git-commit: b5d7a06906a4875524f5c61c0b312828bf6737de
+Patch-mainline: v4.5-rc3
+References: fate#319483
+
+For interrupt controller that doesn't support irq_disable and hardware
+with level interrupt, an extra interrupt may be pending. This patch fixes
+the issue by setting IRQ_DISABLE_UNLAZY flag for the interrupt line,
+as suggested by,
+
+'commit e9849777d0e2 ("genirq: Add flag to force mask in
+ disable_irq[_nosync]()")'
+
+Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
+Tested-by: Toan Le <toanle@apm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 12 +++++++++---
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 +
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index a4799c1..5eb9b20 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -628,6 +628,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
+ int ret;
+
+ ring = pdata->rx_ring;
++ irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+ ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
+ IRQF_SHARED, ring->irq_name, ring);
+ if (ret)
+@@ -635,6 +636,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
+
+ if (pdata->cq_cnt) {
+ ring = pdata->tx_ring->cp_ring;
++ irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
+ ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
+ IRQF_SHARED, ring->irq_name, ring);
+ if (ret) {
+@@ -649,15 +651,19 @@ static int xgene_enet_register_irq(struct net_device *ndev)
+ static void xgene_enet_free_irq(struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata;
++ struct xgene_enet_desc_ring *ring;
+ struct device *dev;
+
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(ndev);
+- devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring);
++ ring = pdata->rx_ring;
++ irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
++ devm_free_irq(dev, ring->irq, ring);
+
+ if (pdata->cq_cnt) {
+- devm_free_irq(dev, pdata->tx_ring->cp_ring->irq,
+- pdata->tx_ring->cp_ring);
++ ring = pdata->tx_ring->cp_ring;
++ irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
++ devm_free_irq(dev, ring->irq, ring);
+ }
+ }
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index 70d5b62..248dfc4 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -25,6 +25,7 @@
+ #include <linux/acpi.h>
+ #include <linux/clk.h>
+ #include <linux/efi.h>
++#include <linux/irq.h>
+ #include <linux/io.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_net.h>
+--
+2.6.6
+
diff --git a/patches.arch/arm64-drivers-net-xgene-optimizing-the-code.patch b/patches.arch/arm64-drivers-net-xgene-optimizing-the-code.patch
new file mode 100644
index 0000000000..4b77fcd0ae
--- /dev/null
+++ b/patches.arch/arm64-drivers-net-xgene-optimizing-the-code.patch
@@ -0,0 +1,83 @@
+From: Saurabh Sengar <saurabh.truth@gmail.com>
+Date: Mon, 23 Nov 2015 19:02:15 +0530
+Subject: drivers: net: xgene: optimizing the code
+Git-commit: 724fe6955c88db8b249681cd78a76c10163bb0ba
+Patch-mainline: v4.5-rc1
+References: fate#319483
+
+this patch does the following:
+1 . remove unnecessary if, else condition
+2 . reduce one variable
+3 . change the return type of 2 functions to void as there return values
+turn out to be 0 always after above changes
+
+Signed-off-by: Saurabh Sengar <saurabh.truth@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 25 +++++++++---------------
+ 1 file changed, 9 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 991412c..6096d02 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -1084,7 +1084,7 @@ static const struct net_device_ops xgene_ndev_ops = {
+ };
+
+ #ifdef CONFIG_ACPI
+-static int xgene_get_port_id_acpi(struct device *dev,
++static void xgene_get_port_id_acpi(struct device *dev,
+ struct xgene_enet_pdata *pdata)
+ {
+ acpi_status status;
+@@ -1097,24 +1097,19 @@ static int xgene_get_port_id_acpi(struct device *dev,
+ pdata->port_id = temp;
+ }
+
+- return 0;
++ return;
+ }
+ #endif
+
+-static int xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pdata)
++static void xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pdata)
+ {
+ u32 id = 0;
+- int ret;
+
+- ret = of_property_read_u32(dev->of_node, "port-id", &id);
+- if (ret) {
+- pdata->port_id = 0;
+- ret = 0;
+- } else {
+- pdata->port_id = id & BIT(0);
+- }
++ of_property_read_u32(dev->of_node, "port-id", &id);
+
+- return ret;
++ pdata->port_id = id & BIT(0);
++
++ return;
+ }
+
+ static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata)
+@@ -1209,13 +1204,11 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+ }
+
+ if (dev->of_node)
+- ret = xgene_get_port_id_dt(dev, pdata);
++ xgene_get_port_id_dt(dev, pdata);
+ #ifdef CONFIG_ACPI
+ else
+- ret = xgene_get_port_id_acpi(dev, pdata);
++ xgene_get_port_id_acpi(dev, pdata);
+ #endif
+- if (ret)
+- return ret;
+
+ if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
+ eth_hw_addr_random(ndev);
+--
+2.6.6
+
diff --git a/patches.arch/arm64-dt-bindings-Add-documentation-for-Broadcom-Vulcan.patch b/patches.arch/arm64-dt-bindings-Add-documentation-for-Broadcom-Vulcan.patch
new file mode 100644
index 0000000000..fcfe6d4a76
--- /dev/null
+++ b/patches.arch/arm64-dt-bindings-Add-documentation-for-Broadcom-Vulcan.patch
@@ -0,0 +1,50 @@
+From f008decc4797979bc1d3b8efd18bd5df1e53e9f0 Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Sat, 20 Feb 2016 19:49:21 +0530
+Subject: [PATCH 4/4] dt-bindings: Add documentation for Broadcom Vulcan
+Patch-mainline: v4.6-rc1
+Git-commit: f008decc4797979bc1d3b8efd18bd5df1e53e9f0
+References: fate#319481
+
+Update arm/cpus.txt to add "brcm,vulcan" CPU. Add documentation
+for Broadcom Vulcan boards in arm/bcm/brcm,vulcan-soc.txt
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt | 10 ++++++++++
+ Documentation/devicetree/bindings/arm/cpus.txt | 1 +
+ 2 files changed, 11 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt
+
+diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt
+new file mode 100644
+index 0000000..223ed34
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/bcm/brcm,vulcan-soc.txt
+@@ -0,0 +1,10 @@
++Broadcom Vulcan device tree bindings
++------------------------------------
++
++Boards with Broadcom Vulcan shall have the following root property:
++
++Broadcom Vulcan Evaluation Board:
++ compatible = "brcm,vulcan-eval", "brcm,vulcan-soc";
++
++Generic Vulcan board:
++ compatible = "brcm,vulcan-soc";
+diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
+index ae9be07..bc43ad7 100644
+--- a/Documentation/devicetree/bindings/arm/cpus.txt
++++ b/Documentation/devicetree/bindings/arm/cpus.txt
+@@ -167,6 +167,7 @@ nodes to be present and contain the properties described below.
+ "arm,cortex-r5"
+ "arm,cortex-r7"
+ "brcm,brahma-b15"
++ "brcm,vulcan"
+ "cavium,thunder"
+ "faraday,fa526"
+ "intel,sa110"
+--
+2.6.6
+
diff --git a/patches.arch/arm64-dts-vulcan-Update-PCI-ranges.patch b/patches.arch/arm64-dts-vulcan-Update-PCI-ranges.patch
new file mode 100644
index 0000000000..3b444b19d4
--- /dev/null
+++ b/patches.arch/arm64-dts-vulcan-Update-PCI-ranges.patch
@@ -0,0 +1,58 @@
+From e6cc3be552f9fedf5fa6b37c285d7d27ffc08b03 Mon Sep 17 00:00:00 2001
+From: Jayachandran C <jchandra@broadcom.com>
+Date: Sun, 28 Feb 2016 13:07:17 +0530
+Subject: [PATCH] arm64: dts: vulcan: Update PCI ranges
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+Git-commit: e6cc3be552f9fedf5fa6b37c285d7d27ffc08b03
+References: fate#319481
+
+
+The PCI memory windows available in vulcan.dtsi are limited to 128MB
+for 32-bit BARs, and 4GB for 64-bit BARs. Given the memory mapped IO
+space available in arm64, these windows can be increased substantially
+to support more use cases.
+
+The change increases the 32-bit window to 256MB and the 64-bit window
+to 128 GB. The firmware on vulcan boards will use these ranges as well.
+
+PCI IO windows are not supported on Vulcan, so remove them instead of
+keeping an unused value.
+
+Signed-off-by: Jayachandran C <jchandra@broadcom.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ arch/arm64/boot/dts/broadcom/vulcan.dtsi | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/broadcom/vulcan.dtsi b/arch/arm64/boot/dts/broadcom/vulcan.dtsi
+index c49b5a8..85820e2 100644
+--- a/arch/arm64/boot/dts/broadcom/vulcan.dtsi
++++ b/arch/arm64/boot/dts/broadcom/vulcan.dtsi
+@@ -108,12 +108,15 @@
+ reg = <0x0 0x30000000 0x0 0x10000000>;
+ reg-names = "PCI ECAM";
+
+- /* IO 0x4000_0000 - 0x4001_0000 */
+- ranges = <0x01000000 0 0x40000000 0 0x40000000 0 0x00010000
+- /* MEM 0x4800_0000 - 0x5000_0000 */
+- 0x02000000 0 0x48000000 0 0x48000000 0 0x08000000
+- /* MEM64 pref 0x6_0000_0000 - 0x7_0000_0000 */
+- 0x43000000 6 0x00000000 6 0x00000000 1 0x00000000>;
++ /*
++ * PCI ranges:
++ * IO no supported
++ * MEM 0x4000_0000 - 0x6000_0000
++ * MEM64 pref 0x40_0000_0000 - 0x60_0000_0000
++ */
++ ranges =
++ <0x02000000 0 0x40000000 0 0x40000000 0 0x20000000
++ 0x43000000 0x40 0x00000000 0x40 0x00000000 0x20 0x00000000>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map =
+ /* addr pin ic icaddr icintr */
+--
+2.6.6
+
diff --git a/patches.arch/arm64-gpio-change-member-.dev-to-.parent.patch b/patches.arch/arm64-gpio-change-member-.dev-to-.parent.patch
new file mode 100644
index 0000000000..e1e2dafa98
--- /dev/null
+++ b/patches.arch/arm64-gpio-change-member-.dev-to-.parent.patch
@@ -0,0 +1,2722 @@
+From 58383c78425e4ee1c077253cf297b641c861c02e Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Wed, 4 Nov 2015 09:56:26 +0100
+Subject: [PATCH] gpio: change member .dev to .parent
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Patch-mainline: v4.5-rc1
+Git-commit:58383c78425e4ee1c077253cf297b641c861c02e
+References: fate#319481
+
+The name .dev in a struct is normally reserved for a struct device
+that is let us say a superclass to the thing described by the struct.
+struct gpio_chip stands out by confusingly using a struct device *dev
+to point to the parent device (such as a platform_device) that
+represents the hardware. As we want to give gpio_chip:s real devices,
+this is not working. We need to rename this member to parent.
+
+This was done by two coccinelle scripts, I guess it is possible to
+combine them into one, but I don't know such stuff. They look like
+this:
+
+@@
+struct gpio_chip *var;
+@@
+-var->dev
++var->parent
+
+and:
+
+@@
+struct gpio_chip var;
+@@
+-var.dev
++var.parent
+
+and:
+
+@@
+struct bgpio_chip *var;
+@@
+-var->gc.dev
++var->gc.parent
+
+Plus a few instances of bgpio that I couldn't figure out how
+to teach Coccinelle to rewrite.
+
+This patch hits all over the place, but I *strongly* prefer this
+solution to any piecemal approaches that just exercise patch
+mechanics all over the place. It mainly hits drivers/gpio and
+drivers/pinctrl which is my own backyard anyway.
+
+Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
+Cc: Rafał Miłecki <zajec5@gmail.com>
+Cc: Richard Purdie <rpurdie@rpsys.net>
+Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Cc: Alek Du <alek.du@intel.com>
+Cc: Jaroslav Kysela <perex@perex.cz>
+Cc: Takashi Iwai <tiwai@suse.com>
+Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Acked-by: Lee Jones <lee.jones@linaro.org>
+Acked-by: Jiri Kosina <jkosina@suse.cz>
+Acked-by: Hans-Christian Egtvedt <egtvedt@samfundet.no>
+Acked-by: Jacek Anaszewski <j.anaszewski@samsung.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Matthias Brugger <mbrugger@suse.com>
+---
+ arch/avr32/mach-at32ap/pio.c | 2 -
+ drivers/bcma/driver_gpio.c | 2 -
+ drivers/gpio/gpio-104-idio-16.c | 2 -
+ drivers/gpio/gpio-74x164.c | 4 +-
+ drivers/gpio/gpio-adnp.c | 19 +++++-----
+ drivers/gpio/gpio-altera.c | 2 -
+ drivers/gpio/gpio-amd8111.c | 2 -
+ drivers/gpio/gpio-amdpt.c | 18 ++++-----
+ drivers/gpio/gpio-arizona.c | 2 -
+ drivers/gpio/gpio-ath79.c | 2 -
+ drivers/gpio/gpio-bcm-kona.c | 6 +--
+ drivers/gpio/gpio-crystalcove.c | 2 -
+ drivers/gpio/gpio-davinci.c | 4 +-
+ drivers/gpio/gpio-dln2.c | 10 ++---
+ drivers/gpio/gpio-em.c | 4 +-
+ drivers/gpio/gpio-f7188x.c | 2 -
+ drivers/gpio/gpio-generic.c | 2 -
+ drivers/gpio/gpio-ich.c | 2 -
+ drivers/gpio/gpio-intel-mid.c | 2 -
+ drivers/gpio/gpio-janz-ttl.c | 6 +--
+ drivers/gpio/gpio-kempld.c | 2 -
+ drivers/gpio/gpio-lp3943.c | 2 -
+ drivers/gpio/gpio-lpc18xx.c | 2 -
+ drivers/gpio/gpio-lynxpoint.c | 2 -
+ drivers/gpio/gpio-max730x.c | 2 -
+ drivers/gpio/gpio-max732x.c | 4 +-
+ drivers/gpio/gpio-mb86s7x.c | 2 -
+ drivers/gpio/gpio-mc33880.c | 2 -
+ drivers/gpio/gpio-mc9s08dz60.c | 2 -
+ drivers/gpio/gpio-mcp23s08.c | 16 ++++----
+ drivers/gpio/gpio-moxart.c | 2 -
+ drivers/gpio/gpio-msic.c | 2 -
+ drivers/gpio/gpio-mvebu.c | 2 -
+ drivers/gpio/gpio-octeon.c | 2 -
+ drivers/gpio/gpio-omap.c | 4 +-
+ drivers/gpio/gpio-palmas.c | 14 ++++---
+ drivers/gpio/gpio-pca953x.c | 2 -
+ drivers/gpio/gpio-pcf857x.c | 2 -
+ drivers/gpio/gpio-pch.c | 2 -
+ drivers/gpio/gpio-pl061.c | 12 +++---
+ drivers/gpio/gpio-rc5t583.c | 2 -
+ drivers/gpio/gpio-rcar.c | 2 -
+ drivers/gpio/gpio-sch.c | 2 -
+ drivers/gpio/gpio-sch311x.c | 4 +-
+ drivers/gpio/gpio-spear-spics.c | 2 -
+ drivers/gpio/gpio-stmpe.c | 2 -
+ drivers/gpio/gpio-stp-xway.c | 4 +-
+ drivers/gpio/gpio-sx150x.c | 2 -
+ drivers/gpio/gpio-syscon.c | 4 +-
+ drivers/gpio/gpio-tb10x.c | 2 -
+ drivers/gpio/gpio-tc3589x.c | 2 -
+ drivers/gpio/gpio-timberdale.c | 2 -
+ drivers/gpio/gpio-tps6586x.c | 2 -
+ drivers/gpio/gpio-tps65910.c | 2 -
+ drivers/gpio/gpio-tps65912.c | 2 -
+ drivers/gpio/gpio-ts5500.c | 5 +-
+ drivers/gpio/gpio-twl4030.c | 4 +-
+ drivers/gpio/gpio-twl6040.c | 6 +--
+ drivers/gpio/gpio-tz1090-pdc.c | 2 -
+ drivers/gpio/gpio-tz1090.c | 2 -
+ drivers/gpio/gpio-vf610.c | 2 -
+ drivers/gpio/gpio-viperboard.c | 16 ++++----
+ drivers/gpio/gpio-vr41xx.c | 4 +-
+ drivers/gpio/gpio-wm831x.c | 2 -
+ drivers/gpio/gpio-wm8350.c | 2 -
+ drivers/gpio/gpio-wm8994.c | 2 -
+ drivers/gpio/gpio-xgene-sb.c | 8 ++--
+ drivers/gpio/gpio-xgene.c | 2 -
+ drivers/gpio/gpio-xilinx.c | 2 -
+ drivers/gpio/gpio-xlp.c | 2 -
+ drivers/gpio/gpio-zevio.c | 4 +-
+ drivers/gpio/gpio-zx.c | 2 -
+ drivers/gpio/gpio-zynq.c | 6 +--
+ drivers/gpio/gpiolib-acpi.c | 47 +++++++++++++-------------
+ drivers/gpio/gpiolib-of.c | 4 +-
+ drivers/gpio/gpiolib-sysfs.c | 5 +-
+ drivers/gpio/gpiolib.c | 19 +++++-----
+ drivers/hid/hid-cp2112.c | 2 -
+ drivers/input/touchscreen/ad7879.c | 2 -
+ drivers/leds/leds-pca9532.c | 6 +--
+ drivers/leds/leds-tca6507.c | 2 -
+ drivers/media/dvb-frontends/cxd2820r_core.c | 2 -
+ drivers/mfd/dm355evm_msp.c | 2 -
+ drivers/mfd/htc-egpio.c | 2 -
+ drivers/mfd/htc-i2cpld.c | 4 +-
+ drivers/mfd/tps65010.c | 2 -
+ drivers/mfd/ucb1x00-core.c | 2 -
+ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 8 ++--
+ drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c | 2 -
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 2 -
+ drivers/pinctrl/intel/pinctrl-cherryview.c | 2 -
+ drivers/pinctrl/intel/pinctrl-intel.c | 2 -
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 12 +++---
+ drivers/pinctrl/meson/pinctrl-meson.c | 2 -
+ drivers/pinctrl/nomadik/pinctrl-abx500.c | 7 ++-
+ drivers/pinctrl/nomadik/pinctrl-nomadik.c | 8 ++--
+ drivers/pinctrl/pinctrl-amd.c | 2 -
+ drivers/pinctrl/pinctrl-as3722.c | 2 -
+ drivers/pinctrl/pinctrl-at91-pio4.c | 12 +++---
+ drivers/pinctrl/pinctrl-at91.c | 2 -
+ drivers/pinctrl/pinctrl-coh901.c | 2 -
+ drivers/pinctrl/pinctrl-digicolor.c | 2 -
+ drivers/pinctrl/pinctrl-pistachio.c | 2 -
+ drivers/pinctrl/pinctrl-rockchip.c | 2 -
+ drivers/pinctrl/pinctrl-st.c | 2 -
+ drivers/pinctrl/pinctrl-xway.c | 10 ++---
+ drivers/pinctrl/qcom/pinctrl-msm.c | 2 -
+ drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 2 -
+ drivers/pinctrl/qcom/pinctrl-spmi-mpp.c | 2 -
+ drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | 2 -
+ drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c | 2 -
+ drivers/pinctrl/samsung/pinctrl-exynos.c | 3 +
+ drivers/pinctrl/samsung/pinctrl-exynos5440.c | 12 +++---
+ drivers/pinctrl/samsung/pinctrl-samsung.c | 2 -
+ drivers/pinctrl/sh-pfc/gpio.c | 2 -
+ drivers/pinctrl/sirf/pinctrl-atlas7.c | 2 -
+ drivers/pinctrl/sirf/pinctrl-sirf.c | 2 -
+ drivers/pinctrl/spear/pinctrl-plgpio.c | 2 -
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 10 ++---
+ drivers/pinctrl/vt8500/pinctrl-wmt.c | 8 ++--
+ drivers/platform/x86/intel_pmic_gpio.c | 4 +-
+ drivers/tty/serial/max310x.c | 2 -
+ drivers/tty/serial/sc16is7xx.c | 2 -
+ include/linux/gpio/driver.h | 4 +-
+ sound/soc/codecs/rt5677.c | 2 -
+ sound/soc/codecs/wm5100.c | 2 -
+ sound/soc/codecs/wm8903.c | 2 -
+ sound/soc/codecs/wm8962.c | 2 -
+ sound/soc/codecs/wm8996.c | 2 -
+ 129 files changed, 278 insertions(+), 265 deletions(-)
+
+--- a/arch/avr32/mach-at32ap/pio.c
++++ b/arch/avr32/mach-at32ap/pio.c
+@@ -397,7 +397,7 @@ static int __init pio_probe(struct platf
+ pio->chip.label = pio->name;
+ pio->chip.base = pdev->id * 32;
+ pio->chip.ngpio = 32;
+- pio->chip.dev = &pdev->dev;
++ pio->chip.parent = &pdev->dev;
+ pio->chip.owner = THIS_MODULE;
+
+ pio->chip.direction_input = direction_input;
+--- a/drivers/bcma/driver_gpio.c
++++ b/drivers/bcma/driver_gpio.c
+@@ -188,7 +188,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c
+ chip->direction_input = bcma_gpio_direction_input;
+ chip->direction_output = bcma_gpio_direction_output;
+ chip->owner = THIS_MODULE;
+- chip->dev = bcma_bus_get_host_dev(bus);
++ chip->parent = bcma_bus_get_host_dev(bus);
+ #if IS_BUILTIN(CONFIG_OF)
+ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
+ chip->of_node = cc->core->dev.of_node;
+--- a/drivers/gpio/gpio-104-idio-16.c
++++ b/drivers/gpio/gpio-104-idio-16.c
+@@ -127,7 +127,7 @@ static int __init idio_16_probe(struct p
+ }
+
+ idio16gpio->chip.label = NAME;
+- idio16gpio->chip.dev = dev;
++ idio16gpio->chip.parent = dev;
+ idio16gpio->chip.owner = THIS_MODULE;
+ idio16gpio->chip.base = -1;
+ idio16gpio->chip.ngpio = 32;
+--- a/drivers/gpio/gpio-74x164.c
++++ b/drivers/gpio/gpio-74x164.c
+@@ -33,7 +33,7 @@ static struct gen_74x164_chip *gpio_to_7
+
+ static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
+ {
+- struct spi_device *spi = to_spi_device(chip->gpio_chip.dev);
++ struct spi_device *spi = to_spi_device(chip->gpio_chip.parent);
+ struct spi_message message;
+ struct spi_transfer *msg_buf;
+ int i, ret = 0;
+@@ -143,7 +143,7 @@ static int gen_74x164_probe(struct spi_d
+ return -ENOMEM;
+
+ chip->gpio_chip.can_sleep = true;
+- chip->gpio_chip.dev = &spi->dev;
++ chip->gpio_chip.parent = &spi->dev;
+ chip->gpio_chip.owner = THIS_MODULE;
+
+ mutex_init(&chip->lock);
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -47,7 +47,7 @@ static int adnp_read(struct adnp *adnp,
+
+ err = i2c_smbus_read_byte_data(adnp->client, offset);
+ if (err < 0) {
+- dev_err(adnp->gpio.dev, "%s failed: %d\n",
++ dev_err(adnp->gpio.parent, "%s failed: %d\n",
+ "i2c_smbus_read_byte_data()", err);
+ return err;
+ }
+@@ -62,7 +62,7 @@ static int adnp_write(struct adnp *adnp,
+
+ err = i2c_smbus_write_byte_data(adnp->client, offset, value);
+ if (err < 0) {
+- dev_err(adnp->gpio.dev, "%s failed: %d\n",
++ dev_err(adnp->gpio.parent, "%s failed: %d\n",
+ "i2c_smbus_write_byte_data()", err);
+ return err;
+ }
+@@ -266,8 +266,8 @@ static int adnp_gpio_setup(struct adnp *
+ chip->base = -1;
+ chip->ngpio = num_gpios;
+ chip->label = adnp->client->name;
+- chip->dev = &adnp->client->dev;
+- chip->of_node = chip->dev->of_node;
++ chip->parent = &adnp->client->dev;
++ chip->of_node = chip->parent->of_node;
+ chip->owner = THIS_MODULE;
+
+ err = gpiochip_add(chip);
+@@ -435,7 +435,8 @@ static int adnp_irq_setup(struct adnp *a
+ * is chosen to match the register layout of the hardware in that
+ * each segment contains the corresponding bits for all interrupts.
+ */
+- adnp->irq_enable = devm_kzalloc(chip->dev, num_regs * 6, GFP_KERNEL);
++ adnp->irq_enable = devm_kzalloc(chip->parent, num_regs * 6,
++ GFP_KERNEL);
+ if (!adnp->irq_enable)
+ return -ENOMEM;
+
+@@ -462,12 +463,12 @@ static int adnp_irq_setup(struct adnp *a
+ adnp->irq_enable[i] = 0x00;
+ }
+
+- err = devm_request_threaded_irq(chip->dev, adnp->client->irq,
++ err = devm_request_threaded_irq(chip->parent, adnp->client->irq,
+ NULL, adnp_irq,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+- dev_name(chip->dev), adnp);
++ dev_name(chip->parent), adnp);
+ if (err != 0) {
+- dev_err(chip->dev, "can't request IRQ#%d: %d\n",
++ dev_err(chip->parent, "can't request IRQ#%d: %d\n",
+ adnp->client->irq, err);
+ return err;
+ }
+@@ -478,7 +479,7 @@ static int adnp_irq_setup(struct adnp *a
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (err) {
+- dev_err(chip->dev,
++ dev_err(chip->parent,
+ "could not connect irqchip to gpiochip\n");
+ return err;
+ }
+--- a/drivers/gpio/gpio-altera.c
++++ b/drivers/gpio/gpio-altera.c
+@@ -290,7 +290,7 @@ static int altera_gpio_probe(struct plat
+ altera_gc->mmchip.gc.get = altera_gpio_get;
+ altera_gc->mmchip.gc.set = altera_gpio_set;
+ altera_gc->mmchip.gc.owner = THIS_MODULE;
+- altera_gc->mmchip.gc.dev = &pdev->dev;
++ altera_gc->mmchip.gc.parent = &pdev->dev;
+
+ ret = of_mm_gpiochip_add(node, &altera_gc->mmchip);
+ if (ret) {
+--- a/drivers/gpio/gpio-amd8111.c
++++ b/drivers/gpio/gpio-amd8111.c
+@@ -220,7 +220,7 @@ found:
+ goto out;
+ }
+ gp.pdev = pdev;
+- gp.chip.dev = &pdev->dev;
++ gp.chip.parent = &pdev->dev;
+
+ spin_lock_init(&gp.lock);
+
+--- a/drivers/gpio/gpio-amdpt.c
++++ b/drivers/gpio/gpio-amdpt.c
+@@ -39,14 +39,14 @@ static int pt_gpio_request(struct gpio_c
+ unsigned long flags;
+ u32 using_pins;
+
+- dev_dbg(gc->dev, "pt_gpio_request offset=%x\n", offset);
++ dev_dbg(gc->parent, "pt_gpio_request offset=%x\n", offset);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+ using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
+ if (using_pins & BIT(offset)) {
+- dev_warn(gc->dev, "PT GPIO pin %x reconfigured\n",
+- offset);
++ dev_warn(gc->parent, "PT GPIO pin %x reconfigured\n",
++ offset);
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+ return -EINVAL;
+ }
+@@ -72,7 +72,7 @@ static void pt_gpio_free(struct gpio_chi
+
+ spin_unlock_irqrestore(&pt_gpio->lock, flags);
+
+- dev_dbg(gc->dev, "pt_gpio_free offset=%x\n", offset);
++ dev_dbg(gc->parent, "pt_gpio_free offset=%x\n", offset);
+ }
+
+ static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
+@@ -81,7 +81,7 @@ static void pt_gpio_set_value(struct gpi
+ unsigned long flags;
+ u32 data;
+
+- dev_dbg(gc->dev, "pt_gpio_set_value offset=%x, value=%x\n",
++ dev_dbg(gc->parent, "pt_gpio_set_value offset=%x, value=%x\n",
+ offset, value);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+@@ -116,7 +116,7 @@ static int pt_gpio_get_value(struct gpio
+ data >>= offset;
+ data &= 1;
+
+- dev_dbg(gc->dev, "pt_gpio_get_value offset=%x, value=%x\n",
++ dev_dbg(gc->parent, "pt_gpio_get_value offset=%x, value=%x\n",
+ offset, data);
+
+ return data;
+@@ -128,7 +128,7 @@ static int pt_gpio_direction_input(struc
+ unsigned long flags;
+ u32 data;
+
+- dev_dbg(gc->dev, "pt_gpio_dirction_input offset=%x\n", offset);
++ dev_dbg(gc->parent, "pt_gpio_dirction_input offset=%x\n", offset);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+
+@@ -148,7 +148,7 @@ static int pt_gpio_direction_output(stru
+ unsigned long flags;
+ u32 data;
+
+- dev_dbg(gc->dev, "pt_gpio_direction_output offset=%x, value=%x\n",
++ dev_dbg(gc->parent, "pt_gpio_direction_output offset=%x, value=%x\n",
+ offset, value);
+
+ spin_lock_irqsave(&pt_gpio->lock, flags);
+@@ -202,7 +202,7 @@ static int pt_gpio_probe(struct platform
+
+ pt_gpio->gc.label = pdev->name;
+ pt_gpio->gc.owner = THIS_MODULE;
+- pt_gpio->gc.dev = dev;
++ pt_gpio->gc.parent = dev;
+ pt_gpio->gc.request = pt_gpio_request;
+ pt_gpio->gc.free = pt_gpio_free;
+ pt_gpio->gc.direction_input = pt_gpio_direction_input;
+--- a/drivers/gpio/gpio-arizona.c
++++ b/drivers/gpio/gpio-arizona.c
+@@ -108,7 +108,7 @@ static int arizona_gpio_probe(struct pla
+
+ arizona_gpio->arizona = arizona;
+ arizona_gpio->gpio_chip = template_chip;
+- arizona_gpio->gpio_chip.dev = &pdev->dev;
++ arizona_gpio->gpio_chip.parent = &pdev->dev;
+ #ifdef CONFIG_OF_GPIO
+ arizona_gpio->gpio_chip.of_node = arizona->dev->of_node;
+ #endif
+--- a/drivers/gpio/gpio-ath79.c
++++ b/drivers/gpio/gpio-ath79.c
+@@ -177,7 +177,7 @@ static int ath79_gpio_probe(struct platf
+
+ spin_lock_init(&ctrl->lock);
+ memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip));
+- ctrl->chip.dev = &pdev->dev;
++ ctrl->chip.parent = &pdev->dev;
+ ctrl->chip.ngpio = ath79_gpio_count;
+ if (oe_inverted) {
+ ctrl->chip.direction_input = ar934x_gpio_direction_input;
+--- a/drivers/gpio/gpio-bcm-kona.c
++++ b/drivers/gpio/gpio-bcm-kona.c
+@@ -273,7 +273,7 @@ static int bcm_kona_gpio_set_debounce(st
+ reg_base = kona_gpio->reg_base;
+ /* debounce must be 1-128ms (or 0) */
+ if ((debounce > 0 && debounce < 1000) || debounce > 128000) {
+- dev_err(chip->dev, "Debounce value %u not in range\n",
++ dev_err(chip->parent, "Debounce value %u not in range\n",
+ debounce);
+ return -EINVAL;
+ }
+@@ -416,7 +416,7 @@ static int bcm_kona_gpio_irq_set_type(st
+ case IRQ_TYPE_LEVEL_LOW:
+ /* BCM GPIO doesn't support level triggering */
+ default:
+- dev_err(kona_gpio->gpio_chip.dev,
++ dev_err(kona_gpio->gpio_chip.parent,
+ "Invalid BCM GPIO irq type 0x%x\n", type);
+ return -EINVAL;
+ }
+@@ -477,7 +477,7 @@ static int bcm_kona_gpio_irq_reqres(stru
+ struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
+
+ if (gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) {
+- dev_err(kona_gpio->gpio_chip.dev,
++ dev_err(kona_gpio->gpio_chip.parent,
+ "unable to lock HW IRQ %lu for IRQ\n",
+ d->hwirq);
+ return -EINVAL;
+--- a/drivers/gpio/gpio-crystalcove.c
++++ b/drivers/gpio/gpio-crystalcove.c
+@@ -341,7 +341,7 @@ static int crystalcove_gpio_probe(struct
+ cg->chip.base = -1;
+ cg->chip.ngpio = CRYSTALCOVE_VGPIO_NUM;
+ cg->chip.can_sleep = true;
+- cg->chip.dev = dev;
++ cg->chip.parent = dev;
+ cg->chip.dbg_show = crystalcove_gpio_dbg_show;
+ cg->regmap = pmic->regmap;
+
+--- a/drivers/gpio/gpio-davinci.c
++++ b/drivers/gpio/gpio-davinci.c
+@@ -179,8 +179,8 @@ static int davinci_gpio_of_xlate(struct
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+ {
+- struct davinci_gpio_controller *chips = dev_get_drvdata(gc->dev);
+- struct davinci_gpio_platform_data *pdata = dev_get_platdata(gc->dev);
++ struct davinci_gpio_controller *chips = dev_get_drvdata(gc->parent);
++ struct davinci_gpio_platform_data *pdata = dev_get_platdata(gc->parent);
+
+ if (gpiospec->args[0] > pdata->ngpio)
+ return -EINVAL;
+--- a/drivers/gpio/gpio-dln2.c
++++ b/drivers/gpio/gpio-dln2.c
+@@ -377,7 +377,7 @@ static void dln2_irq_bus_unlock(struct i
+
+ ret = dln2_gpio_set_event_cfg(dln2, pin, type, 0);
+ if (ret)
+- dev_err(dln2->gpio.dev, "failed to set event\n");
++ dev_err(dln2->gpio.parent, "failed to set event\n");
+ }
+
+ mutex_unlock(&dln2->irq_lock);
+@@ -406,19 +406,19 @@ static void dln2_gpio_event(struct platf
+ struct dln2_gpio *dln2 = platform_get_drvdata(pdev);
+
+ if (len < sizeof(*event)) {
+- dev_err(dln2->gpio.dev, "short event message\n");
++ dev_err(dln2->gpio.parent, "short event message\n");
+ return;
+ }
+
+ pin = le16_to_cpu(event->pin);
+ if (pin >= dln2->gpio.ngpio) {
+- dev_err(dln2->gpio.dev, "out of bounds pin %d\n", pin);
++ dev_err(dln2->gpio.parent, "out of bounds pin %d\n", pin);
+ return;
+ }
+
+ irq = irq_find_mapping(dln2->gpio.irqdomain, pin);
+ if (!irq) {
+- dev_err(dln2->gpio.dev, "pin %d not mapped to IRQ\n", pin);
++ dev_err(dln2->gpio.parent, "pin %d not mapped to IRQ\n", pin);
+ return;
+ }
+
+@@ -462,7 +462,7 @@ static int dln2_gpio_probe(struct platfo
+ dln2->pdev = pdev;
+
+ dln2->gpio.label = "dln2";
+- dln2->gpio.dev = dev;
++ dln2->gpio.parent = dev;
+ dln2->gpio.owner = THIS_MODULE;
+ dln2->gpio.base = -1;
+ dln2->gpio.ngpio = pins;
+--- a/drivers/gpio/gpio-em.c
++++ b/drivers/gpio/gpio-em.c
+@@ -103,7 +103,7 @@ static int em_gio_irq_reqres(struct irq_
+ struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
+
+ if (gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) {
+- dev_err(p->gpio_chip.dev,
++ dev_err(p->gpio_chip.parent,
+ "unable to lock HW IRQ %lu for IRQ\n",
+ irqd_to_hwirq(d));
+ return -EINVAL;
+@@ -332,7 +332,7 @@ static int em_gio_probe(struct platform_
+ gpio_chip->request = em_gio_request;
+ gpio_chip->free = em_gio_free;
+ gpio_chip->label = name;
+- gpio_chip->dev = &pdev->dev;
++ gpio_chip->parent = &pdev->dev;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->base = -1;
+ gpio_chip->ngpio = ngpios;
+--- a/drivers/gpio/gpio-f7188x.c
++++ b/drivers/gpio/gpio-f7188x.c
+@@ -333,7 +333,7 @@ static int f7188x_gpio_probe(struct plat
+ for (i = 0; i < data->nr_bank; i++) {
+ struct f7188x_gpio_bank *bank = &data->bank[i];
+
+- bank->chip.dev = &pdev->dev;
++ bank->chip.parent = &pdev->dev;
+ bank->data = data;
+
+ err = gpiochip_add(&bank->chip);
+--- a/drivers/gpio/gpio-generic.c
++++ b/drivers/gpio/gpio-generic.c
+@@ -518,7 +518,7 @@ int bgpio_init(struct gpio_chip *gc, str
+ return -EINVAL;
+
+ spin_lock_init(&gc->bgpio_lock);
+- gc->dev = dev;
++ gc->parent = dev;
+ gc->label = dev_name(dev);
+ gc->base = -1;
+ gc->ngpio = gc->bgpio_bits;
+--- a/drivers/gpio/gpio-ich.c
++++ b/drivers/gpio/gpio-ich.c
+@@ -282,7 +282,7 @@ static void ichx_gpiolib_setup(struct gp
+ {
+ chip->owner = THIS_MODULE;
+ chip->label = DRV_NAME;
+- chip->dev = &ichx_priv.dev->dev;
++ chip->parent = &ichx_priv.dev->dev;
+
+ /* Allow chip-specific overrides of request()/get() */
+ chip->request = ichx_priv.desc->request ?
+--- a/drivers/gpio/gpio-intel-mid.c
++++ b/drivers/gpio/gpio-intel-mid.c
+@@ -392,7 +392,7 @@ static int intel_gpio_probe(struct pci_d
+
+ priv->reg_base = pcim_iomap_table(pdev)[0];
+ priv->chip.label = dev_name(&pdev->dev);
+- priv->chip.dev = &pdev->dev;
++ priv->chip.parent = &pdev->dev;
+ priv->chip.request = intel_gpio_request;
+ priv->chip.direction_input = intel_gpio_direction_input;
+ priv->chip.direction_output = intel_gpio_direction_output;
+--- a/drivers/gpio/gpio-janz-ttl.c
++++ b/drivers/gpio/gpio-janz-ttl.c
+@@ -59,7 +59,7 @@ struct ttl_module {
+
+ static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
+ {
+- struct ttl_module *mod = dev_get_drvdata(gpio->dev);
++ struct ttl_module *mod = dev_get_drvdata(gpio->parent);
+ u8 *shadow;
+ int ret;
+
+@@ -81,7 +81,7 @@ static int ttl_get_value(struct gpio_chi
+
+ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
+ {
+- struct ttl_module *mod = dev_get_drvdata(gpio->dev);
++ struct ttl_module *mod = dev_get_drvdata(gpio->parent);
+ void __iomem *port;
+ u8 *shadow;
+
+@@ -172,7 +172,7 @@ static int ttl_probe(struct platform_dev
+
+ /* Initialize the GPIO data structures */
+ gpio = &mod->gpio;
+- gpio->dev = &pdev->dev;
++ gpio->parent = &pdev->dev;
+ gpio->label = pdev->name;
+ gpio->get = ttl_get_value;
+ gpio->set = ttl_set_value;
+--- a/drivers/gpio/gpio-kempld.c
++++ b/drivers/gpio/gpio-kempld.c
+@@ -166,7 +166,7 @@ static int kempld_gpio_probe(struct plat
+ chip = &gpio->chip;
+ chip->label = "gpio-kempld";
+ chip->owner = THIS_MODULE;
+- chip->dev = dev;
++ chip->parent = dev;
+ chip->can_sleep = true;
+ if (pdata && pdata->gpio_base)
+ chip->base = pdata->gpio_base;
+--- a/drivers/gpio/gpio-lp3943.c
++++ b/drivers/gpio/gpio-lp3943.c
+@@ -205,7 +205,7 @@ static int lp3943_gpio_probe(struct plat
+
+ lp3943_gpio->lp3943 = lp3943;
+ lp3943_gpio->chip = lp3943_gpio_chip;
+- lp3943_gpio->chip.dev = &pdev->dev;
++ lp3943_gpio->chip.parent = &pdev->dev;
+
+ platform_set_drvdata(pdev, lp3943_gpio);
+
+--- a/drivers/gpio/gpio-lpc18xx.c
++++ b/drivers/gpio/gpio-lpc18xx.c
+@@ -127,7 +127,7 @@ static int lpc18xx_gpio_probe(struct pla
+
+ spin_lock_init(&gc->lock);
+
+- gc->gpio.dev = &pdev->dev;
++ gc->gpio.parent = &pdev->dev;
+
+ ret = gpiochip_add(&gc->gpio);
+ if (ret) {
+--- a/drivers/gpio/gpio-lynxpoint.c
++++ b/drivers/gpio/gpio-lynxpoint.c
+@@ -368,7 +368,7 @@ static int lp_gpio_probe(struct platform
+ gc->base = -1;
+ gc->ngpio = LP_NUM_GPIO;
+ gc->can_sleep = false;
+- gc->dev = dev;
++ gc->parent = dev;
+
+ ret = gpiochip_add(gc);
+ if (ret) {
+--- a/drivers/gpio/gpio-max730x.c
++++ b/drivers/gpio/gpio-max730x.c
+@@ -189,7 +189,7 @@ int __max730x_probe(struct max7301 *ts)
+
+ ts->chip.ngpio = PIN_NUMBER;
+ ts->chip.can_sleep = true;
+- ts->chip.dev = dev;
++ ts->chip.parent = dev;
+ ts->chip.owner = THIS_MODULE;
+
+ /*
+--- a/drivers/gpio/gpio-max732x.c
++++ b/drivers/gpio/gpio-max732x.c
+@@ -603,7 +603,7 @@ static int max732x_setup_gpio(struct max
+ gc->base = gpio_start;
+ gc->ngpio = port;
+ gc->label = chip->client->name;
+- gc->dev = &chip->client->dev;
++ gc->parent = &chip->client->dev;
+ gc->owner = THIS_MODULE;
+
+ return port;
+@@ -649,7 +649,7 @@ static int max732x_probe(struct i2c_clie
+ chip->client = client;
+
+ nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
+- chip->gpio_chip.dev = &client->dev;
++ chip->gpio_chip.parent = &client->dev;
+
+ addr_a = (client->addr & 0x0f) | 0x60;
+ addr_b = (client->addr & 0x0f) | 0x50;
+--- a/drivers/gpio/gpio-mb86s7x.c
++++ b/drivers/gpio/gpio-mb86s7x.c
+@@ -187,7 +187,7 @@ static int mb86s70_gpio_probe(struct pla
+ gchip->gc.label = dev_name(&pdev->dev);
+ gchip->gc.ngpio = 32;
+ gchip->gc.owner = THIS_MODULE;
+- gchip->gc.dev = &pdev->dev;
++ gchip->gc.parent = &pdev->dev;
+ gchip->gc.base = -1;
+
+ platform_set_drvdata(pdev, gchip);
+--- a/drivers/gpio/gpio-mc33880.c
++++ b/drivers/gpio/gpio-mc33880.c
+@@ -116,7 +116,7 @@ static int mc33880_probe(struct spi_devi
+ mc->chip.base = pdata->base;
+ mc->chip.ngpio = PIN_NUMBER;
+ mc->chip.can_sleep = true;
+- mc->chip.dev = &spi->dev;
++ mc->chip.parent = &spi->dev;
+ mc->chip.owner = THIS_MODULE;
+
+ mc->port_config = 0x00;
+--- a/drivers/gpio/gpio-mc9s08dz60.c
++++ b/drivers/gpio/gpio-mc9s08dz60.c
+@@ -99,7 +99,7 @@ static int mc9s08dz60_probe(struct i2c_c
+
+ mc9s->chip.label = client->name;
+ mc9s->chip.base = -1;
+- mc9s->chip.dev = &client->dev;
++ mc9s->chip.parent = &client->dev;
+ mc9s->chip.owner = THIS_MODULE;
+ mc9s->chip.ngpio = GPIO_NUM;
+ mc9s->chip.can_sleep = true;
+--- a/drivers/gpio/gpio-mcp23s08.c
++++ b/drivers/gpio/gpio-mcp23s08.c
+@@ -446,7 +446,7 @@ static int mcp23s08_irq_reqres(struct ir
+ struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
+
+ if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) {
+- dev_err(mcp->chip.dev,
++ dev_err(mcp->chip.parent,
+ "unable to lock HW IRQ %lu for IRQ usage\n",
+ data->hwirq);
+ return -EINVAL;
+@@ -481,7 +481,8 @@ static int mcp23s08_irq_setup(struct mcp
+
+ mutex_init(&mcp->irq_lock);
+
+- mcp->irq_domain = irq_domain_add_linear(chip->dev->of_node, chip->ngpio,
++ mcp->irq_domain = irq_domain_add_linear(chip->parent->of_node,
++ chip->ngpio,
+ &irq_domain_simple_ops, mcp);
+ if (!mcp->irq_domain)
+ return -ENODEV;
+@@ -491,10 +492,11 @@ static int mcp23s08_irq_setup(struct mcp
+ else
+ irqflags |= IRQF_TRIGGER_LOW;
+
+- err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq,
+- irqflags, dev_name(chip->dev), mcp);
++ err = devm_request_threaded_irq(chip->parent, mcp->irq, NULL,
++ mcp23s08_irq,
++ irqflags, dev_name(chip->parent), mcp);
+ if (err != 0) {
+- dev_err(chip->dev, "unable to request IRQ#%d: %d\n",
++ dev_err(chip->parent, "unable to request IRQ#%d: %d\n",
+ mcp->irq, err);
+ return err;
+ }
+@@ -638,7 +640,7 @@ static int mcp23s08_probe_one(struct mcp
+
+ mcp->chip.base = pdata->base;
+ mcp->chip.can_sleep = true;
+- mcp->chip.dev = dev;
++ mcp->chip.parent = dev;
+ mcp->chip.owner = THIS_MODULE;
+
+ /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
+@@ -652,7 +654,7 @@ static int mcp23s08_probe_one(struct mcp
+ mcp->irq_controller = pdata->irq_controller;
+ if (mcp->irq && mcp->irq_controller) {
+ mcp->irq_active_high =
+- of_property_read_bool(mcp->chip.dev->of_node,
++ of_property_read_bool(mcp->chip.parent->of_node,
+ "microchip,irq-active-high");
+
+ if (type == MCP_TYPE_017)
+--- a/drivers/gpio/gpio-moxart.c
++++ b/drivers/gpio/gpio-moxart.c
+@@ -60,7 +60,7 @@ static int moxart_gpio_probe(struct plat
+ gc->bgpio_data = gc->read_reg(gc->reg_set);
+ gc->base = 0;
+ gc->ngpio = 32;
+- gc->dev = dev;
++ gc->parent = dev;
+ gc->owner = THIS_MODULE;
+
+ ret = gpiochip_add_data(gc, NULL);
+--- a/drivers/gpio/gpio-msic.c
++++ b/drivers/gpio/gpio-msic.c
+@@ -293,7 +293,7 @@ static int platform_msic_gpio_probe(stru
+ mg->chip.base = pdata->gpio_base;
+ mg->chip.ngpio = MSIC_NUM_GPIO;
+ mg->chip.can_sleep = true;
+- mg->chip.dev = dev;
++ mg->chip.parent = dev;
+
+ mutex_init(&mg->buslock);
+
+--- a/drivers/gpio/gpio-mvebu.c
++++ b/drivers/gpio/gpio-mvebu.c
+@@ -698,7 +698,7 @@ static int mvebu_gpio_probe(struct platf
+
+ mvchip->soc_variant = soc_variant;
+ mvchip->chip.label = dev_name(&pdev->dev);
+- mvchip->chip.dev = &pdev->dev;
++ mvchip->chip.parent = &pdev->dev;
+ mvchip->chip.request = gpiochip_generic_request;
+ mvchip->chip.free = gpiochip_generic_free;
+ mvchip->chip.direction_input = mvebu_gpio_direction_input;
+--- a/drivers/gpio/gpio-octeon.c
++++ b/drivers/gpio/gpio-octeon.c
+@@ -108,7 +108,7 @@ static int octeon_gpio_probe(struct plat
+
+ pdev->dev.platform_data = chip;
+ chip->label = "octeon-gpio";
+- chip->dev = &pdev->dev;
++ chip->parent = &pdev->dev;
+ chip->owner = THIS_MODULE;
+ chip->base = 0;
+ chip->can_sleep = false;
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1090,7 +1090,7 @@ static int omap_gpio_chip_init(struct gp
+ if (bank->is_mpuio) {
+ bank->chip.label = "mpuio";
+ if (bank->regs->wkup_en)
+- bank->chip.dev = &omap_mpuio_device.dev;
++ bank->chip.parent = &omap_mpuio_device.dev;
+ bank->chip.base = OMAP_MPUIO(0);
+ } else {
+ bank->chip.label = "gpio";
+@@ -1197,7 +1197,7 @@ static int omap_gpio_probe(struct platfo
+ }
+
+ bank->dev = dev;
+- bank->chip.dev = dev;
++ bank->chip.parent = dev;
+ bank->chip.owner = THIS_MODULE;
+ bank->dbck_flag = pdata->dbck_flag;
+ bank->stride = pdata->bank_stride;
+--- a/drivers/gpio/gpio-palmas.c
++++ b/drivers/gpio/gpio-palmas.c
+@@ -54,7 +54,7 @@ static int palmas_gpio_get(struct gpio_c
+
+ ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
+ if (ret < 0) {
+- dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
++ dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);
+ return ret;
+ }
+
+@@ -65,7 +65,7 @@ static int palmas_gpio_get(struct gpio_c
+
+ ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
+ if (ret < 0) {
+- dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
++ dev_err(gc->parent, "Reg 0x%02x read failed, %d\n", reg, ret);
+ return ret;
+ }
+ return !!(val & BIT(offset));
+@@ -90,7 +90,7 @@ static void palmas_gpio_set(struct gpio_
+
+ ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
+ if (ret < 0)
+- dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret);
++ dev_err(gc->parent, "Reg 0x%02x write failed, %d\n", reg, ret);
+ }
+
+ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
+@@ -111,7 +111,8 @@ static int palmas_gpio_output(struct gpi
+ ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
+ BIT(offset), BIT(offset));
+ if (ret < 0)
+- dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
++ dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,
++ ret);
+ return ret;
+ }
+
+@@ -128,7 +129,8 @@ static int palmas_gpio_input(struct gpio
+
+ ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
+ if (ret < 0)
+- dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
++ dev_err(gc->parent, "Reg 0x%02x update failed, %d\n", reg,
++ ret);
+ return ret;
+ }
+
+@@ -188,7 +190,7 @@ static int palmas_gpio_probe(struct plat
+ palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
+ palmas_gpio->gpio_chip.set = palmas_gpio_set;
+ palmas_gpio->gpio_chip.get = palmas_gpio_get;
+- palmas_gpio->gpio_chip.dev = &pdev->dev;
++ palmas_gpio->gpio_chip.parent = &pdev->dev;
+ #ifdef CONFIG_OF_GPIO
+ palmas_gpio->gpio_chip.of_node = pdev->dev.of_node;
+ #endif
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -367,7 +367,7 @@ static void pca953x_setup_gpio(struct pc
+ gc->base = chip->gpio_start;
+ gc->ngpio = gpios;
+ gc->label = chip->client->name;
+- gc->dev = &chip->client->dev;
++ gc->parent = &chip->client->dev;
+ gc->owner = THIS_MODULE;
+ gc->names = chip->names;
+ }
+--- a/drivers/gpio/gpio-pcf857x.c
++++ b/drivers/gpio/gpio-pcf857x.c
+@@ -293,7 +293,7 @@ static int pcf857x_probe(struct i2c_clie
+
+ gpio->chip.base = pdata ? pdata->gpio_base : -1;
+ gpio->chip.can_sleep = true;
+- gpio->chip.dev = &client->dev;
++ gpio->chip.parent = &client->dev;
+ gpio->chip.owner = THIS_MODULE;
+ gpio->chip.get = pcf857x_get;
+ gpio->chip.set = pcf857x_set;
+--- a/drivers/gpio/gpio-pch.c
++++ b/drivers/gpio/gpio-pch.c
+@@ -220,7 +220,7 @@ static void pch_gpio_setup(struct pch_gp
+ struct gpio_chip *gpio = &chip->gpio;
+
+ gpio->label = dev_name(chip->dev);
+- gpio->dev = chip->dev;
++ gpio->parent = chip->dev;
+ gpio->owner = THIS_MODULE;
+ gpio->direction_input = pch_gpio_direction_input;
+ gpio->get = pch_gpio_get;
+--- a/drivers/gpio/gpio-pl061.c
++++ b/drivers/gpio/gpio-pl061.c
+@@ -131,7 +131,7 @@ static int pl061_irq_type(struct irq_dat
+ if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
+ (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
+ {
+- dev_err(gc->dev,
++ dev_err(gc->parent,
+ "trying to configure line %d for both level and edge "
+ "detection, choose one!\n",
+ offset);
+@@ -158,7 +158,7 @@ static int pl061_irq_type(struct irq_dat
+ else
+ gpioiev &= ~bit;
+ irq_set_handler_locked(d, handle_level_irq);
+- dev_dbg(gc->dev, "line %d: IRQ on %s level\n",
++ dev_dbg(gc->parent, "line %d: IRQ on %s level\n",
+ offset,
+ polarity ? "HIGH" : "LOW");
+ } else if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+@@ -167,7 +167,7 @@ static int pl061_irq_type(struct irq_dat
+ /* Select both edges, setting this makes GPIOEV be ignored */
+ gpioibe |= bit;
+ irq_set_handler_locked(d, handle_edge_irq);
+- dev_dbg(gc->dev, "line %d: IRQ on both edges\n", offset);
++ dev_dbg(gc->parent, "line %d: IRQ on both edges\n", offset);
+ } else if ((trigger & IRQ_TYPE_EDGE_RISING) ||
+ (trigger & IRQ_TYPE_EDGE_FALLING)) {
+ bool rising = trigger & IRQ_TYPE_EDGE_RISING;
+@@ -182,7 +182,7 @@ static int pl061_irq_type(struct irq_dat
+ else
+ gpioiev &= ~bit;
+ irq_set_handler_locked(d, handle_edge_irq);
+- dev_dbg(gc->dev, "line %d: IRQ on %s edge\n",
++ dev_dbg(gc->parent, "line %d: IRQ on %s edge\n",
+ offset,
+ rising ? "RISING" : "FALLING");
+ } else {
+@@ -191,7 +191,7 @@ static int pl061_irq_type(struct irq_dat
+ gpioibe &= ~bit;
+ gpioiev &= ~bit;
+ irq_set_handler_locked(d, handle_bad_irq);
+- dev_warn(gc->dev, "no trigger selected for line %d\n",
++ dev_warn(gc->parent, "no trigger selected for line %d\n",
+ offset);
+ }
+
+@@ -316,7 +316,7 @@ static int pl061_probe(struct amba_devic
+ chip->gc.set = pl061_set_value;
+ chip->gc.ngpio = PL061_GPIO_NR;
+ chip->gc.label = dev_name(dev);
+- chip->gc.dev = dev;
++ chip->gc.parent = dev;
+ chip->gc.owner = THIS_MODULE;
+
+ ret = gpiochip_add(&chip->gc);
+--- a/drivers/gpio/gpio-rc5t583.c
++++ b/drivers/gpio/gpio-rc5t583.c
+@@ -132,7 +132,7 @@ static int rc5t583_gpio_probe(struct pla
+ rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq,
+ rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO,
+ rc5t583_gpio->gpio_chip.can_sleep = true,
+- rc5t583_gpio->gpio_chip.dev = &pdev->dev;
++ rc5t583_gpio->gpio_chip.parent = &pdev->dev;
+ rc5t583_gpio->gpio_chip.base = -1;
+ rc5t583_gpio->rc5t583 = rc5t583;
+
+--- a/drivers/gpio/gpio-rcar.c
++++ b/drivers/gpio/gpio-rcar.c
+@@ -449,7 +449,7 @@ static int gpio_rcar_probe(struct platfo
+ gpio_chip->direction_output = gpio_rcar_direction_output;
+ gpio_chip->set = gpio_rcar_set;
+ gpio_chip->label = name;
+- gpio_chip->dev = dev;
++ gpio_chip->parent = dev;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->base = p->config.gpio_base;
+ gpio_chip->ngpio = p->config.number_of_pins;
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -171,7 +171,7 @@ static int sch_gpio_probe(struct platfor
+ sch->iobase = res->start;
+ sch->chip = sch_gpio_chip;
+ sch->chip.label = dev_name(&pdev->dev);
+- sch->chip.dev = &pdev->dev;
++ sch->chip.parent = &pdev->dev;
+
+ switch (pdev->id) {
+ case PCI_DEVICE_ID_INTEL_SCH_LPC:
+--- a/drivers/gpio/gpio-sch311x.c
++++ b/drivers/gpio/gpio-sch311x.c
+@@ -149,7 +149,7 @@ static int sch311x_gpio_request(struct g
+
+ if (!request_region(block->runtime_reg + block->config_regs[offset],
+ 1, DRV_NAME)) {
+- dev_err(chip->dev, "Failed to request region 0x%04x.\n",
++ dev_err(chip->parent, "Failed to request region 0x%04x.\n",
+ block->runtime_reg + block->config_regs[offset]);
+ return -EBUSY;
+ }
+@@ -261,7 +261,7 @@ static int sch311x_gpio_probe(struct pla
+ block->chip.get = sch311x_gpio_get;
+ block->chip.set = sch311x_gpio_set;
+ block->chip.ngpio = 8;
+- block->chip.dev = &pdev->dev;
++ block->chip.parent = &pdev->dev;
+ block->chip.base = sch311x_gpio_blocks[i].base;
+ block->config_regs = sch311x_gpio_blocks[i].config_regs;
+ block->data_reg = sch311x_gpio_blocks[i].data_reg;
+--- a/drivers/gpio/gpio-spear-spics.c
++++ b/drivers/gpio/gpio-spear-spics.c
+@@ -164,7 +164,7 @@ static int spics_gpio_probe(struct platf
+ spics->chip.get = spics_get_value;
+ spics->chip.set = spics_set_value;
+ spics->chip.label = dev_name(&pdev->dev);
+- spics->chip.dev = &pdev->dev;
++ spics->chip.parent = &pdev->dev;
+ spics->chip.owner = THIS_MODULE;
+ spics->last_off = -1;
+
+--- a/drivers/gpio/gpio-stmpe.c
++++ b/drivers/gpio/gpio-stmpe.c
+@@ -356,7 +356,7 @@ static int stmpe_gpio_probe(struct platf
+ stmpe_gpio->stmpe = stmpe;
+ stmpe_gpio->chip = template_chip;
+ stmpe_gpio->chip.ngpio = stmpe->num_gpios;
+- stmpe_gpio->chip.dev = &pdev->dev;
++ stmpe_gpio->chip.parent = &pdev->dev;
+ stmpe_gpio->chip.of_node = np;
+ stmpe_gpio->chip.base = -1;
+
+--- a/drivers/gpio/gpio-stp-xway.c
++++ b/drivers/gpio/gpio-stp-xway.c
+@@ -139,7 +139,7 @@ static int xway_stp_request(struct gpio_
+ container_of(gc, struct xway_stp, gc);
+
+ if ((gpio < 8) && (chip->reserved & BIT(gpio))) {
+- dev_err(gc->dev, "GPIO %d is driven by hardware\n", gpio);
++ dev_err(gc->parent, "GPIO %d is driven by hardware\n", gpio);
+ return -ENODEV;
+ }
+
+@@ -214,7 +214,7 @@ static int xway_stp_probe(struct platfor
+ if (IS_ERR(chip->virt))
+ return PTR_ERR(chip->virt);
+
+- chip->gc.dev = &pdev->dev;
++ chip->gc.parent = &pdev->dev;
+ chip->gc.label = "stp-xway";
+ chip->gc.direction_output = xway_stp_dir_out;
+ chip->gc.set = xway_stp_set;
+--- a/drivers/gpio/gpio-sx150x.c
++++ b/drivers/gpio/gpio-sx150x.c
+@@ -473,7 +473,7 @@ static void sx150x_init_chip(struct sx15
+
+ chip->client = client;
+ chip->dev_cfg = &sx150x_devices[driver_data];
+- chip->gpio_chip.dev = &client->dev;
++ chip->gpio_chip.parent = &client->dev;
+ chip->gpio_chip.label = client->name;
+ chip->gpio_chip.direction_input = sx150x_gpio_direction_input;
+ chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
+--- a/drivers/gpio/gpio-syscon.c
++++ b/drivers/gpio/gpio-syscon.c
+@@ -159,7 +159,7 @@ static void keystone_gpio_set(struct gpi
+ BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT,
+ BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT);
+ if (ret < 0)
+- dev_err(chip->dev, "gpio write failed ret(%d)\n", ret);
++ dev_err(chip->parent, "gpio write failed ret(%d)\n", ret);
+ }
+
+ static const struct syscon_gpio_data keystone_dsp_gpio = {
+@@ -228,7 +228,7 @@ static int syscon_gpio_probe(struct plat
+ priv->dir_reg_offset <<= 3;
+ }
+
+- priv->chip.dev = dev;
++ priv->chip.parent = dev;
+ priv->chip.owner = THIS_MODULE;
+ priv->chip.label = dev_name(dev);
+ priv->chip.base = -1;
+--- a/drivers/gpio/gpio-tb10x.c
++++ b/drivers/gpio/gpio-tb10x.c
+@@ -197,7 +197,7 @@ static int tb10x_gpio_probe(struct platf
+ return PTR_ERR(tb10x_gpio->base);
+
+ tb10x_gpio->gc.label = of_node_full_name(dn);
+- tb10x_gpio->gc.dev = &pdev->dev;
++ tb10x_gpio->gc.parent = &pdev->dev;
+ tb10x_gpio->gc.owner = THIS_MODULE;
+ tb10x_gpio->gc.direction_input = tb10x_gpio_direction_in;
+ tb10x_gpio->gc.get = tb10x_gpio_get;
+--- a/drivers/gpio/gpio-tc3589x.c
++++ b/drivers/gpio/gpio-tc3589x.c
+@@ -258,7 +258,7 @@ static int tc3589x_gpio_probe(struct pla
+
+ tc3589x_gpio->chip = template_chip;
+ tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
+- tc3589x_gpio->chip.dev = &pdev->dev;
++ tc3589x_gpio->chip.parent = &pdev->dev;
+ tc3589x_gpio->chip.base = -1;
+ tc3589x_gpio->chip.of_node = np;
+
+--- a/drivers/gpio/gpio-timberdale.c
++++ b/drivers/gpio/gpio-timberdale.c
+@@ -268,7 +268,7 @@ static int timbgpio_probe(struct platfor
+
+ gc->label = dev_name(&pdev->dev);
+ gc->owner = THIS_MODULE;
+- gc->dev = &pdev->dev;
++ gc->parent = &pdev->dev;
+ gc->direction_input = timbgpio_gpio_direction_input;
+ gc->get = timbgpio_gpio_get;
+ gc->direction_output = timbgpio_gpio_direction_output;
+--- a/drivers/gpio/gpio-tps6586x.c
++++ b/drivers/gpio/gpio-tps6586x.c
+@@ -104,7 +104,7 @@ static int tps6586x_gpio_probe(struct pl
+
+ tps6586x_gpio->gpio_chip.owner = THIS_MODULE;
+ tps6586x_gpio->gpio_chip.label = pdev->name;
+- tps6586x_gpio->gpio_chip.dev = &pdev->dev;
++ tps6586x_gpio->gpio_chip.parent = &pdev->dev;
+ tps6586x_gpio->gpio_chip.ngpio = 4;
+ tps6586x_gpio->gpio_chip.can_sleep = true;
+
+--- a/drivers/gpio/gpio-tps65910.c
++++ b/drivers/gpio/gpio-tps65910.c
+@@ -146,7 +146,7 @@ static int tps65910_gpio_probe(struct pl
+ tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;
+ tps65910_gpio->gpio_chip.set = tps65910_gpio_set;
+ tps65910_gpio->gpio_chip.get = tps65910_gpio_get;
+- tps65910_gpio->gpio_chip.dev = &pdev->dev;
++ tps65910_gpio->gpio_chip.parent = &pdev->dev;
+ #ifdef CONFIG_OF_GPIO
+ tps65910_gpio->gpio_chip.of_node = tps65910->dev->of_node;
+ #endif
+--- a/drivers/gpio/gpio-tps65912.c
++++ b/drivers/gpio/gpio-tps65912.c
+@@ -104,7 +104,7 @@ static int tps65912_gpio_probe(struct pl
+
+ tps65912_gpio->tps65912 = tps65912;
+ tps65912_gpio->gpio_chip = template_chip;
+- tps65912_gpio->gpio_chip.dev = &pdev->dev;
++ tps65912_gpio->gpio_chip.parent = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ tps65912_gpio->gpio_chip.base = pdata->gpio_base;
+
+--- a/drivers/gpio/gpio-ts5500.c
++++ b/drivers/gpio/gpio-ts5500.c
+@@ -315,7 +315,8 @@ static void ts5500_disable_irq(struct ts
+ else if (priv->hwirq == 1)
+ ts5500_clear_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */
+ else
+- dev_err(priv->gpio_chip.dev, "invalid hwirq %d\n", priv->hwirq);
++ dev_err(priv->gpio_chip.parent, "invalid hwirq %d\n",
++ priv->hwirq);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+@@ -346,7 +347,7 @@ static int ts5500_dio_probe(struct platf
+
+ priv->gpio_chip.owner = THIS_MODULE;
+ priv->gpio_chip.label = name;
+- priv->gpio_chip.dev = dev;
++ priv->gpio_chip.parent = dev;
+ priv->gpio_chip.direction_input = ts5500_gpio_input;
+ priv->gpio_chip.direction_output = ts5500_gpio_output;
+ priv->gpio_chip.get = ts5500_gpio_get;
+--- a/drivers/gpio/gpio-twl4030.c
++++ b/drivers/gpio/gpio-twl4030.c
+@@ -256,7 +256,7 @@ static int twl_request(struct gpio_chip
+ /* optionally have the first two GPIOs switch vMMC1
+ * and vMMC2 power supplies based on card presence.
+ */
+- pdata = dev_get_platdata(chip->dev);
++ pdata = dev_get_platdata(chip->parent);
+ if (pdata)
+ value |= pdata->mmc_cd & 0x03;
+
+@@ -509,7 +509,7 @@ no_irqs:
+ priv->gpio_chip = template_chip;
+ priv->gpio_chip.base = -1;
+ priv->gpio_chip.ngpio = TWL4030_GPIO_MAX;
+- priv->gpio_chip.dev = &pdev->dev;
++ priv->gpio_chip.parent = &pdev->dev;
+
+ mutex_init(&priv->mutex);
+
+--- a/drivers/gpio/gpio-twl6040.c
++++ b/drivers/gpio/gpio-twl6040.c
+@@ -36,7 +36,7 @@ static struct gpio_chip twl6040gpo_chip;
+
+ static int twl6040gpo_get(struct gpio_chip *chip, unsigned offset)
+ {
+- struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
++ struct twl6040 *twl6040 = dev_get_drvdata(chip->parent->parent);
+ int ret = 0;
+
+ ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+@@ -55,7 +55,7 @@ static int twl6040gpo_direction_out(stru
+
+ static void twl6040gpo_set(struct gpio_chip *chip, unsigned offset, int value)
+ {
+- struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
++ struct twl6040 *twl6040 = dev_get_drvdata(chip->parent->parent);
+ int ret;
+ u8 gpoctl;
+
+@@ -95,7 +95,7 @@ static int gpo_twl6040_probe(struct plat
+ else
+ twl6040gpo_chip.ngpio = 1; /* twl6041 have 1 GPO */
+
+- twl6040gpo_chip.dev = &pdev->dev;
++ twl6040gpo_chip.parent = &pdev->dev;
+ #ifdef CONFIG_OF_GPIO
+ twl6040gpo_chip.of_node = twl6040_core_dev->of_node;
+ #endif
+--- a/drivers/gpio/gpio-tz1090-pdc.c
++++ b/drivers/gpio/gpio-tz1090-pdc.c
+@@ -188,7 +188,7 @@ static int tz1090_pdc_gpio_probe(struct
+
+ /* Set up GPIO chip */
+ priv->chip.label = "tz1090-pdc-gpio";
+- priv->chip.dev = &pdev->dev;
++ priv->chip.parent = &pdev->dev;
+ priv->chip.direction_input = tz1090_pdc_gpio_direction_input;
+ priv->chip.direction_output = tz1090_pdc_gpio_direction_output;
+ priv->chip.get = tz1090_pdc_gpio_get;
+--- a/drivers/gpio/gpio-tz1090.c
++++ b/drivers/gpio/gpio-tz1090.c
+@@ -425,7 +425,7 @@ static int tz1090_gpio_bank_probe(struct
+ snprintf(bank->label, sizeof(bank->label), "tz1090-gpio-%u",
+ info->index);
+ bank->chip.label = bank->label;
+- bank->chip.dev = dev;
++ bank->chip.parent = dev;
+ bank->chip.direction_input = tz1090_gpio_direction_input;
+ bank->chip.direction_output = tz1090_gpio_direction_output;
+ bank->chip.get = tz1090_gpio_get;
+--- a/drivers/gpio/gpio-vf610.c
++++ b/drivers/gpio/gpio-vf610.c
+@@ -249,7 +249,7 @@ static int vf610_gpio_probe(struct platf
+
+ gc = &port->gc;
+ gc->of_node = np;
+- gc->dev = dev;
++ gc->parent = dev;
+ gc->label = "vf610-gpio";
+ gc->ngpio = VF610_GPIO_PER_PORT;
+ gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
+--- a/drivers/gpio/gpio-viperboard.c
++++ b/drivers/gpio/gpio-viperboard.c
+@@ -173,7 +173,7 @@ static void vprbrd_gpioa_set(struct gpio
+ mutex_unlock(&vb->lock);
+
+ if (ret != sizeof(struct vprbrd_gpioa_msg))
+- dev_err(chip->dev, "usb error setting pin value\n");
++ dev_err(chip->parent, "usb error setting pin value\n");
+ }
+ }
+
+@@ -345,7 +345,7 @@ static void vprbrd_gpiob_set(struct gpio
+ mutex_unlock(&vb->lock);
+
+ if (ret != sizeof(struct vprbrd_gpiob_msg))
+- dev_err(chip->dev, "usb error setting pin value\n");
++ dev_err(chip->parent, "usb error setting pin value\n");
+ }
+ }
+
+@@ -366,7 +366,7 @@ static int vprbrd_gpiob_direction_input(
+ mutex_unlock(&vb->lock);
+
+ if (ret)
+- dev_err(chip->dev, "usb error setting pin to input\n");
++ dev_err(chip->parent, "usb error setting pin to input\n");
+
+ return ret;
+ }
+@@ -385,7 +385,7 @@ static int vprbrd_gpiob_direction_output
+
+ ret = vprbrd_gpiob_setdir(vb, offset, 1);
+ if (ret)
+- dev_err(chip->dev, "usb error setting pin to output\n");
++ dev_err(chip->parent, "usb error setting pin to output\n");
+
+ mutex_unlock(&vb->lock);
+
+@@ -409,7 +409,7 @@ static int vprbrd_gpio_probe(struct plat
+ vb_gpio->vb = vb;
+ /* registering gpio a */
+ vb_gpio->gpioa.label = "viperboard gpio a";
+- vb_gpio->gpioa.dev = &pdev->dev;
++ vb_gpio->gpioa.parent = &pdev->dev;
+ vb_gpio->gpioa.owner = THIS_MODULE;
+ vb_gpio->gpioa.base = -1;
+ vb_gpio->gpioa.ngpio = 16;
+@@ -420,13 +420,13 @@ static int vprbrd_gpio_probe(struct plat
+ vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
+ ret = gpiochip_add(&vb_gpio->gpioa);
+ if (ret < 0) {
+- dev_err(vb_gpio->gpioa.dev, "could not add gpio a");
++ dev_err(vb_gpio->gpioa.parent, "could not add gpio a");
+ goto err_gpioa;
+ }
+
+ /* registering gpio b */
+ vb_gpio->gpiob.label = "viperboard gpio b";
+- vb_gpio->gpiob.dev = &pdev->dev;
++ vb_gpio->gpiob.parent = &pdev->dev;
+ vb_gpio->gpiob.owner = THIS_MODULE;
+ vb_gpio->gpiob.base = -1;
+ vb_gpio->gpiob.ngpio = 16;
+@@ -437,7 +437,7 @@ static int vprbrd_gpio_probe(struct plat
+ vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
+ ret = gpiochip_add(&vb_gpio->gpiob);
+ if (ret < 0) {
+- dev_err(vb_gpio->gpiob.dev, "could not add gpio b");
++ dev_err(vb_gpio->gpiob.parent, "could not add gpio b");
+ goto err_gpiob;
+ }
+
+--- a/drivers/gpio/gpio-vr41xx.c
++++ b/drivers/gpio/gpio-vr41xx.c
+@@ -139,7 +139,7 @@ static void unmask_giuint_low(struct irq
+ static unsigned int startup_giuint(struct irq_data *data)
+ {
+ if (gpiochip_lock_as_irq(&vr41xx_gpio_chip, data->hwirq))
+- dev_err(vr41xx_gpio_chip.dev,
++ dev_err(vr41xx_gpio_chip.parent,
+ "unable to lock HW IRQ %lu for IRQ\n",
+ data->hwirq);
+ /* Satisfy the .enable semantics by unmasking the line */
+@@ -542,7 +542,7 @@ static int giu_probe(struct platform_dev
+ if (!giu_base)
+ return -ENOMEM;
+
+- vr41xx_gpio_chip.dev = &pdev->dev;
++ vr41xx_gpio_chip.parent = &pdev->dev;
+
+ ret = gpiochip_add(&vr41xx_gpio_chip);
+ if (!ret) {
+--- a/drivers/gpio/gpio-wm831x.c
++++ b/drivers/gpio/gpio-wm831x.c
+@@ -258,7 +258,7 @@ static int wm831x_gpio_probe(struct plat
+ wm831x_gpio->wm831x = wm831x;
+ wm831x_gpio->gpio_chip = template_chip;
+ wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio;
+- wm831x_gpio->gpio_chip.dev = &pdev->dev;
++ wm831x_gpio->gpio_chip.parent = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ wm831x_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+--- a/drivers/gpio/gpio-wm8350.c
++++ b/drivers/gpio/gpio-wm8350.c
+@@ -124,7 +124,7 @@ static int wm8350_gpio_probe(struct plat
+ wm8350_gpio->wm8350 = wm8350;
+ wm8350_gpio->gpio_chip = template_chip;
+ wm8350_gpio->gpio_chip.ngpio = 13;
+- wm8350_gpio->gpio_chip.dev = &pdev->dev;
++ wm8350_gpio->gpio_chip.parent = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ wm8350_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+--- a/drivers/gpio/gpio-wm8994.c
++++ b/drivers/gpio/gpio-wm8994.c
+@@ -260,7 +260,7 @@ static int wm8994_gpio_probe(struct plat
+ wm8994_gpio->wm8994 = wm8994;
+ wm8994_gpio->gpio_chip = template_chip;
+ wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
+- wm8994_gpio->gpio_chip.dev = &pdev->dev;
++ wm8994_gpio->gpio_chip.parent = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ wm8994_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+--- a/drivers/gpio/gpio-xgene-sb.c
++++ b/drivers/gpio/gpio-xgene-sb.c
+@@ -130,10 +130,10 @@ static int xgene_gpio_sb_to_irq(struct g
+ (gpio > HWIRQ_TO_GPIO(priv, priv->nirq)))
+ return -ENXIO;
+
+- if (gc->dev->of_node)
+- fwspec.fwnode = of_node_to_fwnode(gc->dev->of_node);
++ if (gc->parent->of_node)
++ fwspec.fwnode = of_node_to_fwnode(gc->parent->of_node);
+ else
+- fwspec.fwnode = gc->dev->fwnode;
++ fwspec.fwnode = gc->parent->fwnode;
+ fwspec.param_count = 2;
+ fwspec.param[0] = GPIO_TO_HWIRQ(priv, gpio);
+ fwspec.param[1] = IRQ_TYPE_NONE;
+@@ -147,7 +147,7 @@ static void xgene_gpio_sb_domain_activat
+ u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq);
+
+ if (gpiochip_lock_as_irq(&priv->gc, gpio)) {
+- dev_err(priv->gc.dev,
++ dev_err(priv->gc.parent,
+ "Unable to configure XGene GPIO standby pin %d as IRQ\n",
+ gpio);
+ return;
+--- a/drivers/gpio/gpio-xgene.c
++++ b/drivers/gpio/gpio-xgene.c
+@@ -188,7 +188,7 @@ static int xgene_gpio_probe(struct platf
+ gpio->chip.ngpio = XGENE_MAX_GPIOS;
+
+ spin_lock_init(&gpio->lock);
+- gpio->chip.dev = &pdev->dev;
++ gpio->chip.parent = &pdev->dev;
+ gpio->chip.direction_input = xgene_gpio_dir_in;
+ gpio->chip.direction_output = xgene_gpio_dir_out;
+ gpio->chip.get = xgene_gpio_get;
+--- a/drivers/gpio/gpio-xilinx.c
++++ b/drivers/gpio/gpio-xilinx.c
+@@ -305,7 +305,7 @@ static int xgpio_probe(struct platform_d
+ }
+
+ chip->mmchip.gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1];
+- chip->mmchip.gc.dev = &pdev->dev;
++ chip->mmchip.gc.parent = &pdev->dev;
+ chip->mmchip.gc.direction_input = xgpio_dir_in;
+ chip->mmchip.gc.direction_output = xgpio_dir_out;
+ chip->mmchip.gc.get = xgpio_get;
+--- a/drivers/gpio/gpio-xlp.c
++++ b/drivers/gpio/gpio-xlp.c
+@@ -384,7 +384,7 @@ static int xlp_gpio_probe(struct platfor
+ gc->owner = THIS_MODULE;
+ gc->label = dev_name(&pdev->dev);
+ gc->base = 0;
+- gc->dev = &pdev->dev;
++ gc->parent = &pdev->dev;
+ gc->ngpio = ngpio;
+ gc->of_node = pdev->dev.of_node;
+ gc->direction_output = xlp_gpio_dir_output;
+--- a/drivers/gpio/gpio-zevio.c
++++ b/drivers/gpio/gpio-zevio.c
+@@ -185,7 +185,7 @@ static int zevio_gpio_probe(struct platf
+
+ /* Copy our reference */
+ controller->chip.gc = zevio_gpio_chip;
+- controller->chip.gc.dev = &pdev->dev;
++ controller->chip.gc.parent = &pdev->dev;
+
+ status = of_mm_gpiochip_add(pdev->dev.of_node, &(controller->chip));
+ if (status) {
+@@ -199,7 +199,7 @@ static int zevio_gpio_probe(struct platf
+ for (i = 0; i < controller->chip.gc.ngpio; i += 8)
+ zevio_gpio_port_set(controller, i, ZEVIO_GPIO_INT_MASK, 0xFF);
+
+- dev_dbg(controller->chip.gc.dev, "ZEVIO GPIO controller set up!\n");
++ dev_dbg(controller->chip.gc.parent, "ZEVIO GPIO controller set up!\n");
+
+ return 0;
+ }
+--- a/drivers/gpio/gpio-zx.c
++++ b/drivers/gpio/gpio-zx.c
+@@ -245,7 +245,7 @@ static int zx_gpio_probe(struct platform
+ chip->gc.base = ZX_GPIO_NR * id;
+ chip->gc.ngpio = ZX_GPIO_NR;
+ chip->gc.label = dev_name(dev);
+- chip->gc.dev = dev;
++ chip->gc.parent = dev;
+ chip->gc.owner = THIS_MODULE;
+
+ ret = gpiochip_add(&chip->gc);
+--- a/drivers/gpio/gpio-zynq.c
++++ b/drivers/gpio/gpio-zynq.c
+@@ -592,7 +592,7 @@ static int zynq_gpio_request(struct gpio
+ {
+ int ret;
+
+- ret = pm_runtime_get_sync(chip->dev);
++ ret = pm_runtime_get_sync(chip->parent);
+
+ /*
+ * If the device is already active pm_runtime_get() will return 1 on
+@@ -603,7 +603,7 @@ static int zynq_gpio_request(struct gpio
+
+ static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset)
+ {
+- pm_runtime_put(chip->dev);
++ pm_runtime_put(chip->parent);
+ }
+
+ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
+@@ -698,7 +698,7 @@ static int zynq_gpio_probe(struct platfo
+ chip = &gpio->chip;
+ chip->label = gpio->p_data->label;
+ chip->owner = THIS_MODULE;
+- chip->dev = &pdev->dev;
++ chip->parent = &pdev->dev;
+ chip->get = zynq_gpio_get_value;
+ chip->set = zynq_gpio_set_value;
+ chip->request = zynq_gpio_request;
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -51,10 +51,10 @@ struct acpi_gpio_chip {
+
+ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
+ {
+- if (!gc->dev)
++ if (!gc->parent)
+ return false;
+
+- return ACPI_HANDLE(gc->dev) == data;
++ return ACPI_HANDLE(gc->parent) == data;
+ }
+
+ #ifdef CONFIG_PINCTRL
+@@ -184,7 +184,7 @@ static acpi_status acpi_gpiochip_request
+ if (agpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_INT)
+ return AE_OK;
+
+- handle = ACPI_HANDLE(chip->dev);
++ handle = ACPI_HANDLE(chip->parent);
+ pin = agpio->pin_table[0];
+
+ if (pin <= 255) {
+@@ -208,7 +208,7 @@ static acpi_status acpi_gpiochip_request
+
+ desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event");
+ if (IS_ERR(desc)) {
+- dev_err(chip->dev, "Failed to request GPIO\n");
++ dev_err(chip->parent, "Failed to request GPIO\n");
+ return AE_ERROR;
+ }
+
+@@ -216,13 +216,13 @@ static acpi_status acpi_gpiochip_request
+
+ ret = gpiochip_lock_as_irq(chip, pin);
+ if (ret) {
+- dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
++ dev_err(chip->parent, "Failed to lock GPIO as interrupt\n");
+ goto fail_free_desc;
+ }
+
+ irq = gpiod_to_irq(desc);
+ if (irq < 0) {
+- dev_err(chip->dev, "Failed to translate GPIO to IRQ\n");
++ dev_err(chip->parent, "Failed to translate GPIO to IRQ\n");
+ goto fail_unlock_irq;
+ }
+
+@@ -259,7 +259,8 @@ static acpi_status acpi_gpiochip_request
+ ret = request_threaded_irq(event->irq, NULL, handler, irqflags,
+ "ACPI:Event", event);
+ if (ret) {
+- dev_err(chip->dev, "Failed to setup interrupt handler for %d\n",
++ dev_err(chip->parent,
++ "Failed to setup interrupt handler for %d\n",
+ event->irq);
+ goto fail_free_event;
+ }
+@@ -293,10 +294,10 @@ void acpi_gpiochip_request_interrupts(st
+ acpi_handle handle;
+ acpi_status status;
+
+- if (!chip->dev || !chip->to_irq)
++ if (!chip->parent || !chip->to_irq)
+ return;
+
+- handle = ACPI_HANDLE(chip->dev);
++ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+@@ -323,10 +324,10 @@ void acpi_gpiochip_free_interrupts(struc
+ acpi_handle handle;
+ acpi_status status;
+
+- if (!chip->dev || !chip->to_irq)
++ if (!chip->parent || !chip->to_irq)
+ return;
+
+- handle = ACPI_HANDLE(chip->dev);
++ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+@@ -748,7 +749,7 @@ out:
+ static void acpi_gpiochip_request_regions(struct acpi_gpio_chip *achip)
+ {
+ struct gpio_chip *chip = achip->chip;
+- acpi_handle handle = ACPI_HANDLE(chip->dev);
++ acpi_handle handle = ACPI_HANDLE(chip->parent);
+ acpi_status status;
+
+ INIT_LIST_HEAD(&achip->conns);
+@@ -757,20 +758,22 @@ static void acpi_gpiochip_request_region
+ acpi_gpio_adr_space_handler,
+ NULL, achip);
+ if (ACPI_FAILURE(status))
+- dev_err(chip->dev, "Failed to install GPIO OpRegion handler\n");
++ dev_err(chip->parent,
++ "Failed to install GPIO OpRegion handler\n");
+ }
+
+ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip)
+ {
+ struct gpio_chip *chip = achip->chip;
+- acpi_handle handle = ACPI_HANDLE(chip->dev);
++ acpi_handle handle = ACPI_HANDLE(chip->parent);
+ struct acpi_gpio_connection *conn, *tmp;
+ acpi_status status;
+
+ status = acpi_remove_address_space_handler(handle, ACPI_ADR_SPACE_GPIO,
+ acpi_gpio_adr_space_handler);
+ if (ACPI_FAILURE(status)) {
+- dev_err(chip->dev, "Failed to remove GPIO OpRegion handler\n");
++ dev_err(chip->parent,
++ "Failed to remove GPIO OpRegion handler\n");
+ return;
+ }
+
+@@ -787,16 +790,16 @@ void acpi_gpiochip_add(struct gpio_chip
+ acpi_handle handle;
+ acpi_status status;
+
+- if (!chip || !chip->dev)
++ if (!chip || !chip->parent)
+ return;
+
+- handle = ACPI_HANDLE(chip->dev);
++ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+ acpi_gpio = kzalloc(sizeof(*acpi_gpio), GFP_KERNEL);
+ if (!acpi_gpio) {
+- dev_err(chip->dev,
++ dev_err(chip->parent,
+ "Failed to allocate memory for ACPI GPIO chip\n");
+ return;
+ }
+@@ -806,7 +809,7 @@ void acpi_gpiochip_add(struct gpio_chip
+
+ status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio);
+ if (ACPI_FAILURE(status)) {
+- dev_err(chip->dev, "Failed to attach ACPI GPIO chip\n");
++ dev_err(chip->parent, "Failed to attach ACPI GPIO chip\n");
+ kfree(acpi_gpio);
+ return;
+ }
+@@ -820,16 +823,16 @@ void acpi_gpiochip_remove(struct gpio_ch
+ acpi_handle handle;
+ acpi_status status;
+
+- if (!chip || !chip->dev)
++ if (!chip || !chip->parent)
+ return;
+
+- handle = ACPI_HANDLE(chip->dev);
++ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status)) {
+- dev_warn(chip->dev, "Failed to retrieve ACPI GPIO chip\n");
++ dev_warn(chip->parent, "Failed to retrieve ACPI GPIO chip\n");
+ return;
+ }
+
+--- a/drivers/gpio/gpiolib-of.c
++++ b/drivers/gpio/gpiolib-of.c
+@@ -423,8 +423,8 @@ int of_gpiochip_add(struct gpio_chip *ch
+ {
+ int status;
+
+- if ((!chip->of_node) && (chip->dev))
+- chip->of_node = chip->dev->of_node;
++ if ((!chip->of_node) && (chip->parent))
++ chip->of_node = chip->parent->of_node;
+
+ if (!chip->of_node)
+ return 0;
+--- a/drivers/gpio/gpiolib-sysfs.c
++++ b/drivers/gpio/gpiolib-sysfs.c
+@@ -605,7 +605,7 @@ int gpiod_export(struct gpio_desc *desc,
+ if (chip->names && chip->names[offset])
+ ioname = chip->names[offset];
+
+- dev = device_create_with_groups(&gpio_class, chip->dev,
++ dev = device_create_with_groups(&gpio_class, chip->parent,
+ MKDEV(0, 0), data, gpio_groups,
+ ioname ? ioname : "gpio%u",
+ desc_to_gpio(desc));
+@@ -730,7 +730,8 @@ int gpiochip_sysfs_register(struct gpio_
+ return 0;
+
+ /* use chip->base for the ID; it's already known to be unique */
+- dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0),
++ dev = device_create_with_groups(&gpio_class, chip->parent,
++ MKDEV(0, 0),
+ chip, gpiochip_groups,
+ "gpiochip%d", chip->base);
+ if (IS_ERR(dev))
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -205,8 +205,8 @@ static int gpiochip_add_to_list(struct g
+ if (pos != &gpio_chips && pos->prev != &gpio_chips) {
+ _chip = list_entry(pos->prev, struct gpio_chip, list);
+ if (_chip->base + _chip->ngpio > chip->base) {
+- dev_err(chip->dev,
+- "GPIO integer space overlap, cannot add chip\n");
++ dev_err(chip->parent,
++ "GPIO integer space overlap, cannot add chip\n");
+ err = -EBUSY;
+ }
+ }
+@@ -267,7 +267,7 @@ static int gpiochip_set_desc_names(struc
+
+ gpio = gpio_name_to_desc(gc->names[i]);
+ if (gpio)
+- dev_warn(gc->dev, "Detected name collision for "
++ dev_warn(gc->parent, "Detected name collision for "
+ "GPIO name '%s'\n",
+ gc->names[i]);
+ }
+@@ -350,8 +350,8 @@ int gpiochip_add_data(struct gpio_chip *
+ INIT_LIST_HEAD(&chip->pin_ranges);
+ #endif
+
+- if (!chip->owner && chip->dev && chip->dev->driver)
+- chip->owner = chip->dev->driver->owner;
++ if (!chip->owner && chip->parent && chip->parent->driver)
++ chip->owner = chip->parent->driver->owner;
+
+ status = gpiochip_set_desc_names(chip);
+ if (status)
+@@ -426,7 +426,8 @@ void gpiochip_remove(struct gpio_chip *c
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ if (requested)
+- dev_crit(chip->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
++ dev_crit(chip->parent,
++ "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
+
+ kfree(chip->desc);
+ chip->desc = NULL;
+@@ -685,11 +686,11 @@ int _gpiochip_irqchip_add(struct gpio_ch
+ if (!gpiochip || !irqchip)
+ return -EINVAL;
+
+- if (!gpiochip->dev) {
++ if (!gpiochip->parent) {
+ pr_err("missing gpiochip .dev parent pointer\n");
+ return -EINVAL;
+ }
+- of_node = gpiochip->dev->of_node;
++ of_node = gpiochip->parent->of_node;
+ #ifdef CONFIG_OF_GPIO
+ /*
+ * If the gpiochip has an assigned OF node this takes precedence
+@@ -2511,7 +2512,7 @@ static int gpiolib_seq_show(struct seq_f
+
+ seq_printf(s, "%sGPIOs %d-%d", (char *)s->private,
+ chip->base, chip->base + chip->ngpio - 1);
+- dev = chip->dev;
++ dev = chip->parent;
+ if (dev)
+ seq_printf(s, ", %s/%s", dev->bus ? dev->bus->name : "no-bus",
+ dev_name(dev));
+--- a/drivers/hid/hid-cp2112.c
++++ b/drivers/hid/hid-cp2112.c
+@@ -1104,7 +1104,7 @@ static int cp2112_probe(struct hid_devic
+ dev->gc.base = -1;
+ dev->gc.ngpio = 8;
+ dev->gc.can_sleep = 1;
+- dev->gc.dev = &hdev->dev;
++ dev->gc.parent = &hdev->dev;
+
+ ret = gpiochip_add(&dev->gc);
+ if (ret < 0) {
+--- a/drivers/input/touchscreen/ad7879.c
++++ b/drivers/input/touchscreen/ad7879.c
+@@ -454,7 +454,7 @@ static int ad7879_gpio_add(struct ad7879
+ ts->gc.ngpio = 1;
+ ts->gc.label = "AD7879-GPIO";
+ ts->gc.owner = THIS_MODULE;
+- ts->gc.dev = ts->dev;
++ ts->gc.parent = ts->dev;
+
+ ret = gpiochip_add(&ts->gc);
+ if (ret)
+--- a/drivers/leds/leds-pca9532.c
++++ b/drivers/leds/leds-pca9532.c
+@@ -319,7 +319,7 @@ static int pca9532_destroy_devices(struc
+ }
+
+ #ifdef CONFIG_LEDS_PCA9532_GPIO
+- if (data->gpio.dev)
++ if (data->gpio.parent)
+ gpiochip_remove(&data->gpio);
+ #endif
+
+@@ -413,13 +413,13 @@ static int pca9532_configure(struct i2c_
+ data->gpio.can_sleep = 1;
+ data->gpio.base = pdata->gpio_base;
+ data->gpio.ngpio = data->chip_info->num_leds;
+- data->gpio.dev = &client->dev;
++ data->gpio.parent = &client->dev;
+ data->gpio.owner = THIS_MODULE;
+
+ err = gpiochip_add(&data->gpio);
+ if (err) {
+ /* Use data->gpio.dev as a flag for freeing gpiochip */
+- data->gpio.dev = NULL;
++ data->gpio.parent = NULL;
+ dev_warn(&client->dev, "could not add gpiochip\n");
+ } else {
+ dev_info(&client->dev, "gpios %i...%i\n",
+--- a/drivers/leds/leds-tca6507.c
++++ b/drivers/leds/leds-tca6507.c
+@@ -651,7 +651,7 @@ static int tca6507_probe_gpios(struct i2
+ tca->gpio.owner = THIS_MODULE;
+ tca->gpio.direction_output = tca6507_gpio_direction_output;
+ tca->gpio.set = tca6507_gpio_set_value;
+- tca->gpio.dev = &client->dev;
++ tca->gpio.parent = &client->dev;
+ #ifdef CONFIG_OF_GPIO
+ tca->gpio.of_node = of_node_get(client->dev.of_node);
+ #endif
+--- a/drivers/media/dvb-frontends/cxd2820r_core.c
++++ b/drivers/media/dvb-frontends/cxd2820r_core.c
+@@ -722,7 +722,7 @@ struct dvb_frontend *cxd2820r_attach(con
+ #ifdef CONFIG_GPIOLIB
+ /* add GPIOs */
+ priv->gpio_chip.label = KBUILD_MODNAME;
+- priv->gpio_chip.dev = &priv->i2c->dev;
++ priv->gpio_chip.parent = &priv->i2c->dev;
+ priv->gpio_chip.owner = THIS_MODULE;
+ priv->gpio_chip.direction_output =
+ cxd2820r_gpio_direction_output;
+--- a/drivers/mfd/dm355evm_msp.c
++++ b/drivers/mfd/dm355evm_msp.c
+@@ -259,7 +259,7 @@ static int add_children(struct i2c_clien
+ int i;
+
+ /* GPIO-ish stuff */
+- dm355evm_msp_gpio.dev = &client->dev;
++ dm355evm_msp_gpio.parent = &client->dev;
+ status = gpiochip_add(&dm355evm_msp_gpio);
+ if (status < 0)
+ return status;
+--- a/drivers/mfd/htc-egpio.c
++++ b/drivers/mfd/htc-egpio.c
+@@ -321,7 +321,7 @@ static int __init egpio_probe(struct pla
+ ei->chip[i].dev = &(pdev->dev);
+ chip = &(ei->chip[i].chip);
+ chip->label = "htc-egpio";
+- chip->dev = &pdev->dev;
++ chip->parent = &pdev->dev;
+ chip->owner = THIS_MODULE;
+ chip->get = egpio_get;
+ chip->set = egpio_set;
+--- a/drivers/mfd/htc-i2cpld.c
++++ b/drivers/mfd/htc-i2cpld.c
+@@ -429,7 +429,7 @@ static int htcpld_register_chip_gpio(
+ /* Setup the GPIO chips */
+ gpio_chip = &(chip->chip_out);
+ gpio_chip->label = "htcpld-out";
+- gpio_chip->dev = dev;
++ gpio_chip->parent = dev;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->get = htcpld_chip_get;
+ gpio_chip->set = htcpld_chip_set;
+@@ -440,7 +440,7 @@ static int htcpld_register_chip_gpio(
+
+ gpio_chip = &(chip->chip_in);
+ gpio_chip->label = "htcpld-in";
+- gpio_chip->dev = dev;
++ gpio_chip->parent = dev;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->get = htcpld_chip_get;
+ gpio_chip->set = NULL;
+--- a/drivers/mfd/tps65010.c
++++ b/drivers/mfd/tps65010.c
+@@ -638,7 +638,7 @@ static int tps65010_probe(struct i2c_cli
+ tps->outmask = board->outmask;
+
+ tps->chip.label = client->name;
+- tps->chip.dev = &client->dev;
++ tps->chip.parent = &client->dev;
+ tps->chip.owner = THIS_MODULE;
+
+ tps->chip.set = tps65010_gpio_set;
+--- a/drivers/mfd/ucb1x00-core.c
++++ b/drivers/mfd/ucb1x00-core.c
+@@ -570,7 +570,7 @@ static int ucb1x00_probe(struct mcp *mcp
+
+ if (pdata && pdata->gpio_base) {
+ ucb->gpio.label = dev_name(&ucb->dev);
+- ucb->gpio.dev = &ucb->dev;
++ ucb->gpio.parent = &ucb->dev;
+ ucb->gpio.owner = THIS_MODULE;
+ ucb->gpio.base = pdata->gpio_base;
+ ucb->gpio.ngpio = 10;
+--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+@@ -337,14 +337,14 @@ static int bcm2835_gpio_direction_input(
+
+ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+- struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
++ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->parent);
+
+ return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
+ }
+
+ static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ {
+- struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
++ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->parent);
+
+ bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
+ }
+@@ -358,7 +358,7 @@ static int bcm2835_gpio_direction_output
+
+ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+- struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
++ struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->parent);
+
+ return irq_linear_revmap(pc->irq_domain, offset);
+ }
+@@ -964,7 +964,7 @@ static int bcm2835_pinctrl_probe(struct
+ return PTR_ERR(pc->base);
+
+ pc->gpio_chip = bcm2835_gpio_chip;
+- pc->gpio_chip.dev = dev;
++ pc->gpio_chip.parent = dev;
+ pc->gpio_chip.of_node = np;
+
+ pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
+--- a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
++++ b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
+@@ -720,7 +720,7 @@ static int cygnus_gpio_probe(struct plat
+ gc->ngpio = ngpios;
+ chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK;
+ gc->label = dev_name(dev);
+- gc->dev = dev;
++ gc->parent = dev;
+ gc->of_node = dev->of_node;
+ gc->request = cygnus_gpio_request;
+ gc->free = cygnus_gpio_free;
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -598,7 +598,7 @@ static int byt_gpio_probe(struct platfor
+ gc->dbg_show = byt_gpio_dbg_show;
+ gc->base = -1;
+ gc->can_sleep = false;
+- gc->dev = dev;
++ gc->parent = dev;
+
+ #ifdef CONFIG_PM_SLEEP
+ vg->saved_context = devm_kcalloc(&pdev->dev, gc->ngpio,
+--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
++++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
+@@ -1436,7 +1436,7 @@ static int chv_gpio_probe(struct chv_pin
+
+ chip->ngpio = pctrl->community->ngpios;
+ chip->label = dev_name(pctrl->dev);
+- chip->dev = pctrl->dev;
++ chip->parent = pctrl->dev;
+ chip->base = -1;
+
+ ret = gpiochip_add(chip);
+--- a/drivers/pinctrl/intel/pinctrl-intel.c
++++ b/drivers/pinctrl/intel/pinctrl-intel.c
+@@ -872,7 +872,7 @@ static int intel_gpio_probe(struct intel
+
+ pctrl->chip.ngpio = pctrl->soc->npins;
+ pctrl->chip.label = dev_name(pctrl->dev);
+- pctrl->chip.dev = pctrl->dev;
++ pctrl->chip.parent = pctrl->dev;
+ pctrl->chip.base = -1;
+
+ ret = gpiochip_add(&pctrl->chip);
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -95,7 +95,7 @@ static void mtk_gpio_set(struct gpio_chi
+ {
+ unsigned int reg_addr;
+ unsigned int bit;
+- struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
++ struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
+
+ reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dout_offset;
+ bit = BIT(offset & 0xf);
+@@ -742,7 +742,7 @@ static int mtk_gpio_get_direction(struct
+ unsigned int bit;
+ unsigned int read_val = 0;
+
+- struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
++ struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
+
+ reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset;
+ bit = BIT(offset & 0xf);
+@@ -755,7 +755,7 @@ static int mtk_gpio_get(struct gpio_chip
+ unsigned int reg_addr;
+ unsigned int bit;
+ unsigned int read_val = 0;
+- struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
++ struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
+
+ reg_addr = mtk_get_port(pctl, offset) +
+ pctl->devdata->din_offset;
+@@ -768,7 +768,7 @@ static int mtk_gpio_get(struct gpio_chip
+ static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+ const struct mtk_desc_pin *pin;
+- struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
++ struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
+ int irq;
+
+ pin = pctl->devdata->pins + offset;
+@@ -936,7 +936,7 @@ static void mtk_eint_unmask(struct irq_d
+ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
+ unsigned debounce)
+ {
+- struct mtk_pinctrl *pctl = dev_get_drvdata(chip->dev);
++ struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
+ int eint_num, virq, eint_offset;
+ unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask, dbnc;
+ static const unsigned int dbnc_arr[] = {0 , 1, 16, 32, 64, 128, 256};
+@@ -1345,7 +1345,7 @@ int mtk_pctrl_init(struct platform_devic
+ *pctl->chip = mtk_gpio_chip;
+ pctl->chip->ngpio = pctl->devdata->npins;
+ pctl->chip->label = dev_name(&pdev->dev);
+- pctl->chip->dev = &pdev->dev;
++ pctl->chip->parent = &pdev->dev;
+ pctl->chip->base = -1;
+
+ ret = gpiochip_add(pctl->chip);
+--- a/drivers/pinctrl/meson/pinctrl-meson.c
++++ b/drivers/pinctrl/meson/pinctrl-meson.c
+@@ -562,7 +562,7 @@ static int meson_gpiolib_register(struct
+ domain = &pc->domains[i];
+
+ domain->chip.label = domain->data->name;
+- domain->chip.dev = pc->dev;
++ domain->chip.parent = pc->dev;
+ domain->chip.request = meson_gpio_request;
+ domain->chip.free = meson_gpio_free;
+ domain->chip.direction_input = meson_gpio_direction_input;
+--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
++++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
+@@ -986,7 +986,7 @@ static int abx500_pin_config_set(struct
+ param = pinconf_to_config_param(configs[i]);
+ argument = pinconf_to_config_argument(configs[i]);
+
+- dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n",
++ dev_dbg(chip->parent, "pin %d [%#lx]: %s %s\n",
+ pin, configs[i],
+ (param == PIN_CONFIG_OUTPUT) ? "output " : "input",
+ (param == PIN_CONFIG_OUTPUT) ?
+@@ -1077,7 +1077,8 @@ static int abx500_pin_config_set(struct
+ break;
+
+ default:
+- dev_err(chip->dev, "illegal configuration requested\n");
++ dev_err(chip->parent,
++ "illegal configuration requested\n");
+ }
+ } /* for each config */
+ out:
+@@ -1172,7 +1173,7 @@ static int abx500_gpio_probe(struct plat
+ pct->dev = &pdev->dev;
+ pct->parent = dev_get_drvdata(pdev->dev.parent);
+ pct->chip = abx500gpio_chip;
+- pct->chip.dev = &pdev->dev;
++ pct->chip.parent = &pdev->dev;
+ pct->chip.base = -1; /* Dynamic allocation */
+
+ match = of_match_device(abx500_gpio_match, &pdev->dev);
+--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
++++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+@@ -438,7 +438,7 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpi
+ nmk_chip->addr + NMK_GPIO_FIMSC);
+ }
+
+- dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
++ dev_dbg(nmk_chip->chip.parent, "%d: clearing interrupt mask\n", gpio);
+ }
+
+ static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value)
+@@ -1188,7 +1188,7 @@ static struct nmk_gpio_chip *nmk_gpio_po
+ chip->base = id * NMK_GPIO_PER_CHIP;
+ chip->ngpio = NMK_GPIO_PER_CHIP;
+ chip->label = dev_name(&gpio_pdev->dev);
+- chip->dev = &gpio_pdev->dev;
++ chip->parent = &gpio_pdev->dev;
+
+ res = platform_get_resource(gpio_pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+@@ -1890,7 +1890,7 @@ static int nmk_pin_config_set(struct pin
+ if (slpm_val)
+ val = slpm_val - 1;
+
+- dev_dbg(nmk_chip->chip.dev,
++ dev_dbg(nmk_chip->chip.parent,
+ "pin %d: sleep pull %s, dir %s, val %s\n",
+ pin,
+ slpm_pull ? pullnames[pull] : "same",
+@@ -1899,7 +1899,7 @@ static int nmk_pin_config_set(struct pin
+ slpm_val ? (val ? "high" : "low") : "same");
+ }
+
+- dev_dbg(nmk_chip->chip.dev,
++ dev_dbg(nmk_chip->chip.parent,
+ "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n",
+ pin, cfg, pullnames[pull], slpmnames[slpm],
+ output ? "output " : "input",
+--- a/drivers/pinctrl/pinctrl-amd.c
++++ b/drivers/pinctrl/pinctrl-amd.c
+@@ -778,7 +778,7 @@ static int amd_gpio_probe(struct platfor
+ gpio_dev->gc.base = 0;
+ gpio_dev->gc.label = pdev->name;
+ gpio_dev->gc.owner = THIS_MODULE;
+- gpio_dev->gc.dev = &pdev->dev;
++ gpio_dev->gc.parent = &pdev->dev;
+ gpio_dev->gc.ngpio = TOTAL_NUMBER_OF_PINS;
+ #if defined(CONFIG_OF_GPIO)
+ gpio_dev->gc.of_node = pdev->dev.of_node;
+--- a/drivers/pinctrl/pinctrl-as3722.c
++++ b/drivers/pinctrl/pinctrl-as3722.c
+@@ -582,7 +582,7 @@ static int as3722_pinctrl_probe(struct p
+ }
+
+ as_pci->gpio_chip = as3722_gpio_chip;
+- as_pci->gpio_chip.dev = &pdev->dev;
++ as_pci->gpio_chip.parent = &pdev->dev;
+ as_pci->gpio_chip.of_node = pdev->dev.parent->of_node;
+ ret = gpiochip_add(&as_pci->gpio_chip);
+ if (ret < 0) {
+--- a/drivers/pinctrl/pinctrl-at91-pio4.c
++++ b/drivers/pinctrl/pinctrl-at91-pio4.c
+@@ -290,7 +290,7 @@ static void atmel_gpio_irq_handler(struc
+
+ static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+ {
+- struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
++ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->parent);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+ unsigned reg;
+
+@@ -305,7 +305,7 @@ static int atmel_gpio_direction_input(st
+
+ static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+- struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
++ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->parent);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+ unsigned reg;
+
+@@ -317,7 +317,7 @@ static int atmel_gpio_get(struct gpio_ch
+ static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+ {
+- struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
++ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->parent);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+ unsigned reg;
+
+@@ -336,7 +336,7 @@ static int atmel_gpio_direction_output(s
+
+ static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+ {
+- struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
++ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->parent);
+ struct atmel_pin *pin = atmel_pioctrl->pins[offset];
+
+ atmel_gpio_write(atmel_pioctrl, pin->bank,
+@@ -346,7 +346,7 @@ static void atmel_gpio_set(struct gpio_c
+
+ static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+- struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->dev);
++ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(chip->parent);
+
+ return irq_find_mapping(atmel_pioctrl->irq_domain, offset);
+ }
+@@ -969,7 +969,7 @@ static int atmel_pinctrl_probe(struct pl
+ atmel_pioctrl->gpio_chip->of_node = dev->of_node;
+ atmel_pioctrl->gpio_chip->ngpio = atmel_pioctrl->npins;
+ atmel_pioctrl->gpio_chip->label = dev_name(dev);
+- atmel_pioctrl->gpio_chip->dev = dev;
++ atmel_pioctrl->gpio_chip->parent = dev;
+ atmel_pioctrl->gpio_chip->names = atmel_pioctrl->group_names;
+
+ atmel_pioctrl->pm_wakeup_sources = devm_kzalloc(dev,
+--- a/drivers/pinctrl/pinctrl-at91.c
++++ b/drivers/pinctrl/pinctrl-at91.c
+@@ -1750,7 +1750,7 @@ static int at91_gpio_probe(struct platfo
+ chip = &at91_chip->chip;
+ chip->of_node = np;
+ chip->label = dev_name(&pdev->dev);
+- chip->dev = &pdev->dev;
++ chip->parent = &pdev->dev;
+ chip->owner = THIS_MODULE;
+ chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+--- a/drivers/pinctrl/pinctrl-coh901.c
++++ b/drivers/pinctrl/pinctrl-coh901.c
+@@ -637,7 +637,7 @@ static int __init u300_gpio_probe(struct
+
+ gpio->chip = u300_gpio_chip;
+ gpio->chip.ngpio = U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT;
+- gpio->chip.dev = &pdev->dev;
++ gpio->chip.parent = &pdev->dev;
+ gpio->chip.base = 0;
+ gpio->dev = &pdev->dev;
+
+--- a/drivers/pinctrl/pinctrl-digicolor.c
++++ b/drivers/pinctrl/pinctrl-digicolor.c
+@@ -244,7 +244,7 @@ static int dc_gpiochip_add(struct dc_pin
+ int ret;
+
+ chip->label = DRIVER_NAME;
+- chip->dev = pmap->dev;
++ chip->parent = pmap->dev;
+ chip->request = gpiochip_generic_request;
+ chip->free = gpiochip_generic_free;
+ chip->direction_input = dc_gpio_direction_input;
+--- a/drivers/pinctrl/pinctrl-pistachio.c
++++ b/drivers/pinctrl/pinctrl-pistachio.c
+@@ -1388,7 +1388,7 @@ static int pistachio_gpio_register(struc
+ bank->pctl = pctl;
+ bank->base = pctl->base + GPIO_BANK_BASE(i);
+
+- bank->gpio_chip.dev = pctl->dev;
++ bank->gpio_chip.parent = pctl->dev;
+ bank->gpio_chip.of_node = child;
+ ret = gpiochip_add(&bank->gpio_chip);
+ if (ret < 0) {
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -1754,7 +1754,7 @@ static int rockchip_gpiolib_register(str
+ gc = &bank->gpio_chip;
+ gc->base = bank->pin_base;
+ gc->ngpio = bank->nr_pins;
+- gc->dev = &pdev->dev;
++ gc->parent = &pdev->dev;
+ gc->of_node = bank->of_node;
+ gc->label = bank->name;
+
+--- a/drivers/pinctrl/pinctrl-st.c
++++ b/drivers/pinctrl/pinctrl-st.c
+@@ -1522,7 +1522,7 @@ static int st_gpiolib_register_bank(stru
+ bank->gpio_chip.base = bank_num * ST_GPIO_PINS_PER_BANK;
+ bank->gpio_chip.ngpio = ST_GPIO_PINS_PER_BANK;
+ bank->gpio_chip.of_node = np;
+- bank->gpio_chip.dev = dev;
++ bank->gpio_chip.parent = dev;
+ spin_lock_init(&bank->lock);
+
+ of_property_read_string(np, "st,bank-name", &range->name);
+--- a/drivers/pinctrl/pinctrl-xway.c
++++ b/drivers/pinctrl/pinctrl-xway.c
+@@ -648,7 +648,7 @@ static struct ltq_pinmux_info xway_info
+ /* --------- gpio_chip related code --------- */
+ static void xway_gpio_set(struct gpio_chip *chip, unsigned int pin, int val)
+ {
+- struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
++ struct ltq_pinmux_info *info = dev_get_drvdata(chip->parent);
+
+ if (val)
+ gpio_setbit(info->membase[0], GPIO_OUT(pin), PORT_PIN(pin));
+@@ -658,14 +658,14 @@ static void xway_gpio_set(struct gpio_ch
+
+ static int xway_gpio_get(struct gpio_chip *chip, unsigned int pin)
+ {
+- struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
++ struct ltq_pinmux_info *info = dev_get_drvdata(chip->parent);
+
+ return gpio_getbit(info->membase[0], GPIO_IN(pin), PORT_PIN(pin));
+ }
+
+ static int xway_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
+ {
+- struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
++ struct ltq_pinmux_info *info = dev_get_drvdata(chip->parent);
+
+ gpio_clearbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+
+@@ -674,7 +674,7 @@ static int xway_gpio_dir_in(struct gpio_
+
+ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
+ {
+- struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
++ struct ltq_pinmux_info *info = dev_get_drvdata(chip->parent);
+
+ gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+ xway_gpio_set(chip, pin, val);
+@@ -783,7 +783,7 @@ static int pinmux_xway_probe(struct plat
+ xway_pctrl_desc.pins = xway_info.pads;
+
+ /* load the gpio chip */
+- xway_chip.dev = &pdev->dev;
++ xway_chip.parent = &pdev->dev;
+ ret = gpiochip_add(&xway_chip);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register gpio chip\n");
+--- a/drivers/pinctrl/qcom/pinctrl-msm.c
++++ b/drivers/pinctrl/qcom/pinctrl-msm.c
+@@ -800,7 +800,7 @@ static int msm_gpio_init(struct msm_pinc
+ chip->base = 0;
+ chip->ngpio = ngpio;
+ chip->label = dev_name(pctrl->dev);
+- chip->dev = pctrl->dev;
++ chip->parent = pctrl->dev;
+ chip->owner = THIS_MODULE;
+ chip->of_node = pctrl->dev->of_node;
+
+--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
++++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+@@ -760,7 +760,7 @@ static int pmic_gpio_probe(struct platfo
+ }
+
+ state->chip = pmic_gpio_gpio_template;
+- state->chip.dev = dev;
++ state->chip.parent = dev;
+ state->chip.base = -1;
+ state->chip.ngpio = npins;
+ state->chip.label = dev_name(dev);
+--- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
++++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
+@@ -862,7 +862,7 @@ static int pmic_mpp_probe(struct platfor
+ }
+
+ state->chip = pmic_mpp_gpio_template;
+- state->chip.dev = dev;
++ state->chip.parent = dev;
+ state->chip.base = -1;
+ state->chip.ngpio = npins;
+ state->chip.label = dev_name(dev);
+--- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
++++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
+@@ -730,7 +730,7 @@ static int pm8xxx_gpio_probe(struct plat
+
+ pctrl->chip = pm8xxx_gpio_template;
+ pctrl->chip.base = -1;
+- pctrl->chip.dev = &pdev->dev;
++ pctrl->chip.parent = &pdev->dev;
+ pctrl->chip.of_node = pdev->dev.of_node;
+ pctrl->chip.of_gpio_n_cells = 2;
+ pctrl->chip.label = dev_name(pctrl->dev);
+--- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
++++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
+@@ -821,7 +821,7 @@ static int pm8xxx_mpp_probe(struct platf
+
+ pctrl->chip = pm8xxx_mpp_template;
+ pctrl->chip.base = -1;
+- pctrl->chip.dev = &pdev->dev;
++ pctrl->chip.parent = &pdev->dev;
+ pctrl->chip.of_node = pdev->dev.of_node;
+ pctrl->chip.of_gpio_n_cells = 2;
+ pctrl->chip.label = dev_name(pctrl->dev);
+--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
++++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
+@@ -176,7 +176,8 @@ static int exynos_irq_request_resources(
+
+ ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
+ if (ret) {
+- dev_err(bank->gpio_chip.dev, "unable to lock pin %s-%lu IRQ\n",
++ dev_err(bank->g