SoCFPGA patches added
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/patches.socfpga/0001-ARM-dts-socfpga-enable-arm-shared-override-in-the-pl.patch b/patches.socfpga/0001-ARM-dts-socfpga-enable-arm-shared-override-in-the-pl.patch
new file mode 100644
index 0000000..8304e41
--- /dev/null
+++ b/patches.socfpga/0001-ARM-dts-socfpga-enable-arm-shared-override-in-the-pl.patch
@@ -0,0 +1,37 @@
+From 2e23d6de091f3e5e913086e223ac30eb4aa1f2a2 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Mon, 26 Sep 2016 14:29:30 -0500
+Subject: [PATCH 001/103] ARM: dts: socfpga: enable arm,shared-override in the
+ pl310
+
+Enable the bit(22) shared-override bit for the SoCFPGA family. While at it,
+enable the prefetch-data and prefetch-instr settings for the Arria10.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga.dtsi | 1 +
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 3 +++
+ 2 files changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga.dtsi
++++ b/arch/arm/boot/dts/socfpga.dtsi
+@@ -686,6 +686,7 @@
+ arm,data-latency = <2 1 1>;
+ prefetch-data = <1>;
+ prefetch-instr = <1>;
++ arm,shared-override;
+ };
+
+ mmc: dwmmc0@ff704000 {
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -573,6 +573,9 @@
+ interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+ cache-unified;
+ cache-level = <2>;
++ prefetch-data = <1>;
++ prefetch-instr = <1>;
++ arm,shared-override;
+ };
+
+ mmc: dwmmc0@ff808000 {
diff --git a/patches.socfpga/0002-ARM-socfpga_defconfig-Enable-HIGHMEM.patch b/patches.socfpga/0002-ARM-socfpga_defconfig-Enable-HIGHMEM.patch
new file mode 100644
index 0000000..214247e
--- /dev/null
+++ b/patches.socfpga/0002-ARM-socfpga_defconfig-Enable-HIGHMEM.patch
@@ -0,0 +1,26 @@
+From c9d8a75227efb5a538da3f00cc675f20d9191602 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Tue, 25 Oct 2016 10:55:40 -0500
+Subject: [PATCH 002/103] ARM: socfpga_defconfig: Enable HIGHMEM
+
+All of the SoCFPGA boards have at least 1GB of RAM, so enabling HIGHMEM
+is necessary to avoid the following warning:
+
+[ 0.000000] Truncating RAM at 0x00000000-0x40000000 to -0x30000000
+[ 0.000000] Consider using a HIGHMEM enabled kernel.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/configs/socfpga_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/socfpga_defconfig
++++ b/arch/arm/configs/socfpga_defconfig
+@@ -25,6 +25,7 @@ CONFIG_PCIE_ALTERA_MSI=y
+ CONFIG_SMP=y
+ CONFIG_NR_CPUS=2
+ CONFIG_AEABI=y
++CONFIG_HIGHMEM=y
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_VFP=y
diff --git a/patches.socfpga/0003-ARM-dts-socfpga-enable-qspi-on-the-Cyclone5-devkit.patch b/patches.socfpga/0003-ARM-dts-socfpga-enable-qspi-on-the-Cyclone5-devkit.patch
new file mode 100644
index 0000000..52ced0c
--- /dev/null
+++ b/patches.socfpga/0003-ARM-dts-socfpga-enable-qspi-on-the-Cyclone5-devkit.patch
@@ -0,0 +1,54 @@
+From 60dab8bcc4915614d4853861f6a6ff35c2799d57 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Tue, 18 Oct 2016 22:51:42 -0500
+Subject: [PATCH 003/103] ARM: dts: socfpga: enable qspi on the Cyclone5 devkit
+
+Enable the qspi controller on the devkit and add the flash chip.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 33 +++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -87,6 +87,39 @@
+ status = "okay";
+ };
+
++&qspi {
++ status = "okay";
++
++ flash0: n25q00@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "n25q00";
++ reg = <0>; /* chip select */
++ spi-max-frequency = <100000000>;
++
++ m25p,fast-read;
++ cdns,page-size = <256>;
++ cdns,block-size = <16>;
++ cdns,read-delay = <4>;
++ cdns,tshsl-ns = <50>;
++ cdns,tsd2d-ns = <50>;
++ cdns,tchsh-ns = <4>;
++ cdns,tslch-ns = <4>;
++
++ partition@qspi-boot {
++ /* 8MB for raw data. */
++ label = "Flash 0 Raw Data";
++ reg = <0x0 0x800000>;
++ };
++
++ partition@qspi-rootfs {
++ /* 120MB for jffs2 data. */
++ label = "Flash 0 jffs2 Filesystem";
++ reg = <0x800000 0x7800000>;
++ };
++ };
++};
++
+ &usb1 {
+ status = "okay";
+ };
diff --git a/patches.socfpga/0004-ARM-dts-socfpga-Add-QSPI-node-for-the-Arria10.patch b/patches.socfpga/0004-ARM-dts-socfpga-Add-QSPI-node-for-the-Arria10.patch
new file mode 100644
index 0000000..7fc973c
--- /dev/null
+++ b/patches.socfpga/0004-ARM-dts-socfpga-Add-QSPI-node-for-the-Arria10.patch
@@ -0,0 +1,35 @@
+From ab6809e7a5eb396b38f0cee59b1cda615de6cd69 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Wed, 19 Oct 2016 10:56:33 -0500
+Subject: [PATCH 004/103] ARM: dts: socfpga: Add QSPI node for the Arria10
+
+Add the QSPI device node for Arria10 SOC.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -660,6 +660,20 @@
+ };
+ };
+
++ qspi: spi@ff809000 {
++ compatible = "cdns,qspi-nor";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0xff809000 0x100>,
++ <0xffa00000 0x100000>;
++ interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
++ cdns,fifo-depth = <128>;
++ cdns,fifo-width = <4>;
++ cdns,trigger-address = <0x00000000>;
++ clocks = <&qspi_clk>;
++ status = "disabled";
++ };
++
+ rst: rstmgr@ffd05000 {
+ #reset-cells = <1>;
+ compatible = "altr,rst-mgr";
diff --git a/patches.socfpga/0005-ARM-dts-socfpga-Enable-QSPI-in-Arria10-devkit.patch b/patches.socfpga/0005-ARM-dts-socfpga-Enable-QSPI-in-Arria10-devkit.patch
new file mode 100644
index 0000000..d13b676
--- /dev/null
+++ b/patches.socfpga/0005-ARM-dts-socfpga-Enable-QSPI-in-Arria10-devkit.patch
@@ -0,0 +1,76 @@
+From 9004406f4a7df7be3ba20eb5299db80ae89a4de8 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Wed, 19 Oct 2016 10:07:48 -0500
+Subject: [PATCH 005/103] ARM: dts: socfpga: Enable QSPI in Arria10 devkit
+
+Enable the QSPI node and add the flash chip.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/Makefile | 1
+ arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts | 49 +++++++++++++++++++++++
+ 2 files changed, 50 insertions(+)
+ create mode 100644 arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -693,6 +693,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
+ sh73a0-kzm9g.dtb
+ dtb-$(CONFIG_ARCH_SOCFPGA) += \
+ socfpga_arria5_socdk.dtb \
++ socfpga_arria10_socdk_qspi.dtb \
+ socfpga_arria10_socdk_sdmmc.dtb \
+ socfpga_cyclone5_mcvevk.dtb \
+ socfpga_cyclone5_socdk.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (C) 2016 Intel. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ */
++
++/dts-v1/;
++#include "socfpga_arria10_socdk.dtsi"
++
++&qspi {
++ status = "okay";
++
++ flash0: n25q00@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "n25q00aa";
++ reg = <0>;
++ spi-max-frequency = <100000000>;
++
++ m25p,fast-read;
++ cdns,page-size = <256>;
++ cdns,block-size = <16>;
++ cdns,read-delay = <4>;
++ cdns,tshsl-ns = <50>;
++ cdns,tsd2d-ns = <50>;
++ cdns,tchsh-ns = <4>;
++ cdns,tslch-ns = <4>;
++
++ partition@qspi-boot {
++ label = "Boot and fpga data";
++ reg = <0x0 0x2720000>;
++ };
++
++ partition@qspi-rootfs {
++ label = "Root Filesystem - JFFS2";
++ reg = <0x2720000 0x58E0000>;
++ };
++ };
++};
diff --git a/patches.socfpga/0006-ARM-dts-socfpga-Enable-QSPI-on-the-Cyclone5-sockit.patch b/patches.socfpga/0006-ARM-dts-socfpga-Enable-QSPI-on-the-Cyclone5-sockit.patch
new file mode 100644
index 0000000..f6d1e75
--- /dev/null
+++ b/patches.socfpga/0006-ARM-dts-socfpga-Enable-QSPI-on-the-Cyclone5-sockit.patch
@@ -0,0 +1,46 @@
+From 72315cbb4c67745c94487884687e469cff71fa88 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Wed, 19 Oct 2016 14:55:54 -0500
+Subject: [PATCH 006/103] ARM: dts: socfpga: Enable QSPI on the Cyclone5 sockit
+
+Enable the QSPI node and add the flash chip.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+v3: Use n25q00 for the compatible entry for the flash part and
+ tested on SoCKit
+v2: Remove partition entries for the SoCKIT
+---
+ arch/arm/boot/dts/socfpga_cyclone5_sockit.dts | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
+@@ -175,6 +175,27 @@
+ status = "okay";
+ };
+
++&qspi {
++ status = "okay";
++
++ flash: flash@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "n25q00";
++ reg = <0>;
++ spi-max-frequency = <100000000>;
++
++ m25p,fast-read;
++ cdns,page-size = <256>;
++ cdns,block-size = <16>;
++ cdns,read-delay = <4>;
++ cdns,tshsl-ns = <50>;
++ cdns,tsd2d-ns = <50>;
++ cdns,tchsh-ns = <4>;
++ cdns,tslch-ns = <4>;
++ };
++};
++
+ &usb1 {
+ status = "okay";
+ };
diff --git a/patches.socfpga/0007-ARM-dts-socfpga-Enable-QSPI-on-the-Arria5-devkit.patch b/patches.socfpga/0007-ARM-dts-socfpga-Enable-QSPI-on-the-Arria5-devkit.patch
new file mode 100644
index 0000000..4b18dbd
--- /dev/null
+++ b/patches.socfpga/0007-ARM-dts-socfpga-Enable-QSPI-on-the-Arria5-devkit.patch
@@ -0,0 +1,54 @@
+From b6010bd7a8f9436f60f0b07ea629b5607251f0b2 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@opensource.altera.com>
+Date: Wed, 19 Oct 2016 15:48:07 -0500
+Subject: [PATCH 007/103] ARM: dts: socfpga: Enable QSPI on the Arria5 devkit
+
+Enable the QSPI node and add the flash chip.
+
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_arria5_socdk.dts | 33 +++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+@@ -82,6 +82,39 @@
+ status = "okay";
+ };
+
++&qspi {
++ status = "okay";
++
++ flash: flash@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "n25q256a";
++ reg = <0>;
++ spi-max-frequency = <100000000>;
++
++ m25p,fast-read;
++ cdns,page-size = <256>;
++ cdns,block-size = <16>;
++ cdns,read-delay = <4>;
++ cdns,tshsl-ns = <50>;
++ cdns,tsd2d-ns = <50>;
++ cdns,tchsh-ns = <4>;
++ cdns,tslch-ns = <4>;
++
++ partition@qspi-boot {
++ /* 8MB for raw data. */
++ label = "Flash 0 Raw Data";
++ reg = <0x0 0x800000>;
++ };
++
++ partition@qspi-rootfs {
++ /* 120MB for jffs2 data. */
++ label = "Flash 0 jffs2 Filesystem";
++ reg = <0x800000 0x7800000>;
++ };
++ };
++};
++
+ &usb1 {
+ status = "okay";
+ };
diff --git a/patches.socfpga/0008-ARM-socfpga_defconfig-enable-FS-configs-to-support-A.patch b/patches.socfpga/0008-ARM-socfpga_defconfig-enable-FS-configs-to-support-A.patch
new file mode 100644
index 0000000..aa320e3
--- /dev/null
+++ b/patches.socfpga/0008-ARM-socfpga_defconfig-enable-FS-configs-to-support-A.patch
@@ -0,0 +1,40 @@
+From 81e36c3e01bbc9cbee6a3882b18d836667758d25 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 8 Nov 2016 15:01:22 -0600
+Subject: [PATCH 008/103] ARM: socfpga_defconfig: enable FS configs to support
+ Angstrom filesystem
+
+systemd on the Angstrom root file system expects AUTOFS to be configured
+as a module and NFSD to be statically linked into the kernel. This patch
+adds the necessary configuration to get rid two "FAILED" error messages
+during systemd startup.
+
+Signed-off-by: Matthew Gerlach <mgerlach@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+v2: provide a more descriptive changelog
+---
+ arch/arm/configs/socfpga_defconfig | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm/configs/socfpga_defconfig
++++ b/arch/arm/configs/socfpga_defconfig
+@@ -107,13 +107,18 @@ CONFIG_EXT2_FS=y
+ CONFIG_EXT2_FS_XATTR=y
+ CONFIG_EXT2_FS_POSIX_ACL=y
+ CONFIG_EXT3_FS=y
++CONFIG_AUTOFS4_FS=y
+ CONFIG_VFAT_FS=y
+ CONFIG_NTFS_FS=y
+ CONFIG_NTFS_RW=y
+ CONFIG_TMPFS=y
+ CONFIG_CONFIGFS_FS=y
+ CONFIG_NFS_FS=y
++CONFIG_NFS_V3_ACL=y
+ CONFIG_ROOT_NFS=y
++CONFIG_NFSD=y
++CONFIG_NFSD_V3_ACL=y
++CONFIG_NFSD_V4=y
+ CONFIG_NLS_CODEPAGE_437=y
+ CONFIG_NLS_ISO8859_1=y
+ CONFIG_PRINTK_TIME=y
diff --git a/patches.socfpga/0009-dt-bindings-Add-Macnica-Americas-vendor-prefix.patch b/patches.socfpga/0009-dt-bindings-Add-Macnica-Americas-vendor-prefix.patch
new file mode 100644
index 0000000..1487c49
--- /dev/null
+++ b/patches.socfpga/0009-dt-bindings-Add-Macnica-Americas-vendor-prefix.patch
@@ -0,0 +1,24 @@
+From fdcef7128b2fcfa244e5b2ae5e2e323a819a2158 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 1 Nov 2016 10:36:30 -0500
+Subject: [PATCH 009/103] dt-bindings: Add Macnica Americas vendor prefix
+
+Add a vendor prefix for the Macnica company.
+http://http://www.macnica.com
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -158,6 +158,7 @@ lg LG Corporation
+ linux Linux-specific binding
+ lltc Linear Technology Corporation
+ lsi LSI Corp. (LSI Logic)
++macnica Macnica Americas
+ marvell Marvell Technology Group Ltd.
+ maxim Maxim Integrated Products
+ meas Measurement Specialties
diff --git a/patches.socfpga/0010-dt-bindings-Add-vendor-prefix-for-Terasic-Inc.patch b/patches.socfpga/0010-dt-bindings-Add-vendor-prefix-for-Terasic-Inc.patch
new file mode 100644
index 0000000..7a2ff47
--- /dev/null
+++ b/patches.socfpga/0010-dt-bindings-Add-vendor-prefix-for-Terasic-Inc.patch
@@ -0,0 +1,25 @@
+From 5ae491dadecfd37b8f00965ada793be6c230dddc Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 1 Nov 2016 10:36:31 -0500
+Subject: [PATCH 010/103] dt-bindings: Add vendor prefix for Terasic Inc.
+
+Add a vendor prefix for Terasic.
+
+http://www.terasic.com
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -276,6 +276,7 @@ tcg Trusted Computing Group
+ tcl Toby Churchill Ltd.
+ technexion TechNexion
+ technologic Technologic Systems
++terasic Terasic Inc.
+ thine THine Electronics, Inc.
+ ti Texas Instruments
+ tlm Trusted Logic Mobility
diff --git a/patches.socfpga/0011-dt-bindings-Add-vendor-prefix-for-Samtec.patch b/patches.socfpga/0011-dt-bindings-Add-vendor-prefix-for-Samtec.patch
new file mode 100644
index 0000000..d0eb1bf
--- /dev/null
+++ b/patches.socfpga/0011-dt-bindings-Add-vendor-prefix-for-Samtec.patch
@@ -0,0 +1,26 @@
+From 886e6363f55f9996be2c7f6e122fbd90fc01c85c Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 1 Nov 2016 10:36:32 -0500
+Subject: [PATCH 011/103] dt-bindings: Add vendor prefix for Samtec
+
+Add a vendor prefix for Samtec, a Softing company.
+
+http://www.samtec.de
+http://www.samtec.org
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -232,6 +232,7 @@ richtek Richtek Technology Corporation
+ ricoh Ricoh Co. Ltd.
+ rockchip Fuzhou Rockchip Electronics Co., Ltd
+ samsung Samsung Semiconductor
++samtec Samtec/Softing company
+ sandisk Sandisk Corporation
+ sbs Smart Battery System
+ schindler Schindler
diff --git a/patches.socfpga/0012-ARM-dts-socfpga-enable-GPIO-and-LEDs-for-Cyclone5-an.patch b/patches.socfpga/0012-ARM-dts-socfpga-enable-GPIO-and-LEDs-for-Cyclone5-an.patch
new file mode 100644
index 0000000..861b736
--- /dev/null
+++ b/patches.socfpga/0012-ARM-dts-socfpga-enable-GPIO-and-LEDs-for-Cyclone5-an.patch
@@ -0,0 +1,117 @@
+From 68ba0c63510af673e2400895aaaa5a6c7c9ec622 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Mon, 12 Dec 2016 22:02:44 -0600
+Subject: [PATCH 012/103] ARM: dts: socfpga: enable GPIO and LEDs for Cyclone5
+ and Arria5 devkits
+
+Enable all the GPIO ports and define the GPIO-based leds on the Cyclone5 and
+Arria5 devkits.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria5_socdk.dts | 35 +++++++++++++++++++++++++++
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 31 +++++++++++++++++++++++
+ 2 files changed, 66 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+@@ -39,6 +39,29 @@
+ ethernet0 = &gmac1;
+ };
+
++ leds {
++ compatible = "gpio-leds";
++ hps0 {
++ label = "hps_led0";
++ gpios = <&porta 0 1>;
++ };
++
++ hps1 {
++ label = "hps_led1";
++ gpios = <&portb 11 1>;
++ };
++
++ hps2 {
++ label = "hps_led2";
++ gpios = <&porta 17 1>;
++ };
++
++ hps3 {
++ label = "hps_led3";
++ gpios = <&porta 18 1>;
++ };
++ };
++
+ regulator_3_3v: 3-3-v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+@@ -61,6 +84,18 @@
+ rxc-skew-ps = <2000>;
+ };
+
++&gpio0 {
++ status = "okay";
++};
++
++&gpio1 {
++ status = "okay";
++};
++
++&gpio2 {
++ status = "okay";
++};
++
+ &i2c0 {
+ status = "okay";
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -39,6 +39,29 @@
+ ethernet0 = &gmac1;
+ };
+
++ leds {
++ compatible = "gpio-leds";
++ hps0 {
++ label = "hps_led0";
++ gpios = <&portb 15 1>;
++ };
++
++ hps1 {
++ label = "hps_led1";
++ gpios = <&portb 14 1>;
++ };
++
++ hps2 {
++ label = "hps_led2";
++ gpios = <&portb 13 1>;
++ };
++
++ hps3 {
++ label = "hps_led3";
++ gpios = <&portb 12 1>;
++ };
++ };
++
+ regulator_3_3v: 3-3-v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "3.3V";
+@@ -61,10 +84,18 @@
+ rxc-skew-ps = <2000>;
+ };
+
++&gpio0 {
++ status = "okay";
++};
++
+ &gpio1 {
+ status = "okay";
+ };
+
++&gpio2 {
++ status = "okay";
++};
++
+ &i2c0 {
+ status = "okay";
+
diff --git a/patches.socfpga/0013-ARM-dts-socfpga-set-desired-i2c-clock-on-Cyclone5-an.patch b/patches.socfpga/0013-ARM-dts-socfpga-set-desired-i2c-clock-on-Cyclone5-an.patch
new file mode 100644
index 0000000..ebcff24
--- /dev/null
+++ b/patches.socfpga/0013-ARM-dts-socfpga-set-desired-i2c-clock-on-Cyclone5-an.patch
@@ -0,0 +1,50 @@
+From bae526e301c40e073379cbcf7d8239905ffcaf7f Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 13 Dec 2016 16:52:11 -0600
+Subject: [PATCH 013/103] ARM: dts: socfpga: set desired i2c clock on Cyclone5
+ and Arria5 devkits
+
+The I2C LCD display on the Cyclone5 and Arria5 devkits is only capable of
+the standard 100 kHz clock. Set the "clock-frequency" of the I2C node
+to be 100000.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria5_socdk.dts | 8 ++++++++
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 8 ++++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+@@ -98,6 +98,14 @@
+
+ &i2c0 {
+ status = "okay";
++ clock-frequency = <100000>;
++
++ /*
++ * adjust the falling times to decrease the i2c frequency to 50Khz
++ * because the LCD module does not work at the standard 100Khz
++ */
++ i2c-sda-falling-time-ns = <5000>;
++ i2c-scl-falling-time-ns = <5000>;
+
+ eeprom@51 {
+ compatible = "atmel,24c32";
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -98,6 +98,14 @@
+
+ &i2c0 {
+ status = "okay";
++ clock-frequency = <100000>;
++
++ /*
++ * adjust the falling times to decrease the i2c frequency to 50Khz
++ * because the LCD module does not work at the standard 100Khz
++ */
++ i2c-sda-falling-time-ns = <5000>;
++ i2c-scl-falling-time-ns = <5000>;
+
+ eeprom@51 {
+ compatible = "atmel,24c32";
diff --git a/patches.socfpga/0014-ARM-dts-socfpga-Add-Rohm-DH2228FV-DAC.patch b/patches.socfpga/0014-ARM-dts-socfpga-Add-Rohm-DH2228FV-DAC.patch
new file mode 100644
index 0000000..4f3e40f
--- /dev/null
+++ b/patches.socfpga/0014-ARM-dts-socfpga-Add-Rohm-DH2228FV-DAC.patch
@@ -0,0 +1,31 @@
+From 3f5e1bdb1957578c511107b2e4bef7c5d287b1bc Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Thu, 15 Dec 2016 23:30:03 -0600
+Subject: [PATCH 014/103] ARM: dts: socfpga: Add Rohm DH2228FV DAC
+
+Enable the SPI node and add the Rohm DH2228FV DAC.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -159,6 +159,16 @@
+ };
+ };
+
++&spi0 {
++ status = "okay";
++
++ spidev@0 {
++ compatible = "rohm,dh2228fv";
++ reg = <0>;
++ spi-max-frequency = <1000000>;
++ };
++};
++
+ &usb1 {
+ status = "okay";
+ };
diff --git a/patches.socfpga/0015-ARM-dts-socfpga-enable-CAN-on-Cyclone5-devkit.patch b/patches.socfpga/0015-ARM-dts-socfpga-enable-CAN-on-Cyclone5-devkit.patch
new file mode 100644
index 0000000..38c7c17
--- /dev/null
+++ b/patches.socfpga/0015-ARM-dts-socfpga-enable-CAN-on-Cyclone5-devkit.patch
@@ -0,0 +1,25 @@
+From 70fa6f9a9bf3bbdcb24f77876dd3787986c4623a Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Fri, 16 Dec 2016 16:55:44 -0600
+Subject: [PATCH 015/103] ARM: dts: socfpga: enable CAN on Cyclone5 devkit
+
+Enable the CAN node on the Cyclone5 devkit.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -70,6 +70,10 @@
+ };
+ };
+
++&can0 {
++ status = "okay";
++};
++
+ &gmac1 {
+ status = "okay";
+ phy-mode = "rgmii";
diff --git a/patches.socfpga/0016-ARM-dts-socfpga-enable-watchdog-timer-on-Arria5-and-.patch b/patches.socfpga/0016-ARM-dts-socfpga-enable-watchdog-timer-on-Arria5-and-.patch
new file mode 100644
index 0000000..136e3cf
--- /dev/null
+++ b/patches.socfpga/0016-ARM-dts-socfpga-enable-watchdog-timer-on-Arria5-and-.patch
@@ -0,0 +1,34 @@
+From 6442fc6873b15415fce505c7dbc3a8e824bb8163 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Fri, 16 Dec 2016 17:15:00 -0600
+Subject: [PATCH 016/103] ARM: dts: socfpga: enable watchdog timer on Arria5
+ and Arria10
+
+Enable the watchdog for Arria5 and Arria10.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 4 ++++
+ arch/arm/boot/dts/socfpga_arria5.dtsi | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -105,3 +105,7 @@
+ &usb0 {
+ status = "okay";
+ };
++
++&watchdog0 {
++ status = "okay";
++};
+--- a/arch/arm/boot/dts/socfpga_arria5.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria5.dtsi
+@@ -42,3 +42,7 @@
+ };
+ };
+ };
++
++&watchdog0 {
++ status = "okay";
++};
diff --git a/patches.socfpga/0017-ARM-dts-socfpga-add-the-LTC2977-power-monitor-on-Arr.patch b/patches.socfpga/0017-ARM-dts-socfpga-add-the-LTC2977-power-monitor-on-Arr.patch
new file mode 100644
index 0000000..656fbdc
--- /dev/null
+++ b/patches.socfpga/0017-ARM-dts-socfpga-add-the-LTC2977-power-monitor-on-Arr.patch
@@ -0,0 +1,27 @@
+From b8ccfd2af325b1bb2cc3fa70cd688850a32e6a54 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Sat, 17 Dec 2016 21:42:32 -0600
+Subject: [PATCH 017/103] ARM: dts: socfpga: add the LTC2977 power monitor on
+ Arria10 devkit
+
+Add the I2C LTC 2977 power monitor that is on the Arria10 devkit.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -96,6 +96,11 @@
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ };
++
++ ltc@5c {
++ compatible = "ltc2977";
++ reg = <0x5c>;
++ };
+ };
+
+ &uart1 {
diff --git a/patches.socfpga/0018-ARM-dts-socfpga-add-fpga-manager-node-for-Arria10.patch b/patches.socfpga/0018-ARM-dts-socfpga-add-fpga-manager-node-for-Arria10.patch
new file mode 100644
index 0000000..252f94d
--- /dev/null
+++ b/patches.socfpga/0018-ARM-dts-socfpga-add-fpga-manager-node-for-Arria10.patch
@@ -0,0 +1,30 @@
+From f968f1aa6c67873082498738e7756e2311eac0af Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Sat, 17 Dec 2016 22:45:03 -0600
+Subject: [PATCH 018/103] ARM: dts: socfpga: add fpga-manager node for Arria10
+
+Add the FPGA manger DTS entry for Arria10.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -512,6 +512,15 @@
+ };
+ };
+
++ fpga_mgr: fpga-mgr@ffd03000 {
++ compatible = "altr,socfpga-a10-fpga-mgr";
++ reg = <0xffd03000 0x100
++ 0xffcfe400 0x20>;
++ clocks = <&l4_mp_clk>;
++ resets = <&rst FPGAMGR_RESET>;
++ reset-names = "fpgamgr";
++ };
++
+ i2c0: i2c@ffc02200 {
+ #address-cells = <1>;
+ #size-cells = <0>;
diff --git a/patches.socfpga/0019-ARM-dts-socfpga-fpga-manager-data-is-32-bits.patch b/patches.socfpga/0019-ARM-dts-socfpga-fpga-manager-data-is-32-bits.patch
new file mode 100644
index 0000000..0be678f
--- /dev/null
+++ b/patches.socfpga/0019-ARM-dts-socfpga-fpga-manager-data-is-32-bits.patch
@@ -0,0 +1,26 @@
+From 5a87081d681bad5b577d1fe2a2a83021cfca989f Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Mon, 19 Dec 2016 22:34:00 -0600
+Subject: [PATCH 019/103] ARM: dts: socfpga: fpga manager data is 32 bits
+
+Adjust regs property for the FPGA manager data register to
+properly reflect that it is a single 32 bit register.
+
+Signed-off-by: Dalon Westergreen <dwesterg@altera.com>
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/socfpga.dtsi
++++ b/arch/arm/boot/dts/socfpga.dtsi
+@@ -516,7 +516,7 @@
+ fpgamgr0: fpgamgr@ff706000 {
+ compatible = "altr,socfpga-fpga-mgr";
+ reg = <0xff706000 0x1000
+- 0xffb90000 0x1000>;
++ 0xffb90000 0x4>;
+ interrupts = <0 175 4>;
+ };
+
diff --git a/patches.socfpga/0020-ARM-dts-socfpga-add-fpga-region-support-on-Arria10.patch b/patches.socfpga/0020-ARM-dts-socfpga-add-fpga-region-support-on-Arria10.patch
new file mode 100644
index 0000000..273ebb6
--- /dev/null
+++ b/patches.socfpga/0020-ARM-dts-socfpga-add-fpga-region-support-on-Arria10.patch
@@ -0,0 +1,31 @@
+From f534c9a2d107eb6255532f19decc1dde219a25e7 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Mon, 19 Dec 2016 23:21:27 -0600
+Subject: [PATCH 020/103] ARM: dts: socfpga: add fpga region support on Arria10
+
+Add the base FPGA region for DT overlay support in FPGA programming.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Matthew Gerlach <mgerlach@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -83,6 +83,14 @@
+ };
+ };
+
++ base_fpga_region {
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++
++ compatible = "fpga-region";
++ fpga-mgr = <&fpga_mgr>;
++ };
++
+ clkmgr@ffd04000 {
+ compatible = "altr,clk-mgr";
+ reg = <0xffd04000 0x1000>;
diff --git a/patches.socfpga/0021-ARM-dts-socfpga-add-missing-compatible-string-for-SD.patch b/patches.socfpga/0021-ARM-dts-socfpga-add-missing-compatible-string-for-SD.patch
new file mode 100644
index 0000000..ce6c180
--- /dev/null
+++ b/patches.socfpga/0021-ARM-dts-socfpga-add-missing-compatible-string-for-SD.patch
@@ -0,0 +1,36 @@
+From 36760f8265fe47bc7176a58aa85ca6c3ec59f812 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 20 Dec 2016 00:01:48 -0600
+Subject: [PATCH 021/103] ARM: dts: socfpga: add missing compatible string for
+ SDRAM controller
+
+Add "altr,sdr-ctl" to the SDRAM controller node.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga.dtsi | 2 +-
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/socfpga.dtsi
++++ b/arch/arm/boot/dts/socfpga.dtsi
+@@ -719,7 +719,7 @@
+ };
+
+ sdr: sdr@ffc25000 {
+- compatible = "syscon";
++ compatible = "altr,sdr-ctl", "syscon";
+ reg = <0xffc25000 0x1000>;
+ };
+
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -580,7 +580,7 @@
+ };
+
+ sdr: sdr@ffc25000 {
+- compatible = "syscon";
++ compatible = "altr,sdr-ctl", "syscon";
+ reg = <0xffcfb100 0x80>;
+ };
+
diff --git a/patches.socfpga/0022-ARM-dts-watchdog0-cannot-reliably-trigger-reset.patch b/patches.socfpga/0022-ARM-dts-watchdog0-cannot-reliably-trigger-reset.patch
new file mode 100644
index 0000000..38c6f1e
--- /dev/null
+++ b/patches.socfpga/0022-ARM-dts-watchdog0-cannot-reliably-trigger-reset.patch
@@ -0,0 +1,28 @@
+From 22f774c2c8c6b463883e3cbada27b5b74155b121 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Wed, 25 Jan 2017 10:01:28 -0600
+Subject: [PATCH 022/103] ARM: dts: watchdog0 cannot reliably trigger reset
+
+On the Arria10, because of hardware bug, watchdog0 cannot reliably trigger
+a reset to the CPU. The workaround would be to use watchdog1 instead.
+
+Also for watchdog1, there is a dependency on the bootloader to enable the
+boot_clk source to be from the cb_intosc_hs_clk/2, versus from EOSC1. This
+corresponds to the (SWCTRLBTCLKEN & SWCTRLBTCLKSEL) bits enabled in the
+control register in the clock manager module of Arria10.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -111,6 +111,6 @@
+ status = "okay";
+ };
+
+-&watchdog0 {
++&watchdog1 {
+ status = "okay";
+ };
diff --git a/patches.socfpga/0023-MAINTAINERS-socfpga-update-email-for-Dinh-Nguyen.patch b/patches.socfpga/0023-MAINTAINERS-socfpga-update-email-for-Dinh-Nguyen.patch
new file mode 100644
index 0000000..0aa0b17
--- /dev/null
+++ b/patches.socfpga/0023-MAINTAINERS-socfpga-update-email-for-Dinh-Nguyen.patch
@@ -0,0 +1,33 @@
+From bd1f3567243bb08db75c610e7475968b2dec1373 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Fri, 3 Feb 2017 09:29:07 -0600
+Subject: [PATCH 023/103] MAINTAINERS: socfpga: update email for Dinh Nguyen
+
+My opensource.altera.com email will be going away soon.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ MAINTAINERS | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1751,7 +1751,7 @@ F: drivers/soc/renesas/
+ F: include/linux/soc/renesas/
+
+ ARM/SOCFPGA ARCHITECTURE
+-M: Dinh Nguyen <dinguyen@opensource.altera.com>
++M: Dinh Nguyen <dinguyen@kernel.org>
+ S: Maintained
+ F: arch/arm/mach-socfpga/
+ F: arch/arm/boot/dts/socfpga*
+@@ -1761,7 +1761,7 @@ W: http://www.rocketboards.org
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
+
+ ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
+-M: Dinh Nguyen <dinguyen@opensource.altera.com>
++M: Dinh Nguyen <dinguyen@kernel.org>
+ S: Maintained
+ F: drivers/clk/socfpga/
+
diff --git a/patches.socfpga/0024-of-overlay-add-of-overlay-notifications.patch b/patches.socfpga/0024-of-overlay-add-of-overlay-notifications.patch
new file mode 100644
index 0000000..bc47fd3
--- /dev/null
+++ b/patches.socfpga/0024-of-overlay-add-of-overlay-notifications.patch
@@ -0,0 +1,175 @@
+From 34c5493a5611f3c1481d98767657ead412c55c18 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:22 -0500
+Subject: [PATCH 024/103] of/overlay: add of overlay notifications
+
+This patch add of overlay notifications.
+
+When DT overlays are being added, some drivers/subsystems
+need to see device tree overlays before the changes go into
+the live tree.
+
+This is distinct from reconfig notifiers that are
+post-apply or post-remove and which issue very granular
+notifications without providing access to the context
+of a whole overlay.
+
+The following 4 notificatons are issued:
+ OF_OVERLAY_PRE_APPLY
+ OF_OVERLAY_POST_APPLY
+ OF_OVERLAY_PRE_REMOVE
+ OF_OVERLAY_POST_REMOVE
+
+In the case of pre-apply notification, if the notifier
+returns error, the overlay will be rejected.
+
+This patch exports two functions for registering/unregistering
+notifications:
+ of_overlay_notifier_register(struct notifier_block *nb)
+ of_overlay_notifier_unregister(struct notifier_block *nb)
+
+The of_mutex is held during these notifications. The
+notification data includes pointers to the overlay target
+and the overlay:
+
+struct of_overlay_notify_data {
+ struct device_node *overlay;
+ struct device_node *target;
+};
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/of/overlay.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
+ include/linux/of.h | 25 +++++++++++++++++++++++++
+ 2 files changed, 71 insertions(+), 1 deletion(-)
+
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -58,6 +58,41 @@ struct of_overlay {
+ static int of_overlay_apply_one(struct of_overlay *ov,
+ struct device_node *target, const struct device_node *overlay);
+
++static BLOCKING_NOTIFIER_HEAD(of_overlay_chain);
++
++int of_overlay_notifier_register(struct notifier_block *nb)
++{
++ return blocking_notifier_chain_register(&of_overlay_chain, nb);
++}
++EXPORT_SYMBOL_GPL(of_overlay_notifier_register);
++
++int of_overlay_notifier_unregister(struct notifier_block *nb)
++{
++ return blocking_notifier_chain_unregister(&of_overlay_chain, nb);
++}
++EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister);
++
++static int of_overlay_notify(struct of_overlay *ov,
++ enum of_overlay_notify_action action)
++{
++ struct of_overlay_notify_data nd;
++ int i, ret;
++
++ for (i = 0; i < ov->count; i++) {
++ struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i];
++
++ nd.target = ovinfo->target;
++ nd.overlay = ovinfo->overlay;
++
++ ret = blocking_notifier_call_chain(&of_overlay_chain,
++ action, &nd);
++ if (ret)
++ return notifier_to_errno(ret);
++ }
++
++ return 0;
++}
++
+ static int of_overlay_apply_single_property(struct of_overlay *ov,
+ struct device_node *target, struct property *prop)
+ {
+@@ -368,6 +403,13 @@ int of_overlay_create(struct device_node
+ goto err_free_idr;
+ }
+
++ err = of_overlay_notify(ov, OF_OVERLAY_PRE_APPLY);
++ if (err < 0) {
++ pr_err("%s: Pre-apply notifier failed (err=%d)\n",
++ __func__, err);
++ goto err_free_idr;
++ }
++
+ /* apply the overlay */
+ err = of_overlay_apply(ov);
+ if (err)
+@@ -382,6 +424,8 @@ int of_overlay_create(struct device_node
+ /* add to the tail of the overlay list */
+ list_add_tail(&ov->node, &ov_list);
+
++ of_overlay_notify(ov, OF_OVERLAY_POST_APPLY);
++
+ mutex_unlock(&of_mutex);
+
+ return id;
+@@ -498,9 +542,10 @@ int of_overlay_destroy(int id)
+ goto out;
+ }
+
+-
++ of_overlay_notify(ov, OF_OVERLAY_PRE_REMOVE);
+ list_del(&ov->node);
+ __of_changeset_revert(&ov->cset);
++ of_overlay_notify(ov, OF_OVERLAY_POST_REMOVE);
+ of_free_overlay_info(ov);
+ idr_remove(&ov_idr, id);
+ of_changeset_destroy(&ov->cset);
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -1266,6 +1266,18 @@ static inline bool of_device_is_system_p
+ * Overlay support
+ */
+
++enum of_overlay_notify_action {
++ OF_OVERLAY_PRE_APPLY,
++ OF_OVERLAY_POST_APPLY,
++ OF_OVERLAY_PRE_REMOVE,
++ OF_OVERLAY_POST_REMOVE,
++};
++
++struct of_overlay_notify_data {
++ struct device_node *overlay;
++ struct device_node *target;
++};
++
+ #ifdef CONFIG_OF_OVERLAY
+
+ /* ID based overlays; the API for external users */
+@@ -1273,6 +1285,9 @@ int of_overlay_create(struct device_node
+ int of_overlay_destroy(int id);
+ int of_overlay_destroy_all(void);
+
++int of_overlay_notifier_register(struct notifier_block *nb);
++int of_overlay_notifier_unregister(struct notifier_block *nb);
++
+ #else
+
+ static inline int of_overlay_create(struct device_node *tree)
+@@ -1290,6 +1305,16 @@ static inline int of_overlay_destroy_all
+ return -ENOTSUPP;
+ }
+
++static inline int of_overlay_notifier_register(struct notifier_block *nb)
++{
++ return 0;
++}
++
++static inline int of_overlay_notifier_unregister(struct notifier_block *nb)
++{
++ return 0;
++}
++
+ #endif
+
+ #endif /* _LINUX_OF_H */
diff --git a/patches.socfpga/0025-fpga-add-method-to-get-fpga-manager-from-device.patch b/patches.socfpga/0025-fpga-add-method-to-get-fpga-manager-from-device.patch
new file mode 100644
index 0000000..a671185
--- /dev/null
+++ b/patches.socfpga/0025-fpga-add-method-to-get-fpga-manager-from-device.patch
@@ -0,0 +1,159 @@
+From 6cc9e7b146fc8e24e1ca6b7ae0b0e27ca6cc3fae Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:23 -0500
+Subject: [PATCH 025/103] fpga: add method to get fpga manager from device
+
+The intent is to provide a non-DT method of getting
+ahold of a FPGA manager to do some FPGA programming.
+
+This patch refactors of_fpga_mgr_get() to reuse most of it
+while adding a new method fpga_mgr_get() for getting a
+pointer to a fpga manager struct, given the device.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/fpga/fpga-mgr.txt | 6 ++-
+ drivers/fpga/fpga-mgr.c | 76 ++++++++++++++++++++++++++++------------
+ include/linux/fpga/fpga-mgr.h | 2 +
+ 3 files changed, 60 insertions(+), 24 deletions(-)
+
+--- a/Documentation/fpga/fpga-mgr.txt
++++ b/Documentation/fpga/fpga-mgr.txt
+@@ -38,11 +38,13 @@ To get/put a reference to a FPGA manager
+ -----------------------------------------
+
+ struct fpga_manager *of_fpga_mgr_get(struct device_node *node);
++ struct fpga_manager *fpga_mgr_get(struct device *dev);
++
++Given a DT node or device, get an exclusive reference to a FPGA manager.
+
+ void fpga_mgr_put(struct fpga_manager *mgr);
+
+-Given a DT node, get an exclusive reference to a FPGA manager or release
+-the reference.
++Release the reference.
+
+
+ To register or unregister the low level FPGA-specific driver:
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -39,7 +39,8 @@ static struct class *fpga_mgr_class;
+ * Step the low level fpga manager through the device-specific steps of getting
+ * an FPGA ready to be configured, writing the image to it, then doing whatever
+ * post-configuration steps necessary. This code assumes the caller got the
+- * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
++ * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is
++ * not an error code.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+@@ -99,7 +100,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
+ * Request an FPGA image using the firmware class, then write out to the FPGA.
+ * Update the state before each step to provide info on what step failed if
+ * there is a failure. This code assumes the caller got the mgr pointer
+- * from of_fpga_mgr_get() and checked that it is not an error code.
++ * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error
++ * code.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+@@ -181,30 +183,11 @@ static struct attribute *fpga_mgr_attrs[
+ };
+ ATTRIBUTE_GROUPS(fpga_mgr);
+
+-static int fpga_mgr_of_node_match(struct device *dev, const void *data)
+-{
+- return dev->of_node == data;
+-}
+-
+-/**
+- * of_fpga_mgr_get - get an exclusive reference to a fpga mgr
+- * @node: device node
+- *
+- * Given a device node, get an exclusive reference to a fpga mgr.
+- *
+- * Return: fpga manager struct or IS_ERR() condition containing error code.
+- */
+-struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
++struct fpga_manager *__fpga_mgr_get(struct device *dev)
+ {
+ struct fpga_manager *mgr;
+- struct device *dev;
+ int ret = -ENODEV;
+
+- dev = class_find_device(fpga_mgr_class, NULL, node,
+- fpga_mgr_of_node_match);
+- if (!dev)
+- return ERR_PTR(-ENODEV);
+-
+ mgr = to_fpga_manager(dev);
+ if (!mgr)
+ goto err_dev;
+@@ -226,6 +209,55 @@ err_dev:
+ put_device(dev);
+ return ERR_PTR(ret);
+ }
++
++static int fpga_mgr_dev_match(struct device *dev, const void *data)
++{
++ return dev->parent == data;
++}
++
++/**
++ * fpga_mgr_get - get an exclusive reference to a fpga mgr
++ * @dev: parent device that fpga mgr was registered with
++ *
++ * Given a device, get an exclusive reference to a fpga mgr.
++ *
++ * Return: fpga manager struct or IS_ERR() condition containing error code.
++ */
++struct fpga_manager *fpga_mgr_get(struct device *dev)
++{
++ struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev,
++ fpga_mgr_dev_match);
++ if (!mgr_dev)
++ return ERR_PTR(-ENODEV);
++
++ return __fpga_mgr_get(mgr_dev);
++}
++EXPORT_SYMBOL_GPL(fpga_mgr_get);
++
++static int fpga_mgr_of_node_match(struct device *dev, const void *data)
++{
++ return dev->of_node == data;
++}
++
++/**
++ * of_fpga_mgr_get - get an exclusive reference to a fpga mgr
++ * @node: device node
++ *
++ * Given a device node, get an exclusive reference to a fpga mgr.
++ *
++ * Return: fpga manager struct or IS_ERR() condition containing error code.
++ */
++struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
++{
++ struct device *dev;
++
++ dev = class_find_device(fpga_mgr_class, NULL, node,
++ fpga_mgr_of_node_match);
++ if (!dev)
++ return ERR_PTR(-ENODEV);
++
++ return __fpga_mgr_get(dev);
++}
+ EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
+
+ /**
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -117,6 +117,8 @@ int fpga_mgr_firmware_load(struct fpga_m
+
+ struct fpga_manager *of_fpga_mgr_get(struct device_node *node);
+
++struct fpga_manager *fpga_mgr_get(struct device *dev);
++
+ void fpga_mgr_put(struct fpga_manager *mgr);
+
+ int fpga_mgr_register(struct device *dev, const char *name,
diff --git a/patches.socfpga/0026-doc-fpga-mgr-add-fpga-image-info-to-api.patch b/patches.socfpga/0026-doc-fpga-mgr-add-fpga-image-info-to-api.patch
new file mode 100644
index 0000000..f7b3d35
--- /dev/null
+++ b/patches.socfpga/0026-doc-fpga-mgr-add-fpga-image-info-to-api.patch
@@ -0,0 +1,110 @@
+From d4a7acc57d114fb9b54dd9dd9a21465393bb90e8 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:24 -0500
+Subject: [PATCH 026/103] doc: fpga-mgr: add fpga image info to api
+
+This patch adds a minor change in the FPGA Manager API
+to hold information that is specific to an FPGA image
+file. This change is expected to bring little, if any,
+pain.
+
+An FPGA image file will have particulars that affect how the
+image is programmed to the FPGA. One example is that
+current 'flags' currently has one bit which shows whether the
+FPGA image was built for full reconfiguration or partial
+reconfiguration. Another example is timeout values for
+enabling or disabling the bridges in the FPGA. As the
+complexity of the FPGA design increases, the bridges in the
+FPGA may take longer times to enable or disable.
+
+This patch documents the change in the FPGA Manager API
+functions, replacing the 'u32 flag' parameter with a pointer
+to struct fpga_image_info.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/fpga/fpga-mgr.txt | 34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+--- a/Documentation/fpga/fpga-mgr.txt
++++ b/Documentation/fpga/fpga-mgr.txt
+@@ -18,21 +18,25 @@ API Functions:
+ To program the FPGA from a file or from a buffer:
+ -------------------------------------------------
+
+- int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags,
++ int fpga_mgr_buf_load(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *buf, size_t count);
+
+ Load the FPGA from an image which exists as a buffer in memory.
+
+- int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
++ int fpga_mgr_firmware_load(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *image_name);
+
+ Load the FPGA from an image which exists as a file. The image file must be on
+-the firmware search path (see the firmware class documentation).
+-
+-For both these functions, flags == 0 for normal full reconfiguration or
+-FPGA_MGR_PARTIAL_RECONFIG for partial reconfiguration. If successful, the FPGA
+-ends up in operating mode. Return 0 on success or a negative error code.
+-
++the firmware search path (see the firmware class documentation). If successful,
++the FPGA ends up in operating mode. Return 0 on success or a negative error
++code.
++
++A FPGA design contained in a FPGA image file will likely have particulars that
++affect how the image is programmed to the FPGA. These are contained in struct
++fpga_image_info. Currently the only such particular is a single flag bit
++indicating whether the image is for full or partial reconfiguration.
+
+ To get/put a reference to a FPGA manager:
+ -----------------------------------------
+@@ -72,8 +76,11 @@ struct device_node *mgr_node = ...
+ char *buf = ...
+ int count = ...
+
++/* struct with information about the FPGA image to program. */
++struct fpga_image_info info;
++
+ /* flags indicates whether to do full or partial reconfiguration */
+-int flags = 0;
++info.flags = 0;
+
+ int ret;
+
+@@ -81,7 +88,7 @@ int ret;
+ struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node);
+
+ /* Load the buffer to the FPGA */
+-ret = fpga_mgr_buf_load(mgr, flags, buf, count);
++ret = fpga_mgr_buf_load(mgr, &info, buf, count);
+
+ /* Release the FPGA manager */
+ fpga_mgr_put(mgr);
+@@ -98,8 +105,11 @@ struct device_node *mgr_node = ...
+ /* FPGA image is in this file which is in the firmware search path */
+ const char *path = "fpga-image-9.rbf"
+
++/* struct with information about the FPGA image to program. */
++struct fpga_image_info info;
++
+ /* flags indicates whether to do full or partial reconfiguration */
+-int flags = 0;
++info.flags = 0;
+
+ int ret;
+
+@@ -107,7 +117,7 @@ int ret;
+ struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node);
+
+ /* Get the firmware image (path) and load it to the FPGA */
+-ret = fpga_mgr_firmware_load(mgr, flags, path);
++ret = fpga_mgr_firmware_load(mgr, &info, path);
+
+ /* Release the FPGA manager */
+ fpga_mgr_put(mgr);
diff --git a/patches.socfpga/0027-fpga-add-bindings-document-for-fpga-region.patch b/patches.socfpga/0027-fpga-add-bindings-document-for-fpga-region.patch
new file mode 100644
index 0000000..78d970c
--- /dev/null
+++ b/patches.socfpga/0027-fpga-add-bindings-document-for-fpga-region.patch
@@ -0,0 +1,514 @@
+From a3f533d02f5643af9679ef50d4a2ea24d4766924 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:25 -0500
+Subject: [PATCH 027/103] fpga: add bindings document for fpga region
+
+New bindings document for FPGA Region to support programming
+FPGA's under Device Tree control
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/fpga/fpga-region.txt | 494 +++++++++++++++++
+ 1 file changed, 494 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/fpga-region.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/fpga-region.txt
+@@ -0,0 +1,494 @@
++FPGA Region Device Tree Binding
++
++Alan Tull 2016
++
++ CONTENTS
++ - Introduction
++ - Terminology
++ - Sequence
++ - FPGA Region
++ - Supported Use Models
++ - Device Tree Examples
++ - Constraints
++
++
++Introduction
++============
++
++FPGA Regions represent FPGA's and partial reconfiguration regions of FPGA's in
++the Device Tree. FPGA Regions provide a way to program FPGAs under device tree
++control.
++
++This device tree binding document hits some of the high points of FPGA usage and
++attempts to include terminology used by both major FPGA manufacturers. This
++document isn't a replacement for any manufacturers specifications for FPGA
++usage.
++
++
++Terminology
++===========
++
++Full Reconfiguration
++ * The entire FPGA is programmed.
++
++Partial Reconfiguration (PR)
++ * A section of an FPGA is reprogrammed while the rest of the FPGA is not
++ affected.
++ * Not all FPGA's support PR.
++
++Partial Reconfiguration Region (PRR)
++ * Also called a "reconfigurable partition"
++ * A PRR is a specific section of a FPGA reserved for reconfiguration.
++ * A base (or static) FPGA image may create a set of PRR's that later may
++ be independently reprogrammed many times.
++ * The size and specific location of each PRR is fixed.
++ * The connections at the edge of each PRR are fixed. The image that is loaded
++ into a PRR must fit and must use a subset of the region's connections.
++ * The busses within the FPGA are split such that each region gets its own
++ branch that may be gated independently.
++
++Persona
++ * Also called a "partial bit stream"
++ * An FPGA image that is designed to be loaded into a PRR. There may be
++ any number of personas designed to fit into a PRR, but only one at at time
++ may be loaded.
++ * A persona may create more regions.
++
++FPGA Bridge
++ * FPGA Bridges gate bus signals between a host and FPGA.
++ * FPGA Bridges should be disabled while the FPGA is being programmed to
++ prevent spurious signals on the cpu bus and to the soft logic.
++ * FPGA bridges may be actual hardware or soft logic on an FPGA.
++ * During Full Reconfiguration, hardware bridges between the host and FPGA
++ will be disabled.
++ * During Partial Reconfiguration of a specific region, that region's bridge
++ will be used to gate the busses. Traffic to other regions is not affected.
++ * In some implementations, the FPGA Manager transparantly handles gating the
++ buses, eliminating the need to show the hardware FPGA bridges in the
++ device tree.
++ * An FPGA image may create a set of reprogrammable regions, each having its
++ own bridge and its own split of the busses in the FPGA.
++
++FPGA Manager
++ * An FPGA Manager is a hardware block that programs an FPGA under the control
++ of a host processor.
++
++Base Image
++ * Also called the "static image"
++ * An FPGA image that is designed to do full reconfiguration of the FPGA.
++ * A base image may set up a set of partial reconfiguration regions that may
++ later be reprogrammed.
++
++ ---------------- ----------------------------------
++ | Host CPU | | FPGA |
++ | | | |
++ | ----| | ----------- -------- |
++ | | H | | |==>| Bridge0 |<==>| PRR0 | |
++ | | W | | | ----------- -------- |
++ | | | | | |
++ | | B |<=====>|<==| ----------- -------- |
++ | | R | | |==>| Bridge1 |<==>| PRR1 | |
++ | | I | | | ----------- -------- |
++ | | D | | | |
++ | | G | | | ----------- -------- |
++ | | E | | |==>| Bridge2 |<==>| PRR2 | |
++ | ----| | ----------- -------- |
++ | | | |
++ ---------------- ----------------------------------
++
++Figure 1: An FPGA set up with a base image that created three regions. Each
++region (PRR0-2) gets its own split of the busses that is independently gated by
++a soft logic bridge (Bridge0-2) in the FPGA. The contents of each PRR can be
++reprogrammed independently while the rest of the system continues to function.
++
++
++Sequence
++========
++
++When a DT overlay that targets a FPGA Region is applied, the FPGA Region will
++do the following:
++
++ 1. Disable appropriate FPGA bridges.
++ 2. Program the FPGA using the FPGA manager.
++ 3. Enable the FPGA bridges.
++ 4. The Device Tree overlay is accepted into the live tree.
++ 5. Child devices are populated.
++
++When the overlay is removed, the child nodes will be removed and the FPGA Region
++will disable the bridges.
++
++
++FPGA Region
++===========
++
++FPGA Regions represent FPGA's and FPGA PR regions in the device tree. An FPGA
++Region brings together the elements needed to program on a running system and
++add the child devices:
++
++ * FPGA Manager
++ * FPGA Bridges
++ * image-specific information needed to to the programming.
++ * child nodes
++
++The intended use is that a Device Tree overlay (DTO) can be used to reprogram an
++FPGA while an operating system is running.
++
++An FPGA Region that exists in the live Device Tree reflects the current state.
++If the live tree shows a "firmware-name" property or child nodes under a FPGA
++Region, the FPGA already has been programmed. A DTO that targets a FPGA Region
++and adds the "firmware-name" property is taken as a request to reprogram the
++FPGA. After reprogramming is successful, the overlay is accepted into the live
++tree.
++
++The base FPGA Region in the device tree represents the FPGA and supports full
++reconfiguration. It must include a phandle to an FPGA Manager. The base
++FPGA region will be the child of one of the hardware bridges (the bridge that
++allows register access) between the cpu and the FPGA. If there are more than
++one bridge to control during FPGA programming, the region will also contain a
++list of phandles to the additional hardware FPGA Bridges.
++
++For partial reconfiguration (PR), each PR region will have an FPGA Region.
++These FPGA regions are children of FPGA bridges which are then children of the
++base FPGA region. The "Full Reconfiguration to add PRR's" example below shows
++this.
++
++If an FPGA Region does not specify a FPGA Manager, it will inherit the FPGA
++Manager specified by its ancestor FPGA Region. This supports both the case
++where the same FPGA Manager is used for all of a FPGA as well the case where
++a different FPGA Manager is used for each region.
++
++FPGA Regions do not inherit their ancestor FPGA regions' bridges. This prevents
++shutting down bridges that are upstream from the other active regions while one
++region is getting reconfigured (see Figure 1 above). During PR, the FPGA's
++hardware bridges remain enabled. The PR regions' bridges will be FPGA bridges
++within the static image of the FPGA.
++
++Required properties:
++- compatible : should contain "fpga-region"
++- fpga-mgr : should contain a phandle to an FPGA Manager. Child FPGA Regions
++ inherit this property from their ancestor regions. A fpga-mgr property
++ in a region will override any inherited FPGA manager.
++- #address-cells, #size-cells, ranges : must be present to handle address space
++ mapping for child nodes.
++
++Optional properties:
++- firmware-name : should contain the name of an FPGA image file located on the
++ firmware search path. If this property shows up in a live device tree
++ it indicates that the FPGA has already been programmed with this image.
++ If this property is in an overlay targeting a FPGA region, it is a
++ request to program the FPGA with that image.
++- fpga-bridges : should contain a list of phandles to FPGA Bridges that must be
++ controlled during FPGA programming along with the parent FPGA bridge.
++ This property is optional if the FPGA Manager handles the bridges.
++ If the fpga-region is the child of a fpga-bridge, the list should not
++ contain the parent bridge.
++- partial-fpga-config : boolean, set if partial reconfiguration is to be done,
++ otherwise full reconfiguration is done.
++- external-fpga-config : boolean, set if the FPGA has already been configured
++ prior to OS boot up.
++- region-unfreeze-timeout-us : The maximum time in microseconds to wait for
++ bridges to successfully become enabled after the region has been
++ programmed.
++- region-freeze-timeout-us : The maximum time in microseconds to wait for
++ bridges to successfully become disabled before the region has been
++ programmed.
++- child nodes : devices in the FPGA after programming.
++
++In the example below, when an overlay is applied targeting fpga-region0,
++fpga_mgr is used to program the FPGA. Two bridges are controlled during
++programming: the parent fpga_bridge0 and fpga_bridge1. Because the region is
++the child of fpga_bridge0, only fpga_bridge1 needs to be specified in the
++fpga-bridges property. During programming, these bridges are disabled, the
++firmware specified in the overlay is loaded to the FPGA using the FPGA manager
++specified in the region. If FPGA programming succeeds, the bridges are
++reenabled and the overlay makes it into the live device tree. The child devices
++are then populated. If FPGA programming fails, the bridges are left disabled
++and the overlay is rejected. The overlay's ranges property maps the lwhps
++bridge's region (0xff200000) and the hps bridge's region (0xc0000000) for use by
++the two child devices.
++
++Example:
++Base tree contains:
++
++ fpga_mgr: fpga-mgr@ff706000 {
++ compatible = "altr,socfpga-fpga-mgr";
++ reg = <0xff706000 0x1000
++ 0xffb90000 0x20>;
++ interrupts = <0 175 4>;
++ };
++
++ fpga_bridge0: fpga-bridge@ff400000 {
++ compatible = "altr,socfpga-lwhps2fpga-bridge";
++ reg = <0xff400000 0x100000>;
++ resets = <&rst LWHPS2FPGA_RESET>;
++ clocks = <&l4_main_clk>;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ fpga_region0: fpga-region0 {
++ compatible = "fpga-region";
++ fpga-mgr = <&fpga_mgr>;
++ };
++ };
++
++ fpga_bridge1: fpga-bridge@ff500000 {
++ compatible = "altr,socfpga-hps2fpga-bridge";
++ reg = <0xff500000 0x10000>;
++ resets = <&rst HPS2FPGA_RESET>;
++ clocks = <&l4_main_clk>;
++ };
++
++Overlay contains:
++
++/dts-v1/ /plugin/;
++/ {
++ fragment@0 {
++ target = <&fpga_region0>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ firmware-name = "soc_system.rbf";
++ fpga-bridges = <&fpga_bridge1>;
++ ranges = <0x20000 0xff200000 0x100000>,
++ <0x0 0xc0000000 0x20000000>;
++
++ gpio@10040 {
++ compatible = "altr,pio-1.0";
++ reg = <0x10040 0x20>;
++ altr,gpio-bank-width = <4>;
++ #gpio-cells = <2>;
++ clocks = <2>;
++ gpio-controller;
++ };
++
++ onchip-memory {
++ device_type = "memory";
++ compatible = "altr,onchipmem-15.1";
++ reg = <0x0 0x10000>;
++ };
++ };
++ };
++};
++
++
++Supported Use Models
++====================
++
++In all cases the live DT must have the FPGA Manager, FPGA Bridges (if any), and
++a FPGA Region. The target of the Device Tree Overlay is the FPGA Region. Some
++uses are specific to a FPGA device.
++
++ * No FPGA Bridges
++ In this case, the FPGA Manager which programs the FPGA also handles the
++ bridges behind the scenes. No FPGA Bridge devices are needed for full
++ reconfiguration.
++
++ * Full reconfiguration with hardware bridges
++ In this case, there are hardware bridges between the processor and FPGA that
++ need to be controlled during full reconfiguration. Before the overlay is
++ applied, the live DT must include the FPGA Manager, FPGA Bridges, and a
++ FPGA Region. The FPGA Region is the child of the bridge that allows
++ register access to the FPGA. Additional bridges may be listed in a
++ fpga-bridges property in the FPGA region or in the device tree overlay.
++
++ * Partial reconfiguration with bridges in the FPGA
++ In this case, the FPGA will have one or more PRR's that may be programmed
++ separately while the rest of the FPGA can remain active. To manage this,
++ bridges need to exist in the FPGA that can gate the buses going to each FPGA
++ region while the buses are enabled for other sections. Before any partial
++ reconfiguration can be done, a base FPGA image must be loaded which includes
++ PRR's with FPGA bridges. The device tree should have a FPGA region for each
++ PRR.
++
++Device Tree Examples
++====================
++
++The intention of this section is to give some simple examples, focusing on
++the placement of the elements detailed above, especially:
++ * FPGA Manager
++ * FPGA Bridges
++ * FPGA Region
++ * ranges
++ * target-path or target
++
++For the purposes of this section, I'm dividing the Device Tree into two parts,
++each with its own requirements. The two parts are:
++ * The live DT prior to the overlay being added
++ * The DT overlay
++
++The live Device Tree must contain an FPGA Region, an FPGA Manager, and any FPGA
++Bridges. The FPGA Region's "fpga-mgr" property specifies the manager by phandle
++to handle programming the FPGA. If the FPGA Region is the child of another FPGA
++Region, the parent's FPGA Manager is used. If FPGA Bridges need to be involved,
++they are specified in the FPGA Region by the "fpga-bridges" property. During
++FPGA programming, the FPGA Region will disable the bridges that are in its
++"fpga-bridges" list and will re-enable them after FPGA programming has
++succeeded.
++
++The Device Tree Overlay will contain:
++ * "target-path" or "target"
++ The insertion point where the the contents of the overlay will go into the
++ live tree. target-path is a full path, while target is a phandle.
++ * "ranges"
++ The address space mapping from processor to FPGA bus(ses).
++ * "firmware-name"
++ Specifies the name of the FPGA image file on the firmware search
++ path. The search path is described in the firmware class documentation.
++ * "partial-fpga-config"
++ This binding is a boolean and should be present if partial reconfiguration
++ is to be done.
++ * child nodes corresponding to hardware that will be loaded in this region of
++ the FPGA.
++
++Device Tree Example: Full Reconfiguration without Bridges
++=========================================================
++
++Live Device Tree contains:
++ fpga_mgr0: fpga-mgr@f8007000 {
++ compatible = "xlnx,zynq-devcfg-1.0";
++ reg = <0xf8007000 0x100>;
++ interrupt-parent = <&intc>;
++ interrupts = <0 8 4>;
++ clocks = <&clkc 12>;
++ clock-names = "ref_clk";
++ syscon = <&slcr>;
++ };
++
++ fpga_region0: fpga-region0 {
++ compatible = "fpga-region";
++ fpga-mgr = <&fpga_mgr0>;
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++ ranges;
++ };
++
++DT Overlay contains:
++/dts-v1/ /plugin/;
++/ {
++fragment@0 {
++ target = <&fpga_region0>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ firmware-name = "zynq-gpio.bin";
++
++ gpio1: gpio@40000000 {
++ compatible = "xlnx,xps-gpio-1.00.a";
++ reg = <0x40000000 0x10000>;
++ gpio-controller;
++ #gpio-cells = <0x2>;
++ xlnx,gpio-width= <0x6>;
++ };
++ };
++};
++
++Device Tree Example: Full Reconfiguration to add PRR's
++======================================================
++
++The base FPGA Region is specified similar to the first example above.
++
++This example programs the FPGA to have two regions that can later be partially
++configured. Each region has its own bridge in the FPGA fabric.
++
++DT Overlay contains:
++/dts-v1/ /plugin/;
++/ {
++ fragment@0 {
++ target = <&fpga_region0>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ firmware-name = "base.rbf";
++
++ fpga-bridge@4400 {
++ compatible = "altr,freeze-bridge";
++ reg = <0x4400 0x10>;
++
++ fpga_region1: fpga-region1 {
++ compatible = "fpga-region";
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++ ranges;
++ };
++ };
++
++ fpga-bridge@4420 {
++ compatible = "altr,freeze-bridge";
++ reg = <0x4420 0x10>;
++
++ fpga_region2: fpga-region2 {
++ compatible = "fpga-region";
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++ ranges;
++ };
++ };
++ };
++ };
++};
++
++Device Tree Example: Partial Reconfiguration
++============================================
++
++This example reprograms one of the PRR's set up in the previous example.
++
++The sequence that occurs when this overlay is similar to the above, the only
++differences are that the FPGA is partially reconfigured due to the
++"partial-fpga-config" boolean and the only bridge that is controlled during
++programming is the FPGA based bridge of fpga_region1.
++
++/dts-v1/ /plugin/;
++/ {
++ fragment@0 {
++ target = <&fpga_region1>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ firmware-name = "soc_image2.rbf";
++ partial-fpga-config;
++
++ gpio@10040 {
++ compatible = "altr,pio-1.0";
++ reg = <0x10040 0x20>;
++ clocks = <0x2>;
++ altr,gpio-bank-width = <0x4>;
++ resetvalue = <0x0>;
++ #gpio-cells = <0x2>;
++ gpio-controller;
++ };
++ };
++ };
++};
++
++Constraints
++===========
++
++It is beyond the scope of this document to fully describe all the FPGA design
++constraints required to make partial reconfiguration work[1] [2] [3], but a few
++deserve quick mention.
++
++A persona must have boundary connections that line up with those of the partion
++or region it is designed to go into.
++
++During programming, transactions through those connections must be stopped and
++the connections must be held at a fixed logic level. This can be achieved by
++FPGA Bridges that exist on the FPGA fabric prior to the partial reconfiguration.
++
++--
++[1] www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_partrecon.pdf
++[2] tspace.library.utoronto.ca/bitstream/1807/67932/1/Byma_Stuart_A_201411_MAS_thesis.pdf
++[3] http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_1/ug702.pdf
diff --git a/patches.socfpga/0028-fpga-mgr-add-fpga-image-information-struct.patch b/patches.socfpga/0028-fpga-mgr-add-fpga-image-information-struct.patch
new file mode 100644
index 0000000..c0283f5
--- /dev/null
+++ b/patches.socfpga/0028-fpga-mgr-add-fpga-image-information-struct.patch
@@ -0,0 +1,224 @@
+From dcc67124b4337a29ce04452a177953b3ff14b87a Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:26 -0500
+Subject: [PATCH 028/103] fpga-mgr: add fpga image information struct
+
+This patch adds a minor change in the FPGA Manager API
+to hold information that is specific to an FPGA image
+file. This change is expected to bring little, if any,
+pain. The socfpga and zynq drivers are fixed up in
+this patch.
+
+An FPGA image file will have particulars that affect how the
+image is programmed to the FPGA. One example is that
+current 'flags' currently has one bit which shows whether the
+FPGA image was built for full reconfiguration or partial
+reconfiguration. Another example is timeout values for
+enabling or disabling the bridges in the FPGA. As the
+complexity of the FPGA design increases, the bridges in the
+FPGA may take longer times to enable or disable.
+
+This patch adds a new 'struct fpga_image_info', moves the
+current 'u32 flags' to it. Two other image-specific u32's
+are added for the bridge enable/disable timeouts. The FPGA
+Manager API functions are changed, replacing the 'u32 flag'
+parameter with a pointer to struct fpga_image_info.
+Subsequent patches fix the existing low level FPGA manager
+drivers.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/fpga-mgr.c | 17 +++++++++--------
+ drivers/fpga/socfpga.c | 7 ++++---
+ drivers/fpga/zynq-fpga.c | 10 ++++++----
+ include/linux/fpga/fpga-mgr.h | 23 +++++++++++++++++++----
+ 4 files changed, 38 insertions(+), 19 deletions(-)
+
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -32,7 +32,7 @@ static struct class *fpga_mgr_class;
+ /**
+ * fpga_mgr_buf_load - load fpga from image in buffer
+ * @mgr: fpga manager
+- * @flags: flags setting fpga confuration modes
++ * @info: fpga image specific information
+ * @buf: buffer contain fpga image
+ * @count: byte count of buf
+ *
+@@ -44,8 +44,8 @@ static struct class *fpga_mgr_class;
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+-int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf,
+- size_t count)
++int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
++ const char *buf, size_t count)
+ {
+ struct device *dev = &mgr->dev;
+ int ret;
+@@ -56,7 +56,7 @@ int fpga_mgr_buf_load(struct fpga_manage
+ * ready to receive an FPGA image.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+- ret = mgr->mops->write_init(mgr, flags, buf, count);
++ ret = mgr->mops->write_init(mgr, info, buf, count);
+ if (ret) {
+ dev_err(dev, "Error preparing FPGA for writing\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+@@ -79,7 +79,7 @@ int fpga_mgr_buf_load(struct fpga_manage
+ * steps to finish and set the FPGA into operating mode.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+- ret = mgr->mops->write_complete(mgr, flags);
++ ret = mgr->mops->write_complete(mgr, info);
+ if (ret) {
+ dev_err(dev, "Error after writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+@@ -94,7 +94,7 @@ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
+ /**
+ * fpga_mgr_firmware_load - request firmware and load to fpga
+ * @mgr: fpga manager
+- * @flags: flags setting fpga confuration modes
++ * @info: fpga image specific information
+ * @image_name: name of image file on the firmware search path
+ *
+ * Request an FPGA image using the firmware class, then write out to the FPGA.
+@@ -105,7 +105,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+-int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
++int fpga_mgr_firmware_load(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *image_name)
+ {
+ struct device *dev = &mgr->dev;
+@@ -123,7 +124,7 @@ int fpga_mgr_firmware_load(struct fpga_m
+ return ret;
+ }
+
+- ret = fpga_mgr_buf_load(mgr, flags, fw->data, fw->size);
++ ret = fpga_mgr_buf_load(mgr, info, fw->data, fw->size);
+
+ release_firmware(fw);
+
+--- a/drivers/fpga/socfpga.c
++++ b/drivers/fpga/socfpga.c
+@@ -407,13 +407,14 @@ static int socfpga_fpga_reset(struct fpg
+ /*
+ * Prepare the FPGA to receive the configuration data.
+ */
+-static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr, u32 flags,
++static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *buf, size_t count)
+ {
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ int ret;
+
+- if (flags & FPGA_MGR_PARTIAL_RECONFIG) {
++ if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
+ dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
+ return -EINVAL;
+ }
+@@ -478,7 +479,7 @@ static int socfpga_fpga_ops_configure_wr
+ }
+
+ static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr,
+- u32 flags)
++ struct fpga_image_info *info)
+ {
+ struct socfpga_fpga_priv *priv = mgr->priv;
+ u32 status;
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -175,7 +175,8 @@ static irqreturn_t zynq_fpga_isr(int irq
+ return IRQ_HANDLED;
+ }
+
+-static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
++static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *buf, size_t count)
+ {
+ struct zynq_fpga_priv *priv;
+@@ -189,7 +190,7 @@ static int zynq_fpga_ops_write_init(stru
+ return err;
+
+ /* don't globally reset PL if we're doing partial reconfig */
+- if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
++ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ /* assert AXI interface resets */
+ regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
+ FPGA_RST_ALL_MASK);
+@@ -343,7 +344,8 @@ out_free:
+ return err;
+ }
+
+-static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr, u32 flags)
++static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
+ {
+ struct zynq_fpga_priv *priv = mgr->priv;
+ int err;
+@@ -364,7 +366,7 @@ static int zynq_fpga_ops_write_complete(
+ return err;
+
+ /* for the partial reconfig case we didn't touch the level shifters */
+- if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
++ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ /* enable level shifters from PL to PS */
+ regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
+ LVL_SHFTR_ENABLE_PL_TO_PS);
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -69,6 +69,18 @@ enum fpga_mgr_states {
+ #define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
+
+ /**
++ * struct fpga_image_info - information specific to a FPGA image
++ * @flags: boolean flags as defined above
++ * @enable_timeout_us: maximum time to enable traffic through bridge (uSec)
++ * @disable_timeout_us: maximum time to disable traffic through bridge (uSec)
++ */
++struct fpga_image_info {
++ u32 flags;
++ u32 enable_timeout_us;
++ u32 disable_timeout_us;
++};
++
++/**
+ * struct fpga_manager_ops - ops for low level fpga manager drivers
+ * @state: returns an enum value of the FPGA's state
+ * @write_init: prepare the FPGA to receive confuration data
+@@ -82,10 +94,12 @@ enum fpga_mgr_states {
+ */
+ struct fpga_manager_ops {
+ enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
+- int (*write_init)(struct fpga_manager *mgr, u32 flags,
++ int (*write_init)(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *buf, size_t count);
+ int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
+- int (*write_complete)(struct fpga_manager *mgr, u32 flags);
++ int (*write_complete)(struct fpga_manager *mgr,
++ struct fpga_image_info *info);
+ void (*fpga_remove)(struct fpga_manager *mgr);
+ };
+
+@@ -109,10 +123,11 @@ struct fpga_manager {
+
+ #define to_fpga_manager(d) container_of(d, struct fpga_manager, dev)
+
+-int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags,
++int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
+ const char *buf, size_t count);
+
+-int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
++int fpga_mgr_firmware_load(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
+ const char *image_name);
+
+ struct fpga_manager *of_fpga_mgr_get(struct device_node *node);
diff --git a/patches.socfpga/0029-add-sysfs-document-for-fpga-bridge-class.patch b/patches.socfpga/0029-add-sysfs-document-for-fpga-bridge-class.patch
new file mode 100644
index 0000000..9fe70d9
--- /dev/null
+++ b/patches.socfpga/0029-add-sysfs-document-for-fpga-bridge-class.patch
@@ -0,0 +1,29 @@
+From 61dfd4be91d2b0b62631b47d6fe2e775b97ca990 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:27 -0500
+Subject: [PATCH 029/103] add sysfs document for fpga bridge class
+
+Add documentation for new FPGA bridge class's sysfs interface.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/ABI/testing/sysfs-class-fpga-bridge | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-bridge
+
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-class-fpga-bridge
+@@ -0,0 +1,11 @@
++What: /sys/class/fpga_bridge/<bridge>/name
++Date: January 2016
++KernelVersion: 4.5
++Contact: Alan Tull <atull@opensource.altera.com>
++Description: Name of low level FPGA bridge driver.
++
++What: /sys/class/fpga_bridge/<bridge>/state
++Date: January 2016
++KernelVersion: 4.5
++Contact: Alan Tull <atull@opensource.altera.com>
++Description: Show bridge state as "enabled" or "disabled"
diff --git a/patches.socfpga/0030-fpga-add-fpga-bridge-framework.patch b/patches.socfpga/0030-fpga-add-fpga-bridge-framework.patch
new file mode 100644
index 0000000..5a582d3
--- /dev/null
+++ b/patches.socfpga/0030-fpga-add-fpga-bridge-framework.patch
@@ -0,0 +1,534 @@
+From 2649550bc9bf2246dfe843874012c7cf621bdfca Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:28 -0500
+Subject: [PATCH 030/103] fpga: add fpga bridge framework
+
+This framework adds API functions for enabling/
+disabling FPGA bridges under kernel control.
+
+This allows the Linux kernel to disable FPGA bridges
+during FPGA reprogramming and to enable FPGA bridges
+when FPGA reprogramming is done. This framework is
+be manufacturer-agnostic, allowing it to be used in
+interfaces that use the FPGA Manager Framework to
+reprogram FPGA's.
+
+The functions are:
+* of_fpga_bridge_get
+* fpga_bridge_put
+ Get/put an exclusive reference to a FPGA bridge.
+
+* fpga_bridge_enable
+* fpga_bridge_disable
+ Enable/Disable traffic through a bridge.
+
+* fpga_bridge_register
+* fpga_bridge_unregister
+ Register/unregister a device-specific low level FPGA
+ Bridge driver.
+
+Get an exclusive reference to a bridge and add it to a list:
+* fpga_bridge_get_to_list
+
+To enable/disable/put a set of bridges that are on a list:
+* fpga_bridges_enable
+* fpga_bridges_disable
+* fpga_bridges_put
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 7
+ drivers/fpga/Makefile | 3
+ drivers/fpga/fpga-bridge.c | 395 +++++++++++++++++++++++++++++++++++++++
+ include/linux/fpga/fpga-bridge.h | 60 +++++
+ 4 files changed, 465 insertions(+)
+ create mode 100644 drivers/fpga/fpga-bridge.c
+ create mode 100644 include/linux/fpga/fpga-bridge.h
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -26,6 +26,13 @@ config FPGA_MGR_ZYNQ_FPGA
+ help
+ FPGA manager driver support for Xilinx Zynq FPGAs.
+
++config FPGA_BRIDGE
++ tristate "FPGA Bridge Framework"
++ depends on OF
++ help
++ Say Y here if you want to support bridges connected between host
++ processors and FPGAs or between FPGAs.
++
+ endif # FPGA
+
+ endmenu
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -8,3 +8,6 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o
+ # FPGA Manager Drivers
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
+ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
++
++# FPGA Bridge Drivers
++obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
+--- /dev/null
++++ b/drivers/fpga/fpga-bridge.c
+@@ -0,0 +1,395 @@
++/*
++ * FPGA Bridge Framework Driver
++ *
++ * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/fpga/fpga-bridge.h>
++#include <linux/idr.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++
++static DEFINE_IDA(fpga_bridge_ida);
++static struct class *fpga_bridge_class;
++
++/* Lock for adding/removing bridges to linked lists*/
++spinlock_t bridge_list_lock;
++
++static int fpga_bridge_of_node_match(struct device *dev, const void *data)
++{
++ return dev->of_node == data;
++}
++
++/**
++ * fpga_bridge_enable - Enable transactions on the bridge
++ *
++ * @bridge: FPGA bridge
++ *
++ * Return: 0 for success, error code otherwise.
++ */
++int fpga_bridge_enable(struct fpga_bridge *bridge)
++{
++ dev_dbg(&bridge->dev, "enable\n");
++
++ if (bridge->br_ops && bridge->br_ops->enable_set)
++ return bridge->br_ops->enable_set(bridge, 1);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(fpga_bridge_enable);
++
++/**
++ * fpga_bridge_disable - Disable transactions on the bridge
++ *
++ * @bridge: FPGA bridge
++ *
++ * Return: 0 for success, error code otherwise.
++ */
++int fpga_bridge_disable(struct fpga_bridge *bridge)
++{
++ dev_dbg(&bridge->dev, "disable\n");
++
++ if (bridge->br_ops && bridge->br_ops->enable_set)
++ return bridge->br_ops->enable_set(bridge, 0);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(fpga_bridge_disable);
++
++/**
++ * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
++ *
++ * @np: node pointer of a FPGA bridge
++ * @info: fpga image specific information
++ *
++ * Return fpga_bridge struct if successful.
++ * Return -EBUSY if someone already has a reference to the bridge.
++ * Return -ENODEV if @np is not a FPGA Bridge.
++ */
++struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
++ struct fpga_image_info *info)
++
++{
++ struct device *dev;
++ struct fpga_bridge *bridge;
++ int ret = -ENODEV;
++
++ dev = class_find_device(fpga_bridge_class, NULL, np,
++ fpga_bridge_of_node_match);
++ if (!dev)
++ goto err_dev;
++
++ bridge = to_fpga_bridge(dev);
++ if (!bridge)
++ goto err_dev;
++
++ bridge->info = info;
++
++ if (!mutex_trylock(&bridge->mutex)) {
++ ret = -EBUSY;
++ goto err_dev;
++ }
++
++ if (!try_module_get(dev->parent->driver->owner))
++ goto err_ll_mod;
++
++ dev_dbg(&bridge->dev, "get\n");
++
++ return bridge;
++
++err_ll_mod:
++ mutex_unlock(&bridge->mutex);
++err_dev:
++ put_device(dev);
++ return ERR_PTR(ret);
++}
++EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
++
++/**
++ * fpga_bridge_put - release a reference to a bridge
++ *
++ * @bridge: FPGA bridge
++ */
++void fpga_bridge_put(struct fpga_bridge *bridge)
++{
++ dev_dbg(&bridge->dev, "put\n");
++
++ bridge->info = NULL;
++ module_put(bridge->dev.parent->driver->owner);
++ mutex_unlock(&bridge->mutex);
++ put_device(&bridge->dev);
++}
++EXPORT_SYMBOL_GPL(fpga_bridge_put);
++
++/**
++ * fpga_bridges_enable - enable bridges in a list
++ * @bridge_list: list of FPGA bridges
++ *
++ * Enable each bridge in the list. If list is empty, do nothing.
++ *
++ * Return 0 for success or empty bridge list; return error code otherwise.
++ */
++int fpga_bridges_enable(struct list_head *bridge_list)
++{
++ struct fpga_bridge *bridge;
++ struct list_head *node;
++ int ret;
++
++ list_for_each(node, bridge_list) {
++ bridge = list_entry(node, struct fpga_bridge, node);
++ ret = fpga_bridge_enable(bridge);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(fpga_bridges_enable);
++
++/**
++ * fpga_bridges_disable - disable bridges in a list
++ *
++ * @bridge_list: list of FPGA bridges
++ *
++ * Disable each bridge in the list. If list is empty, do nothing.
++ *
++ * Return 0 for success or empty bridge list; return error code otherwise.
++ */
++int fpga_bridges_disable(struct list_head *bridge_list)
++{
++ struct fpga_bridge *bridge;
++ struct list_head *node;
++ int ret;
++
++ list_for_each(node, bridge_list) {
++ bridge = list_entry(node, struct fpga_bridge, node);
++ ret = fpga_bridge_disable(bridge);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(fpga_bridges_disable);
++
++/**
++ * fpga_bridges_put - put bridges
++ *
++ * @bridge_list: list of FPGA bridges
++ *
++ * For each bridge in the list, put the bridge and remove it from the list.
++ * If list is empty, do nothing.
++ */
++void fpga_bridges_put(struct list_head *bridge_list)
++{
++ struct fpga_bridge *bridge;
++ struct list_head *node, *next;
++ unsigned long flags;
++
++ list_for_each_safe(node, next, bridge_list) {
++ bridge = list_entry(node, struct fpga_bridge, node);
++
++ fpga_bridge_put(bridge);
++
++ spin_lock_irqsave(&bridge_list_lock, flags);
++ list_del(&bridge->node);
++ spin_unlock_irqrestore(&bridge_list_lock, flags);
++ }
++}
++EXPORT_SYMBOL_GPL(fpga_bridges_put);
++
++/**
++ * fpga_bridges_get_to_list - get a bridge, add it to a list
++ *
++ * @np: node pointer of a FPGA bridge
++ * @info: fpga image specific information
++ * @bridge_list: list of FPGA bridges
++ *
++ * Get an exclusive reference to the bridge and and it to the list.
++ *
++ * Return 0 for success, error code from of_fpga_bridge_get() othewise.
++ */
++int fpga_bridge_get_to_list(struct device_node *np,
++ struct fpga_image_info *info,
++ struct list_head *bridge_list)
++{
++ struct fpga_bridge *bridge;
++ unsigned long flags;
++
++ bridge = of_fpga_bridge_get(np, info);
++ if (IS_ERR(bridge))
++ return PTR_ERR(bridge);
++
++ spin_lock_irqsave(&bridge_list_lock, flags);
++ list_add(&bridge->node, bridge_list);
++ spin_unlock_irqrestore(&bridge_list_lock, flags);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
++
++static ssize_t name_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fpga_bridge *bridge = to_fpga_bridge(dev);
++
++ return sprintf(buf, "%s\n", bridge->name);
++}
++
++static ssize_t state_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct fpga_bridge *bridge = to_fpga_bridge(dev);
++ int enable = 1;
++
++ if (bridge->br_ops && bridge->br_ops->enable_show)
++ enable = bridge->br_ops->enable_show(bridge);
++
++ return sprintf(buf, "%s\n", enable ? "enabled" : "disabled");
++}
++
++static DEVICE_ATTR_RO(name);
++static DEVICE_ATTR_RO(state);
++
++static struct attribute *fpga_bridge_attrs[] = {
++ &dev_attr_name.attr,
++ &dev_attr_state.attr,
++ NULL,
++};
++ATTRIBUTE_GROUPS(fpga_bridge);
++
++/**
++ * fpga_bridge_register - register a fpga bridge driver
++ * @dev: FPGA bridge device from pdev
++ * @name: FPGA bridge name
++ * @br_ops: pointer to structure of fpga bridge ops
++ * @priv: FPGA bridge private data
++ *
++ * Return: 0 for success, error code otherwise.
++ */
++int fpga_bridge_register(struct device *dev, const char *name,
++ const struct fpga_bridge_ops *br_ops, void *priv)
++{
++ struct fpga_bridge *bridge;
++ int id, ret = 0;
++
++ if (!name || !strlen(name)) {
++ dev_err(dev, "Attempt to register with no name!\n");
++ return -EINVAL;
++ }
++
++ bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
++ if (!bridge)
++ return -ENOMEM;
++
++ id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
++ if (id < 0) {
++ ret = id;
++ goto error_kfree;
++ }
++
++ mutex_init(&bridge->mutex);
++ INIT_LIST_HEAD(&bridge->node);
++
++ bridge->name = name;
++ bridge->br_ops = br_ops;
++ bridge->priv = priv;
++
++ device_initialize(&bridge->dev);
++ bridge->dev.class = fpga_bridge_class;
++ bridge->dev.parent = dev;
++ bridge->dev.of_node = dev->of_node;
++ bridge->dev.id = id;
++ dev_set_drvdata(dev, bridge);
++
++ ret = dev_set_name(&bridge->dev, "br%d", id);
++ if (ret)
++ goto error_device;
++
++ ret = device_add(&bridge->dev);
++ if (ret)
++ goto error_device;
++
++ of_platform_populate(dev->of_node, NULL, NULL, dev);
++
++ dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
++ bridge->name);
++
++ return 0;
++
++error_device:
++ ida_simple_remove(&fpga_bridge_ida, id);
++error_kfree:
++ kfree(bridge);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(fpga_bridge_register);
++
++/**
++ * fpga_bridge_unregister - unregister a fpga bridge driver
++ * @dev: FPGA bridge device from pdev
++ */
++void fpga_bridge_unregister(struct device *dev)
++{
++ struct fpga_bridge *bridge = dev_get_drvdata(dev);
++
++ /*
++ * If the low level driver provides a method for putting bridge into
++ * a desired state upon unregister, do it.
++ */
++ if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)
++ bridge->br_ops->fpga_bridge_remove(bridge);
++
++ device_unregister(&bridge->dev);
++}
++EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
++
++static void fpga_bridge_dev_release(struct device *dev)
++{
++ struct fpga_bridge *bridge = to_fpga_bridge(dev);
++
++ ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
++ kfree(bridge);
++}
++
++static int __init fpga_bridge_dev_init(void)
++{
++ spin_lock_init(&bridge_list_lock);
++
++ fpga_bridge_class = class_create(THIS_MODULE, "fpga_bridge");
++ if (IS_ERR(fpga_bridge_class))
++ return PTR_ERR(fpga_bridge_class);
++
++ fpga_bridge_class->dev_groups = fpga_bridge_groups;
++ fpga_bridge_class->dev_release = fpga_bridge_dev_release;
++
++ return 0;
++}
++
++static void __exit fpga_bridge_dev_exit(void)
++{
++ class_destroy(fpga_bridge_class);
++ ida_destroy(&fpga_bridge_ida);
++}
++
++MODULE_DESCRIPTION("FPGA Bridge Driver");
++MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
++MODULE_LICENSE("GPL v2");
++
++subsys_initcall(fpga_bridge_dev_init);
++module_exit(fpga_bridge_dev_exit);
+--- /dev/null
++++ b/include/linux/fpga/fpga-bridge.h
+@@ -0,0 +1,60 @@
++#include <linux/device.h>
++#include <linux/fpga/fpga-mgr.h>
++
++#ifndef _LINUX_FPGA_BRIDGE_H
++#define _LINUX_FPGA_BRIDGE_H
++
++struct fpga_bridge;
++
++/**
++ * struct fpga_bridge_ops - ops for low level FPGA bridge drivers
++ * @enable_show: returns the FPGA bridge's status
++ * @enable_set: set a FPGA bridge as enabled or disabled
++ * @fpga_bridge_remove: set FPGA into a specific state during driver remove
++ */
++struct fpga_bridge_ops {
++ int (*enable_show)(struct fpga_bridge *bridge);
++ int (*enable_set)(struct fpga_bridge *bridge, bool enable);
++ void (*fpga_bridge_remove)(struct fpga_bridge *bridge);
++};
++
++/**
++ * struct fpga_bridge - FPGA bridge structure
++ * @name: name of low level FPGA bridge
++ * @dev: FPGA bridge device
++ * @mutex: enforces exclusive reference to bridge
++ * @br_ops: pointer to struct of FPGA bridge ops
++ * @info: fpga image specific information
++ * @node: FPGA bridge list node
++ * @priv: low level driver private date
++ */
++struct fpga_bridge {
++ const char *name;
++ struct device dev;
++ struct mutex mutex; /* for exclusive reference to bridge */
++ const struct fpga_bridge_ops *br_ops;
++ struct fpga_image_info *info;
++ struct list_head node;
++ void *priv;
++};
++
++#define to_fpga_bridge(d) container_of(d, struct fpga_bridge, dev)
++
++struct fpga_bridge *of_fpga_bridge_get(struct device_node *node,
++ struct fpga_image_info *info);
++void fpga_bridge_put(struct fpga_bridge *bridge);
++int fpga_bridge_enable(struct fpga_bridge *bridge);
++int fpga_bridge_disable(struct fpga_bridge *bridge);
++
++int fpga_bridges_enable(struct list_head *bridge_list);
++int fpga_bridges_disable(struct list_head *bridge_list);
++void fpga_bridges_put(struct list_head *bridge_list);
++int fpga_bridge_get_to_list(struct device_node *np,
++ struct fpga_image_info *info,
++ struct list_head *bridge_list);
++
++int fpga_bridge_register(struct device *dev, const char *name,
++ const struct fpga_bridge_ops *br_ops, void *priv);
++void fpga_bridge_unregister(struct device *dev);
++
++#endif /* _LINUX_FPGA_BRIDGE_H */
diff --git a/patches.socfpga/0031-fpga-fpga-region-device-tree-control-for-FPGA.patch b/patches.socfpga/0031-fpga-fpga-region-device-tree-control-for-FPGA.patch
new file mode 100644
index 0000000..e69a9ba
--- /dev/null
+++ b/patches.socfpga/0031-fpga-fpga-region-device-tree-control-for-FPGA.patch
@@ -0,0 +1,662 @@
+From 1959ad1708f7ec01af7377787b9e117e2eae61f8 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:29 -0500
+Subject: [PATCH 031/103] fpga: fpga-region: device tree control for FPGA
+
+FPGA Regions support programming FPGA under control of the Device
+Tree.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 7
+ drivers/fpga/Makefile | 3
+ drivers/fpga/fpga-region.c | 603 ++++++++++++++++++++++++++++++++++++++++++
+ include/linux/fpga/fpga-mgr.h | 2
+ 4 files changed, 615 insertions(+)
+ create mode 100644 drivers/fpga/fpga-region.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -13,6 +13,13 @@ config FPGA
+
+ if FPGA
+
++config FPGA_REGION
++ tristate "FPGA Region"
++ depends on OF && FPGA_BRIDGE
++ help
++ FPGA Regions allow loading FPGA images under control of
++ the Device Tree.
++
+ config FPGA_MGR_SOCFPGA
+ tristate "Altera SOCFPGA FPGA Manager"
+ depends on ARCH_SOCFPGA
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -11,3 +11,6 @@ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq
+
+ # FPGA Bridge Drivers
+ obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
++
++# High Level Interfaces
++obj-$(CONFIG_FPGA_REGION) += fpga-region.o
+--- /dev/null
++++ b/drivers/fpga/fpga-region.c
+@@ -0,0 +1,603 @@
++/*
++ * FPGA Region - Device Tree support for FPGA programming under Linux
++ *
++ * Copyright (C) 2013-2016 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/fpga/fpga-bridge.h>
++#include <linux/fpga/fpga-mgr.h>
++#include <linux/idr.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++
++/**
++ * struct fpga_region - FPGA Region structure
++ * @dev: FPGA Region device
++ * @mutex: enforces exclusive reference to region
++ * @bridge_list: list of FPGA bridges specified in region
++ * @info: fpga image specific information
++ */
++struct fpga_region {
++ struct device dev;
++ struct mutex mutex; /* for exclusive reference to region */
++ struct list_head bridge_list;
++ struct fpga_image_info *info;
++};
++
++#define to_fpga_region(d) container_of(d, struct fpga_region, dev)
++
++static DEFINE_IDA(fpga_region_ida);
++static struct class *fpga_region_class;
++
++static const struct of_device_id fpga_region_of_match[] = {
++ { .compatible = "fpga-region", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, fpga_region_of_match);
++
++static int fpga_region_of_node_match(struct device *dev, const void *data)
++{
++ return dev->of_node == data;
++}
++
++/**
++ * fpga_region_find - find FPGA region
++ * @np: device node of FPGA Region
++ * Caller will need to put_device(®ion->dev) when done.
++ * Returns FPGA Region struct or NULL
++ */
++static struct fpga_region *fpga_region_find(struct device_node *np)
++{
++ struct device *dev;
++
++ dev = class_find_device(fpga_region_class, NULL, np,
++ fpga_region_of_node_match);
++ if (!dev)
++ return NULL;
++
++ return to_fpga_region(dev);
++}
++
++/**
++ * fpga_region_get - get an exclusive reference to a fpga region
++ * @region: FPGA Region struct
++ *
++ * Caller should call fpga_region_put() when done with region.
++ *
++ * Return fpga_region struct if successful.
++ * Return -EBUSY if someone already has a reference to the region.
++ * Return -ENODEV if @np is not a FPGA Region.
++ */
++static struct fpga_region *fpga_region_get(struct fpga_region *region)
++{
++ struct device *dev = ®ion->dev;
++
++ if (!mutex_trylock(®ion->mutex)) {
++ dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
++ return ERR_PTR(-EBUSY);
++ }
++
++ get_device(dev);
++ of_node_get(dev->of_node);
++ if (!try_module_get(dev->parent->driver->owner)) {
++ of_node_put(dev->of_node);
++ put_device(dev);
++ mutex_unlock(®ion->mutex);
++ return ERR_PTR(-ENODEV);
++ }
++
++ dev_dbg(®ion->dev, "get\n");
++
++ return region;
++}
++
++/**
++ * fpga_region_put - release a reference to a region
++ *
++ * @region: FPGA region
++ */
++static void fpga_region_put(struct fpga_region *region)
++{
++ struct device *dev = ®ion->dev;
++
++ dev_dbg(®ion->dev, "put\n");
++
++ module_put(dev->parent->driver->owner);
++ of_node_put(dev->of_node);
++ put_device(dev);
++ mutex_unlock(®ion->mutex);
++}
++
++/**
++ * fpga_region_get_manager - get exclusive reference for FPGA manager
++ * @region: FPGA region
++ *
++ * Get FPGA Manager from "fpga-mgr" property or from ancestor region.
++ *
++ * Caller should call fpga_mgr_put() when done with manager.
++ *
++ * Return: fpga manager struct or IS_ERR() condition containing error code.
++ */
++static struct fpga_manager *fpga_region_get_manager(struct fpga_region *region)
++{
++ struct device *dev = ®ion->dev;
++ struct device_node *np = dev->of_node;
++ struct device_node *mgr_node;
++ struct fpga_manager *mgr;
++
++ of_node_get(np);
++ while (np) {
++ if (of_device_is_compatible(np, "fpga-region")) {
++ mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
++ if (mgr_node) {
++ mgr = of_fpga_mgr_get(mgr_node);
++ of_node_put(np);
++ return mgr;
++ }
++ }
++ np = of_get_next_parent(np);
++ }
++ of_node_put(np);
++
++ return ERR_PTR(-EINVAL);
++}
++
++/**
++ * fpga_region_get_bridges - create a list of bridges
++ * @region: FPGA region
++ * @overlay: device node of the overlay
++ *
++ * Create a list of bridges including the parent bridge and the bridges
++ * specified by "fpga-bridges" property. Note that the
++ * fpga_bridges_enable/disable/put functions are all fine with an empty list
++ * if that happens.
++ *
++ * Caller should call fpga_bridges_put(®ion->bridge_list) when
++ * done with the bridges.
++ *
++ * Return 0 for success (even if there are no bridges specified)
++ * or -EBUSY if any of the bridges are in use.
++ */
++static int fpga_region_get_bridges(struct fpga_region *region,
++ struct device_node *overlay)
++{
++ struct device *dev = ®ion->dev;
++ struct device_node *region_np = dev->of_node;
++ struct device_node *br, *np, *parent_br = NULL;
++ int i, ret;
++
++ /* If parent is a bridge, add to list */
++ ret = fpga_bridge_get_to_list(region_np->parent, region->info,
++ ®ion->bridge_list);
++ if (ret == -EBUSY)
++ return ret;
++
++ if (!ret)
++ parent_br = region_np->parent;
++
++ /* If overlay has a list of bridges, use it. */
++ if (of_parse_phandle(overlay, "fpga-bridges", 0))
++ np = overlay;
++ else
++ np = region_np;
++
++ for (i = 0; ; i++) {
++ br = of_parse_phandle(np, "fpga-bridges", i);
++ if (!br)
++ break;
++
++ /* If parent bridge is in list, skip it. */
++ if (br == parent_br)
++ continue;
++
++ /* If node is a bridge, get it and add to list */
++ ret = fpga_bridge_get_to_list(br, region->info,
++ ®ion->bridge_list);
++
++ /* If any of the bridges are in use, give up */
++ if (ret == -EBUSY) {
++ fpga_bridges_put(®ion->bridge_list);
++ return -EBUSY;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * fpga_region_program_fpga - program FPGA
++ * @region: FPGA region
++ * @firmware_name: name of FPGA image firmware file
++ * @overlay: device node of the overlay
++ * Program an FPGA using information in the device tree.
++ * Function assumes that there is a firmware-name property.
++ * Return 0 for success or negative error code.
++ */
++static int fpga_region_program_fpga(struct fpga_region *region,
++ const char *firmware_name,
++ struct device_node *overlay)
++{
++ struct fpga_manager *mgr;
++ int ret;
++
++ region = fpga_region_get(region);
++ if (IS_ERR(region)) {
++ pr_err("failed to get fpga region\n");
++ return PTR_ERR(region);
++ }
++
++ mgr = fpga_region_get_manager(region);
++ if (IS_ERR(mgr)) {
++ pr_err("failed to get fpga region manager\n");
++ return PTR_ERR(mgr);
++ }
++
++ ret = fpga_region_get_bridges(region, overlay);
++ if (ret) {
++ pr_err("failed to get fpga region bridges\n");
++ goto err_put_mgr;
++ }
++
++ ret = fpga_bridges_disable(®ion->bridge_list);
++ if (ret) {
++ pr_err("failed to disable region bridges\n");
++ goto err_put_br;
++ }
++
++ ret = fpga_mgr_firmware_load(mgr, region->info, firmware_name);
++ if (ret) {
++ pr_err("failed to load fpga image\n");
++ goto err_put_br;
++ }
++
++ ret = fpga_bridges_enable(®ion->bridge_list);
++ if (ret) {
++ pr_err("failed to enable region bridges\n");
++ goto err_put_br;
++ }
++
++ fpga_mgr_put(mgr);
++ fpga_region_put(region);
++
++ return 0;
++
++err_put_br:
++ fpga_bridges_put(®ion->bridge_list);
++err_put_mgr:
++ fpga_mgr_put(mgr);
++ fpga_region_put(region);
++
++ return ret;
++}
++
++/**
++ * child_regions_with_firmware
++ * @overlay: device node of the overlay
++ *
++ * If the overlay adds child FPGA regions, they are not allowed to have
++ * firmware-name property.
++ *
++ * Return 0 for OK or -EINVAL if child FPGA region adds firmware-name.
++ */
++static int child_regions_with_firmware(struct device_node *overlay)
++{
++ struct device_node *child_region;
++ const char *child_firmware_name;
++ int ret = 0;
++
++ of_node_get(overlay);
++
++ child_region = of_find_matching_node(overlay, fpga_region_of_match);
++ while (child_region) {
++ if (!of_property_read_string(child_region, "firmware-name",
++ &child_firmware_name)) {
++ ret = -EINVAL;
++ break;
++ }
++ child_region = of_find_matching_node(child_region,
++ fpga_region_of_match);
++ }
++
++ of_node_put(child_region);
++
++ if (ret)
++ pr_err("firmware-name not allowed in child FPGA region: %s",
++ child_region->full_name);
++
++ return ret;
++}
++
++/**
++ * fpga_region_notify_pre_apply - pre-apply overlay notification
++ *
++ * @region: FPGA region that the overlay was applied to
++ * @nd: overlay notification data
++ *
++ * Called after when an overlay targeted to a FPGA Region is about to be
++ * applied. Function will check the properties that will be added to the FPGA
++ * region. If the checks pass, it will program the FPGA.
++ *
++ * The checks are:
++ * The overlay must add either firmware-name or external-fpga-config property
++ * to the FPGA Region.
++ *
++ * firmware-name : program the FPGA
++ * external-fpga-config : FPGA is already programmed
++ *
++ * The overlay can add other FPGA regions, but child FPGA regions cannot have a
++ * firmware-name property since those regions don't exist yet.
++ *
++ * If the overlay that breaks the rules, notifier returns an error and the
++ * overlay is rejected before it goes into the main tree.
++ *
++ * Returns 0 for success or negative error code for failure.
++ */
++static int fpga_region_notify_pre_apply(struct fpga_region *region,
++ struct of_overlay_notify_data *nd)
++{
++ const char *firmware_name = NULL;
++ struct fpga_image_info *info;
++ int ret;
++
++ info = devm_kzalloc(®ion->dev, sizeof(*info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ region->info = info;
++
++ /* Reject overlay if child FPGA Regions have firmware-name property */
++ ret = child_regions_with_firmware(nd->overlay);
++ if (ret)
++ return ret;
++
++ /* Read FPGA region properties from the overlay */
++ if (of_property_read_bool(nd->overlay, "partial-fpga-config"))
++ info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
++
++ if (of_property_read_bool(nd->overlay, "external-fpga-config"))
++ info->flags |= FPGA_MGR_EXTERNAL_CONFIG;
++
++ of_property_read_string(nd->overlay, "firmware-name", &firmware_name);
++
++ of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us",
++ &info->enable_timeout_us);
++
++ of_property_read_u32(nd->overlay, "region-freeze-timeout-us",
++ &info->disable_timeout_us);
++
++ /* If FPGA was externally programmed, don't specify firmware */
++ if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && firmware_name) {
++ pr_err("error: specified firmware and external-fpga-config");
++ return -EINVAL;
++ }
++
++ /* FPGA is already configured externally. We're done. */
++ if (info->flags & FPGA_MGR_EXTERNAL_CONFIG)
++ return 0;
++
++ /* If we got this far, we should be programming the FPGA */
++ if (!firmware_name) {
++ pr_err("should specify firmware-name or external-fpga-config\n");
++ return -EINVAL;
++ }
++
++ return fpga_region_program_fpga(region, firmware_name, nd->overlay);
++}
++
++/**
++ * fpga_region_notify_post_remove - post-remove overlay notification
++ *
++ * @region: FPGA region that was targeted by the overlay that was removed
++ * @nd: overlay notification data
++ *
++ * Called after an overlay has been removed if the overlay's target was a
++ * FPGA region.
++ */
++static void fpga_region_notify_post_remove(struct fpga_region *region,
++ struct of_overlay_notify_data *nd)
++{
++ fpga_bridges_disable(®ion->bridge_list);
++ fpga_bridges_put(®ion->bridge_list);
++ devm_kfree(®ion->dev, region->info);
++ region->info = NULL;
++}
++
++/**
++ * of_fpga_region_notify - reconfig notifier for dynamic DT changes
++ * @nb: notifier block
++ * @action: notifier action
++ * @arg: reconfig data
++ *
++ * This notifier handles programming a FPGA when a "firmware-name" property is
++ * added to a fpga-region.
++ *
++ * Returns NOTIFY_OK or error if FPGA programming fails.
++ */
++static int of_fpga_region_notify(struct notifier_block *nb,
++ unsigned long action, void *arg)
++{
++ struct of_overlay_notify_data *nd = arg;
++ struct fpga_region *region;
++ int ret;
++
++ switch (action) {
++ case OF_OVERLAY_PRE_APPLY:
++ pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__);
++ break;
++ case OF_OVERLAY_POST_APPLY:
++ pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__);
++ return NOTIFY_OK; /* not for us */
++ case OF_OVERLAY_PRE_REMOVE:
++ pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__);
++ return NOTIFY_OK; /* not for us */
++ case OF_OVERLAY_POST_REMOVE:
++ pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__);
++ break;
++ default: /* should not happen */
++ return NOTIFY_OK;
++ }
++
++ region = fpga_region_find(nd->target);
++ if (!region)
++ return NOTIFY_OK;
++
++ ret = 0;
++ switch (action) {
++ case OF_OVERLAY_PRE_APPLY:
++ ret = fpga_region_notify_pre_apply(region, nd);
++ break;
++
++ case OF_OVERLAY_POST_REMOVE:
++ fpga_region_notify_post_remove(region, nd);
++ break;
++ }
++
++ put_device(®ion->dev);
++
++ if (ret)
++ return notifier_from_errno(ret);
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block fpga_region_of_nb = {
++ .notifier_call = of_fpga_region_notify,
++};
++
++static int fpga_region_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct fpga_region *region;
++ int id, ret = 0;
++
++ region = kzalloc(sizeof(*region), GFP_KERNEL);
++ if (!region)
++ return -ENOMEM;
++
++ id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
++ if (id < 0) {
++ ret = id;
++ goto err_kfree;
++ }
++
++ mutex_init(®ion->mutex);
++ INIT_LIST_HEAD(®ion->bridge_list);
++
++ device_initialize(®ion->dev);
++ region->dev.class = fpga_region_class;
++ region->dev.parent = dev;
++ region->dev.of_node = np;
++ region->dev.id = id;
++ dev_set_drvdata(dev, region);
++
++ ret = dev_set_name(®ion->dev, "region%d", id);
++ if (ret)
++ goto err_remove;
++
++ ret = device_add(®ion->dev);
++ if (ret)
++ goto err_remove;
++
++ of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev);
++
++ dev_info(dev, "FPGA Region probed\n");
++
++ return 0;
++
++err_remove:
++ ida_simple_remove(&fpga_region_ida, id);
++err_kfree:
++ kfree(region);
++
++ return ret;
++}
++
++static int fpga_region_remove(struct platform_device *pdev)
++{
++ struct fpga_region *region = platform_get_drvdata(pdev);
++
++ device_unregister(®ion->dev);
++
++ return 0;
++}
++
++static struct platform_driver fpga_region_driver = {
++ .probe = fpga_region_probe,
++ .remove = fpga_region_remove,
++ .driver = {
++ .name = "fpga-region",
++ .of_match_table = of_match_ptr(fpga_region_of_match),
++ },
++};
++
++static void fpga_region_dev_release(struct device *dev)
++{
++ struct fpga_region *region = to_fpga_region(dev);
++
++ ida_simple_remove(&fpga_region_ida, region->dev.id);
++ kfree(region);
++}
++
++/**
++ * fpga_region_init - init function for fpga_region class
++ * Creates the fpga_region class and registers a reconfig notifier.
++ */
++static int __init fpga_region_init(void)
++{
++ int ret;
++
++ fpga_region_class = class_create(THIS_MODULE, "fpga_region");
++ if (IS_ERR(fpga_region_class))
++ return PTR_ERR(fpga_region_class);
++
++ fpga_region_class->dev_release = fpga_region_dev_release;
++
++ ret = of_overlay_notifier_register(&fpga_region_of_nb);
++ if (ret)
++ goto err_class;
++
++ ret = platform_driver_register(&fpga_region_driver);
++ if (ret)
++ goto err_plat;
++
++ return 0;
++
++err_plat:
++ of_overlay_notifier_unregister(&fpga_region_of_nb);
++err_class:
++ class_destroy(fpga_region_class);
++ ida_destroy(&fpga_region_ida);
++ return ret;
++}
++
++static void __exit fpga_region_exit(void)
++{
++ platform_driver_unregister(&fpga_region_driver);
++ of_overlay_notifier_unregister(&fpga_region_of_nb);
++ class_destroy(fpga_region_class);
++ ida_destroy(&fpga_region_ida);
++}
++
++subsys_initcall(fpga_region_init);
++module_exit(fpga_region_exit);
++
++MODULE_DESCRIPTION("FPGA Region");
++MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
++MODULE_LICENSE("GPL v2");
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -65,8 +65,10 @@ enum fpga_mgr_states {
+ /*
+ * FPGA Manager flags
+ * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
++ * FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
+ */
+ #define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
++#define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
+
+ /**
+ * struct fpga_image_info - information specific to a FPGA image
diff --git a/patches.socfpga/0032-ARM-socfpga-fpga-bridge-driver-support.patch b/patches.socfpga/0032-ARM-socfpga-fpga-bridge-driver-support.patch
new file mode 100644
index 0000000..c5a8ca9
--- /dev/null
+++ b/patches.socfpga/0032-ARM-socfpga-fpga-bridge-driver-support.patch
@@ -0,0 +1,473 @@
+From ffe325ed88d349106ded4459366514e91fd1a175 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:30 -0500
+Subject: [PATCH 032/103] ARM: socfpga: fpga bridge driver support
+
+Supports Altera SOCFPGA bridges:
+ * fpga2sdram
+ * fpga2hps
+ * hps2fpga
+ * lwhps2fpga
+
+Allows enabling/disabling the bridges through the FPGA
+Bridge Framework API functions.
+
+The fpga2sdram driver only supports enabling and disabling
+of the ports that been configured early on. This is due to
+a hardware limitation where the read, write, and command
+ports on the fpga2sdram bridge can only be reconfigured
+while there are no transactions to the sdram, i.e. when
+running out of OCRAM before the kernel boots.
+
+Device tree property 'init-val' configures the driver to
+enable or disable the bridge during probe. If the property
+does not exist, the driver will leave the bridge in its
+current state.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Matthew Gerlach <mgerlach@altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 7 +
+ drivers/fpga/Makefile | 1
+ drivers/fpga/altera-fpga2sdram.c | 180 +++++++++++++++++++++++++++++++
+ drivers/fpga/altera-hps2fpga.c | 222 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 410 insertions(+)
+ create mode 100644 drivers/fpga/altera-fpga2sdram.c
+ create mode 100644 drivers/fpga/altera-hps2fpga.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -40,6 +40,13 @@ config FPGA_BRIDGE
+ Say Y here if you want to support bridges connected between host
+ processors and FPGAs or between FPGAs.
+
++config SOCFPGA_FPGA_BRIDGE
++ tristate "Altera SoCFPGA FPGA Bridges"
++ depends on ARCH_SOCFPGA && FPGA_BRIDGE
++ help
++ Say Y to enable drivers for FPGA bridges for Altera SOCFPGA
++ devices.
++
+ endif # FPGA
+
+ endmenu
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq
+
+ # FPGA Bridge Drivers
+ obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
++obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE) += altera-hps2fpga.o altera-fpga2sdram.o
+
+ # High Level Interfaces
+ obj-$(CONFIG_FPGA_REGION) += fpga-region.o
+--- /dev/null
++++ b/drivers/fpga/altera-fpga2sdram.c
+@@ -0,0 +1,180 @@
++/*
++ * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices
++ *
++ * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ */
++
++/*
++ * This driver manages a bridge between an FPGA and the SDRAM used by the ARM
++ * host processor system (HPS).
++ *
++ * The bridge contains 4 read ports, 4 write ports, and 6 command ports.
++ * Reconfiguring these ports requires that no SDRAM transactions occur during
++ * reconfiguration. The code reconfiguring the ports cannot run out of SDRAM
++ * nor can the FPGA access the SDRAM during reconfiguration. This driver does
++ * not support reconfiguring the ports. The ports are configured by code
++ * running out of on chip ram before Linux is started and the configuration
++ * is passed in a handoff register in the system manager.
++ *
++ * This driver supports enabling and disabling of the configured ports, which
++ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
++ * uses the same port configuration. Bridges must be disabled before
++ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
++ */
++
++#include <linux/fpga/fpga-bridge.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/regmap.h>
++
++#define ALT_SDR_CTL_FPGAPORTRST_OFST 0x80
++#define ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK 0x00003fff
++#define ALT_SDR_CTL_FPGAPORTRST_RD_SHIFT 0
++#define ALT_SDR_CTL_FPGAPORTRST_WR_SHIFT 4
++#define ALT_SDR_CTL_FPGAPORTRST_CTRL_SHIFT 8
++
++/*
++ * From the Cyclone V HPS Memory Map document:
++ * These registers are used to store handoff information between the
++ * preloader and the OS. These 8 registers can be used to store any
++ * information. The contents of these registers have no impact on
++ * the state of the HPS hardware.
++ */
++#define SYSMGR_ISWGRP_HANDOFF3 (0x8C)
++
++#define F2S_BRIDGE_NAME "fpga2sdram"
++
++struct alt_fpga2sdram_data {
++ struct device *dev;
++ struct regmap *sdrctl;
++ int mask;
++};
++
++static int alt_fpga2sdram_enable_show(struct fpga_bridge *bridge)
++{
++ struct alt_fpga2sdram_data *priv = bridge->priv;
++ int value;
++
++ regmap_read(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST, &value);
++
++ return (value & priv->mask) == priv->mask;
++}
++
++static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
++ bool enable)
++{
++ return regmap_update_bits(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST,
++ priv->mask, enable ? priv->mask : 0);
++}
++
++static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable)
++{
++ return _alt_fpga2sdram_enable_set(bridge->priv, enable);
++}
++
++struct prop_map {
++ char *prop_name;
++ u32 *prop_value;
++ u32 prop_max;
++};
++
++static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
++ .enable_set = alt_fpga2sdram_enable_set,
++ .enable_show = alt_fpga2sdram_enable_show,
++};
++
++static const struct of_device_id altera_fpga_of_match[] = {
++ { .compatible = "altr,socfpga-fpga2sdram-bridge" },
++ {},
++};
++
++static int alt_fpga_bridge_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct alt_fpga2sdram_data *priv;
++ u32 enable;
++ struct regmap *sysmgr;
++ int ret = 0;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->dev = dev;
++
++ priv->sdrctl = syscon_regmap_lookup_by_compatible("altr,sdr-ctl");
++ if (IS_ERR(priv->sdrctl)) {
++ dev_err(dev, "regmap for altr,sdr-ctl lookup failed.\n");
++ return PTR_ERR(priv->sdrctl);
++ }
++
++ sysmgr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
++ if (IS_ERR(priv->sdrctl)) {
++ dev_err(dev, "regmap for altr,sys-mgr lookup failed.\n");
++ return PTR_ERR(sysmgr);
++ }
++
++ /* Get f2s bridge configuration saved in handoff register */
++ regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
++
++ ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
++ &altera_fpga2sdram_br_ops, priv);
++ if (ret)
++ return ret;
++
++ dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
++
++ if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
++ if (enable > 1) {
++ dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
++ } else {
++ dev_info(dev, "%s bridge\n",
++ (enable ? "enabling" : "disabling"));
++ ret = _alt_fpga2sdram_enable_set(priv, enable);
++ if (ret) {
++ fpga_bridge_unregister(&pdev->dev);
++ return ret;
++ }
++ }
++ }
++
++ return ret;
++}
++
++static int alt_fpga_bridge_remove(struct platform_device *pdev)
++{
++ fpga_bridge_unregister(&pdev->dev);
++
++ return 0;
++}
++
++MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
++
++static struct platform_driver altera_fpga_driver = {
++ .probe = alt_fpga_bridge_probe,
++ .remove = alt_fpga_bridge_remove,
++ .driver = {
++ .name = "altera_fpga2sdram_bridge",
++ .of_match_table = of_match_ptr(altera_fpga_of_match),
++ },
++};
++
++module_platform_driver(altera_fpga_driver);
++
++MODULE_DESCRIPTION("Altera SoCFPGA FPGA to SDRAM Bridge");
++MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
++MODULE_LICENSE("GPL v2");
+--- /dev/null
++++ b/drivers/fpga/altera-hps2fpga.c
+@@ -0,0 +1,222 @@
++/*
++ * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices
++ *
++ * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
++ *
++ * Includes this patch from the mailing list:
++ * fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters
++ * Signed-off-by: Anatolij Gustschin <agust@denx.de>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ */
++
++/*
++ * This driver manages bridges on a Altera SOCFPGA between the ARM host
++ * processor system (HPS) and the embedded FPGA.
++ *
++ * This driver supports enabling and disabling of the configured ports, which
++ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
++ * uses the same port configuration. Bridges must be disabled before
++ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
++ */
++
++#include <linux/clk.h>
++#include <linux/fpga/fpga-bridge.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++#include <linux/spinlock.h>
++
++#define ALT_L3_REMAP_OFST 0x0
++#define ALT_L3_REMAP_MPUZERO_MSK 0x00000001
++#define ALT_L3_REMAP_H2F_MSK 0x00000008
++#define ALT_L3_REMAP_LWH2F_MSK 0x00000010
++
++#define HPS2FPGA_BRIDGE_NAME "hps2fpga"
++#define LWHPS2FPGA_BRIDGE_NAME "lwhps2fpga"
++#define FPGA2HPS_BRIDGE_NAME "fpga2hps"
++
++struct altera_hps2fpga_data {
++ const char *name;
++ struct reset_control *bridge_reset;
++ struct regmap *l3reg;
++ unsigned int remap_mask;
++ struct clk *clk;
++};
++
++static int alt_hps2fpga_enable_show(struct fpga_bridge *bridge)
++{
++ struct altera_hps2fpga_data *priv = bridge->priv;
++
++ return reset_control_status(priv->bridge_reset);
++}
++
++/* The L3 REMAP register is write only, so keep a cached value. */
++static unsigned int l3_remap_shadow;
++static spinlock_t l3_remap_lock;
++
++static int _alt_hps2fpga_enable_set(struct altera_hps2fpga_data *priv,
++ bool enable)
++{
++ unsigned long flags;
++ int ret;
++
++ /* bring bridge out of reset */
++ if (enable)
++ ret = reset_control_deassert(priv->bridge_reset);
++ else
++ ret = reset_control_assert(priv->bridge_reset);
++ if (ret)
++ return ret;
++
++ /* Allow bridge to be visible to L3 masters or not */
++ if (priv->remap_mask) {
++ spin_lock_irqsave(&l3_remap_lock, flags);
++ l3_remap_shadow |= ALT_L3_REMAP_MPUZERO_MSK;
++
++ if (enable)
++ l3_remap_shadow |= priv->remap_mask;
++ else
++ l3_remap_shadow &= ~priv->remap_mask;
++
++ ret = regmap_write(priv->l3reg, ALT_L3_REMAP_OFST,
++ l3_remap_shadow);
++ spin_unlock_irqrestore(&l3_remap_lock, flags);
++ }
++
++ return ret;
++}
++
++static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
++{
++ return _alt_hps2fpga_enable_set(bridge->priv, enable);
++}
++
++static const struct fpga_bridge_ops altera_hps2fpga_br_ops = {
++ .enable_set = alt_hps2fpga_enable_set,
++ .enable_show = alt_hps2fpga_enable_show,
++};
++
++static struct altera_hps2fpga_data hps2fpga_data = {
++ .name = HPS2FPGA_BRIDGE_NAME,
++ .remap_mask = ALT_L3_REMAP_H2F_MSK,
++};
++
++static struct altera_hps2fpga_data lwhps2fpga_data = {
++ .name = LWHPS2FPGA_BRIDGE_NAME,
++ .remap_mask = ALT_L3_REMAP_LWH2F_MSK,
++};
++
++static struct altera_hps2fpga_data fpga2hps_data = {
++ .name = FPGA2HPS_BRIDGE_NAME,
++};
++
++static const struct of_device_id altera_fpga_of_match[] = {
++ { .compatible = "altr,socfpga-hps2fpga-bridge",
++ .data = &hps2fpga_data },
++ { .compatible = "altr,socfpga-lwhps2fpga-bridge",
++ .data = &lwhps2fpga_data },
++ { .compatible = "altr,socfpga-fpga2hps-bridge",
++ .data = &fpga2hps_data },
++ {},
++};
++
++static int alt_fpga_bridge_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct altera_hps2fpga_data *priv;
++ const struct of_device_id *of_id;
++ u32 enable;
++ int ret;
++
++ of_id = of_match_device(altera_fpga_of_match, dev);
++ priv = (struct altera_hps2fpga_data *)of_id->data;
++
++ priv->bridge_reset = of_reset_control_get_by_index(dev->of_node, 0);
++ if (IS_ERR(priv->bridge_reset)) {
++ dev_err(dev, "Could not get %s reset control\n", priv->name);
++ return PTR_ERR(priv->bridge_reset);
++ }
++
++ if (priv->remap_mask) {
++ priv->l3reg = syscon_regmap_lookup_by_compatible("altr,l3regs");
++ if (IS_ERR(priv->l3reg)) {
++ dev_err(dev, "regmap for altr,l3regs lookup failed\n");
++ return PTR_ERR(priv->l3reg);
++ }
++ }
++
++ priv->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ dev_err(dev, "no clock specified\n");
++ return PTR_ERR(priv->clk);
++ }
++
++ ret = clk_prepare_enable(priv->clk);
++ if (ret) {
++ dev_err(dev, "could not enable clock\n");
++ return -EBUSY;
++ }
++
++ spin_lock_init(&l3_remap_lock);
++
++ if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
++ if (enable > 1) {
++ dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
++ } else {
++ dev_info(dev, "%s bridge\n",
++ (enable ? "enabling" : "disabling"));
++
++ ret = _alt_hps2fpga_enable_set(priv, enable);
++ if (ret) {
++ fpga_bridge_unregister(&pdev->dev);
++ return ret;
++ }
++ }
++ }
++
++ return fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
++ priv);
++}
++
++static int alt_fpga_bridge_remove(struct platform_device *pdev)
++{
++ struct fpga_bridge *bridge = platform_get_drvdata(pdev);
++ struct altera_hps2fpga_data *priv = bridge->priv;
++
++ fpga_bridge_unregister(&pdev->dev);
++
++ clk_disable_unprepare(priv->clk);
++
++ return 0;
++}
++
++MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
++
++static struct platform_driver alt_fpga_bridge_driver = {
++ .probe = alt_fpga_bridge_probe,
++ .remove = alt_fpga_bridge_remove,
++ .driver = {
++ .name = "altera_hps2fpga_bridge",
++ .of_match_table = of_match_ptr(altera_fpga_of_match),
++ },
++};
++
++module_platform_driver(alt_fpga_bridge_driver);
++
++MODULE_DESCRIPTION("Altera SoCFPGA HPS to FPGA Bridge");
++MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0033-fpga-add-altera-freeze-bridge-support.patch b/patches.socfpga/0033-fpga-add-altera-freeze-bridge-support.patch
new file mode 100644
index 0000000..f63baf1
--- /dev/null
+++ b/patches.socfpga/0033-fpga-add-altera-freeze-bridge-support.patch
@@ -0,0 +1,324 @@
+From cd1d46154270d9ee1e740b310999ae0bb7449e21 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:31 -0500
+Subject: [PATCH 033/103] fpga: add altera freeze bridge support
+
+Add a low level driver for Altera Freeze Bridges to the FPGA Bridge
+framework. A freeze bridge is a bridge that exists in the FPGA
+fabric to isolate one region of the FPGA from the busses while that
+one region is being reprogrammed.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Matthew Gerlach <mgerlach@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 9 +
+ drivers/fpga/Makefile | 1
+ drivers/fpga/altera-freeze-bridge.c | 273 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 283 insertions(+)
+ create mode 100644 drivers/fpga/altera-freeze-bridge.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -47,6 +47,15 @@ config SOCFPGA_FPGA_BRIDGE
+ Say Y to enable drivers for FPGA bridges for Altera SOCFPGA
+ devices.
+
++config ALTERA_FREEZE_BRIDGE
++ tristate "Altera FPGA Freeze Bridge"
++ depends on ARCH_SOCFPGA && FPGA_BRIDGE
++ help
++ Say Y to enable drivers for Altera FPGA Freeze bridges. A
++ freeze bridge is a bridge that exists in the FPGA fabric to
++ isolate one region of the FPGA from the busses while that
++ region is being reprogrammed.
++
+ endif # FPGA
+
+ endmenu
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq
+ # FPGA Bridge Drivers
+ obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
+ obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE) += altera-hps2fpga.o altera-fpga2sdram.o
++obj-$(CONFIG_ALTERA_FREEZE_BRIDGE) += altera-freeze-bridge.o
+
+ # High Level Interfaces
+ obj-$(CONFIG_FPGA_REGION) += fpga-region.o
+--- /dev/null
++++ b/drivers/fpga/altera-freeze-bridge.c
+@@ -0,0 +1,273 @@
++/*
++ * FPGA Freeze Bridge Controller
++ *
++ * Copyright (C) 2016 Altera Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/of_device.h>
++#include <linux/module.h>
++#include <linux/fpga/fpga-bridge.h>
++
++#define FREEZE_CSR_STATUS_OFFSET 0
++#define FREEZE_CSR_CTRL_OFFSET 4
++#define FREEZE_CSR_ILLEGAL_REQ_OFFSET 8
++#define FREEZE_CSR_REG_VERSION 12
++
++#define FREEZE_CSR_SUPPORTED_VERSION 2
++
++#define FREEZE_CSR_STATUS_FREEZE_REQ_DONE BIT(0)
++#define FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE BIT(1)
++
++#define FREEZE_CSR_CTRL_FREEZE_REQ BIT(0)
++#define FREEZE_CSR_CTRL_RESET_REQ BIT(1)
++#define FREEZE_CSR_CTRL_UNFREEZE_REQ BIT(2)
++
++#define FREEZE_BRIDGE_NAME "freeze"
++
++struct altera_freeze_br_data {
++ struct device *dev;
++ void __iomem *base_addr;
++ bool enable;
++};
++
++/*
++ * Poll status until status bit is set or we have a timeout.
++ */
++static int altera_freeze_br_req_ack(struct altera_freeze_br_data *priv,
++ u32 timeout, u32 req_ack)
++{
++ struct device *dev = priv->dev;
++ void __iomem *csr_illegal_req_addr = priv->base_addr +
++ FREEZE_CSR_ILLEGAL_REQ_OFFSET;
++ u32 status, illegal, ctrl;
++ int ret = -ETIMEDOUT;
++
++ do {
++ illegal = readl(csr_illegal_req_addr);
++ if (illegal) {
++ dev_err(dev, "illegal request detected 0x%x", illegal);
++
++ writel(1, csr_illegal_req_addr);
++
++ illegal = readl(csr_illegal_req_addr);
++ if (illegal)
++ dev_err(dev, "illegal request not cleared 0x%x",
++ illegal);
++
++ ret = -EINVAL;
++ break;
++ }
++
++ status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
++ dev_dbg(dev, "%s %x %x\n", __func__, status, req_ack);
++ status &= req_ack;
++ if (status) {
++ ctrl = readl(priv->base_addr + FREEZE_CSR_CTRL_OFFSET);
++ dev_dbg(dev, "%s request %x acknowledged %x %x\n",
++ __func__, req_ack, status, ctrl);
++ ret = 0;
++ break;
++ }
++
++ udelay(1);
++ } while (timeout--);
++
++ if (ret == -ETIMEDOUT)
++ dev_err(dev, "%s timeout waiting for 0x%x\n",
++ __func__, req_ack);
++
++ return ret;
++}
++
++static int altera_freeze_br_do_freeze(struct altera_freeze_br_data *priv,
++ u32 timeout)
++{
++ struct device *dev = priv->dev;
++ void __iomem *csr_ctrl_addr = priv->base_addr +
++ FREEZE_CSR_CTRL_OFFSET;
++ u32 status;
++ int ret;
++
++ status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
++
++ dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
++
++ if (status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE) {
++ dev_dbg(dev, "%s bridge already disabled %d\n",
++ __func__, status);
++ return 0;
++ } else if (!(status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)) {
++ dev_err(dev, "%s bridge not enabled %d\n", __func__, status);
++ return -EINVAL;
++ }
++
++ writel(FREEZE_CSR_CTRL_FREEZE_REQ, csr_ctrl_addr);
++
++ ret = altera_freeze_br_req_ack(priv, timeout,
++ FREEZE_CSR_STATUS_FREEZE_REQ_DONE);
++
++ if (ret)
++ writel(0, csr_ctrl_addr);
++ else
++ writel(FREEZE_CSR_CTRL_RESET_REQ, csr_ctrl_addr);
++
++ return ret;
++}
++
++static int altera_freeze_br_do_unfreeze(struct altera_freeze_br_data *priv,
++ u32 timeout)
++{
++ struct device *dev = priv->dev;
++ void __iomem *csr_ctrl_addr = priv->base_addr +
++ FREEZE_CSR_CTRL_OFFSET;
++ u32 status;
++ int ret;
++
++ writel(0, csr_ctrl_addr);
++
++ status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
++
++ dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
++
++ if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE) {
++ dev_dbg(dev, "%s bridge already enabled %d\n",
++ __func__, status);
++ return 0;
++ } else if (!(status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE)) {
++ dev_err(dev, "%s bridge not frozen %d\n", __func__, status);
++ return -EINVAL;
++ }
++
++ writel(FREEZE_CSR_CTRL_UNFREEZE_REQ, csr_ctrl_addr);
++
++ ret = altera_freeze_br_req_ack(priv, timeout,
++ FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE);
++
++ status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
++
++ dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
++
++ writel(0, csr_ctrl_addr);
++
++ return ret;
++}
++
++/*
++ * enable = 1 : allow traffic through the bridge
++ * enable = 0 : disable traffic through the bridge
++ */
++static int altera_freeze_br_enable_set(struct fpga_bridge *bridge,
++ bool enable)
++{
++ struct altera_freeze_br_data *priv = bridge->priv;
++ struct fpga_image_info *info = bridge->info;
++ u32 timeout = 0;
++ int ret;
++
++ if (enable) {
++ if (info)
++ timeout = info->enable_timeout_us;
++
++ ret = altera_freeze_br_do_unfreeze(bridge->priv, timeout);
++ } else {
++ if (info)
++ timeout = info->disable_timeout_us;
++
++ ret = altera_freeze_br_do_freeze(bridge->priv, timeout);
++ }
++
++ if (!ret)
++ priv->enable = enable;
++
++ return ret;
++}
++
++static int altera_freeze_br_enable_show(struct fpga_bridge *bridge)
++{
++ struct altera_freeze_br_data *priv = bridge->priv;
++
++ return priv->enable;
++}
++
++static struct fpga_bridge_ops altera_freeze_br_br_ops = {
++ .enable_set = altera_freeze_br_enable_set,
++ .enable_show = altera_freeze_br_enable_show,
++};
++
++static const struct of_device_id altera_freeze_br_of_match[] = {
++ { .compatible = "altr,freeze-bridge-controller", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, altera_freeze_br_of_match);
++
++static int altera_freeze_br_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *np = pdev->dev.of_node;
++ struct altera_freeze_br_data *priv;
++ struct resource *res;
++ u32 status, revision;
++
++ if (!np)
++ return -ENODEV;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->dev = dev;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ priv->base_addr = devm_ioremap_resource(dev, res);
++ if (IS_ERR(priv->base_addr))
++ return PTR_ERR(priv->base_addr);
++
++ status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
++ if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)
++ priv->enable = 1;
++
++ revision = readl(priv->base_addr + FREEZE_CSR_REG_VERSION);
++ if (revision != FREEZE_CSR_SUPPORTED_VERSION)
++ dev_warn(dev,
++ "%s Freeze Controller unexpected revision %d != %d\n",
++ __func__, revision, FREEZE_CSR_SUPPORTED_VERSION);
++
++ return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME,
++ &altera_freeze_br_br_ops, priv);
++}
++
++static int altera_freeze_br_remove(struct platform_device *pdev)
++{
++ fpga_bridge_unregister(&pdev->dev);
++
++ return 0;
++}
++
++static struct platform_driver altera_freeze_br_driver = {
++ .probe = altera_freeze_br_probe,
++ .remove = altera_freeze_br_remove,
++ .driver = {
++ .name = "altera_freeze_br",
++ .of_match_table = of_match_ptr(altera_freeze_br_of_match),
++ },
++};
++
++module_platform_driver(altera_freeze_br_driver);
++
++MODULE_DESCRIPTION("Altera Freeze Bridge");
++MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0034-fpga-manager-Add-Socfpga-Arria10-support.patch b/patches.socfpga/0034-fpga-manager-Add-Socfpga-Arria10-support.patch
new file mode 100644
index 0000000..7eed0ff
--- /dev/null
+++ b/patches.socfpga/0034-fpga-manager-Add-Socfpga-Arria10-support.patch
@@ -0,0 +1,602 @@
+From d2d6523f3ef50daee666b364d8438de62ed5a40b Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 1 Nov 2016 14:14:32 -0500
+Subject: [PATCH 034/103] fpga-manager: Add Socfpga Arria10 support
+
+Add low level driver to support reprogramming FPGAs for Altera
+SoCFPGA Arria10.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 6
+ drivers/fpga/Makefile | 1
+ drivers/fpga/socfpga-a10.c | 556 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 563 insertions(+)
+ create mode 100644 drivers/fpga/socfpga-a10.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -26,6 +26,12 @@ config FPGA_MGR_SOCFPGA
+ help
+ FPGA manager driver support for Altera SOCFPGA.
+
++config FPGA_MGR_SOCFPGA_A10
++ tristate "Altera SoCFPGA Arria10"
++ depends on ARCH_SOCFPGA
++ help
++ FPGA manager driver support for Altera Arria10 SoCFPGA.
++
+ config FPGA_MGR_ZYNQ_FPGA
+ tristate "Xilinx Zynq FPGA"
+ depends on ARCH_ZYNQ || COMPILE_TEST
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o
+
+ # FPGA Manager Drivers
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
++obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
+ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
+
+ # FPGA Bridge Drivers
+--- /dev/null
++++ b/drivers/fpga/socfpga-a10.c
+@@ -0,0 +1,556 @@
++/*
++ * FPGA Manager Driver for Altera Arria10 SoCFPGA
++ *
++ * Copyright (C) 2015-2016 Altera Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/clk.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/fpga/fpga-mgr.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/regmap.h>
++
++#define A10_FPGAMGR_DCLKCNT_OFST 0x08
++#define A10_FPGAMGR_DCLKSTAT_OFST 0x0c
++#define A10_FPGAMGR_IMGCFG_CTL_00_OFST 0x70
++#define A10_FPGAMGR_IMGCFG_CTL_01_OFST 0x74
++#define A10_FPGAMGR_IMGCFG_CTL_02_OFST 0x78
++#define A10_FPGAMGR_IMGCFG_STAT_OFST 0x80
++
++#define A10_FPGAMGR_DCLKSTAT_DCLKDONE BIT(0)
++
++#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG BIT(0)
++#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS BIT(1)
++#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE BIT(2)
++#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG BIT(8)
++#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE BIT(16)
++#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE BIT(24)
++
++#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG BIT(0)
++#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST BIT(16)
++#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE BIT(24)
++
++#define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL BIT(0)
++#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK (BIT(16) | BIT(17))
++#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT 16
++#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH BIT(24)
++#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT 24
++
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR BIT(0)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE BIT(1)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE BIT(2)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN BIT(4)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN BIT(6)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY BIT(9)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE BIT(10)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR BIT(11)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN BIT(12)
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK (BIT(16) | BIT(17) | BIT(18))
++#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT 16
++
++/* FPGA CD Ratio Value */
++#define CDRATIO_x1 0x0
++#define CDRATIO_x2 0x1
++#define CDRATIO_x4 0x2
++#define CDRATIO_x8 0x3
++
++/* Configuration width 16/32 bit */
++#define CFGWDTH_32 1
++#define CFGWDTH_16 0
++
++/*
++ * struct a10_fpga_priv - private data for fpga manager
++ * @regmap: regmap for register access
++ * @fpga_data_addr: iomap for single address data register to FPGA
++ * @clk: clock
++ */
++struct a10_fpga_priv {
++ struct regmap *regmap;
++ void __iomem *fpga_data_addr;
++ struct clk *clk;
++};
++
++static bool socfpga_a10_fpga_writeable_reg(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case A10_FPGAMGR_DCLKCNT_OFST:
++ case A10_FPGAMGR_DCLKSTAT_OFST:
++ case A10_FPGAMGR_IMGCFG_CTL_00_OFST:
++ case A10_FPGAMGR_IMGCFG_CTL_01_OFST:
++ case A10_FPGAMGR_IMGCFG_CTL_02_OFST:
++ return true;
++ }
++ return false;
++}
++
++static bool socfpga_a10_fpga_readable_reg(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case A10_FPGAMGR_DCLKCNT_OFST:
++ case A10_FPGAMGR_DCLKSTAT_OFST:
++ case A10_FPGAMGR_IMGCFG_CTL_00_OFST:
++ case A10_FPGAMGR_IMGCFG_CTL_01_OFST:
++ case A10_FPGAMGR_IMGCFG_CTL_02_OFST:
++ case A10_FPGAMGR_IMGCFG_STAT_OFST:
++ return true;
++ }
++ return false;
++}
++
++static const struct regmap_config socfpga_a10_fpga_regmap_config = {
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++ .writeable_reg = socfpga_a10_fpga_writeable_reg,
++ .readable_reg = socfpga_a10_fpga_readable_reg,
++ .max_register = A10_FPGAMGR_IMGCFG_STAT_OFST,
++ .cache_type = REGCACHE_NONE,
++};
++
++/*
++ * from the register map description of cdratio in imgcfg_ctrl_02:
++ * Normal Configuration : 32bit Passive Parallel
++ * Partial Reconfiguration : 16bit Passive Parallel
++ */
++static void socfpga_a10_fpga_set_cfg_width(struct a10_fpga_priv *priv,
++ int width)
++{
++ width <<= A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT;
++
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH, width);
++}
++
++static void socfpga_a10_fpga_generate_dclks(struct a10_fpga_priv *priv,
++ u32 count)
++{
++ u32 val;
++
++ /* Clear any existing DONE status. */
++ regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,
++ A10_FPGAMGR_DCLKSTAT_DCLKDONE);
++
++ /* Issue the DCLK regmap. */
++ regmap_write(priv->regmap, A10_FPGAMGR_DCLKCNT_OFST, count);
++
++ /* wait till the dclkcnt done */
++ regmap_read_poll_timeout(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, val,
++ val, 1, 100);
++
++ /* Clear DONE status. */
++ regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,
++ A10_FPGAMGR_DCLKSTAT_DCLKDONE);
++}
++
++#define RBF_ENCRYPTION_MODE_OFFSET 69
++#define RBF_DECOMPRESS_OFFSET 229
++
++static int socfpga_a10_fpga_encrypted(u32 *buf32, size_t buf32_size)
++{
++ if (buf32_size < RBF_ENCRYPTION_MODE_OFFSET + 1)
++ return -EINVAL;
++
++ /* Is the bitstream encrypted? */
++ return ((buf32[RBF_ENCRYPTION_MODE_OFFSET] >> 2) & 3) != 0;
++}
++
++static int socfpga_a10_fpga_compressed(u32 *buf32, size_t buf32_size)
++{
++ if (buf32_size < RBF_DECOMPRESS_OFFSET + 1)
++ return -EINVAL;
++
++ /* Is the bitstream compressed? */
++ return !((buf32[RBF_DECOMPRESS_OFFSET] >> 1) & 1);
++}
++
++static unsigned int socfpga_a10_fpga_get_cd_ratio(unsigned int cfg_width,
++ bool encrypt, bool compress)
++{
++ unsigned int cd_ratio;
++
++ /*
++ * cd ratio is dependent on cfg width and whether the bitstream
++ * is encrypted and/or compressed.
++ *
++ * | width | encr. | compr. | cd ratio |
++ * | 16 | 0 | 0 | 1 |
++ * | 16 | 0 | 1 | 4 |
++ * | 16 | 1 | 0 | 2 |
++ * | 16 | 1 | 1 | 4 |
++ * | 32 | 0 | 0 | 1 |
++ * | 32 | 0 | 1 | 8 |
++ * | 32 | 1 | 0 | 4 |
++ * | 32 | 1 | 1 | 8 |
++ */
++ if (!compress && !encrypt)
++ return CDRATIO_x1;
++
++ if (compress)
++ cd_ratio = CDRATIO_x4;
++ else
++ cd_ratio = CDRATIO_x2;
++
++ /* If 32 bit, double the cd ratio by incrementing the field */
++ if (cfg_width == CFGWDTH_32)
++ cd_ratio += 1;
++
++ return cd_ratio;
++}
++
++static int socfpga_a10_fpga_set_cdratio(struct fpga_manager *mgr,
++ unsigned int cfg_width,
++ const char *buf, size_t count)
++{
++ struct a10_fpga_priv *priv = mgr->priv;
++ unsigned int cd_ratio;
++ int encrypt, compress;
++
++ encrypt = socfpga_a10_fpga_encrypted((u32 *)buf, count / 4);
++ if (encrypt < 0)
++ return -EINVAL;
++
++ compress = socfpga_a10_fpga_compressed((u32 *)buf, count / 4);
++ if (compress < 0)
++ return -EINVAL;
++
++ cd_ratio = socfpga_a10_fpga_get_cd_ratio(cfg_width, encrypt, compress);
++
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK,
++ cd_ratio << A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT);
++
++ return 0;
++}
++
++static u32 socfpga_a10_fpga_read_stat(struct a10_fpga_priv *priv)
++{
++ u32 val;
++
++ regmap_read(priv->regmap, A10_FPGAMGR_IMGCFG_STAT_OFST, &val);
++
++ return val;
++}
++
++static int socfpga_a10_fpga_wait_for_pr_ready(struct a10_fpga_priv *priv)
++{
++ u32 reg, i;
++
++ for (i = 0; i < 10 ; i++) {
++ reg = socfpga_a10_fpga_read_stat(priv);
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)
++ return -EINVAL;
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)
++ return 0;
++ }
++
++ return -ETIMEDOUT;
++}
++
++static int socfpga_a10_fpga_wait_for_pr_done(struct a10_fpga_priv *priv)
++{
++ u32 reg, i;
++
++ for (i = 0; i < 10 ; i++) {
++ reg = socfpga_a10_fpga_read_stat(priv);
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)
++ return -EINVAL;
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE)
++ return 0;
++ }
++
++ return -ETIMEDOUT;
++}
++
++/* Start the FPGA programming by initialize the FPGA Manager */
++static int socfpga_a10_fpga_write_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ struct a10_fpga_priv *priv = mgr->priv;
++ unsigned int cfg_width;
++ u32 msel, stat, mask;
++ int ret;
++
++ if (info->flags & FPGA_MGR_PARTIAL_RECONFIG)
++ cfg_width = CFGWDTH_16;
++ else
++ return -EINVAL;
++
++ /* Check for passive parallel (msel == 000 or 001) */
++ msel = socfpga_a10_fpga_read_stat(priv);
++ msel &= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK;
++ msel >>= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT;
++ if ((msel != 0) && (msel != 1)) {
++ dev_dbg(&mgr->dev, "Fail: invalid msel=%d\n", msel);
++ return -EINVAL;
++ }
++
++ /* Make sure no external devices are interfering */
++ stat = socfpga_a10_fpga_read_stat(priv);
++ mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN |
++ A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN;
++ if ((stat & mask) != mask)
++ return -EINVAL;
++
++ /* Set cfg width */
++ socfpga_a10_fpga_set_cfg_width(priv, cfg_width);
++
++ /* Determine cd ratio from bitstream header and set cd ratio */
++ ret = socfpga_a10_fpga_set_cdratio(mgr, cfg_width, buf, count);
++ if (ret)
++ return ret;
++
++ /*
++ * Clear s2f_nce to enable chip select. Leave pr_request
++ * unasserted and override disabled.
++ */
++ regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);
++
++ /* Set cfg_ctrl to enable s2f dclk and data */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL,
++ A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL);
++
++ /*
++ * Disable overrides not needed for pr.
++ * s2f_config==1 leaves reset deasseted.
++ */
++ regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_00_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG |
++ A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS |
++ A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE |
++ A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG);
++
++ /* Enable override for data, dclk, nce, and pr_request to CSS */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, 0);
++
++ /* Send some clocks to clear out any errors */
++ socfpga_a10_fpga_generate_dclks(priv, 256);
++
++ /* Assert pr_request */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST);
++
++ /* Provide 2048 DCLKs before starting the config data streaming. */
++ socfpga_a10_fpga_generate_dclks(priv, 0x7ff);
++
++ /* Wait for pr_ready */
++ return socfpga_a10_fpga_wait_for_pr_ready(priv);
++}
++
++/*
++ * write data to the FPGA data register
++ */
++static int socfpga_a10_fpga_write(struct fpga_manager *mgr, const char *buf,
++ size_t count)
++{
++ struct a10_fpga_priv *priv = mgr->priv;
++ u32 *buffer_32 = (u32 *)buf;
++ size_t i = 0;
++
++ if (count <= 0)
++ return -EINVAL;
++
++ /* Write out the complete 32-bit chunks */
++ while (count >= sizeof(u32)) {
++ writel(buffer_32[i++], priv->fpga_data_addr);
++ count -= sizeof(u32);
++ }
++
++ /* Write out remaining non 32-bit chunks */
++ switch (count) {
++ case 3:
++ writel(buffer_32[i++] & 0x00ffffff, priv->fpga_data_addr);
++ break;
++ case 2:
++ writel(buffer_32[i++] & 0x0000ffff, priv->fpga_data_addr);
++ break;
++ case 1:
++ writel(buffer_32[i++] & 0x000000ff, priv->fpga_data_addr);
++ break;
++ case 0:
++ break;
++ default:
++ /* This will never happen */
++ return -EFAULT;
++ }
++
++ return 0;
++}
++
++static int socfpga_a10_fpga_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
++{
++ struct a10_fpga_priv *priv = mgr->priv;
++ u32 reg;
++ int ret;
++
++ /* Wait for pr_done */
++ ret = socfpga_a10_fpga_wait_for_pr_done(priv);
++
++ /* Clear pr_request */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, 0);
++
++ /* Send some clocks to clear out any errors */
++ socfpga_a10_fpga_generate_dclks(priv, 256);
++
++ /* Disable s2f dclk and data */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0);
++
++ /* Deassert chip select */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE);
++
++ /* Disable data, dclk, nce, and pr_request override to CSS */
++ regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG,
++ A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);
++
++ /* Return any errors regarding pr_done or pr_error */
++ if (ret)
++ return ret;
++
++ /* Final check */
++ reg = socfpga_a10_fpga_read_stat(priv);
++
++ if (((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) == 0) ||
++ ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) == 0) ||
++ ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)) {
++ dev_dbg(&mgr->dev,
++ "Timeout in final check. Status=%08xf\n", reg);
++ return -ETIMEDOUT;
++ }
++
++ return 0;
++}
++
++static enum fpga_mgr_states socfpga_a10_fpga_state(struct fpga_manager *mgr)
++{
++ struct a10_fpga_priv *priv = mgr->priv;
++ u32 reg = socfpga_a10_fpga_read_stat(priv);
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE)
++ return FPGA_MGR_STATE_OPERATING;
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)
++ return FPGA_MGR_STATE_WRITE;
++
++ if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR)
++ return FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
++
++ if ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)
++ return FPGA_MGR_STATE_RESET;
++
++ return FPGA_MGR_STATE_UNKNOWN;
++}
++
++static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {
++ .state = socfpga_a10_fpga_state,
++ .write_init = socfpga_a10_fpga_write_init,
++ .write = socfpga_a10_fpga_write,
++ .write_complete = socfpga_a10_fpga_write_complete,
++};
++
++static int socfpga_a10_fpga_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct a10_fpga_priv *priv;
++ void __iomem *reg_base;
++ struct resource *res;
++ int ret;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ /* First mmio base is for register access */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ reg_base = devm_ioremap_resource(dev, res);
++ if (IS_ERR(reg_base))
++ return PTR_ERR(reg_base);
++
++ /* Second mmio base is for writing FPGA image data */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ priv->fpga_data_addr = devm_ioremap_resource(dev, res);
++ if (IS_ERR(priv->fpga_data_addr))
++ return PTR_ERR(priv->fpga_data_addr);
++
++ /* regmap for register access */
++ priv->regmap = devm_regmap_init_mmio(dev, reg_base,
++ &socfpga_a10_fpga_regmap_config);
++ if (IS_ERR(priv->regmap))
++ return -ENODEV;
++
++ priv->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ dev_err(dev, "no clock specified\n");
++ return PTR_ERR(priv->clk);
++ }
++
++ ret = clk_prepare_enable(priv->clk);
++ if (ret) {
++ dev_err(dev, "could not enable clock\n");
++ return -EBUSY;
++ }
++
++ return fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",
++ &socfpga_a10_fpga_mgr_ops, priv);
++}
++
++static int socfpga_a10_fpga_remove(struct platform_device *pdev)
++{
++ struct fpga_manager *mgr = platform_get_drvdata(pdev);
++ struct a10_fpga_priv *priv = mgr->priv;
++
++ fpga_mgr_unregister(&pdev->dev);
++ clk_disable_unprepare(priv->clk);
++
++ return 0;
++}
++
++static const struct of_device_id socfpga_a10_fpga_of_match[] = {
++ { .compatible = "altr,socfpga-a10-fpga-mgr", },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);
++
++static struct platform_driver socfpga_a10_fpga_driver = {
++ .probe = socfpga_a10_fpga_probe,
++ .remove = socfpga_a10_fpga_remove,
++ .driver = {
++ .name = "socfpga_a10_fpga_manager",
++ .of_match_table = socfpga_a10_fpga_of_match,
++ },
++};
++
++module_platform_driver(socfpga_a10_fpga_driver);
++
++MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
++MODULE_DESCRIPTION("SoCFPGA Arria10 FPGA Manager");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0035-ARM-socfpga-checking-the-wrong-variable.patch b/patches.socfpga/0035-ARM-socfpga-checking-the-wrong-variable.patch
new file mode 100644
index 0000000..91fbf44
--- /dev/null
+++ b/patches.socfpga/0035-ARM-socfpga-checking-the-wrong-variable.patch
@@ -0,0 +1,27 @@
+From 66990794c5c8e372ef07dd76272f5ac550e5be74 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 16 Nov 2016 19:54:40 -0600
+Subject: [PATCH 035/103] ARM: socfpga: checking the wrong variable
+
+This is a cut and paste bug. We had intended to check "sysmgr".
+
+Fixes: e5f8efa5c8bf ("ARM: socfpga: fpga bridge driver support")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/altera-fpga2sdram.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/fpga/altera-fpga2sdram.c
++++ b/drivers/fpga/altera-fpga2sdram.c
+@@ -123,7 +123,7 @@ static int alt_fpga_bridge_probe(struct
+ }
+
+ sysmgr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+- if (IS_ERR(priv->sdrctl)) {
++ if (IS_ERR(sysmgr)) {
+ dev_err(dev, "regmap for altr,sys-mgr lookup failed.\n");
+ return PTR_ERR(sysmgr);
+ }
diff --git a/patches.socfpga/0036-fpga-Add-COMPILE_TEST-to-all-drivers.patch b/patches.socfpga/0036-fpga-Add-COMPILE_TEST-to-all-drivers.patch
new file mode 100644
index 0000000..be90b9b
--- /dev/null
+++ b/patches.socfpga/0036-fpga-Add-COMPILE_TEST-to-all-drivers.patch
@@ -0,0 +1,36 @@
+From 9ab5031fea8fa46c96663d537ad0652d944cf880 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Mon, 21 Nov 2016 22:26:42 +0000
+Subject: [PATCH 036/103] fpga: Add COMPILE_TEST to all drivers
+
+Like Zynq the Altera drivers compile fine on x86 and others too,
+so make it easier to compile test this stuff.
+
+A10 requires REGMAP_MMIO to compile, so be explicit rather than
+relying on it via ARCH_SOCFPGA.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+---
+ drivers/fpga/Kconfig | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -22,13 +22,14 @@ config FPGA_REGION
+
+ config FPGA_MGR_SOCFPGA
+ tristate "Altera SOCFPGA FPGA Manager"
+- depends on ARCH_SOCFPGA
++ depends on ARCH_SOCFPGA || COMPILE_TEST
+ help
+ FPGA manager driver support for Altera SOCFPGA.
+
+ config FPGA_MGR_SOCFPGA_A10
+ tristate "Altera SoCFPGA Arria10"
+- depends on ARCH_SOCFPGA
++ depends on ARCH_SOCFPGA || COMPILE_TEST
++ select REGMAP_MMIO
+ help
+ FPGA manager driver support for Altera Arria10 SoCFPGA.
+
diff --git a/patches.socfpga/0037-fpga-zynq-Add-missing-n-to-messages.patch b/patches.socfpga/0037-fpga-zynq-Add-missing-n-to-messages.patch
new file mode 100644
index 0000000..0a8a31a
--- /dev/null
+++ b/patches.socfpga/0037-fpga-zynq-Add-missing-n-to-messages.patch
@@ -0,0 +1,112 @@
+From 5dc43314ce4663a705a0a91a3ad6e9aba3457de1 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Mon, 21 Nov 2016 22:26:43 +0000
+Subject: [PATCH 037/103] fpga zynq: Add missing \n to messages
+
+Function dev_err doesn't add a newline at the end of the string. This will
+lead to a hard to read kernel log.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
+Reviewed-by: Matthias Brugger <mbrugger@suse.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+---
+ drivers/fpga/zynq-fpga.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -218,7 +218,7 @@ static int zynq_fpga_ops_write_init(stru
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+- dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
++ dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
+ goto out_err;
+ }
+
+@@ -232,7 +232,7 @@ static int zynq_fpga_ops_write_init(stru
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+- dev_err(priv->dev, "Timeout waiting for !PCFG_INIT");
++ dev_err(priv->dev, "Timeout waiting for !PCFG_INIT\n");
+ goto out_err;
+ }
+
+@@ -246,7 +246,7 @@ static int zynq_fpga_ops_write_init(stru
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+- dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
++ dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
+ goto out_err;
+ }
+ }
+@@ -263,7 +263,7 @@ static int zynq_fpga_ops_write_init(stru
+ /* check that we have room in the command queue */
+ status = zynq_fpga_read(priv, STATUS_OFFSET);
+ if (status & STATUS_DMA_Q_F) {
+- dev_err(priv->dev, "DMA command queue full");
++ dev_err(priv->dev, "DMA command queue full\n");
+ err = -EBUSY;
+ goto out_err;
+ }
+@@ -332,7 +332,7 @@ static int zynq_fpga_ops_write(struct fp
+ zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
+
+ if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
+- dev_err(priv->dev, "Error configuring FPGA");
++ dev_err(priv->dev, "Error configuring FPGA\n");
+ err = -EFAULT;
+ }
+
+@@ -428,7 +428,7 @@ static int zynq_fpga_probe(struct platfo
+ priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "syscon");
+ if (IS_ERR(priv->slcr)) {
+- dev_err(dev, "unable to get zynq-slcr regmap");
++ dev_err(dev, "unable to get zynq-slcr regmap\n");
+ return PTR_ERR(priv->slcr);
+ }
+
+@@ -436,26 +436,26 @@ static int zynq_fpga_probe(struct platfo
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0) {
+- dev_err(dev, "No IRQ available");
++ dev_err(dev, "No IRQ available\n");
+ return priv->irq;
+ }
+
+ err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
+ dev_name(dev), priv);
+ if (err) {
+- dev_err(dev, "unable to request IRQ");
++ dev_err(dev, "unable to request IRQ\n");
+ return err;
+ }
+
+ priv->clk = devm_clk_get(dev, "ref_clk");
+ if (IS_ERR(priv->clk)) {
+- dev_err(dev, "input clock not found");
++ dev_err(dev, "input clock not found\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+- dev_err(dev, "unable to enable clock");
++ dev_err(dev, "unable to enable clock\n");
+ return err;
+ }
+
+@@ -467,7 +467,7 @@ static int zynq_fpga_probe(struct platfo
+ err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
+ &zynq_fpga_ops, priv);
+ if (err) {
+- dev_err(dev, "unable to register FPGA manager");
++ dev_err(dev, "unable to register FPGA manager\n");
+ clk_unprepare(priv->clk);
+ return err;
+ }
diff --git a/patches.socfpga/0038-fpga-zynq-Remove-priv-dev.patch b/patches.socfpga/0038-fpga-zynq-Remove-priv-dev.patch
new file mode 100644
index 0000000..869b493
--- /dev/null
+++ b/patches.socfpga/0038-fpga-zynq-Remove-priv-dev.patch
@@ -0,0 +1,99 @@
+From df7528d1c3d7c2151dfe9419c7b3eed183860b8f Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Mon, 21 Nov 2016 22:26:44 +0000
+Subject: [PATCH 038/103] fpga zynq: Remove priv->dev
+
+socfpga uses mgr->dev for debug prints, there should be consistency
+here, so standardize on that. The only other use was for dma
+which can be replaced with mgr->dev.parent.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+---
+ drivers/fpga/zynq-fpga.c | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -118,7 +118,6 @@
+ #define FPGA_RST_NONE_MASK 0x0
+
+ struct zynq_fpga_priv {
+- struct device *dev;
+ int irq;
+ struct clk *clk;
+
+@@ -218,7 +217,7 @@ static int zynq_fpga_ops_write_init(stru
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+- dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
++ dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
+ goto out_err;
+ }
+
+@@ -232,7 +231,7 @@ static int zynq_fpga_ops_write_init(stru
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+- dev_err(priv->dev, "Timeout waiting for !PCFG_INIT\n");
++ dev_err(&mgr->dev, "Timeout waiting for !PCFG_INIT\n");
+ goto out_err;
+ }
+
+@@ -246,7 +245,7 @@ static int zynq_fpga_ops_write_init(stru
+ INIT_POLL_DELAY,
+ INIT_POLL_TIMEOUT);
+ if (err) {
+- dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
++ dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
+ goto out_err;
+ }
+ }
+@@ -263,7 +262,7 @@ static int zynq_fpga_ops_write_init(stru
+ /* check that we have room in the command queue */
+ status = zynq_fpga_read(priv, STATUS_OFFSET);
+ if (status & STATUS_DMA_Q_F) {
+- dev_err(priv->dev, "DMA command queue full\n");
++ dev_err(&mgr->dev, "DMA command queue full\n");
+ err = -EBUSY;
+ goto out_err;
+ }
+@@ -296,7 +295,8 @@ static int zynq_fpga_ops_write(struct fp
+ in_count = count;
+ priv = mgr->priv;
+
+- kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
++ kbuf =
++ dma_alloc_coherent(mgr->dev.parent, count, &dma_addr, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+@@ -332,15 +332,14 @@ static int zynq_fpga_ops_write(struct fp
+ zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
+
+ if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
+- dev_err(priv->dev, "Error configuring FPGA\n");
++ dev_err(&mgr->dev, "Error configuring FPGA\n");
+ err = -EFAULT;
+ }
+
+ clk_disable(priv->clk);
+
+ out_free:
+- dma_free_coherent(priv->dev, in_count, kbuf, dma_addr);
+-
++ dma_free_coherent(mgr->dev.parent, count, kbuf, dma_addr);
+ return err;
+ }
+
+@@ -418,8 +417,6 @@ static int zynq_fpga_probe(struct platfo
+ if (!priv)
+ return -ENOMEM;
+
+- priv->dev = dev;
+-
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->io_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->io_base))
diff --git a/patches.socfpga/0039-fpga-zynq-Fix-incorrect-ISR-state-on-bootup.patch b/patches.socfpga/0039-fpga-zynq-Fix-incorrect-ISR-state-on-bootup.patch
new file mode 100644
index 0000000..21d94e8
--- /dev/null
+++ b/patches.socfpga/0039-fpga-zynq-Fix-incorrect-ISR-state-on-bootup.patch
@@ -0,0 +1,56 @@
+From fb85a83e56bbe1a3899b8293a2db442696aa7631 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Mon, 21 Nov 2016 22:26:45 +0000
+Subject: [PATCH 039/103] fpga zynq: Fix incorrect ISR state on bootup
+
+It is best practice to clear and mask all interrupts before
+associating the IRQ, and this should be done after the clock
+is enabled.
+
+This corrects a bad result from zynq_fpga_ops_state on bootup
+where left over latched values in INT_STS_OFFSET caused it to
+report an unconfigured FPGA as configured.
+
+After this change the boot up operating state for an unconfigured
+FPGA reports 'unknown'.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+---
+ drivers/fpga/zynq-fpga.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -437,13 +437,6 @@ static int zynq_fpga_probe(struct platfo
+ return priv->irq;
+ }
+
+- err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
+- dev_name(dev), priv);
+- if (err) {
+- dev_err(dev, "unable to request IRQ\n");
+- return err;
+- }
+-
+ priv->clk = devm_clk_get(dev, "ref_clk");
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "input clock not found\n");
+@@ -459,6 +452,16 @@ static int zynq_fpga_probe(struct platfo
+ /* unlock the device */
+ zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
+
++ zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF);
++ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
++ err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
++ priv);
++ if (err) {
++ dev_err(dev, "unable to request IRQ\n");
++ clk_disable_unprepare(priv->clk);
++ return err;
++ }
++
+ clk_disable(priv->clk);
+
+ err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
diff --git a/patches.socfpga/0040-fpga-Clarify-how-write_init-works-streaming-modes.patch b/patches.socfpga/0040-fpga-Clarify-how-write_init-works-streaming-modes.patch
new file mode 100644
index 0000000..b5e5f0c
--- /dev/null
+++ b/patches.socfpga/0040-fpga-Clarify-how-write_init-works-streaming-modes.patch
@@ -0,0 +1,82 @@
+From 66eb655c5286bd01e7fbe9db237ed4cbde6c4857 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Tue, 22 Nov 2016 18:22:09 +0000
+Subject: [PATCH 040/103] fpga: Clarify how write_init works streaming modes
+
+This interface was designed for streaming, but write_init's buf
+argument has an unclear purpose. Define it to be the first bytes
+of the bitstream. Each driver gets to set how many bytes (at most)
+it wants to see. Short bitstreams will be passed through as-is, while
+long ones will be truncated.
+
+The intent is to allow drivers to peek at the header before the transfer
+actually starts.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+---
+ Documentation/fpga/fpga-mgr.txt | 5 ++++-
+ drivers/fpga/fpga-mgr.c | 6 ++++--
+ drivers/fpga/socfpga-a10.c | 1 +
+ include/linux/fpga/fpga-mgr.h | 2 ++
+ 4 files changed, 11 insertions(+), 3 deletions(-)
+
+--- a/Documentation/fpga/fpga-mgr.txt
++++ b/Documentation/fpga/fpga-mgr.txt
+@@ -169,7 +169,10 @@ The programming sequence is:
+ 2. .write (may be called once or multiple times)
+ 3. .write_complete
+
+-The .write_init function will prepare the FPGA to receive the image data.
++The .write_init function will prepare the FPGA to receive the image data. The
++buffer passed into .write_init will be atmost .initial_header_size bytes long,
++if the whole bitstream is not immediately available then the core code will
++buffer up at least this much before starting.
+
+ The .write function writes a buffer to the FPGA. The buffer may be contain the
+ whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -53,10 +53,12 @@ int fpga_mgr_buf_load(struct fpga_manage
+ /*
+ * Call the low level driver's write_init function. This will do the
+ * device-specific things to get the FPGA into the state where it is
+- * ready to receive an FPGA image.
++ * ready to receive an FPGA image. The low level driver only gets to
++ * see the first initial_header_size bytes in the buffer.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+- ret = mgr->mops->write_init(mgr, info, buf, count);
++ ret = mgr->mops->write_init(mgr, info, buf,
++ min(mgr->mops->initial_header_size, count));
+ if (ret) {
+ dev_err(dev, "Error preparing FPGA for writing\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
+--- a/drivers/fpga/socfpga-a10.c
++++ b/drivers/fpga/socfpga-a10.c
+@@ -470,6 +470,7 @@ static enum fpga_mgr_states socfpga_a10_
+ }
+
+ static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {
++ .initial_header_size = (RBF_DECOMPRESS_OFFSET + 1) * 4,
+ .state = socfpga_a10_fpga_state,
+ .write_init = socfpga_a10_fpga_write_init,
+ .write = socfpga_a10_fpga_write,
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -84,6 +84,7 @@ struct fpga_image_info {
+
+ /**
+ * struct fpga_manager_ops - ops for low level fpga manager drivers
++ * @initial_header_size: Maximum number of bytes that should be passed into write_init
+ * @state: returns an enum value of the FPGA's state
+ * @write_init: prepare the FPGA to receive confuration data
+ * @write: write count bytes of configuration data to the FPGA
+@@ -95,6 +96,7 @@ struct fpga_image_info {
+ * called, so leaving them out is fine.
+ */
+ struct fpga_manager_ops {
++ size_t initial_header_size;
+ enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
+ int (*write_init)(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
diff --git a/patches.socfpga/0041-fpga-zynq-Check-for-errors-after-completing-DMA.patch b/patches.socfpga/0041-fpga-zynq-Check-for-errors-after-completing-DMA.patch
new file mode 100644
index 0000000..2a0f8b5
--- /dev/null
+++ b/patches.socfpga/0041-fpga-zynq-Check-for-errors-after-completing-DMA.patch
@@ -0,0 +1,130 @@
+From 5340a4560aaaaa7807b8e0070d6ee6541ee5fb3b Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Wed, 1 Feb 2017 12:48:42 -0700
+Subject: [PATCH 041/103] fpga zynq: Check for errors after completing DMA
+
+The completion did not check the interrupt status to see if any error
+bits were asserted, check error bits and dump some registers if things
+went wrong.
+
+A few fixes are needed to make this work, the IXR_ERROR_FLAGS_MASK was
+wrong, it included the done bits, which shows a bug in mask/unmask_irqs
+which were using the wrong bits, simplify all of this stuff.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/zynq-fpga.c | 54 +++++++++++++++++++++++++++--------------------
+ 1 file changed, 32 insertions(+), 22 deletions(-)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -89,7 +89,7 @@
+ #define IXR_D_P_DONE_MASK BIT(12)
+ /* FPGA programmed */
+ #define IXR_PCFG_DONE_MASK BIT(2)
+-#define IXR_ERROR_FLAGS_MASK 0x00F0F860
++#define IXR_ERROR_FLAGS_MASK 0x00F0C860
+ #define IXR_ALL_MASK 0xF8F7F87F
+
+ /* Miscellaneous constant values */
+@@ -143,23 +143,10 @@ static inline u32 zynq_fpga_read(const s
+ readl_poll_timeout(priv->io_base + addr, val, cond, sleep_us, \
+ timeout_us)
+
+-static void zynq_fpga_mask_irqs(struct zynq_fpga_priv *priv)
++/* Cause the specified irq mask bits to generate IRQs */
++static inline void zynq_fpga_set_irq(struct zynq_fpga_priv *priv, u32 enable)
+ {
+- u32 intr_mask;
+-
+- intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
+- zynq_fpga_write(priv, INT_MASK_OFFSET,
+- intr_mask | IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK);
+-}
+-
+-static void zynq_fpga_unmask_irqs(struct zynq_fpga_priv *priv)
+-{
+- u32 intr_mask;
+-
+- intr_mask = zynq_fpga_read(priv, INT_MASK_OFFSET);
+- zynq_fpga_write(priv, INT_MASK_OFFSET,
+- intr_mask
+- & ~(IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK));
++ zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable);
+ }
+
+ static irqreturn_t zynq_fpga_isr(int irq, void *data)
+@@ -167,7 +154,7 @@ static irqreturn_t zynq_fpga_isr(int irq
+ struct zynq_fpga_priv *priv = data;
+
+ /* disable DMA and error IRQs */
+- zynq_fpga_mask_irqs(priv);
++ zynq_fpga_set_irq(priv, 0);
+
+ complete(&priv->dma_done);
+
+@@ -285,6 +272,7 @@ static int zynq_fpga_ops_write(struct fp
+ const char *buf, size_t count)
+ {
+ struct zynq_fpga_priv *priv;
++ const char *why;
+ int err;
+ char *kbuf;
+ size_t in_count;
+@@ -312,7 +300,7 @@ static int zynq_fpga_ops_write(struct fp
+ reinit_completion(&priv->dma_done);
+
+ /* enable DMA and error IRQs */
+- zynq_fpga_unmask_irqs(priv);
++ zynq_fpga_set_irq(priv, IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
+
+ /* the +1 in the src addr is used to hold off on DMA_DONE IRQ
+ * until both AXI and PCAP are done ...
+@@ -331,11 +319,33 @@ static int zynq_fpga_ops_write(struct fp
+ intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
+ zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
+
++ if (intr_status & IXR_ERROR_FLAGS_MASK) {
++ why = "DMA reported error";
++ err = -EIO;
++ goto out_report;
++ }
++
+ if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
+- dev_err(&mgr->dev, "Error configuring FPGA\n");
+- err = -EFAULT;
++ why = "DMA did not complete";
++ err = -EIO;
++ goto out_report;
+ }
+
++ err = 0;
++ goto out_clk;
++
++out_report:
++ dev_err(&mgr->dev,
++ "%s: INT_STS:0x%x CTRL:0x%x LOCK:0x%x INT_MASK:0x%x STATUS:0x%x MCTRL:0x%x\n",
++ why,
++ intr_status,
++ zynq_fpga_read(priv, CTRL_OFFSET),
++ zynq_fpga_read(priv, LOCK_OFFSET),
++ zynq_fpga_read(priv, INT_MASK_OFFSET),
++ zynq_fpga_read(priv, STATUS_OFFSET),
++ zynq_fpga_read(priv, MCTRL_OFFSET));
++
++out_clk:
+ clk_disable(priv->clk);
+
+ out_free:
+@@ -452,7 +462,7 @@ static int zynq_fpga_probe(struct platfo
+ /* unlock the device */
+ zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
+
+- zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF);
++ zynq_fpga_set_irq(priv, 0);
+ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+ err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
+ priv);
diff --git a/patches.socfpga/0042-fpga-zynq-Check-the-bitstream-for-validity.patch b/patches.socfpga/0042-fpga-zynq-Check-the-bitstream-for-validity.patch
new file mode 100644
index 0000000..b5a3ac8
--- /dev/null
+++ b/patches.socfpga/0042-fpga-zynq-Check-the-bitstream-for-validity.patch
@@ -0,0 +1,72 @@
+From 1e390eb9365008a5f3713e390ffe4484f078468c Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Wed, 1 Feb 2017 12:48:43 -0700
+Subject: [PATCH 042/103] fpga zynq: Check the bitstream for validity
+
+There is no sense in sending a bitstream we know will not work, and
+with the variety of options for bitstream generation in Xilinx tools
+it is not terribly clear what the correct input should be.
+
+This is particularly important for Zynq since auto-correction was
+removed from the driver and the Zynq hardware only accepts a bitstream
+format that is different from what the Xilinx tools typically produce.
+
+Worse, the hardware provides no indication why the bitstream fails,
+it simply times out if the input is wrong.
+
+The best option here is to have the kernel print a message informing
+the user they are using a malformed bistream and programming failure
+isn't for any of the myriad of other reasons.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/zynq-fpga.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -161,6 +161,19 @@ static irqreturn_t zynq_fpga_isr(int irq
+ return IRQ_HANDLED;
+ }
+
++/* Sanity check the proposed bitstream. It must start with the sync word in
++ * the correct byte order, and be dword aligned. The input is a Xilinx .bin
++ * file with every 32 bit quantity swapped.
++ */
++static bool zynq_fpga_has_sync(const u8 *buf, size_t count)
++{
++ for (; count >= 4; buf += 4, count -= 4)
++ if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 &&
++ buf[3] == 0xaa)
++ return true;
++ return false;
++}
++
+ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t count)
+@@ -177,6 +190,13 @@ static int zynq_fpga_ops_write_init(stru
+
+ /* don't globally reset PL if we're doing partial reconfig */
+ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
++ if (!zynq_fpga_has_sync(buf, count)) {
++ dev_err(&mgr->dev,
++ "Invalid bitstream, could not find a sync word. Bitstream must be a byte swapped .bin file\n");
++ err = -EINVAL;
++ goto out_err;
++ }
++
+ /* assert AXI interface resets */
+ regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
+ FPGA_RST_ALL_MASK);
+@@ -410,6 +430,7 @@ static enum fpga_mgr_states zynq_fpga_op
+ }
+
+ static const struct fpga_manager_ops zynq_fpga_ops = {
++ .initial_header_size = 128,
+ .state = zynq_fpga_ops_state,
+ .write_init = zynq_fpga_ops_write_init,
+ .write = zynq_fpga_ops_write,
diff --git a/patches.socfpga/0043-fpga-Add-scatterlist-based-programming.patch b/patches.socfpga/0043-fpga-Add-scatterlist-based-programming.patch
new file mode 100644
index 0000000..b2b44e9
--- /dev/null
+++ b/patches.socfpga/0043-fpga-Add-scatterlist-based-programming.patch
@@ -0,0 +1,396 @@
+From 5b97663f81233b359315a0e26af540ad11e24171 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Wed, 1 Feb 2017 12:48:44 -0700
+Subject: [PATCH 043/103] fpga: Add scatterlist based programming
+
+Requiring contiguous kernel memory is not a good idea, this is a limited
+resource and allocation can fail under normal work loads.
+
+This introduces a .write_sg op that supporting drivers can provide
+to DMA directly from dis-contiguous memory and a new entry point
+fpga_mgr_buf_load_sg that users can call to directly provide page
+lists.
+
+The full matrix of compatibility is provided, either the linear or sg
+interface can be used by the user with a driver supporting either
+interface.
+
+A notable change for drivers is that the .write op can now be called
+multiple times.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/fpga/fpga-mgr.txt | 19 ++-
+ drivers/fpga/fpga-mgr.c | 236 ++++++++++++++++++++++++++++++++++------
+ include/linux/fpga/fpga-mgr.h | 5
+ 3 files changed, 227 insertions(+), 33 deletions(-)
+
+--- a/Documentation/fpga/fpga-mgr.txt
++++ b/Documentation/fpga/fpga-mgr.txt
+@@ -22,7 +22,16 @@ To program the FPGA from a file or from
+ struct fpga_image_info *info,
+ const char *buf, size_t count);
+
+-Load the FPGA from an image which exists as a buffer in memory.
++Load the FPGA from an image which exists as a contiguous buffer in
++memory. Allocating contiguous kernel memory for the buffer should be avoided,
++users are encouraged to use the _sg interface instead of this.
++
++ int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ struct sg_table *sgt);
++
++Load the FPGA from an image from non-contiguous in memory. Callers can
++construct a sg_table using alloc_page backed memory.
+
+ int fpga_mgr_firmware_load(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+@@ -166,7 +175,7 @@ success or negative error codes otherwis
+
+ The programming sequence is:
+ 1. .write_init
+- 2. .write (may be called once or multiple times)
++ 2. .write or .write_sg (may be called once or multiple times)
+ 3. .write_complete
+
+ The .write_init function will prepare the FPGA to receive the image data. The
+@@ -176,7 +185,11 @@ buffer up at least this much before star
+
+ The .write function writes a buffer to the FPGA. The buffer may be contain the
+ whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
+-case, this function is called multiple times for successive chunks.
++case, this function is called multiple times for successive chunks. This interface
++is suitable for drivers which use PIO.
++
++The .write_sg version behaves the same as .write except the input is a sg_table
++scatter list. This interface is suitable for drivers which use DMA.
+
+ The .write_complete function is called after all the image has been written
+ to put the FPGA into operating mode.
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -25,16 +25,106 @@
+ #include <linux/of.h>
+ #include <linux/mutex.h>
+ #include <linux/slab.h>
++#include <linux/scatterlist.h>
++#include <linux/highmem.h>
+
+ static DEFINE_IDA(fpga_mgr_ida);
+ static struct class *fpga_mgr_class;
+
++/*
++ * Call the low level driver's write_init function. This will do the
++ * device-specific things to get the FPGA into the state where it is ready to
++ * receive an FPGA image. The low level driver only gets to see the first
++ * initial_header_size bytes in the buffer.
++ */
++static int fpga_mgr_write_init_buf(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ int ret;
++
++ mgr->state = FPGA_MGR_STATE_WRITE_INIT;
++ if (!mgr->mops->initial_header_size)
++ ret = mgr->mops->write_init(mgr, info, NULL, 0);
++ else
++ ret = mgr->mops->write_init(
++ mgr, info, buf, min(mgr->mops->initial_header_size, count));
++
++ if (ret) {
++ dev_err(&mgr->dev, "Error preparing FPGA for writing\n");
++ mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
++ return ret;
++ }
++
++ return 0;
++}
++
++static int fpga_mgr_write_init_sg(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ struct sg_table *sgt)
++{
++ struct sg_mapping_iter miter;
++ size_t len;
++ char *buf;
++ int ret;
++
++ if (!mgr->mops->initial_header_size)
++ return fpga_mgr_write_init_buf(mgr, info, NULL, 0);
++
++ /*
++ * First try to use miter to map the first fragment to access the
++ * header, this is the typical path.
++ */
++ sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
++ if (sg_miter_next(&miter) &&
++ miter.length >= mgr->mops->initial_header_size) {
++ ret = fpga_mgr_write_init_buf(mgr, info, miter.addr,
++ miter.length);
++ sg_miter_stop(&miter);
++ return ret;
++ }
++ sg_miter_stop(&miter);
++
++ /* Otherwise copy the fragments into temporary memory. */
++ buf = kmalloc(mgr->mops->initial_header_size, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ len = sg_copy_to_buffer(sgt->sgl, sgt->nents, buf,
++ mgr->mops->initial_header_size);
++ ret = fpga_mgr_write_init_buf(mgr, info, buf, len);
++
++ kfree(buf);
++
++ return ret;
++}
++
++/*
++ * After all the FPGA image has been written, do the device specific steps to
++ * finish and set the FPGA into operating mode.
++ */
++static int fpga_mgr_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
++{
++ int ret;
++
++ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
++ ret = mgr->mops->write_complete(mgr, info);
++ if (ret) {
++ dev_err(&mgr->dev, "Error after writing image data to FPGA\n");
++ mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
++ return ret;
++ }
++ mgr->state = FPGA_MGR_STATE_OPERATING;
++
++ return 0;
++}
++
+ /**
+- * fpga_mgr_buf_load - load fpga from image in buffer
++ * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list
+ * @mgr: fpga manager
+ * @info: fpga image specific information
+- * @buf: buffer contain fpga image
+- * @count: byte count of buf
++ * @sgt: scatterlist table
+ *
+ * Step the low level fpga manager through the device-specific steps of getting
+ * an FPGA ready to be configured, writing the image to it, then doing whatever
+@@ -42,54 +132,139 @@ static struct class *fpga_mgr_class;
+ * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is
+ * not an error code.
+ *
++ * This is the preferred entry point for FPGA programming, it does not require
++ * any contiguous kernel memory.
++ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+-int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
+- const char *buf, size_t count)
++int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info,
++ struct sg_table *sgt)
+ {
+- struct device *dev = &mgr->dev;
+ int ret;
+
+- /*
+- * Call the low level driver's write_init function. This will do the
+- * device-specific things to get the FPGA into the state where it is
+- * ready to receive an FPGA image. The low level driver only gets to
+- * see the first initial_header_size bytes in the buffer.
+- */
+- mgr->state = FPGA_MGR_STATE_WRITE_INIT;
+- ret = mgr->mops->write_init(mgr, info, buf,
+- min(mgr->mops->initial_header_size, count));
++ ret = fpga_mgr_write_init_sg(mgr, info, sgt);
++ if (ret)
++ return ret;
++
++ /* Write the FPGA image to the FPGA. */
++ mgr->state = FPGA_MGR_STATE_WRITE;
++ if (mgr->mops->write_sg) {
++ ret = mgr->mops->write_sg(mgr, sgt);
++ } else {
++ struct sg_mapping_iter miter;
++
++ sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
++ while (sg_miter_next(&miter)) {
++ ret = mgr->mops->write(mgr, miter.addr, miter.length);
++ if (ret)
++ break;
++ }
++ sg_miter_stop(&miter);
++ }
++
+ if (ret) {
+- dev_err(dev, "Error preparing FPGA for writing\n");
+- mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
++ dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
++ mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+ return ret;
+ }
+
++ return fpga_mgr_write_complete(mgr, info);
++}
++EXPORT_SYMBOL_GPL(fpga_mgr_buf_load_sg);
++
++static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ int ret;
++
++ ret = fpga_mgr_write_init_buf(mgr, info, buf, count);
++ if (ret)
++ return ret;
++
+ /*
+ * Write the FPGA image to the FPGA.
+ */
+ mgr->state = FPGA_MGR_STATE_WRITE;
+ ret = mgr->mops->write(mgr, buf, count);
+ if (ret) {
+- dev_err(dev, "Error while writing image data to FPGA\n");
++ dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
+ mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+ return ret;
+ }
+
++ return fpga_mgr_write_complete(mgr, info);
++}
++
++/**
++ * fpga_mgr_buf_load - load fpga from image in buffer
++ * @mgr: fpga manager
++ * @flags: flags setting fpga confuration modes
++ * @buf: buffer contain fpga image
++ * @count: byte count of buf
++ *
++ * Step the low level fpga manager through the device-specific steps of getting
++ * an FPGA ready to be configured, writing the image to it, then doing whatever
++ * post-configuration steps necessary. This code assumes the caller got the
++ * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
++ *
++ * Return: 0 on success, negative error code otherwise.
++ */
++int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ struct page **pages;
++ struct sg_table sgt;
++ const void *p;
++ int nr_pages;
++ int index;
++ int rc;
++
+ /*
+- * After all the FPGA image has been written, do the device specific
+- * steps to finish and set the FPGA into operating mode.
++ * This is just a fast path if the caller has already created a
++ * contiguous kernel buffer and the driver doesn't require SG, non-SG
++ * drivers will still work on the slow path.
+ */
+- mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
+- ret = mgr->mops->write_complete(mgr, info);
+- if (ret) {
+- dev_err(dev, "Error after writing image data to FPGA\n");
+- mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+- return ret;
++ if (mgr->mops->write)
++ return fpga_mgr_buf_load_mapped(mgr, info, buf, count);
++
++ /*
++ * Convert the linear kernel pointer into a sg_table of pages for use
++ * by the driver.
++ */
++ nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) -
++ (unsigned long)buf / PAGE_SIZE;
++ pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
++ if (!pages)
++ return -ENOMEM;
++
++ p = buf - offset_in_page(buf);
++ for (index = 0; index < nr_pages; index++) {
++ if (is_vmalloc_addr(p))
++ pages[index] = vmalloc_to_page(p);
++ else
++ pages[index] = kmap_to_page((void *)p);
++ if (!pages[index]) {
++ kfree(pages);
++ return -EFAULT;
++ }
++ p += PAGE_SIZE;
+ }
+- mgr->state = FPGA_MGR_STATE_OPERATING;
+
+- return 0;
++ /*
++ * The temporary pages list is used to code share the merging algorithm
++ * in sg_alloc_table_from_pages
++ */
++ rc = sg_alloc_table_from_pages(&sgt, pages, index, offset_in_page(buf),
++ count, GFP_KERNEL);
++ kfree(pages);
++ if (rc)
++ return rc;
++
++ rc = fpga_mgr_buf_load_sg(mgr, info, &sgt);
++ sg_free_table(&sgt);
++
++ return rc;
+ }
+ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
+
+@@ -291,8 +466,9 @@ int fpga_mgr_register(struct device *dev
+ struct fpga_manager *mgr;
+ int id, ret;
+
+- if (!mops || !mops->write_init || !mops->write ||
+- !mops->write_complete || !mops->state) {
++ if (!mops || !mops->write_complete || !mops->state ||
++ !mops->write_init || (!mops->write && !mops->write_sg) ||
++ (mops->write && mops->write_sg)) {
+ dev_err(dev, "Attempt to register without fpga_manager_ops\n");
+ return -EINVAL;
+ }
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -22,6 +22,7 @@
+ #define _LINUX_FPGA_MGR_H
+
+ struct fpga_manager;
++struct sg_table;
+
+ /**
+ * enum fpga_mgr_states - fpga framework states
+@@ -88,6 +89,7 @@ struct fpga_image_info {
+ * @state: returns an enum value of the FPGA's state
+ * @write_init: prepare the FPGA to receive confuration data
+ * @write: write count bytes of configuration data to the FPGA
++ * @write_sg: write the scatter list of configuration data to the FPGA
+ * @write_complete: set FPGA to operating state after writing is done
+ * @fpga_remove: optional: Set FPGA into a specific state during driver remove
+ *
+@@ -102,6 +104,7 @@ struct fpga_manager_ops {
+ struct fpga_image_info *info,
+ const char *buf, size_t count);
+ int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
++ int (*write_sg)(struct fpga_manager *mgr, struct sg_table *sgt);
+ int (*write_complete)(struct fpga_manager *mgr,
+ struct fpga_image_info *info);
+ void (*fpga_remove)(struct fpga_manager *mgr);
+@@ -129,6 +132,8 @@ struct fpga_manager {
+
+ int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
+ const char *buf, size_t count);
++int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info,
++ struct sg_table *sgt);
+
+ int fpga_mgr_firmware_load(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
diff --git a/patches.socfpga/0044-fpga-zynq-Use-the-scatterlist-interface.patch b/patches.socfpga/0044-fpga-zynq-Use-the-scatterlist-interface.patch
new file mode 100644
index 0000000..f14aebd
--- /dev/null
+++ b/patches.socfpga/0044-fpga-zynq-Use-the-scatterlist-interface.patch
@@ -0,0 +1,304 @@
+From d8b26435b18259639f39aab9ff96cfbf5fdd1076 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Wed, 1 Feb 2017 12:48:45 -0700
+Subject: [PATCH 044/103] fpga zynq: Use the scatterlist interface
+
+This allows the driver to avoid a high order coherent DMA allocation
+and memory copy. With this patch it can DMA directly from the kernel
+pages that the bitfile is stored in.
+
+Since this is now a gather DMA operation the driver uses the ISR
+to feed the chips DMA queue with each entry from the SGL.
+
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/zynq-fpga.c | 174 ++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 135 insertions(+), 39 deletions(-)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -30,6 +30,7 @@
+ #include <linux/pm.h>
+ #include <linux/regmap.h>
+ #include <linux/string.h>
++#include <linux/scatterlist.h>
+
+ /* Offsets into SLCR regmap */
+
+@@ -80,6 +81,7 @@
+
+ /* FPGA init status */
+ #define STATUS_DMA_Q_F BIT(31)
++#define STATUS_DMA_Q_E BIT(30)
+ #define STATUS_PCFG_INIT_MASK BIT(4)
+
+ /* Interrupt Status/Mask Register Bit definitions */
+@@ -98,12 +100,16 @@
+ #define DMA_INVALID_ADDRESS GENMASK(31, 0)
+ /* Used to unlock the dev */
+ #define UNLOCK_MASK 0x757bdf0d
+-/* Timeout for DMA to complete */
+-#define DMA_DONE_TIMEOUT msecs_to_jiffies(1000)
+ /* Timeout for polling reset bits */
+ #define INIT_POLL_TIMEOUT 2500000
+ /* Delay for polling reset bits */
+ #define INIT_POLL_DELAY 20
++/* Signal this is the last DMA transfer, wait for the AXI and PCAP before
++ * interrupting
++ */
++#define DMA_SRC_LAST_TRANSFER 1
++/* Timeout for DMA completion */
++#define DMA_TIMEOUT_MS 5000
+
+ /* Masks for controlling stuff in SLCR */
+ /* Disable all Level shifters */
+@@ -124,6 +130,11 @@ struct zynq_fpga_priv {
+ void __iomem *io_base;
+ struct regmap *slcr;
+
++ spinlock_t dma_lock;
++ unsigned int dma_elm;
++ unsigned int dma_nelms;
++ struct scatterlist *cur_sg;
++
+ struct completion dma_done;
+ };
+
+@@ -149,13 +160,80 @@ static inline void zynq_fpga_set_irq(str
+ zynq_fpga_write(priv, INT_MASK_OFFSET, ~enable);
+ }
+
++/* Must be called with dma_lock held */
++static void zynq_step_dma(struct zynq_fpga_priv *priv)
++{
++ u32 addr;
++ u32 len;
++ bool first;
++
++ first = priv->dma_elm == 0;
++ while (priv->cur_sg) {
++ /* Feed the DMA queue until it is full. */
++ if (zynq_fpga_read(priv, STATUS_OFFSET) & STATUS_DMA_Q_F)
++ break;
++
++ addr = sg_dma_address(priv->cur_sg);
++ len = sg_dma_len(priv->cur_sg);
++ if (priv->dma_elm + 1 == priv->dma_nelms) {
++ /* The last transfer waits for the PCAP to finish too,
++ * notice this also changes the irq_mask to ignore
++ * IXR_DMA_DONE_MASK which ensures we do not trigger
++ * the completion too early.
++ */
++ addr |= DMA_SRC_LAST_TRANSFER;
++ priv->cur_sg = NULL;
++ } else {
++ priv->cur_sg = sg_next(priv->cur_sg);
++ priv->dma_elm++;
++ }
++
++ zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, addr);
++ zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, DMA_INVALID_ADDRESS);
++ zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, len / 4);
++ zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
++ }
++
++ /* Once the first transfer is queued we can turn on the ISR, future
++ * calls to zynq_step_dma will happen from the ISR context. The
++ * dma_lock spinlock guarentees this handover is done coherently, the
++ * ISR enable is put at the end to avoid another CPU spinning in the
++ * ISR on this lock.
++ */
++ if (first && priv->cur_sg) {
++ zynq_fpga_set_irq(priv,
++ IXR_DMA_DONE_MASK | IXR_ERROR_FLAGS_MASK);
++ } else if (!priv->cur_sg) {
++ /* The last transfer changes to DMA & PCAP mode since we do
++ * not want to continue until everything has been flushed into
++ * the PCAP.
++ */
++ zynq_fpga_set_irq(priv,
++ IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
++ }
++}
++
+ static irqreturn_t zynq_fpga_isr(int irq, void *data)
+ {
+ struct zynq_fpga_priv *priv = data;
++ u32 intr_status;
+
+- /* disable DMA and error IRQs */
+- zynq_fpga_set_irq(priv, 0);
++ /* If anything other than DMA completion is reported stop and hand
++ * control back to zynq_fpga_ops_write, something went wrong,
++ * otherwise progress the DMA.
++ */
++ spin_lock(&priv->dma_lock);
++ intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
++ if (!(intr_status & IXR_ERROR_FLAGS_MASK) &&
++ (intr_status & IXR_DMA_DONE_MASK) && priv->cur_sg) {
++ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_DMA_DONE_MASK);
++ zynq_step_dma(priv);
++ spin_unlock(&priv->dma_lock);
++ return IRQ_HANDLED;
++ }
++ spin_unlock(&priv->dma_lock);
+
++ zynq_fpga_set_irq(priv, 0);
+ complete(&priv->dma_done);
+
+ return IRQ_HANDLED;
+@@ -266,10 +344,11 @@ static int zynq_fpga_ops_write_init(stru
+ zynq_fpga_write(priv, CTRL_OFFSET,
+ (CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK | ctrl));
+
+- /* check that we have room in the command queue */
++ /* We expect that the command queue is empty right now. */
+ status = zynq_fpga_read(priv, STATUS_OFFSET);
+- if (status & STATUS_DMA_Q_F) {
+- dev_err(&mgr->dev, "DMA command queue full\n");
++ if ((status & STATUS_DMA_Q_F) ||
++ (status & STATUS_DMA_Q_E) != STATUS_DMA_Q_E) {
++ dev_err(&mgr->dev, "DMA command queue not right\n");
+ err = -EBUSY;
+ goto out_err;
+ }
+@@ -288,27 +367,36 @@ out_err:
+ return err;
+ }
+
+-static int zynq_fpga_ops_write(struct fpga_manager *mgr,
+- const char *buf, size_t count)
++static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
+ {
+ struct zynq_fpga_priv *priv;
+ const char *why;
+ int err;
+- char *kbuf;
+- size_t in_count;
+- dma_addr_t dma_addr;
+- u32 transfer_length;
+ u32 intr_status;
++ unsigned long timeout;
++ unsigned long flags;
++ struct scatterlist *sg;
++ int i;
+
+- in_count = count;
+ priv = mgr->priv;
+
+- kbuf =
+- dma_alloc_coherent(mgr->dev.parent, count, &dma_addr, GFP_KERNEL);
+- if (!kbuf)
+- return -ENOMEM;
++ /* The hardware can only DMA multiples of 4 bytes, and it requires the
++ * starting addresses to be aligned to 64 bits (UG585 pg 212).
++ */
++ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
++ if ((sg->offset % 8) || (sg->length % 4)) {
++ dev_err(&mgr->dev,
++ "Invalid bitstream, chunks must be aligned\n");
++ return -EINVAL;
++ }
++ }
+
+- memcpy(kbuf, buf, count);
++ priv->dma_nelms =
++ dma_map_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE);
++ if (priv->dma_nelms == 0) {
++ dev_err(&mgr->dev, "Unable to DMA map (TO_DEVICE)\n");
++ return -ENOMEM;
++ }
+
+ /* enable clock */
+ err = clk_enable(priv->clk);
+@@ -316,28 +404,31 @@ static int zynq_fpga_ops_write(struct fp
+ goto out_free;
+
+ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+-
+ reinit_completion(&priv->dma_done);
+
+- /* enable DMA and error IRQs */
+- zynq_fpga_set_irq(priv, IXR_D_P_DONE_MASK | IXR_ERROR_FLAGS_MASK);
+-
+- /* the +1 in the src addr is used to hold off on DMA_DONE IRQ
+- * until both AXI and PCAP are done ...
+- */
+- zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, (u32)(dma_addr) + 1);
+- zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, (u32)DMA_INVALID_ADDRESS);
+-
+- /* convert #bytes to #words */
+- transfer_length = (count + 3) / 4;
++ /* zynq_step_dma will turn on interrupts */
++ spin_lock_irqsave(&priv->dma_lock, flags);
++ priv->dma_elm = 0;
++ priv->cur_sg = sgt->sgl;
++ zynq_step_dma(priv);
++ spin_unlock_irqrestore(&priv->dma_lock, flags);
+
+- zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, transfer_length);
+- zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
++ timeout = wait_for_completion_timeout(&priv->dma_done,
++ msecs_to_jiffies(DMA_TIMEOUT_MS));
+
+- wait_for_completion(&priv->dma_done);
++ spin_lock_irqsave(&priv->dma_lock, flags);
++ zynq_fpga_set_irq(priv, 0);
++ priv->cur_sg = NULL;
++ spin_unlock_irqrestore(&priv->dma_lock, flags);
+
+ intr_status = zynq_fpga_read(priv, INT_STS_OFFSET);
+- zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
++ zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
++
++ /* There doesn't seem to be a way to force cancel any DMA, so if
++ * something went wrong we are relying on the hardware to have halted
++ * the DMA before we get here, if there was we could use
++ * wait_for_completion_interruptible too.
++ */
+
+ if (intr_status & IXR_ERROR_FLAGS_MASK) {
+ why = "DMA reported error";
+@@ -345,8 +436,12 @@ static int zynq_fpga_ops_write(struct fp
+ goto out_report;
+ }
+
+- if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
+- why = "DMA did not complete";
++ if (priv->cur_sg ||
++ !((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
++ if (timeout == 0)
++ why = "DMA timed out";
++ else
++ why = "DMA did not complete";
+ err = -EIO;
+ goto out_report;
+ }
+@@ -369,7 +464,7 @@ out_clk:
+ clk_disable(priv->clk);
+
+ out_free:
+- dma_free_coherent(mgr->dev.parent, count, kbuf, dma_addr);
++ dma_unmap_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE);
+ return err;
+ }
+
+@@ -433,7 +528,7 @@ static const struct fpga_manager_ops zyn
+ .initial_header_size = 128,
+ .state = zynq_fpga_ops_state,
+ .write_init = zynq_fpga_ops_write_init,
+- .write = zynq_fpga_ops_write,
++ .write_sg = zynq_fpga_ops_write,
+ .write_complete = zynq_fpga_ops_write_complete,
+ };
+
+@@ -447,6 +542,7 @@ static int zynq_fpga_probe(struct platfo
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
++ spin_lock_init(&priv->dma_lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->io_base = devm_ioremap_resource(dev, res);
diff --git a/patches.socfpga/0045-fpga-fix-sparse-warnings-in-fpga-mgr-and-fpga-bridge.patch b/patches.socfpga/0045-fpga-fix-sparse-warnings-in-fpga-mgr-and-fpga-bridge.patch
new file mode 100644
index 0000000..8c9fde3
--- /dev/null
+++ b/patches.socfpga/0045-fpga-fix-sparse-warnings-in-fpga-mgr-and-fpga-bridge.patch
@@ -0,0 +1,41 @@
+From e465a0699c040d68ea3790af91f6e73cd4797ea7 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Mon, 27 Feb 2017 09:18:59 -0600
+Subject: [PATCH 045/103] fpga: fix sparse warnings in fpga-mgr and fpga-bridge
+
+Fix up these sparse warnings:
+
+drivers/fpga/fpga-mgr.c:189:21: warning: symbol '__fpga_mgr_get' was not declared. Should it be static?
+drivers/fpga/fpga-bridge.c:30:12: warning: symbol 'bridge_list_lock' was not declared. Should it be static?
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Acked-by: Moritz Fischer <mdf@kernel.org>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/fpga-bridge.c | 2 +-
+ drivers/fpga/fpga-mgr.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/fpga/fpga-bridge.c
++++ b/drivers/fpga/fpga-bridge.c
+@@ -27,7 +27,7 @@ static DEFINE_IDA(fpga_bridge_ida);
+ static struct class *fpga_bridge_class;
+
+ /* Lock for adding/removing bridges to linked lists*/
+-spinlock_t bridge_list_lock;
++static spinlock_t bridge_list_lock;
+
+ static int fpga_bridge_of_node_match(struct device *dev, const void *data)
+ {
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -361,7 +361,7 @@ static struct attribute *fpga_mgr_attrs[
+ };
+ ATTRIBUTE_GROUPS(fpga_mgr);
+
+-struct fpga_manager *__fpga_mgr_get(struct device *dev)
++static struct fpga_manager *__fpga_mgr_get(struct device *dev)
+ {
+ struct fpga_manager *mgr;
+ int ret = -ENODEV;
diff --git a/patches.socfpga/0046-fpga-Add-flag-to-indicate-bitstream-needs-decrypting.patch b/patches.socfpga/0046-fpga-Add-flag-to-indicate-bitstream-needs-decrypting.patch
new file mode 100644
index 0000000..f2327b0
--- /dev/null
+++ b/patches.socfpga/0046-fpga-Add-flag-to-indicate-bitstream-needs-decrypting.patch
@@ -0,0 +1,29 @@
+From 52ae233165163bb6c71e8be8ee703a1eb0fa3e25 Mon Sep 17 00:00:00 2001
+From: Moritz Fischer <mdf@kernel.org>
+Date: Mon, 27 Feb 2017 09:19:00 -0600
+Subject: [PATCH 046/103] fpga: Add flag to indicate bitstream needs decrypting
+
+Add a flag that is passed to the write_init() callback, indicating
+that the bitstream is encrypted.
+
+The low-level driver will deal with the flag, or return an error,
+if encrypted bitstreams are not supported.
+
+Signed-off-by: Moritz Fischer <mdf@kernel.org>
+Acked-by: Michal Simek <michal.simek@xilinx.com>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/fpga/fpga-mgr.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -70,6 +70,7 @@ enum fpga_mgr_states {
+ */
+ #define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
+ #define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
++#define FPGA_MGR_ENCRYPTED_BITSTREAM BIT(2)
+
+ /**
+ * struct fpga_image_info - information specific to a FPGA image
diff --git a/patches.socfpga/0047-fpga-zynq-Add-support-for-encrypted-bitstreams.patch b/patches.socfpga/0047-fpga-zynq-Add-support-for-encrypted-bitstreams.patch
new file mode 100644
index 0000000..db09d00
--- /dev/null
+++ b/patches.socfpga/0047-fpga-zynq-Add-support-for-encrypted-bitstreams.patch
@@ -0,0 +1,73 @@
+From 478e30d8b329c3c6212e903e6ba68997e2f0582a Mon Sep 17 00:00:00 2001
+From: Moritz Fischer <mdf@kernel.org>
+Date: Mon, 27 Feb 2017 09:19:01 -0600
+Subject: [PATCH 047/103] fpga: zynq: Add support for encrypted bitstreams
+
+Add support for encrypted bitstreams. For this to work the system
+must be booted in secure mode.
+
+In order for on-the-fly decryption to work, the PCAP clock rate
+needs to be lowered via the PCAP_RATE_EN bit.
+
+Signed-off-by: Moritz Fischer <mdf@kernel.org>
+Acked-by: Michal Simek <michal.simek@xilinx.com>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/zynq-fpga.c | 28 +++++++++++++++++++++++++---
+ 1 file changed, 25 insertions(+), 3 deletions(-)
+
+--- a/drivers/fpga/zynq-fpga.c
++++ b/drivers/fpga/zynq-fpga.c
+@@ -72,6 +72,10 @@
+ #define CTRL_PCAP_PR_MASK BIT(27)
+ /* Enable PCAP */
+ #define CTRL_PCAP_MODE_MASK BIT(26)
++/* Lower rate to allow decrypt on the fly */
++#define CTRL_PCAP_RATE_EN_MASK BIT(25)
++/* System booted in secure mode */
++#define CTRL_SEC_EN_MASK BIT(7)
+
+ /* Miscellaneous Control Register bit definitions */
+ /* Internal PCAP loopback */
+@@ -266,6 +270,17 @@ static int zynq_fpga_ops_write_init(stru
+ if (err)
+ return err;
+
++ /* check if bitstream is encrypted & and system's still secure */
++ if (info->flags & FPGA_MGR_ENCRYPTED_BITSTREAM) {
++ ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
++ if (!(ctrl & CTRL_SEC_EN_MASK)) {
++ dev_err(&mgr->dev,
++ "System not secure, can't use crypted bitstreams\n");
++ err = -EINVAL;
++ goto out_err;
++ }
++ }
++
+ /* don't globally reset PL if we're doing partial reconfig */
+ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ if (!zynq_fpga_has_sync(buf, count)) {
+@@ -337,12 +352,19 @@ static int zynq_fpga_ops_write_init(stru
+
+ /* set configuration register with following options:
+ * - enable PCAP interface
+- * - set throughput for maximum speed
++ * - set throughput for maximum speed (if bistream not crypted)
+ * - set CPU in user mode
+ */
+ ctrl = zynq_fpga_read(priv, CTRL_OFFSET);
+- zynq_fpga_write(priv, CTRL_OFFSET,
+- (CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK | ctrl));
++ if (info->flags & FPGA_MGR_ENCRYPTED_BITSTREAM)
++ zynq_fpga_write(priv, CTRL_OFFSET,
++ (CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK
++ | CTRL_PCAP_RATE_EN_MASK | ctrl));
++ else
++ zynq_fpga_write(priv, CTRL_OFFSET,
++ (CTRL_PCAP_PR_MASK | CTRL_PCAP_MODE_MASK
++ | ctrl));
++
+
+ /* We expect that the command queue is empty right now. */
+ status = zynq_fpga_read(priv, STATUS_OFFSET);
diff --git a/patches.socfpga/0048-fpga-region-Add-fpga-region-property-encrypted-fpga-.patch b/patches.socfpga/0048-fpga-region-Add-fpga-region-property-encrypted-fpga-.patch
new file mode 100644
index 0000000..2b425ec
--- /dev/null
+++ b/patches.socfpga/0048-fpga-region-Add-fpga-region-property-encrypted-fpga-.patch
@@ -0,0 +1,52 @@
+From 273c66a75fbbc3ca0afc73fc39c36932da94b37f Mon Sep 17 00:00:00 2001
+From: Moritz Fischer <mdf@kernel.org>
+Date: Mon, 27 Feb 2017 09:19:02 -0600
+Subject: [PATCH 048/103] fpga: region: Add fpga-region property
+ 'encrypted-fpga-config'
+
+Add fpga-region property to allow passing the fact that the bitstream is
+encrypted to the fpga-region and ultimately to the low-level driver.
+
+Signed-off-by: Moritz Fischer <mdf@kernel.org>
+Acked-by: Michal Simek <michal.simek@xilinx.com>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/fpga/fpga-region.txt | 1 +
+ drivers/fpga/fpga-region.c | 8 ++++++--
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/Documentation/devicetree/bindings/fpga/fpga-region.txt
++++ b/Documentation/devicetree/bindings/fpga/fpga-region.txt
+@@ -186,6 +186,7 @@ Optional properties:
+ otherwise full reconfiguration is done.
+ - external-fpga-config : boolean, set if the FPGA has already been configured
+ prior to OS boot up.
++- encrypted-fpga-config : boolean, set if the bitstream is encrypted
+ - region-unfreeze-timeout-us : The maximum time in microseconds to wait for
+ bridges to successfully become enabled after the region has been
+ programmed.
+--- a/drivers/fpga/fpga-region.c
++++ b/drivers/fpga/fpga-region.c
+@@ -337,8 +337,9 @@ static int child_regions_with_firmware(s
+ * The overlay must add either firmware-name or external-fpga-config property
+ * to the FPGA Region.
+ *
+- * firmware-name : program the FPGA
+- * external-fpga-config : FPGA is already programmed
++ * firmware-name : program the FPGA
++ * external-fpga-config : FPGA is already programmed
++ * encrypted-fpga-config : FPGA bitstream is encrypted
+ *
+ * The overlay can add other FPGA regions, but child FPGA regions cannot have a
+ * firmware-name property since those regions don't exist yet.
+@@ -373,6 +374,9 @@ static int fpga_region_notify_pre_apply(
+ if (of_property_read_bool(nd->overlay, "external-fpga-config"))
+ info->flags |= FPGA_MGR_EXTERNAL_CONFIG;
+
++ if (of_property_read_bool(nd->overlay, "encrypted-fpga-config"))
++ info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM;
++
+ of_property_read_string(nd->overlay, "firmware-name", &firmware_name);
+
+ of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us",
diff --git a/patches.socfpga/0049-FPGA-Add-TS-7300-FPGA-manager.patch b/patches.socfpga/0049-FPGA-Add-TS-7300-FPGA-manager.patch
new file mode 100644
index 0000000..6dbc86a
--- /dev/null
+++ b/patches.socfpga/0049-FPGA-Add-TS-7300-FPGA-manager.patch
@@ -0,0 +1,211 @@
+From bed35874b4fe30165188c479341d04fdb7d74230 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <f.fainelli@gmail.com>
+Date: Mon, 27 Feb 2017 16:14:22 -0600
+Subject: [PATCH 049/103] FPGA: Add TS-7300 FPGA manager
+
+Add support for loading bitstreams on the Altera Cyclone II FPGA
+populated on the TS-7300 board. This is done through the configuration
+and data registers offered through a memory interface between the EP93xx
+SoC and the FPGA via an intermediate CPLD device.
+
+The EP93xx SoC on the TS-7300 does not have direct means of configuring
+the on-board FPGA other than by using the special memory mapped
+interface to the CPLD. No other entity on the system can control the
+FPGA bitstream.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 7 ++
+ drivers/fpga/Makefile | 1
+ drivers/fpga/ts73xx-fpga.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 164 insertions(+)
+ create mode 100644 drivers/fpga/ts73xx-fpga.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -33,6 +33,13 @@ config FPGA_MGR_SOCFPGA_A10
+ help
+ FPGA manager driver support for Altera Arria10 SoCFPGA.
+
++config FPGA_MGR_TS73XX
++ tristate "Technologic Systems TS-73xx SBC FPGA Manager"
++ depends on ARCH_EP93XX && MACH_TS72XX
++ help
++ FPGA manager driver support for the Altera Cyclone II FPGA
++ present on the TS-73xx SBC boards.
++
+ config FPGA_MGR_ZYNQ_FPGA
+ tristate "Xilinx Zynq FPGA"
+ depends on ARCH_ZYNQ || COMPILE_TEST
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o
+ # FPGA Manager Drivers
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
++obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
+ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
+
+ # FPGA Bridge Drivers
+--- /dev/null
++++ b/drivers/fpga/ts73xx-fpga.c
+@@ -0,0 +1,156 @@
++/*
++ * Technologic Systems TS-73xx SBC FPGA loader
++ *
++ * Copyright (C) 2016 Florian Fainelli <f.fainelli@gmail.com>
++ *
++ * FPGA Manager Driver for the on-board Altera Cyclone II FPGA found on
++ * TS-7300, heavily based on load_fpga.c in their vendor tree.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/string.h>
++#include <linux/iopoll.h>
++#include <linux/fpga/fpga-mgr.h>
++
++#define TS73XX_FPGA_DATA_REG 0
++#define TS73XX_FPGA_CONFIG_REG 1
++
++#define TS73XX_FPGA_WRITE_DONE 0x1
++#define TS73XX_FPGA_WRITE_DONE_TIMEOUT 1000 /* us */
++#define TS73XX_FPGA_RESET 0x2
++#define TS73XX_FPGA_RESET_LOW_DELAY 30 /* us */
++#define TS73XX_FPGA_RESET_HIGH_DELAY 80 /* us */
++#define TS73XX_FPGA_LOAD_OK 0x4
++#define TS73XX_FPGA_CONFIG_LOAD 0x8
++
++struct ts73xx_fpga_priv {
++ void __iomem *io_base;
++ struct device *dev;
++};
++
++static enum fpga_mgr_states ts73xx_fpga_state(struct fpga_manager *mgr)
++{
++ return FPGA_MGR_STATE_UNKNOWN;
++}
++
++static int ts73xx_fpga_write_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ struct ts73xx_fpga_priv *priv = mgr->priv;
++
++ /* Reset the FPGA */
++ writeb(0, priv->io_base + TS73XX_FPGA_CONFIG_REG);
++ udelay(TS73XX_FPGA_RESET_LOW_DELAY);
++ writeb(TS73XX_FPGA_RESET, priv->io_base + TS73XX_FPGA_CONFIG_REG);
++ udelay(TS73XX_FPGA_RESET_HIGH_DELAY);
++
++ return 0;
++}
++
++static int ts73xx_fpga_write(struct fpga_manager *mgr, const char *buf,
++ size_t count)
++{
++ struct ts73xx_fpga_priv *priv = mgr->priv;
++ size_t i = 0;
++ int ret;
++ u8 reg;
++
++ while (count--) {
++ ret = readb_poll_timeout(priv->io_base + TS73XX_FPGA_CONFIG_REG,
++ reg, !(reg & TS73XX_FPGA_WRITE_DONE),
++ 1, TS73XX_FPGA_WRITE_DONE_TIMEOUT);
++ if (ret < 0)
++ return ret;
++
++ writeb(buf[i], priv->io_base + TS73XX_FPGA_DATA_REG);
++ i++;
++ }
++
++ return 0;
++}
++
++static int ts73xx_fpga_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
++{
++ struct ts73xx_fpga_priv *priv = mgr->priv;
++ u8 reg;
++
++ usleep_range(1000, 2000);
++ reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
++ reg |= TS73XX_FPGA_CONFIG_LOAD;
++ writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
++
++ usleep_range(1000, 2000);
++ reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
++ reg &= ~TS73XX_FPGA_CONFIG_LOAD;
++ writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
++
++ reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
++ if ((reg & TS73XX_FPGA_LOAD_OK) != TS73XX_FPGA_LOAD_OK)
++ return -ETIMEDOUT;
++
++ return 0;
++}
++
++static const struct fpga_manager_ops ts73xx_fpga_ops = {
++ .state = ts73xx_fpga_state,
++ .write_init = ts73xx_fpga_write_init,
++ .write = ts73xx_fpga_write,
++ .write_complete = ts73xx_fpga_write_complete,
++};
++
++static int ts73xx_fpga_probe(struct platform_device *pdev)
++{
++ struct device *kdev = &pdev->dev;
++ struct ts73xx_fpga_priv *priv;
++ struct resource *res;
++
++ priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->dev = kdev;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ priv->io_base = devm_ioremap_resource(kdev, res);
++ if (IS_ERR(priv->io_base)) {
++ dev_err(kdev, "unable to remap registers\n");
++ return PTR_ERR(priv->io_base);
++ }
++
++ return fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
++ &ts73xx_fpga_ops, priv);
++}
++
++static int ts73xx_fpga_remove(struct platform_device *pdev)
++{
++ fpga_mgr_unregister(&pdev->dev);
++
++ return 0;
++}
++
++static struct platform_driver ts73xx_fpga_driver = {
++ .driver = {
++ .name = "ts73xx-fpga-mgr",
++ },
++ .probe = ts73xx_fpga_probe,
++ .remove = ts73xx_fpga_remove,
++};
++module_platform_driver(ts73xx_fpga_driver);
++
++MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>");
++MODULE_DESCRIPTION("TS-73xx FPGA Manager driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0050-Documentation-Add-binding-document-for-Lattice-iCE40.patch b/patches.socfpga/0050-Documentation-Add-binding-document-for-Lattice-iCE40.patch
new file mode 100644
index 0000000..c933e57
--- /dev/null
+++ b/patches.socfpga/0050-Documentation-Add-binding-document-for-Lattice-iCE40.patch
@@ -0,0 +1,44 @@
+From 17e3c8974a87f231c91825ff809988797a001f35 Mon Sep 17 00:00:00 2001
+From: Joel Holdsworth <joel@airwebreathe.org.uk>
+Date: Mon, 27 Feb 2017 16:14:25 -0600
+Subject: [PATCH 050/103] Documentation: Add binding document for Lattice iCE40
+ FPGA manager
+
+This adds documentation of the device tree bindings of the Lattice iCE40
+FPGA driver for the FPGA manager framework.
+
+Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Acked-by: Marek Vasut <marex@denx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt | 21 ++++++++++
+ 1 file changed, 21 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
+@@ -0,0 +1,21 @@
++Lattice iCE40 FPGA Manager
++
++Required properties:
++- compatible: Should contain "lattice,ice40-fpga-mgr"
++- reg: SPI chip select
++- spi-max-frequency: Maximum SPI frequency (>=1000000, <=25000000)
++- cdone-gpios: GPIO input connected to CDONE pin
++- reset-gpios: Active-low GPIO output connected to CRESET_B pin. Note
++ that unless the GPIO is held low during startup, the
++ FPGA will enter Master SPI mode and drive SCK with a
++ clock signal potentially jamming other devices on the
++ bus until the firmware is loaded.
++
++Example:
++ fpga: fpga@0 {
++ compatible = "lattice,ice40-fpga-mgr";
++ reg = <0>;
++ spi-max-frequency = <1000000>;
++ cdone-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
++ reset-gpios = <&gpio 22 GPIO_ACTIVE_LOW>;
++ };
diff --git a/patches.socfpga/0051-fpga-Add-support-for-Lattice-iCE40-FPGAs.patch b/patches.socfpga/0051-fpga-Add-support-for-Lattice-iCE40-FPGAs.patch
new file mode 100644
index 0000000..afe02a5
--- /dev/null
+++ b/patches.socfpga/0051-fpga-Add-support-for-Lattice-iCE40-FPGAs.patch
@@ -0,0 +1,256 @@
+From dea9de651d978f61922c8cebd01a3089c0acfd04 Mon Sep 17 00:00:00 2001
+From: Joel Holdsworth <joel@airwebreathe.org.uk>
+Date: Mon, 27 Feb 2017 16:14:26 -0600
+Subject: [PATCH 051/103] fpga: Add support for Lattice iCE40 FPGAs
+
+This patch adds support to the FPGA manager for configuring the SRAM of
+iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40
+UltraPlus devices, through slave SPI.
+
+Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
+Reviewed-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
+Acked-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 6 +
+ drivers/fpga/Makefile | 1
+ drivers/fpga/ice40-spi.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 214 insertions(+)
+ create mode 100644 drivers/fpga/ice40-spi.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -20,6 +20,12 @@ config FPGA_REGION
+ FPGA Regions allow loading FPGA images under control of
+ the Device Tree.
+
++config FPGA_MGR_ICE40_SPI
++ tristate "Lattice iCE40 SPI"
++ depends on OF && SPI
++ help
++ FPGA manager driver support for Lattice iCE40 FPGAs over SPI.
++
+ config FPGA_MGR_SOCFPGA
+ tristate "Altera SOCFPGA FPGA Manager"
+ depends on ARCH_SOCFPGA || COMPILE_TEST
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -6,6 +6,7 @@
+ obj-$(CONFIG_FPGA) += fpga-mgr.o
+
+ # FPGA Manager Drivers
++obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
+ obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
+--- /dev/null
++++ b/drivers/fpga/ice40-spi.c
+@@ -0,0 +1,207 @@
++/*
++ * FPGA Manager Driver for Lattice iCE40.
++ *
++ * Copyright (c) 2016 Joel Holdsworth
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This driver adds support to the FPGA manager for configuring the SRAM of
++ * Lattice iCE40 FPGAs through slave SPI.
++ */
++
++#include <linux/fpga/fpga-mgr.h>
++#include <linux/gpio/consumer.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/spi/spi.h>
++#include <linux/stringify.h>
++
++#define ICE40_SPI_MAX_SPEED 25000000 /* Hz */
++#define ICE40_SPI_MIN_SPEED 1000000 /* Hz */
++
++#define ICE40_SPI_RESET_DELAY 1 /* us (>200ns) */
++#define ICE40_SPI_HOUSEKEEPING_DELAY 1200 /* us */
++
++#define ICE40_SPI_NUM_ACTIVATION_BYTES DIV_ROUND_UP(49, 8)
++
++struct ice40_fpga_priv {
++ struct spi_device *dev;
++ struct gpio_desc *reset;
++ struct gpio_desc *cdone;
++};
++
++static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr)
++{
++ struct ice40_fpga_priv *priv = mgr->priv;
++
++ return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING :
++ FPGA_MGR_STATE_UNKNOWN;
++}
++
++static int ice40_fpga_ops_write_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ struct ice40_fpga_priv *priv = mgr->priv;
++ struct spi_device *dev = priv->dev;
++ struct spi_message message;
++ struct spi_transfer assert_cs_then_reset_delay = {
++ .cs_change = 1,
++ .delay_usecs = ICE40_SPI_RESET_DELAY
++ };
++ struct spi_transfer housekeeping_delay_then_release_cs = {
++ .delay_usecs = ICE40_SPI_HOUSEKEEPING_DELAY
++ };
++ int ret;
++
++ if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
++ dev_err(&dev->dev,
++ "Partial reconfiguration is not supported\n");
++ return -ENOTSUPP;
++ }
++
++ /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */
++ spi_bus_lock(dev->master);
++
++ gpiod_set_value(priv->reset, 1);
++
++ spi_message_init(&message);
++ spi_message_add_tail(&assert_cs_then_reset_delay, &message);
++ ret = spi_sync_locked(dev, &message);
++
++ /* Come out of reset */
++ gpiod_set_value(priv->reset, 0);
++
++ /* Abort if the chip-select failed */
++ if (ret)
++ goto fail;
++
++ /* Check CDONE is de-asserted i.e. the FPGA is reset */
++ if (gpiod_get_value(priv->cdone)) {
++ dev_err(&dev->dev, "Device reset failed, CDONE is asserted\n");
++ ret = -EIO;
++ goto fail;
++ }
++
++ /* Wait for the housekeeping to complete, and release SS_B */
++ spi_message_init(&message);
++ spi_message_add_tail(&housekeeping_delay_then_release_cs, &message);
++ ret = spi_sync_locked(dev, &message);
++
++fail:
++ spi_bus_unlock(dev->master);
++
++ return ret;
++}
++
++static int ice40_fpga_ops_write(struct fpga_manager *mgr,
++ const char *buf, size_t count)
++{
++ struct ice40_fpga_priv *priv = mgr->priv;
++
++ return spi_write(priv->dev, buf, count);
++}
++
++static int ice40_fpga_ops_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
++{
++ struct ice40_fpga_priv *priv = mgr->priv;
++ struct spi_device *dev = priv->dev;
++ const u8 padding[ICE40_SPI_NUM_ACTIVATION_BYTES] = {0};
++
++ /* Check CDONE is asserted */
++ if (!gpiod_get_value(priv->cdone)) {
++ dev_err(&dev->dev,
++ "CDONE was not asserted after firmware transfer\n");
++ return -EIO;
++ }
++
++ /* Send of zero-padding to activate the firmware */
++ return spi_write(dev, padding, sizeof(padding));
++}
++
++static const struct fpga_manager_ops ice40_fpga_ops = {
++ .state = ice40_fpga_ops_state,
++ .write_init = ice40_fpga_ops_write_init,
++ .write = ice40_fpga_ops_write,
++ .write_complete = ice40_fpga_ops_write_complete,
++};
++
++static int ice40_fpga_probe(struct spi_device *spi)
++{
++ struct device *dev = &spi->dev;
++ struct ice40_fpga_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->dev = spi;
++
++ /* Check board setup data. */
++ if (spi->max_speed_hz > ICE40_SPI_MAX_SPEED) {
++ dev_err(dev, "SPI speed is too high, maximum speed is "
++ __stringify(ICE40_SPI_MAX_SPEED) "\n");
++ return -EINVAL;
++ }
++
++ if (spi->max_speed_hz < ICE40_SPI_MIN_SPEED) {
++ dev_err(dev, "SPI speed is too low, minimum speed is "
++ __stringify(ICE40_SPI_MIN_SPEED) "\n");
++ return -EINVAL;
++ }
++
++ if (spi->mode & SPI_CPHA) {
++ dev_err(dev, "Bad SPI mode, CPHA not supported\n");
++ return -EINVAL;
++ }
++
++ /* Set up the GPIOs */
++ priv->cdone = devm_gpiod_get(dev, "cdone", GPIOD_IN);
++ if (IS_ERR(priv->cdone)) {
++ ret = PTR_ERR(priv->cdone);
++ dev_err(dev, "Failed to get CDONE GPIO: %d\n", ret);
++ return ret;
++ }
++
++ priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
++ if (IS_ERR(priv->reset)) {
++ ret = PTR_ERR(priv->reset);
++ dev_err(dev, "Failed to get CRESET_B GPIO: %d\n", ret);
++ return ret;
++ }
++
++ /* Register with the FPGA manager */
++ return fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager",
++ &ice40_fpga_ops, priv);
++}
++
++static int ice40_fpga_remove(struct spi_device *spi)
++{
++ fpga_mgr_unregister(&spi->dev);
++ return 0;
++}
++
++static const struct of_device_id ice40_fpga_of_match[] = {
++ { .compatible = "lattice,ice40-fpga-mgr", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ice40_fpga_of_match);
++
++static struct spi_driver ice40_fpga_driver = {
++ .probe = ice40_fpga_probe,
++ .remove = ice40_fpga_remove,
++ .driver = {
++ .name = "ice40spi",
++ .of_match_table = of_match_ptr(ice40_fpga_of_match),
++ },
++};
++
++module_spi_driver(ice40_fpga_driver);
++
++MODULE_AUTHOR("Joel Holdsworth <joel@airwebreathe.org.uk>");
++MODULE_DESCRIPTION("Lattice iCE40 FPGA Manager");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0052-fpga-bridge-Replace-open-coded-list_for_each-list_en.patch b/patches.socfpga/0052-fpga-bridge-Replace-open-coded-list_for_each-list_en.patch
new file mode 100644
index 0000000..a218c13
--- /dev/null
+++ b/patches.socfpga/0052-fpga-bridge-Replace-open-coded-list_for_each-list_en.patch
@@ -0,0 +1,62 @@
+From 65107537be49563835a6accd0a7ef0dd078020cb Mon Sep 17 00:00:00 2001
+From: Moritz Fischer <mdf@kernel.org>
+Date: Fri, 10 Mar 2017 12:47:11 -0800
+Subject: [PATCH 052/103] fpga: bridge: Replace open-coded list_for_each +
+ list_entry
+
+Replaces open-coded list_for_each() + list_entry() with macro
+list_for_each_entry()
+
+Signed-off-by: Moritz Fischer <mdf@kernel.org>
+Cc: linux-fpga@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/fpga-bridge.c | 15 ++++-----------
+ 1 file changed, 4 insertions(+), 11 deletions(-)
+
+--- a/drivers/fpga/fpga-bridge.c
++++ b/drivers/fpga/fpga-bridge.c
+@@ -146,11 +146,9 @@ EXPORT_SYMBOL_GPL(fpga_bridge_put);
+ int fpga_bridges_enable(struct list_head *bridge_list)
+ {
+ struct fpga_bridge *bridge;
+- struct list_head *node;
+ int ret;
+
+- list_for_each(node, bridge_list) {
+- bridge = list_entry(node, struct fpga_bridge, node);
++ list_for_each_entry(bridge, bridge_list, node) {
+ ret = fpga_bridge_enable(bridge);
+ if (ret)
+ return ret;
+@@ -172,11 +170,9 @@ EXPORT_SYMBOL_GPL(fpga_bridges_enable);
+ int fpga_bridges_disable(struct list_head *bridge_list)
+ {
+ struct fpga_bridge *bridge;
+- struct list_head *node;
+ int ret;
+
+- list_for_each(node, bridge_list) {
+- bridge = list_entry(node, struct fpga_bridge, node);
++ list_for_each_entry(bridge, bridge_list, node) {
+ ret = fpga_bridge_disable(bridge);
+ if (ret)
+ return ret;
+@@ -196,13 +192,10 @@ EXPORT_SYMBOL_GPL(fpga_bridges_disable);
+ */
+ void fpga_bridges_put(struct list_head *bridge_list)
+ {
+- struct fpga_bridge *bridge;
+- struct list_head *node, *next;
++ struct fpga_bridge *bridge, *next;
+ unsigned long flags;
+
+- list_for_each_safe(node, next, bridge_list) {
+- bridge = list_entry(node, struct fpga_bridge, node);
+-
++ list_for_each_entry_safe(bridge, next, bridge_list, node) {
+ fpga_bridge_put(bridge);
+
+ spin_lock_irqsave(&bridge_list_lock, flags);
diff --git a/patches.socfpga/0053-fpga-altera_freeze_bridge-Constify-ops.patch b/patches.socfpga/0053-fpga-altera_freeze_bridge-Constify-ops.patch
new file mode 100644
index 0000000..2747428
--- /dev/null
+++ b/patches.socfpga/0053-fpga-altera_freeze_bridge-Constify-ops.patch
@@ -0,0 +1,28 @@
+From a55d3c2ff9848a13ccd78a45551bd38c390426fb Mon Sep 17 00:00:00 2001
+From: Moritz Fischer <mdf@kernel.org>
+Date: Thu, 23 Mar 2017 19:34:24 -0500
+Subject: [PATCH 053/103] fpga: altera_freeze_bridge: Constify ops
+
+The ops are not changing, make them const.
+
+Signed-off-by: Moritz Fischer <mdf@kernel.org>
+Cc: Alan Tull <atull@kernel.org>
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-fpga@vger.kernel.org
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/altera-freeze-bridge.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/fpga/altera-freeze-bridge.c
++++ b/drivers/fpga/altera-freeze-bridge.c
+@@ -203,7 +203,7 @@ static int altera_freeze_br_enable_show(
+ return priv->enable;
+ }
+
+-static struct fpga_bridge_ops altera_freeze_br_br_ops = {
++static const struct fpga_bridge_ops altera_freeze_br_br_ops = {
+ .enable_set = altera_freeze_br_enable_set,
+ .enable_show = altera_freeze_br_enable_show,
+ };
diff --git a/patches.socfpga/0054-dt-bindings-fpga-add-xilinx-slave-serial-binding-des.patch b/patches.socfpga/0054-dt-bindings-fpga-add-xilinx-slave-serial-binding-des.patch
new file mode 100644
index 0000000..1c4bcc6
--- /dev/null
+++ b/patches.socfpga/0054-dt-bindings-fpga-add-xilinx-slave-serial-binding-des.patch
@@ -0,0 +1,67 @@
+From bad33a7dfec8bc8eb393519a9b2348d009a2fa6d Mon Sep 17 00:00:00 2001
+From: Anatolij Gustschin <agust@denx.de>
+Date: Thu, 23 Mar 2017 19:34:25 -0500
+Subject: [PATCH 054/103] dt: bindings: fpga: add xilinx slave-serial binding
+ description
+
+Add dt binding documentation details for Xilinx FPGA configuration
+over slave serial interface.
+
+Signed-off-by: Anatolij Gustschin <agust@denx.de>
+Acked-by: Moritz Fischer <mdf@kernel.org>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Michal Simek <michal.simek@xilinx.com>
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/fpga/xilinx-slave-serial.txt | 44 ++++++++++
+ 1 file changed, 44 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/xilinx-slave-serial.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/xilinx-slave-serial.txt
+@@ -0,0 +1,44 @@
++Xilinx Slave Serial SPI FPGA Manager
++
++Xilinx Spartan-6 FPGAs support a method of loading the bitstream over
++what is referred to as "slave serial" interface.
++The slave serial link is not technically SPI, and might require extra
++circuits in order to play nicely with other SPI slaves on the same bus.
++
++See https://www.xilinx.com/support/documentation/user_guides/ug380.pdf
++
++Required properties:
++- compatible: should contain "xlnx,fpga-slave-serial"
++- reg: spi chip select of the FPGA
++- prog_b-gpios: config pin (referred to as PROGRAM_B in the manual)
++- done-gpios: config status pin (referred to as DONE in the manual)
++
++Example for full FPGA configuration:
++
++ fpga-region0 {
++ compatible = "fpga-region";
++ fpga-mgr = <&fpga_mgr_spi>;
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++ };
++
++ spi1: spi@10680 {
++ compatible = "marvell,armada-xp-spi", "marvell,orion-spi";
++ pinctrl-0 = <&spi0_pins>;
++ pinctrl-names = "default";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <1>;
++ interrupts = <92>;
++ clocks = <&coreclk 0>;
++ status = "okay";
++
++ fpga_mgr_spi: fpga-mgr@0 {
++ compatible = "xlnx,fpga-slave-serial";
++ spi-max-frequency = <60000000>;
++ spi-cpha;
++ reg = <0>;
++ done-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
++ prog_b-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
++ };
++ };
diff --git a/patches.socfpga/0055-fpga-manager-Add-Xilinx-slave-serial-SPI-driver.patch b/patches.socfpga/0055-fpga-manager-Add-Xilinx-slave-serial-SPI-driver.patch
new file mode 100644
index 0000000..0f10393
--- /dev/null
+++ b/patches.socfpga/0055-fpga-manager-Add-Xilinx-slave-serial-SPI-driver.patch
@@ -0,0 +1,247 @@
+From d4cd4955c34d18b9849d52ddfe6ca83f9f04e5a5 Mon Sep 17 00:00:00 2001
+From: Anatolij Gustschin <agust@denx.de>
+Date: Thu, 23 Mar 2017 19:34:26 -0500
+Subject: [PATCH 055/103] fpga manager: Add Xilinx slave serial SPI driver
+
+The driver loads FPGA firmware over SPI, using the "slave serial"
+configuration interface on Xilinx FPGAs.
+
+Signed-off-by: Anatolij Gustschin <agust@denx.de>
+Acked-by: Michal Simek <michal.simek@xilinx.com>
+Reviewed-by: Moritz Fischer <mdf@kernel.org>
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 7 +
+ drivers/fpga/Makefile | 1
+ drivers/fpga/xilinx-spi.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 206 insertions(+)
+ create mode 100644 drivers/fpga/xilinx-spi.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -46,6 +46,13 @@ config FPGA_MGR_TS73XX
+ FPGA manager driver support for the Altera Cyclone II FPGA
+ present on the TS-73xx SBC boards.
+
++config FPGA_MGR_XILINX_SPI
++ tristate "Xilinx Configuration over Slave Serial (SPI)"
++ depends on SPI
++ help
++ FPGA manager driver support for Xilinx FPGA configuration
++ over slave serial interface.
++
+ config FPGA_MGR_ZYNQ_FPGA
+ tristate "Xilinx Zynq FPGA"
+ depends on ARCH_ZYNQ || COMPILE_TEST
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice4
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
+ obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
+ obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
++obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o
+ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
+
+ # FPGA Bridge Drivers
+--- /dev/null
++++ b/drivers/fpga/xilinx-spi.c
+@@ -0,0 +1,198 @@
++/*
++ * Xilinx Spartan6 Slave Serial SPI Driver
++ *
++ * Copyright (C) 2017 DENX Software Engineering
++ *
++ * Anatolij Gustschin <agust@denx.de>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * Manage Xilinx FPGA firmware that is loaded over SPI using
++ * the slave serial configuration interface.
++ */
++
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/fpga/fpga-mgr.h>
++#include <linux/gpio/consumer.h>
++#include <linux/module.h>
++#include <linux/mod_devicetable.h>
++#include <linux/of.h>
++#include <linux/spi/spi.h>
++#include <linux/sizes.h>
++
++struct xilinx_spi_conf {
++ struct spi_device *spi;
++ struct gpio_desc *prog_b;
++ struct gpio_desc *done;
++};
++
++static enum fpga_mgr_states xilinx_spi_state(struct fpga_manager *mgr)
++{
++ struct xilinx_spi_conf *conf = mgr->priv;
++
++ if (!gpiod_get_value(conf->done))
++ return FPGA_MGR_STATE_RESET;
++
++ return FPGA_MGR_STATE_UNKNOWN;
++}
++
++static int xilinx_spi_write_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ struct xilinx_spi_conf *conf = mgr->priv;
++ const size_t prog_latency_7500us = 7500;
++ const size_t prog_pulse_1us = 1;
++
++ if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
++ dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
++ return -EINVAL;
++ }
++
++ gpiod_set_value(conf->prog_b, 1);
++
++ udelay(prog_pulse_1us); /* min is 500 ns */
++
++ gpiod_set_value(conf->prog_b, 0);
++
++ if (gpiod_get_value(conf->done)) {
++ dev_err(&mgr->dev, "Unexpected DONE pin state...\n");
++ return -EIO;
++ }
++
++ /* program latency */
++ usleep_range(prog_latency_7500us, prog_latency_7500us + 100);
++ return 0;
++}
++
++static int xilinx_spi_write(struct fpga_manager *mgr, const char *buf,
++ size_t count)
++{
++ struct xilinx_spi_conf *conf = mgr->priv;
++ const char *fw_data = buf;
++ const char *fw_data_end = fw_data + count;
++
++ while (fw_data < fw_data_end) {
++ size_t remaining, stride;
++ int ret;
++
++ remaining = fw_data_end - fw_data;
++ stride = min_t(size_t, remaining, SZ_4K);
++
++ ret = spi_write(conf->spi, fw_data, stride);
++ if (ret) {
++ dev_err(&mgr->dev, "SPI error in firmware write: %d\n",
++ ret);
++ return ret;
++ }
++ fw_data += stride;
++ }
++
++ return 0;
++}
++
++static int xilinx_spi_apply_cclk_cycles(struct xilinx_spi_conf *conf)
++{
++ struct spi_device *spi = conf->spi;
++ const u8 din_data[1] = { 0xff };
++ int ret;
++
++ ret = spi_write(conf->spi, din_data, sizeof(din_data));
++ if (ret)
++ dev_err(&spi->dev, "applying CCLK cycles failed: %d\n", ret);
++
++ return ret;
++}
++
++static int xilinx_spi_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
++{
++ struct xilinx_spi_conf *conf = mgr->priv;
++ unsigned long timeout;
++ int ret;
++
++ if (gpiod_get_value(conf->done))
++ return xilinx_spi_apply_cclk_cycles(conf);
++
++ timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us);
++
++ while (time_before(jiffies, timeout)) {
++
++ ret = xilinx_spi_apply_cclk_cycles(conf);
++ if (ret)
++ return ret;
++
++ if (gpiod_get_value(conf->done))
++ return xilinx_spi_apply_cclk_cycles(conf);
++ }
++
++ dev_err(&mgr->dev, "Timeout after config data transfer.\n");
++ return -ETIMEDOUT;
++}
++
++static const struct fpga_manager_ops xilinx_spi_ops = {
++ .state = xilinx_spi_state,
++ .write_init = xilinx_spi_write_init,
++ .write = xilinx_spi_write,
++ .write_complete = xilinx_spi_write_complete,
++};
++
++static int xilinx_spi_probe(struct spi_device *spi)
++{
++ struct xilinx_spi_conf *conf;
++
++ conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
++ if (!conf)
++ return -ENOMEM;
++
++ conf->spi = spi;
++
++ /* PROGRAM_B is active low */
++ conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW);
++ if (IS_ERR(conf->prog_b)) {
++ dev_err(&spi->dev, "Failed to get PROGRAM_B gpio: %ld\n",
++ PTR_ERR(conf->prog_b));
++ return PTR_ERR(conf->prog_b);
++ }
++
++ conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN);
++ if (IS_ERR(conf->done)) {
++ dev_err(&spi->dev, "Failed to get DONE gpio: %ld\n",
++ PTR_ERR(conf->done));
++ return PTR_ERR(conf->done);
++ }
++
++ return fpga_mgr_register(&spi->dev, "Xilinx Slave Serial FPGA Manager",
++ &xilinx_spi_ops, conf);
++}
++
++static int xilinx_spi_remove(struct spi_device *spi)
++{
++ fpga_mgr_unregister(&spi->dev);
++
++ return 0;
++}
++
++static const struct of_device_id xlnx_spi_of_match[] = {
++ { .compatible = "xlnx,fpga-slave-serial", },
++ {}
++};
++MODULE_DEVICE_TABLE(of, xlnx_spi_of_match);
++
++static struct spi_driver xilinx_slave_spi_driver = {
++ .driver = {
++ .name = "xlnx-slave-spi",
++ .of_match_table = of_match_ptr(xlnx_spi_of_match),
++ },
++ .probe = xilinx_spi_probe,
++ .remove = xilinx_spi_remove,
++};
++
++module_spi_driver(xilinx_slave_spi_driver)
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
++MODULE_DESCRIPTION("Load Xilinx FPGA firmware over SPI");
diff --git a/patches.socfpga/0056-ARM-socfpga-add-bindings-document-for-fpga-bridge-dr.patch b/patches.socfpga/0056-ARM-socfpga-add-bindings-document-for-fpga-bridge-dr.patch
new file mode 100644
index 0000000..3665718
--- /dev/null
+++ b/patches.socfpga/0056-ARM-socfpga-add-bindings-document-for-fpga-bridge-dr.patch
@@ -0,0 +1,85 @@
+From be625b6c7234e180a34bcee690d64bfd52ae116d Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 12 Jul 2016 14:36:41 -0500
+Subject: [PATCH 056/103] ARM: socfpga: add bindings document for fpga bridge
+ drivers
+
+Add bindings documentation for Altera SOCFPGA bridges:
+ * fpga2sdram
+ * fpga2hps
+ * hps2fpga
+ * lwhps2fpga
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Matthew Gerlach <mgerlach@altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt | 16 ++++
+ Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt | 39 ++++++++++
+ 2 files changed, 55 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
+ create mode 100644 Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
+@@ -0,0 +1,16 @@
++Altera FPGA To SDRAM Bridge Driver
++
++Required properties:
++- compatible : Should contain "altr,socfpga-fpga2sdram-bridge"
++
++Optional properties:
++- bridge-enable : 0 if driver should disable bridge at startup
++ 1 if driver should enable bridge at startup
++ Default is to leave bridge in current state.
++
++Example:
++ fpga_bridge3: fpga-bridge@ffc25080 {
++ compatible = "altr,socfpga-fpga2sdram-bridge";
++ reg = <0xffc25080 0x4>;
++ bridge-enable = <0>;
++ };
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
+@@ -0,0 +1,39 @@
++Altera FPGA/HPS Bridge Driver
++
++Required properties:
++- regs : base address and size for AXI bridge module
++- compatible : Should contain one of:
++ "altr,socfpga-lwhps2fpga-bridge",
++ "altr,socfpga-hps2fpga-bridge", or
++ "altr,socfpga-fpga2hps-bridge"
++- resets : Phandle and reset specifier for this bridge's reset
++- clocks : Clocks used by this module.
++
++Optional properties:
++- bridge-enable : 0 if driver should disable bridge at startup.
++ 1 if driver should enable bridge at startup.
++ Default is to leave bridge in its current state.
++
++Example:
++ fpga_bridge0: fpga-bridge@ff400000 {
++ compatible = "altr,socfpga-lwhps2fpga-bridge";
++ reg = <0xff400000 0x100000>;
++ resets = <&rst LWHPS2FPGA_RESET>;
++ clocks = <&l4_main_clk>;
++ bridge-enable = <0>;
++ };
++
++ fpga_bridge1: fpga-bridge@ff500000 {
++ compatible = "altr,socfpga-hps2fpga-bridge";
++ reg = <0xff500000 0x10000>;
++ resets = <&rst HPS2FPGA_RESET>;
++ clocks = <&l4_main_clk>;
++ bridge-enable = <1>;
++ };
++
++ fpga_bridge2: fpga-bridge@ff600000 {
++ compatible = "altr,socfpga-fpga2hps-bridge";
++ reg = <0xff600000 0x100000>;
++ resets = <&rst FPGA2HPS_RESET>;
++ clocks = <&l4_main_clk>;
++ };
diff --git a/patches.socfpga/0057-ARM-socfpga-add-bindings-doc-for-arria10-fpga-manage.patch b/patches.socfpga/0057-ARM-socfpga-add-bindings-doc-for-arria10-fpga-manage.patch
new file mode 100644
index 0000000..a7a2904
--- /dev/null
+++ b/patches.socfpga/0057-ARM-socfpga-add-bindings-doc-for-arria10-fpga-manage.patch
@@ -0,0 +1,40 @@
+From 94068d8c8be80b81e019683b4997a46627e3dd86 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 12 Jul 2016 14:07:08 -0500
+Subject: [PATCH 057/103] ARM: socfpga: add bindings doc for arria10 fpga
+ manager
+
+Add a device tree bindings document for the SoCFPGA Arria10
+FPGA Manager driver.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-By: Moritz Fischer <moritz.fischer@ettus.com>
+Signed-off-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt | 19 ++++++++++
+ 1 file changed, 19 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt
+@@ -0,0 +1,19 @@
++Altera SOCFPGA Arria10 FPGA Manager
++
++Required properties:
++- compatible : should contain "altr,socfpga-a10-fpga-mgr"
++- reg : base address and size for memory mapped io.
++ - The first index is for FPGA manager register access.
++ - The second index is for writing FPGA configuration data.
++- resets : Phandle and reset specifier for the device's reset.
++- clocks : Clocks used by the device.
++
++Example:
++
++ fpga_mgr: fpga-mgr@ffd03000 {
++ compatible = "altr,socfpga-a10-fpga-mgr";
++ reg = <0xffd03000 0x100
++ 0xffcfe400 0x20>;
++ clocks = <&l4_mp_clk>;
++ resets = <&rst FPGAMGR_RESET>;
++ };
diff --git a/patches.socfpga/0058-add-bindings-document-for-altera-freeze-bridge.patch b/patches.socfpga/0058-add-bindings-document-for-altera-freeze-bridge.patch
new file mode 100644
index 0000000..8863758
--- /dev/null
+++ b/patches.socfpga/0058-add-bindings-document-for-altera-freeze-bridge.patch
@@ -0,0 +1,45 @@
+From 48e56f16d7bc13665e037dc17935a23dc440e0df Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Mon, 17 Oct 2016 11:09:34 -0500
+Subject: [PATCH 058/103] add bindings document for altera freeze bridge
+
+Add bindings document for the Altera Freeze Bridge. A Freeze
+Bridge is used to gate traffic to/from a region of a FPGA
+such that that region can be reprogrammed. The Freeze Bridge
+exist in FPGA fabric that is not currently being reconfigured.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Matthew Gerlach <mgerlach@opensource.altera.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt | 23 ++++++++++
+ 1 file changed, 23 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt
+@@ -0,0 +1,23 @@
++Altera Freeze Bridge Controller Driver
++
++The Altera Freeze Bridge Controller manages one or more freeze bridges.
++The controller can freeze/disable the bridges which prevents signal
++changes from passing through the bridge. The controller can also
++unfreeze/enable the bridges which allows traffic to pass through the
++bridge normally.
++
++Required properties:
++- compatible : Should contain "altr,freeze-bridge-controller"
++- regs : base address and size for freeze bridge module
++
++Optional properties:
++- bridge-enable : 0 if driver should disable bridge at startup
++ 1 if driver should enable bridge at startup
++ Default is to leave bridge in current state.
++
++Example:
++ freeze-controller@100000450 {
++ compatible = "altr,freeze-bridge-controller";
++ regs = <0x1000 0x10>;
++ bridge-enable = <0>;
++ };
diff --git a/patches.socfpga/0059-MAINTAINERS-add-git-url-for-fpga.patch b/patches.socfpga/0059-MAINTAINERS-add-git-url-for-fpga.patch
new file mode 100644
index 0000000..e7a9286
--- /dev/null
+++ b/patches.socfpga/0059-MAINTAINERS-add-git-url-for-fpga.patch
@@ -0,0 +1,22 @@
+From c642ff14e89edf9cb54008765c97e75e505545b7 Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Tue, 29 Nov 2016 15:15:45 -0600
+Subject: [PATCH 059/103] MAINTAINERS: add git url for fpga
+
+Add git url for fpga stuff.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+---
+ MAINTAINERS | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4959,6 +4959,7 @@ FPGA MANAGER FRAMEWORK
+ M: Alan Tull <atull@opensource.altera.com>
+ R: Moritz Fischer <moritz.fischer@ettus.com>
+ S: Maintained
++T: git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
+ F: drivers/fpga/
+ F: include/linux/fpga/fpga-mgr.h
+ W: http://www.rocketboards.org
diff --git a/patches.socfpga/0060-ARM-dts-socfpga-add-base-fpga-region-and-fpga-bridge.patch b/patches.socfpga/0060-ARM-dts-socfpga-add-base-fpga-region-and-fpga-bridge.patch
new file mode 100644
index 0000000..704a2dc
--- /dev/null
+++ b/patches.socfpga/0060-ARM-dts-socfpga-add-base-fpga-region-and-fpga-bridge.patch
@@ -0,0 +1,68 @@
+From d063b52520c412dccb99b0737b5e2b462d83dd8a Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Fri, 26 Feb 2016 14:21:04 -0600
+Subject: [PATCH 060/103] ARM: dts: socfpga: add base fpga region and fpga
+ bridges
+
+Add h2f and lwh2f bridges.
+Add base FPGA Region to support DT overlays for FPGA programming.
+Add l3regs.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+v2: removed fpga-bridges, ranges, and reset-names
+---
+ arch/arm/boot/dts/socfpga.dtsi | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga.dtsi
++++ b/arch/arm/boot/dts/socfpga.dtsi
+@@ -93,6 +93,14 @@
+ };
+ };
+
++ base_fpga_region {
++ compatible = "fpga-region";
++ fpga-mgr = <&fpgamgr0>;
++
++ #address-cells = <0x1>;
++ #size-cells = <0x1>;
++ };
++
+ can0: can@ffc00000 {
+ compatible = "bosch,d_can";
+ reg = <0xffc00000 0x1000>;
+@@ -513,6 +521,20 @@
+ };
+ };
+
++ fpga_bridge0: fpga_bridge@ff400000 {
++ compatible = "altr,socfpga-lwhps2fpga-bridge";
++ reg = <0xff400000 0x100000>;
++ resets = <&rst LWHPS2FPGA_RESET>;
++ clocks = <&l4_main_clk>;
++ };
++
++ fpga_bridge1: fpga_bridge@ff500000 {
++ compatible = "altr,socfpga-hps2fpga-bridge";
++ reg = <0xff500000 0x10000>;
++ resets = <&rst HPS2FPGA_RESET>;
++ clocks = <&l4_main_clk>;
++ };
++
+ fpgamgr0: fpgamgr@ff706000 {
+ compatible = "altr,socfpga-fpga-mgr";
+ reg = <0xff706000 0x1000
+@@ -689,6 +711,11 @@
+ arm,shared-override;
+ };
+
++ l3regs@0xff800000 {
++ compatible = "altr,l3regs", "syscon";
++ reg = <0xff800000 0x1000>;
++ };
++
+ mmc: dwmmc0@ff704000 {
+ compatible = "altr,socfpga-dw-mshc";
+ reg = <0xff704000 0x1000>;
diff --git a/patches.socfpga/0061-fpga-add-config-complete-timeout.patch b/patches.socfpga/0061-fpga-add-config-complete-timeout.patch
new file mode 100644
index 0000000..b3594a4
--- /dev/null
+++ b/patches.socfpga/0061-fpga-add-config-complete-timeout.patch
@@ -0,0 +1,44 @@
+From 3871c39c6683965dbafdedc7b9f9b558cf620f0f Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Thu, 23 Mar 2017 19:34:27 -0500
+Subject: [PATCH 061/103] fpga: add config complete timeout
+
+Adding timeout for maximum allowed time for FPGA to go to
+operating mode after a FPGA region has been programmed.
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/fpga-region.c | 3 +++
+ include/linux/fpga/fpga-mgr.h | 3 +++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/fpga/fpga-region.c
++++ b/drivers/fpga/fpga-region.c
+@@ -385,6 +385,9 @@ static int fpga_region_notify_pre_apply(
+ of_property_read_u32(nd->overlay, "region-freeze-timeout-us",
+ &info->disable_timeout_us);
+
++ of_property_read_u32(nd->overlay, "config-complete-timeout-us",
++ &info->config_complete_timeout_us);
++
+ /* If FPGA was externally programmed, don't specify firmware */
+ if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && firmware_name) {
+ pr_err("error: specified firmware and external-fpga-config");
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -77,11 +77,14 @@ enum fpga_mgr_states {
+ * @flags: boolean flags as defined above
+ * @enable_timeout_us: maximum time to enable traffic through bridge (uSec)
+ * @disable_timeout_us: maximum time to disable traffic through bridge (uSec)
++ * @config_complete_timeout_us: maximum time for FPGA to switch to operating
++ * status in the write_complete op.
+ */
+ struct fpga_image_info {
+ u32 flags;
+ u32 enable_timeout_us;
+ u32 disable_timeout_us;
++ u32 config_complete_timeout_us;
+ };
+
+ /**
diff --git a/patches.socfpga/0062-MAINTAINERS-Add-file-patterns-for-fpga-device-tree-b.patch b/patches.socfpga/0062-MAINTAINERS-Add-file-patterns-for-fpga-device-tree-b.patch
new file mode 100644
index 0000000..5180d45
--- /dev/null
+++ b/patches.socfpga/0062-MAINTAINERS-Add-file-patterns-for-fpga-device-tree-b.patch
@@ -0,0 +1,30 @@
+From f2e9e7db072f6445f9fea325f93f3406b78edc11 Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+Date: Thu, 23 Mar 2017 19:34:31 -0500
+Subject: [PATCH 062/103] MAINTAINERS: Add file patterns for fpga device tree
+ bindings
+
+Submitters of device tree binding documentation may forget to CC
+the subsystem maintainer if this is missing.
+
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
+Cc: Alan Tull <atull@opensource.altera.com>
+Cc: Moritz Fischer <moritz.fischer@ettus.com>
+Cc: linux-fpga@vger.kernel.org
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4960,6 +4960,7 @@ M: Alan Tull <atull@opensource.altera.co
+ R: Moritz Fischer <moritz.fischer@ettus.com>
+ S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
++F: Documentation/devicetree/bindings/fpga/
+ F: drivers/fpga/
+ F: include/linux/fpga/fpga-mgr.h
+ W: http://www.rocketboards.org
diff --git a/patches.socfpga/0063-MAINTAINERS-fpga-update-email-and-directory-paths.patch b/patches.socfpga/0063-MAINTAINERS-fpga-update-email-and-directory-paths.patch
new file mode 100644
index 0000000..499db05
--- /dev/null
+++ b/patches.socfpga/0063-MAINTAINERS-fpga-update-email-and-directory-paths.patch
@@ -0,0 +1,35 @@
+From efcf802e63e2d545f6695ed386a3737ed9f1d77e Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@kernel.org>
+Date: Thu, 30 Mar 2017 13:23:12 -0500
+Subject: [PATCH 063/103] MAINTAINERS: fpga: update email and directory paths
+
+A few updates:
+* Updating my email address
+* Adding another docs directory: Documentation/fpga
+* Making the include path not specific to fpga-mgr.h only
+
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ MAINTAINERS | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4956,13 +4956,14 @@ F: include/linux/ipmi-fru.h
+ K: fmc_d.*register
+
+ FPGA MANAGER FRAMEWORK
+-M: Alan Tull <atull@opensource.altera.com>
++M: Alan Tull <atull@kernel.org>
+ R: Moritz Fischer <moritz.fischer@ettus.com>
+ S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
++F: Documentation/fpga/
+ F: Documentation/devicetree/bindings/fpga/
+ F: drivers/fpga/
+-F: include/linux/fpga/fpga-mgr.h
++F: include/linux/fpga/
+ W: http://www.rocketboards.org
+
+ FPU EMULATOR
diff --git a/patches.socfpga/0064-spi-Add-Flag-to-Enable-Slave-Select-with-GPIO-Chip-S.patch b/patches.socfpga/0064-spi-Add-Flag-to-Enable-Slave-Select-with-GPIO-Chip-S.patch
new file mode 100644
index 0000000..b64e9d5
--- /dev/null
+++ b/patches.socfpga/0064-spi-Add-Flag-to-Enable-Slave-Select-with-GPIO-Chip-S.patch
@@ -0,0 +1,56 @@
+From d500a6439c32092db46195c550ef617ce3a3ffc2 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Mon, 10 Oct 2016 09:25:24 -0500
+Subject: [PATCH 064/103] spi: Add Flag to Enable Slave Select with GPIO Chip
+ Select.
+
+Some SPI masters require slave selection before the transfer
+can begin [1]. The SPI framework currently selects the chip using
+either 1) the internal CS mechanism or 2) the GPIO CS, but not both.
+
+This patch adds a new master->flags define to indicate both the GPIO
+CS and the internal chip select mechanism should be used.
+
+Tested On:
+ Altera CycloneV development kit
+ Compile tested for build errors on x86_64 (allyesconfigs)
+
+[1] DesignWare dw_apb_ssi Databook, Version 3.20a (page 39)
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/spi/spi.c | 9 +++++++--
+ include/linux/spi/spi.h | 1 +
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -699,10 +699,15 @@ static void spi_set_cs(struct spi_device
+ if (spi->mode & SPI_CS_HIGH)
+ enable = !enable;
+
+- if (gpio_is_valid(spi->cs_gpio))
++ if (gpio_is_valid(spi->cs_gpio)) {
+ gpio_set_value(spi->cs_gpio, !enable);
+- else if (spi->master->set_cs)
++ /* Some SPI masters need both GPIO CS & slave_select */
++ if ((spi->master->flags & SPI_MASTER_GPIO_SS) &&
++ spi->master->set_cs)
++ spi->master->set_cs(spi, !enable);
++ } else if (spi->master->set_cs) {
+ spi->master->set_cs(spi, !enable);
++ }
+ }
+
+ #ifdef CONFIG_HAS_DMA
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -442,6 +442,7 @@ struct spi_master {
+ #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
+ #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */
+ #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
++#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */
+
+ /*
+ * on some hardware transfer / message size may be constrained
diff --git a/patches.socfpga/0065-spi-dw-Set-GPIO_SS-flag-to-toggle-Slave-Select-on-GP.patch b/patches.socfpga/0065-spi-dw-Set-GPIO_SS-flag-to-toggle-Slave-Select-on-GP.patch
new file mode 100644
index 0000000..861baed
--- /dev/null
+++ b/patches.socfpga/0065-spi-dw-Set-GPIO_SS-flag-to-toggle-Slave-Select-on-GP.patch
@@ -0,0 +1,34 @@
+From 1d1b6b573a601464ca8ec40ace560a30fa00bdf4 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Mon, 10 Oct 2016 09:25:25 -0500
+Subject: [PATCH 065/103] spi: dw: Set GPIO_SS flag to toggle Slave Select on
+ GPIO CS
+
+The Designware SPI master requires slave selection before the transfer
+can begin [1].
+
+This patch uses the new master flag to indicate both the GPIO CS and
+the internal chip select should be used.
+
+Tested On:
+ Altera CycloneV development kit
+ Compile tested for build errors on x86_64 (allyesconfigs)
+
+[1] DesignWare dw_apb_ssi Databook, Version 3.20a (page 39)
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/spi/spi-dw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/spi/spi-dw.c
++++ b/drivers/spi/spi-dw.c
+@@ -502,6 +502,7 @@ int dw_spi_add_host(struct device *dev,
+ master->handle_err = dw_spi_handle_err;
+ master->max_speed_hz = dws->max_freq;
+ master->dev.of_node = dev->of_node;
++ master->flags = SPI_MASTER_GPIO_SS;
+
+ /* Basic HW init */
+ spi_hw_init(dev, dws);
diff --git a/patches.socfpga/0066-ARM-dts-socfpga-Add-SPI-Master1-for-Arria10-SR-chip.patch b/patches.socfpga/0066-ARM-dts-socfpga-Add-SPI-Master1-for-Arria10-SR-chip.patch
new file mode 100644
index 0000000..a6a2449
--- /dev/null
+++ b/patches.socfpga/0066-ARM-dts-socfpga-Add-SPI-Master1-for-Arria10-SR-chip.patch
@@ -0,0 +1,39 @@
+From 591692b01bed97f524daa7623e58543276e32abd Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Thu, 2 Jun 2016 17:52:25 +0000
+Subject: [PATCH 066/103] ARM: dts: socfpga: Add SPI Master1 for Arria10 SR
+ chip
+
+Add the Altera Arria10 SPI Master Node in preparation for
+the A10SR MFD node.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -579,6 +579,21 @@
+ status = "disabled";
+ };
+
++ spi1: spi@ffda5000 {
++ compatible = "snps,dw-apb-ssi";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0xffda5000 0x100>;
++ interrupts = <0 102 4>;
++ num-chipselect = <4>;
++ bus-num = <0>;
++ /*32bit_access;*/
++ tx-dma-channel = <&pdma 16>;
++ rx-dma-channel = <&pdma 17>;
++ clocks = <&spi_m_clk>;
++ status = "disabled";
++ };
++
+ sdr: sdr@ffc25000 {
+ compatible = "altr,sdr-ctl", "syscon";
+ reg = <0xffcfb100 0x80>;
diff --git a/patches.socfpga/0067-ARM-dts-socfpga-Add-Devkit-A10-SR-fields-for-Arria10.patch b/patches.socfpga/0067-ARM-dts-socfpga-Add-Devkit-A10-SR-fields-for-Arria10.patch
new file mode 100644
index 0000000..4797dfc
--- /dev/null
+++ b/patches.socfpga/0067-ARM-dts-socfpga-Add-Devkit-A10-SR-fields-for-Arria10.patch
@@ -0,0 +1,45 @@
+From dd696cdcf4973ec6ba54ed24283548c1e57948cf Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Thu, 2 Jun 2016 17:52:26 +0000
+Subject: [PATCH 067/103] ARM: dts: socfpga: Add Devkit A10-SR fields for
+ Arria10
+
+Add the Altera Arria10 System Resource node. This is a Multi-Function
+device with GPIO expander support.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -75,6 +75,27 @@
+ status = "okay";
+ };
+
++&spi1 {
++ status = "okay";
++
++ resource-manager@0 {
++ compatible = "altr,a10sr";
++ reg = <0>;
++ spi-max-frequency = <100000>;
++ /* low-level active IRQ at GPIO1_5 */
++ interrupt-parent = <&portb>;
++ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-controller;
++ #interrupt-cells = <2>;
++
++ a10sr_gpio: gpio-controller {
++ compatible = "altr,a10sr-gpio";
++ gpio-controller;
++ #gpio-cells = <2>;
++ };
++ };
++};
++
+ &i2c1 {
+ speed-mode = <0>;
+ status = "okay";
diff --git a/patches.socfpga/0068-ARM-dts-socfpga-Enable-GPIO-parent-for-Arria10-SR-ch.patch b/patches.socfpga/0068-ARM-dts-socfpga-Enable-GPIO-parent-for-Arria10-SR-ch.patch
new file mode 100644
index 0000000..d24d027
--- /dev/null
+++ b/patches.socfpga/0068-ARM-dts-socfpga-Enable-GPIO-parent-for-Arria10-SR-ch.patch
@@ -0,0 +1,27 @@
+From a672d36e350129ca4b0d5fd127d2672c6484100d Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Thu, 2 Jun 2016 17:52:27 +0000
+Subject: [PATCH 068/103] ARM: dts: socfpga: Enable GPIO parent for Arria10 SR
+ chip
+
+Enable the Altera Arria10 GPIO parent for MFD operation.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -75,6 +75,10 @@
+ status = "okay";
+ };
+
++&gpio1 {
++ status = "okay";
++};
++
+ &spi1 {
+ status = "okay";
+
diff --git a/patches.socfpga/0069-ARM-dts-socfpga-Add-LED-framework-to-A10-SR-GPIO.patch b/patches.socfpga/0069-ARM-dts-socfpga-Add-LED-framework-to-A10-SR-GPIO.patch
new file mode 100644
index 0000000..0a3341b
--- /dev/null
+++ b/patches.socfpga/0069-ARM-dts-socfpga-Add-LED-framework-to-A10-SR-GPIO.patch
@@ -0,0 +1,46 @@
+From 40c6c417eabe97c7a3364f418880e00e9da7b420 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Thu, 2 Jun 2016 17:52:28 +0000
+Subject: [PATCH 069/103] ARM: dts: socfpga: Add LED framework to A10-SR GPIO
+
+Add the LED framework to the Arria10 System Resource chip GPIO hooks.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -36,6 +36,30 @@
+ reg = <0x0 0x40000000>; /* 1GB */
+ };
+
++ a10leds {
++ compatible = "gpio-leds";
++
++ a10sr_led0 {
++ label = "a10sr-led0";
++ gpios = <&a10sr_gpio 0 1>;
++ };
++
++ a10sr_led1 {
++ label = "a10sr-led1";
++ gpios = <&a10sr_gpio 1 1>;
++ };
++
++ a10sr_led2 {
++ label = "a10sr-led2";
++ gpios = <&a10sr_gpio 2 1>;
++ };
++
++ a10sr_led3 {
++ label = "a10sr-led3";
++ gpios = <&a10sr_gpio 3 1>;
++ };
++ };
++
+ soc {
+ clkmgr@ffd04000 {
+ clocks {
diff --git a/patches.socfpga/0070-EDAC-altera-Disable-IRQs-while-injecting-SDRAM-error.patch b/patches.socfpga/0070-EDAC-altera-Disable-IRQs-while-injecting-SDRAM-error.patch
new file mode 100644
index 0000000..6edb883
--- /dev/null
+++ b/patches.socfpga/0070-EDAC-altera-Disable-IRQs-while-injecting-SDRAM-error.patch
@@ -0,0 +1,40 @@
+From ea62c7b1bf6a7fa765bddfc710a279e233ead67c Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Wed, 19 Oct 2016 14:53:47 -0500
+Subject: [PATCH 070/103] EDAC, altera: Disable IRQs while injecting SDRAM
+ errors
+
+Disable IRQs while injecting SDRAM errors. The RT patches exposed
+a spinlock deadlock where the spinlock taken for the regmap write
+deadlocked with the IRQ clear regmap write.
+
+Error injection is not normally enabled for ECC but only for testing.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Cc: linux-edac <linux-edac@vger.kernel.org>
+Link: http://lkml.kernel.org/r/1476906827-9412-1-git-send-email-tthayer@opensource.altera.com
+Signed-off-by: Borislav Petkov <bp@suse.de>
+---
+ drivers/edac/altera_edac.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/edac/altera_edac.c
++++ b/drivers/edac/altera_edac.c
+@@ -153,13 +153,17 @@ static ssize_t altr_sdr_mc_err_inject_wr
+ if (count == 3) {
+ edac_printk(KERN_ALERT, EDAC_MC,
+ "Inject Double bit error\n");
++ local_irq_disable();
+ regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
+ (read_reg | priv->ue_set_mask));
++ local_irq_enable();
+ } else {
+ edac_printk(KERN_ALERT, EDAC_MC,
+ "Inject Single bit error\n");
++ local_irq_disable();
+ regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
+ (read_reg | priv->ce_set_mask));
++ local_irq_enable();
+ }
+
+ ptemp[0] = 0x5A5A5A5A;
diff --git a/patches.socfpga/0071-gpio-altera-a10sr-Add-A10-System-Resource-Chip-GPIO-.patch b/patches.socfpga/0071-gpio-altera-a10sr-Add-A10-System-Resource-Chip-GPIO-.patch
new file mode 100644
index 0000000..29332fa
--- /dev/null
+++ b/patches.socfpga/0071-gpio-altera-a10sr-Add-A10-System-Resource-Chip-GPIO-.patch
@@ -0,0 +1,190 @@
+From 26b18f6bff88d437c9949a2251c5bc62de427311 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Thu, 2 Jun 2016 12:52:24 -0500
+Subject: [PATCH 071/103] gpio: altera-a10sr: Add A10 System Resource Chip GPIO
+ support.
+
+Add the GPIO functionality for the Altera Arria10 MAX5 System Resource
+Chip. The A10 MAX5 has 12 bits of GPIO assigned to switches, buttons,
+and LEDs as a GPIO extender on the SPI bus.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>i
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/Kconfig | 8 ++
+ drivers/gpio/Makefile | 1
+ drivers/gpio/gpio-altera-a10sr.c | 140 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 149 insertions(+)
+ create mode 100644 drivers/gpio/gpio-altera-a10sr.c
+
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -814,6 +814,14 @@ config GPIO_ADP5520
+ This option enables support for on-chip GPIO found
+ on Analog Devices ADP5520 PMICs.
+
++config GPIO_ALTERA_A10SR
++ tristate "Altera Arria10 System Resource GPIO"
++ depends on MFD_ALTERA_A10SR
++ help
++ Driver for Arria10 Development Kit GPIO expansion which
++ includes reads of pushbuttons and DIP switches as well
++ as writes to LEDs.
++
+ config GPIO_ARIZONA
+ tristate "Wolfson Microelectronics Arizona class devices"
+ depends on MFD_ARIZONA
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -24,6 +24,7 @@ obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
+ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
+ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
+ obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
++obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
+ obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
+ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
+ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
+--- /dev/null
++++ b/drivers/gpio/gpio-altera-a10sr.c
+@@ -0,0 +1,140 @@
++/*
++ * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ *
++ * GPIO driver for Altera Arria10 MAX5 System Resource Chip
++ *
++ * Adapted from gpio-tps65910.c
++ */
++
++#include <linux/gpio/driver.h>
++#include <linux/mfd/altera-a10sr.h>
++#include <linux/module.h>
++
++/**
++ * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure
++ * @gp: : instance of the gpio_chip
++ * @regmap: the regmap from the parent device.
++ */
++struct altr_a10sr_gpio {
++ struct gpio_chip gp;
++ struct regmap *regmap;
++};
++
++static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset)
++{
++ struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
++ int ret, val;
++
++ ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val);
++ if (ret < 0)
++ return ret;
++
++ return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT));
++}
++
++static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset,
++ int value)
++{
++ struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
++
++ regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG,
++ BIT(ALTR_A10SR_LED_VALID_SHIFT + offset),
++ value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset)
++ : 0);
++}
++
++static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
++ unsigned int nr)
++{
++ if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT))
++ return 0;
++ return -EINVAL;
++}
++
++static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
++ unsigned int nr, int value)
++{
++ if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
++ return 0;
++ return -EINVAL;
++}
++
++static struct gpio_chip altr_a10sr_gc = {
++ .label = "altr_a10sr_gpio",
++ .owner = THIS_MODULE,
++ .get = altr_a10sr_gpio_get,
++ .set = altr_a10sr_gpio_set,
++ .direction_input = altr_a10sr_gpio_direction_input,
++ .direction_output = altr_a10sr_gpio_direction_output,
++ .can_sleep = true,
++ .ngpio = 12,
++ .base = -1,
++};
++
++static int altr_a10sr_gpio_probe(struct platform_device *pdev)
++{
++ struct altr_a10sr_gpio *gpio;
++ int ret;
++ struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
++
++ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
++ if (!gpio)
++ return -ENOMEM;
++
++ gpio->regmap = a10sr->regmap;
++
++ gpio->gp = altr_a10sr_gc;
++
++ gpio->gp.of_node = pdev->dev.of_node;
++
++ ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, gpio);
++
++ return 0;
++}
++
++static int altr_a10sr_gpio_remove(struct platform_device *pdev)
++{
++ struct altr_a10sr_gpio *gpio = platform_get_drvdata(pdev);
++
++ gpiochip_remove(&gpio->gp);
++
++ return 0;
++}
++
++static const struct of_device_id altr_a10sr_gpio_of_match[] = {
++ { .compatible = "altr,a10sr-gpio" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match);
++
++static struct platform_driver altr_a10sr_gpio_driver = {
++ .probe = altr_a10sr_gpio_probe,
++ .remove = altr_a10sr_gpio_remove,
++ .driver = {
++ .name = "altr_a10sr_gpio",
++ .of_match_table = of_match_ptr(altr_a10sr_gpio_of_match),
++ },
++};
++module_platform_driver(altr_a10sr_gpio_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>");
++MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO");
diff --git a/patches.socfpga/0072-dt-bindings-mfd-Add-Altera-Arria10-System-Resource-C.patch b/patches.socfpga/0072-dt-bindings-mfd-Add-Altera-Arria10-System-Resource-C.patch
new file mode 100644
index 0000000..48faa04
--- /dev/null
+++ b/patches.socfpga/0072-dt-bindings-mfd-Add-Altera-Arria10-System-Resource-C.patch
@@ -0,0 +1,67 @@
+From e9ea91f657e4f88cbedf1e93a19176d45d47548e Mon Sep 17 00:00:00 2001
+From: Thor Thayer <tthayer@opensource.altera.com>
+Date: Thu, 2 Jun 2016 12:52:21 -0500
+Subject: [PATCH 072/103] dt-bindings: mfd: Add Altera Arria10 System Resource
+ Chip bindings
+
+The Altera Arria10 Devkit System Resource chip is a Multi-Function
+Device with a GPIO expander.
+
+This patch adds documentation for the Altera A10-SR DT bindings.
+
+Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ Documentation/devicetree/bindings/mfd/altera-a10sr.txt | 46 +++++++++++++++++
+ 1 file changed, 46 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mfd/altera-a10sr.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
+@@ -0,0 +1,46 @@
++* Altera Arria10 Development Kit System Resource Chip
++
++Required parent device properties:
++- compatible : "altr,a10sr"
++- spi-max-frequency : Maximum SPI frequency.
++- reg : The SPI Chip Select address for the Arria10
++ System Resource chip
++- interrupt-parent : The parent interrupt controller.
++- interrupts : The interrupt line the device is connected to.
++- interrupt-controller : Marks the device node as an interrupt controller.
++- #interrupt-cells : The number of cells to describe an IRQ, should be 2.
++ The first cell is the IRQ number.
++ The second cell is the flags, encoded as trigger
++ masks from ../interrupt-controller/interrupts.txt.
++
++The A10SR consists of these sub-devices:
++
++Device Description
++------ ----------
++a10sr_gpio GPIO Controller
++
++Arria10 GPIO
++Required Properties:
++- compatible : Should be "altr,a10sr-gpio"
++- gpio-controller : Marks the device node as a GPIO Controller.
++- #gpio-cells : Should be two. The first cell is the pin number and
++ the second cell is used to specify flags.
++ See ../gpio/gpio.txt for more information.
++
++Example:
++
++ resource-manager@0 {
++ compatible = "altr,a10sr";
++ reg = <0>;
++ spi-max-frequency = <100000>;
++ interrupt-parent = <&portb>;
++ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-controller;
++ #interrupt-cells = <2>;
++
++ a10sr_gpio: gpio-controller {
++ compatible = "altr,a10sr-gpio";
++ gpio-controller;
++ #gpio-cells = <2>;
++ };
++ };
diff --git a/patches.socfpga/0073-ARM-dts-Add-EMAC-AXI-settings-for-Arria10.patch b/patches.socfpga/0073-ARM-dts-Add-EMAC-AXI-settings-for-Arria10.patch
new file mode 100644
index 0000000..a721ede
--- /dev/null
+++ b/patches.socfpga/0073-ARM-dts-Add-EMAC-AXI-settings-for-Arria10.patch
@@ -0,0 +1,53 @@
+From 0484444cbff352dc6c1882ed5a6f9ac502875ad7 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Thu, 2 Feb 2017 16:05:21 -0600
+Subject: [PATCH 073/103] ARM: dts: Add EMAC AXI settings for Arria10
+
+Add the device tree entries needed to support the EMAC AXI
+bus settings on the Arria10 SoCFPGA chip.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -408,6 +408,12 @@
+ };
+ };
+
++ socfpga_axi_setup: stmmac-axi-config {
++ snps,wr_osr_lmt = <0xf>;
++ snps,rd_osr_lmt = <0xf>;
++ snps,blen = <0 0 0 0 16 0 0>;
++ };
++
+ gmac0: ethernet@ff800000 {
+ compatible = "altr,socfpga-stmmac", "snps,dwmac-3.72a", "snps,dwmac";
+ altr,sysmgr-syscon = <&sysmgr 0x44 0>;
+@@ -424,6 +430,7 @@
+ clock-names = "stmmaceth";
+ resets = <&rst EMAC0_RESET>;
+ reset-names = "stmmaceth";
++ snps,axi-config = <&socfpga_axi_setup>;
+ status = "disabled";
+ };
+
+@@ -443,6 +450,7 @@
+ clock-names = "stmmaceth";
+ resets = <&rst EMAC1_RESET>;
+ reset-names = "stmmaceth";
++ snps,axi-config = <&socfpga_axi_setup>;
+ status = "disabled";
+ };
+
+@@ -460,6 +468,7 @@
+ rx-fifo-depth = <16384>;
+ clocks = <&l4_mp_clk>;
+ clock-names = "stmmaceth";
++ snps,axi-config = <&socfpga_axi_setup>;
+ status = "disabled";
+ };
+
diff --git a/patches.socfpga/0074-MAINTAINERS-EDAC-Update-email-for-Thor-Thayer.patch b/patches.socfpga/0074-MAINTAINERS-EDAC-Update-email-for-Thor-Thayer.patch
new file mode 100644
index 0000000..2a20ff5
--- /dev/null
+++ b/patches.socfpga/0074-MAINTAINERS-EDAC-Update-email-for-Thor-Thayer.patch
@@ -0,0 +1,36 @@
+From 46436c057d4b2210fe487f76a51fdfe7eb9c3d15 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Mon, 13 Feb 2017 13:30:41 -0600
+Subject: [PATCH 074/103] MAINTAINERS, EDAC: Update email for Thor Thayer
+
+My opensource.altera.com email will be going away soon. Switch to new
+email address (linux.intel.com).
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Cc: linux-edac <linux-edac@vger.kernel.org>
+Link: http://lkml.kernel.org/r/1487014241-3771-1-git-send-email-thor.thayer@linux.intel.com
+Signed-off-by: Borislav Petkov <bp@suse.de>
+---
+ MAINTAINERS | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -628,7 +628,7 @@ S: Maintained
+ F: drivers/gpio/gpio-altera.c
+
+ ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT
+-M: Thor Thayer <tthayer@opensource.altera.com>
++M: Thor Thayer <thor.thayer@linux.intel.com>
+ S: Maintained
+ F: drivers/gpio/gpio-altera-a10sr.c
+ F: drivers/mfd/altera-a10sr.c
+@@ -1766,7 +1766,7 @@ S: Maintained
+ F: drivers/clk/socfpga/
+
+ ARM/SOCFPGA EDAC SUPPORT
+-M: Thor Thayer <tthayer@opensource.altera.com>
++M: Thor Thayer <thor.thayer@linux.intel.com>
+ S: Maintained
+ F: drivers/edac/altera_edac.
+
diff --git a/patches.socfpga/0075-gpio-altera-a10sr-Set-gpio_chip-parent-property.patch b/patches.socfpga/0075-gpio-altera-a10sr-Set-gpio_chip-parent-property.patch
new file mode 100644
index 0000000..22a0a2e
--- /dev/null
+++ b/patches.socfpga/0075-gpio-altera-a10sr-Set-gpio_chip-parent-property.patch
@@ -0,0 +1,25 @@
+From 53c9bf5edfe4359a3baa2e42da49dabcc25d789a Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Mon, 13 Feb 2017 13:49:58 -0600
+Subject: [PATCH 075/103] gpio: altera-a10sr: Set gpio_chip parent property
+
+Set the gpio_chip parent property since some recent functions
+such as devprop_gpiochip_set_names() can use it.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-altera-a10sr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-altera-a10sr.c
++++ b/drivers/gpio/gpio-altera-a10sr.c
+@@ -96,7 +96,7 @@ static int altr_a10sr_gpio_probe(struct
+ gpio->regmap = a10sr->regmap;
+
+ gpio->gp = altr_a10sr_gc;
+-
++ gpio->gp.parent = pdev->dev.parent;
+ gpio->gp.of_node = pdev->dev.of_node;
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
diff --git a/patches.socfpga/0076-dt-bindings-reset-a10sr-Add-Arria10-SR-Reset-Control.patch b/patches.socfpga/0076-dt-bindings-reset-a10sr-Add-Arria10-SR-Reset-Control.patch
new file mode 100644
index 0000000..343c5d3
--- /dev/null
+++ b/patches.socfpga/0076-dt-bindings-reset-a10sr-Add-Arria10-SR-Reset-Control.patch
@@ -0,0 +1,64 @@
+From 472534014030a4dc7abfa55952e6fdcb60d12f55 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Wed, 22 Feb 2017 11:10:16 -0600
+Subject: [PATCH 076/103] dt-bindings: reset: a10sr: Add Arria10 SR Reset
+ Controller offsets
+
+The Arria10 System Resource Chip reset controller handles the
+Arria10 peripheral PHYs. This patch adds the offsets for
+these PHYs.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+---
+ MAINTAINERS | 1
+ include/dt-bindings/reset/altr,rst-mgr-a10sr.h | 33 +++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+)
+ create mode 100644 include/dt-bindings/reset/altr,rst-mgr-a10sr.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -633,6 +633,7 @@ S: Maintained
+ F: drivers/gpio/gpio-altera-a10sr.c
+ F: drivers/mfd/altera-a10sr.c
+ F: include/linux/mfd/altera-a10sr.h
++F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h
+
+ ALTERA TRIPLE SPEED ETHERNET DRIVER
+ M: Vince Bridgers <vbridger@opensource.altera.com>
+--- /dev/null
++++ b/include/dt-bindings/reset/altr,rst-mgr-a10sr.h
+@@ -0,0 +1,33 @@
++/*
++ * Copyright Intel Corporation (C) 2017. All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ *
++ * Reset binding definitions for Altera Arria10 MAX5 System Resource Chip
++ *
++ * Adapted from altr,rst-mgr-a10.h
++ */
++
++#ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
++#define _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
++
++/* Peripheral PHY resets */
++#define A10SR_RESET_ENET_HPS 0
++#define A10SR_RESET_PCIE 1
++#define A10SR_RESET_FILE 2
++#define A10SR_RESET_BQSPI 3
++#define A10SR_RESET_USB 4
++
++#define A10SR_RESET_NUM 5
++
++#endif
diff --git a/patches.socfpga/0077-reset-Add-Altera-Arria10-SR-Reset-Controller.patch b/patches.socfpga/0077-reset-Add-Altera-Arria10-SR-Reset-Controller.patch
new file mode 100644
index 0000000..e845232
--- /dev/null
+++ b/patches.socfpga/0077-reset-Add-Altera-Arria10-SR-Reset-Controller.patch
@@ -0,0 +1,199 @@
+From 5d4c070628323b330cd36b4013d373ed0433a4eb Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Wed, 22 Feb 2017 11:10:17 -0600
+Subject: [PATCH 077/103] reset: Add Altera Arria10 SR Reset Controller
+
+This patch adds the reset controller functionality for
+Peripheral PHYs to the Arria10 System Resource Chip.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+
+Conflicts:
+
+ drivers/reset/Makefile
+---
+ MAINTAINERS | 1
+ drivers/reset/Kconfig | 7 ++
+ drivers/reset/Makefile | 1
+ drivers/reset/reset-a10sr.c | 138 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 147 insertions(+)
+ create mode 100644 drivers/reset/reset-a10sr.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -632,6 +632,7 @@ M: Thor Thayer <thor.thayer@linux.intel.
+ S: Maintained
+ F: drivers/gpio/gpio-altera-a10sr.c
+ F: drivers/mfd/altera-a10sr.c
++F: drivers/reset/reset-a10sr.c
+ F: include/linux/mfd/altera-a10sr.h
+ F: include/dt-bindings/reset/altr,rst-mgr-a10sr.h
+
+--- a/drivers/reset/Kconfig
++++ b/drivers/reset/Kconfig
+@@ -14,6 +14,13 @@ menuconfig RESET_CONTROLLER
+
+ if RESET_CONTROLLER
+
++config RESET_A10SR
++ tristate "Altera Arria10 System Resource Reset"
++ depends on MFD_ALTERA_A10SR
++ help
++ This option enables support for the external reset functions for
++ peripheral PHYs on the Altera Arria10 System Resource Chip.
++
+ config RESET_ATH79
+ bool "AR71xx Reset Driver" if COMPILE_TEST
+ default ATH79
+--- a/drivers/reset/Makefile
++++ b/drivers/reset/Makefile
+@@ -1,6 +1,7 @@
+ obj-y += core.o
+ obj-y += hisilicon/
+ obj-$(CONFIG_ARCH_STI) += sti/
++obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
+ obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
+ obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
+ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
+--- /dev/null
++++ b/drivers/reset/reset-a10sr.c
+@@ -0,0 +1,138 @@
++/*
++ * Copyright Intel Corporation (C) 2017. All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ *
++ * Reset driver for Altera Arria10 MAX5 System Resource Chip
++ *
++ * Adapted from reset-socfpga.c
++ */
++
++#include <linux/err.h>
++#include <linux/mfd/altera-a10sr.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/reset-controller.h>
++
++#include <dt-bindings/reset/altr,rst-mgr-a10sr.h>
++
++struct a10sr_reset {
++ struct reset_controller_dev rcdev;
++ struct regmap *regmap;
++};
++
++static inline struct a10sr_reset *to_a10sr_rst(struct reset_controller_dev *rc)
++{
++ return container_of(rc, struct a10sr_reset, rcdev);
++}
++
++static inline int a10sr_reset_shift(unsigned long id)
++{
++ switch (id) {
++ case A10SR_RESET_ENET_HPS:
++ return 1;
++ case A10SR_RESET_PCIE:
++ case A10SR_RESET_FILE:
++ case A10SR_RESET_BQSPI:
++ case A10SR_RESET_USB:
++ return id + 11;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int a10sr_reset_update(struct reset_controller_dev *rcdev,
++ unsigned long id, bool assert)
++{
++ struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
++ int offset = a10sr_reset_shift(id);
++ u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
++ int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
++
++ return regmap_update_bits(a10r->regmap, index, mask, assert ? 0 : mask);
++}
++
++static int a10sr_reset_assert(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ return a10sr_reset_update(rcdev, id, true);
++}
++
++static int a10sr_reset_deassert(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ return a10sr_reset_update(rcdev, id, false);
++}
++
++static int a10sr_reset_status(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ int ret;
++ struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
++ int offset = a10sr_reset_shift(id);
++ u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
++ int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
++ unsigned int value;
++
++ ret = regmap_read(a10r->regmap, index, &value);
++ if (ret < 0)
++ return ret;
++
++ return !!(value & mask);
++}
++
++static const struct reset_control_ops a10sr_reset_ops = {
++ .assert = a10sr_reset_assert,
++ .deassert = a10sr_reset_deassert,
++ .status = a10sr_reset_status,
++};
++
++static int a10sr_reset_probe(struct platform_device *pdev)
++{
++ struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
++ struct a10sr_reset *a10r;
++
++ a10r = devm_kzalloc(&pdev->dev, sizeof(struct a10sr_reset),
++ GFP_KERNEL);
++ if (!a10r)
++ return -ENOMEM;
++
++ a10r->rcdev.owner = THIS_MODULE;
++ a10r->rcdev.nr_resets = A10SR_RESET_NUM;
++ a10r->rcdev.ops = &a10sr_reset_ops;
++ a10r->rcdev.of_node = pdev->dev.of_node;
++ a10r->regmap = a10sr->regmap;
++
++ platform_set_drvdata(pdev, a10r);
++
++ return devm_reset_controller_register(&pdev->dev, &a10r->rcdev);
++}
++
++static const struct of_device_id a10sr_reset_of_match[] = {
++ { .compatible = "altr,a10sr-reset" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, a10sr_reset_of_match);
++
++static struct platform_driver a10sr_reset_driver = {
++ .probe = a10sr_reset_probe,
++ .driver = {
++ .name = "altr_a10sr_reset",
++ },
++};
++module_platform_driver(a10sr_reset_driver);
++
++MODULE_AUTHOR("Thor Thayer <thor.thayer@linux.intel.com>");
++MODULE_DESCRIPTION("Altera Arria10 System Resource Reset Controller Driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0078-ARM-dts-socfpga-Add-Devkit-A10-SR-Reset-Controller.patch b/patches.socfpga/0078-ARM-dts-socfpga-Add-Devkit-A10-SR-Reset-Controller.patch
new file mode 100644
index 0000000..bbbafba
--- /dev/null
+++ b/patches.socfpga/0078-ARM-dts-socfpga-Add-Devkit-A10-SR-Reset-Controller.patch
@@ -0,0 +1,29 @@
+From c948058fb2a34b35c935b947f4c4f07c3d3e7d24 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Thu, 16 Mar 2017 07:57:16 -0500
+Subject: [PATCH 078/103] ARM: dts: socfpga: Add Devkit A10-SR Reset Controller
+
+Add the Altera Arria10 System Resource Reset Controller to the MFD
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+v2 change commit header to ARM: dts: socfpga.
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -121,6 +121,11 @@
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
++
++ a10sr_rst: reset-controller {
++ compatible = "altr,a10sr-reset";
++ #reset-cells = <1>;
++ };
+ };
+ };
+
diff --git a/patches.socfpga/0079-EDAC-altera-Fix-peripheral-warnings-for-Cyclone5.patch b/patches.socfpga/0079-EDAC-altera-Fix-peripheral-warnings-for-Cyclone5.patch
new file mode 100644
index 0000000..7f6e80c
--- /dev/null
+++ b/patches.socfpga/0079-EDAC-altera-Fix-peripheral-warnings-for-Cyclone5.patch
@@ -0,0 +1,61 @@
+From 5a77f16dd47f75102d12d86a6ad7bb230b256077 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Wed, 5 Apr 2017 13:01:02 -0500
+Subject: [PATCH 079/103] EDAC, altera: Fix peripheral warnings for Cyclone5
+
+The peripherals' RAS functionality only exist on the Arria10 SoCFPGA.
+The Cyclone5 initialization generates EDAC warnings when the peripherals
+aren't found in the device tree. Fix by checking for Arria10 in the init
+functions.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Cc: linux-edac <linux-edac@vger.kernel.org>
+Link: http://lkml.kernel.org/r/1491415262-5018-1-git-send-email-thor.thayer@linux.intel.com
+Signed-off-by: Borislav Petkov <bp@suse.de>
+---
+ drivers/edac/altera_edac.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/drivers/edac/altera_edac.c
++++ b/drivers/edac/altera_edac.c
+@@ -1024,13 +1024,23 @@ out:
+ return ret;
+ }
+
++static int socfpga_is_a10(void)
++{
++ return of_machine_is_compatible("altr,socfpga-arria10");
++}
++
+ static int validate_parent_available(struct device_node *np);
+ static const struct of_device_id altr_edac_a10_device_of_match[];
+ static int __init __maybe_unused altr_init_a10_ecc_device_type(char *compat)
+ {
+ int irq;
+- struct device_node *child, *np = of_find_compatible_node(NULL, NULL,
+- "altr,socfpga-a10-ecc-manager");
++ struct device_node *child, *np;
++
++ if (!socfpga_is_a10())
++ return -ENODEV;
++
++ np = of_find_compatible_node(NULL, NULL,
++ "altr,socfpga-a10-ecc-manager");
+ if (!np) {
+ edac_printk(KERN_ERR, EDAC_DEVICE, "ECC Manager not found\n");
+ return -ENODEV;
+@@ -1546,8 +1556,12 @@ static const struct edac_device_prv_data
+ static int __init socfpga_init_sdmmc_ecc(void)
+ {
+ int rc = -ENODEV;
+- struct device_node *child = of_find_compatible_node(NULL, NULL,
+- "altr,socfpga-sdmmc-ecc");
++ struct device_node *child;
++
++ if (!socfpga_is_a10())
++ return -ENODEV;
++
++ child = of_find_compatible_node(NULL, NULL, "altr,socfpga-sdmmc-ecc");
+ if (!child) {
+ edac_printk(KERN_WARNING, EDAC_DEVICE, "SDMMC node not found\n");
+ return -ENODEV;
diff --git a/patches.socfpga/0080-mfd-altr_a10sr-Add-Arria10-DevKit-Reset-Controller.patch b/patches.socfpga/0080-mfd-altr_a10sr-Add-Arria10-DevKit-Reset-Controller.patch
new file mode 100644
index 0000000..8da8b04
--- /dev/null
+++ b/patches.socfpga/0080-mfd-altr_a10sr-Add-Arria10-DevKit-Reset-Controller.patch
@@ -0,0 +1,27 @@
+From 3c7b3fce2cf21f284518116f77bff9d6c7f4b327 Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Wed, 22 Feb 2017 11:10:18 -0600
+Subject: [PATCH 080/103] mfd: altr_a10sr: Add Arria10 DevKit Reset Controller
+
+Add Peripheral PHY Reset Controller to the Arria10
+Development Kit System Resource Chip's MFD.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ drivers/mfd/altera-a10sr.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/mfd/altera-a10sr.c
++++ b/drivers/mfd/altera-a10sr.c
+@@ -33,6 +33,10 @@ static const struct mfd_cell altr_a10sr_
+ .name = "altr_a10sr_gpio",
+ .of_compatible = "altr,a10sr-gpio",
+ },
++ {
++ .name = "altr_a10sr_reset",
++ .of_compatible = "altr,a10sr-reset",
++ },
+ };
+
+ static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg)
diff --git a/patches.socfpga/0081-dt-bindings-mfd-Add-Altera-Arria10-SR-Reset-Controll.patch b/patches.socfpga/0081-dt-bindings-mfd-Add-Altera-Arria10-SR-Reset-Controll.patch
new file mode 100644
index 0000000..2541f56
--- /dev/null
+++ b/patches.socfpga/0081-dt-bindings-mfd-Add-Altera-Arria10-SR-Reset-Controll.patch
@@ -0,0 +1,48 @@
+From f12e2e73318394511538aa49c150a864d4f1a91a Mon Sep 17 00:00:00 2001
+From: Thor Thayer <thor.thayer@linux.intel.com>
+Date: Wed, 22 Feb 2017 11:10:15 -0600
+Subject: [PATCH 081/103] dt-bindings: mfd: Add Altera Arria10 SR Reset
+ Controller bindings
+
+This patch adds documentation for the Altera A10-SR Reset
+Controller DT bindings.
+
+Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ Documentation/devicetree/bindings/mfd/altera-a10sr.txt | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
++++ b/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
+@@ -18,6 +18,7 @@ The A10SR consists of these sub-devices:
+ Device Description
+ ------ ----------
+ a10sr_gpio GPIO Controller
++a10sr_rst Reset Controller
+
+ Arria10 GPIO
+ Required Properties:
+@@ -27,6 +28,11 @@ Required Properties:
+ the second cell is used to specify flags.
+ See ../gpio/gpio.txt for more information.
+
++Arria10 Peripheral PHY Reset
++Required Properties:
++- compatible : Should be "altr,a10sr-reset"
++- #reset-cells : Should be one.
++
+ Example:
+
+ resource-manager@0 {
+@@ -43,4 +49,9 @@ Example:
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
++
++ a10sr_rst: reset-controller {
++ compatible = "altr,a10sr-reset";
++ #reset-cells = <1>;
++ };
+ };
diff --git a/patches.socfpga/0082-ARM-socfpga-defconfig-enable-qspi.patch b/patches.socfpga/0082-ARM-socfpga-defconfig-enable-qspi.patch
new file mode 100644
index 0000000..406f407
--- /dev/null
+++ b/patches.socfpga/0082-ARM-socfpga-defconfig-enable-qspi.patch
@@ -0,0 +1,23 @@
+From fa54ece4ad77749237745ea23796f8a2a368cbfc Mon Sep 17 00:00:00 2001
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Tue, 18 Oct 2016 07:43:04 +0000
+Subject: [PATCH 082/103] ARM: socfpga: defconfig: enable qspi
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/configs/socfpga_defconfig | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm/configs/socfpga_defconfig
++++ b/arch/arm/configs/socfpga_defconfig
+@@ -51,6 +51,9 @@ CONFIG_CAN_DEBUG_DEVICES=y
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_DEVTMPFS=y
+ CONFIG_DEVTMPFS_MOUNT=y
++CONFIG_MTD=y
++CONFIG_MTD_SPI_NOR=y
++CONFIG_SPI_CADENCE_QUADSPI=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=2
+ CONFIG_BLK_DEV_RAM_SIZE=8192
diff --git a/patches.socfpga/0083-ARM-socfpga-updates-for-socfpga_defconfig.patch b/patches.socfpga/0083-ARM-socfpga-updates-for-socfpga_defconfig.patch
new file mode 100644
index 0000000..3fc4ef2
--- /dev/null
+++ b/patches.socfpga/0083-ARM-socfpga-updates-for-socfpga_defconfig.patch
@@ -0,0 +1,58 @@
+From b7e82058125354c24224ef475ffed4a8f30d025c Mon Sep 17 00:00:00 2001
+From: Alan Tull <atull@opensource.altera.com>
+Date: Wed, 2 Nov 2016 16:22:36 -0500
+Subject: [PATCH 083/103] ARM: socfpga: updates for socfpga_defconfig
+
+This patch enables the following in the
+socfpga_defconfig:
+
++CONFIG_OF_OVERLAY=y
+ Enable support for Device Tree Overlays
+
++CONFIG_FPGA_REGION=y
+ Enable device tree overlay support for FPGA
+ programming
+
++CONFIG_FPGA_MGR_SOCFPGA_A10=y
+ Enable partial reconfiguration for Altera
+ Arria 10 FPGA
+
++CONFIG_FPGA_BRIDGE=y
+ Enable the FPGA Bridges framework
+
++CONFIG_SOCFPGA_FPGA_BRIDGE=y
+ Enable support for SoCFPGA hardware
+ bridges
+
++CONFIG_ALTERA_FREEZE_BRIDGE=y
+ Enable support for the Altera Soft IP
+ Freeze bridges
+
+Signed-off-by: Alan Tull <atull@opensource.altera.com>
+---
+ arch/arm/configs/socfpga_defconfig | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/configs/socfpga_defconfig
++++ b/arch/arm/configs/socfpga_defconfig
+@@ -54,6 +54,7 @@ CONFIG_DEVTMPFS_MOUNT=y
+ CONFIG_MTD=y
+ CONFIG_MTD_SPI_NOR=y
+ CONFIG_SPI_CADENCE_QUADSPI=y
++CONFIG_OF_OVERLAY=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=2
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+@@ -105,7 +106,12 @@ CONFIG_DMADEVICES=y
+ CONFIG_PL330_DMA=y
+ CONFIG_DMATEST=m
+ CONFIG_FPGA=y
++CONFIG_FPGA_REGION=y
+ CONFIG_FPGA_MGR_SOCFPGA=y
++CONFIG_FPGA_MGR_SOCFPGA_A10=y
++CONFIG_FPGA_BRIDGE=y
++CONFIG_SOCFPGA_FPGA_BRIDGE=y
++CONFIG_ALTERA_FREEZE_BRIDGE=y
+ CONFIG_EXT2_FS=y
+ CONFIG_EXT2_FS_XATTR=y
+ CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/patches.socfpga/0084-ARM-socfpga_defconfig-update-defconfig-for-SoCFPGA.patch b/patches.socfpga/0084-ARM-socfpga_defconfig-update-defconfig-for-SoCFPGA.patch
new file mode 100644
index 0000000..8930358
--- /dev/null
+++ b/patches.socfpga/0084-ARM-socfpga_defconfig-update-defconfig-for-SoCFPGA.patch
@@ -0,0 +1,112 @@
+From b0068141c565214d7682a9fa95c1673648ab159d Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Wed, 14 Dec 2016 04:25:54 -0600
+Subject: [PATCH 084/103] ARM: socfpga_defconfig: update defconfig for SoCFPGA
+
+MARVELL_PHY - support for the Marvell PHY that is on most of the devkits
+EEPROM_AT24 - support for I2C EEPROMs on the devkits
+GPIO_ALTERA - support for Altera's GPIO driver
+NAND - support for the Denali NAND controller along with MTD subsystem
+SPI_DESIGNWARE - support for SPI that is on SoCFPGA
+SPI_DW_MMIO - support for the memory-mapped io interface for the DW SPI core
+OF_CONFIGFS - SoCFPGA makes use of DT overlays using configfs, enable it
+GPIO_ALTERA_A10SR - support for the newly added Altera HWMON driver
+LEDS - support for the GPIO LEDs on the SoCFPGA devkits
+RTC - support for the DS1307 RTC
+JFFS2_FS - support for the JFFS2 filesystem
+NFS_V4 - supports for v4 NFS
+FUNCTION_TRACER - supports debug function tracing
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/configs/socfpga_defconfig | 28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/configs/socfpga_defconfig
++++ b/arch/arm/configs/socfpga_defconfig
+@@ -52,14 +52,20 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug
+ CONFIG_DEVTMPFS=y
+ CONFIG_DEVTMPFS_MOUNT=y
+ CONFIG_MTD=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_M25P80=y
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_DENALI_DT=y
+ CONFIG_MTD_SPI_NOR=y
+ CONFIG_SPI_CADENCE_QUADSPI=y
+ CONFIG_OF_OVERLAY=y
++CONFIG_OF_CONFIGFS=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=2
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_NVME=m
+ CONFIG_SRAM=y
++CONFIG_EEPROM_AT24=y
+ CONFIG_SCSI=y
+ # CONFIG_SCSI_PROC_FS is not set
+ CONFIG_BLK_DEV_SD=y
+@@ -69,6 +75,7 @@ CONFIG_E1000E=m
+ CONFIG_IGB=m
+ CONFIG_IXGBE=m
+ CONFIG_STMMAC_ETH=y
++CONFIG_MARVELL_PHY=y
+ CONFIG_MICREL_PHY=y
+ CONFIG_INPUT_EVDEV=y
+ CONFIG_INPUT_TOUCHSCREEN=y
+@@ -84,14 +91,22 @@ CONFIG_SERIAL_8250_DW=y
+ CONFIG_I2C=y
+ CONFIG_I2C_CHARDEV=y
+ CONFIG_I2C_DESIGNWARE_PLATFORM=y
++CONFIG_SPI=y
++CONFIG_SPI_DESIGNWARE=y
++CONFIG_SPI_DW_MMIO=y
++CONFIG_SPI_SPIDEV=y
+ CONFIG_GPIOLIB=y
+ CONFIG_GPIO_SYSFS=y
++CONFIG_GPIO_ALTERA=y
+ CONFIG_GPIO_DWAPB=y
++CONFIG_GPIO_ALTERA_A10SR=y
++CONFIG_SENSORS_MAX1619=y
+ CONFIG_PMBUS=y
+ CONFIG_SENSORS_LTC2978=y
+ CONFIG_SENSORS_LTC2978_REGULATOR=y
+ CONFIG_WATCHDOG=y
+ CONFIG_DW_WATCHDOG=y
++CONFIG_MFD_ALTERA_A10SR=y
+ CONFIG_MFD_STMPE=y
+ CONFIG_REGULATOR=y
+ CONFIG_REGULATOR_FIXED_VOLTAGE=y
+@@ -102,6 +117,14 @@ CONFIG_NOP_USB_XCEIV=y
+ CONFIG_USB_GADGET=y
+ CONFIG_MMC=y
+ CONFIG_MMC_DW=y
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_CPU=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_DRV_DS1307=y
+ CONFIG_DMADEVICES=y
+ CONFIG_PL330_DMA=y
+ CONFIG_DMATEST=m
+@@ -121,9 +144,10 @@ CONFIG_VFAT_FS=y
+ CONFIG_NTFS_FS=y
+ CONFIG_NTFS_RW=y
+ CONFIG_TMPFS=y
+-CONFIG_CONFIGFS_FS=y
++CONFIG_JFFS2_FS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
+ CONFIG_ROOT_NFS=y
+ CONFIG_NFSD=y
+ CONFIG_NFSD_V3_ACL=y
+@@ -135,5 +159,5 @@ CONFIG_DEBUG_INFO=y
+ CONFIG_MAGIC_SYSRQ=y
+ CONFIG_DETECT_HUNG_TASK=y
+ # CONFIG_SCHED_DEBUG is not set
+-CONFIG_ENABLE_DEFAULT_TRACERS=y
++CONFIG_FUNCTION_TRACER=y
+ CONFIG_DEBUG_USER=y
diff --git a/patches.socfpga/0085-ARM-socfpga-updates-for-socfpga_defconfig.patch b/patches.socfpga/0085-ARM-socfpga-updates-for-socfpga_defconfig.patch
new file mode 100644
index 0000000..022150a
--- /dev/null
+++ b/patches.socfpga/0085-ARM-socfpga-updates-for-socfpga_defconfig.patch
@@ -0,0 +1,23 @@
+From 6dd0a8c7a2e167fd63ef04f038b0e1cbf6e33188 Mon Sep 17 00:00:00 2001
+From: Jia Jie Ho <ho.jia.jie@intel.com>
+Date: Thu, 16 Mar 2017 08:05:46 -0500
+Subject: [PATCH 085/103] ARM: socfpga: updates for socfpga_defconfig
+
+This patch enables Altera TSE support in socfpga_defconfig
+
+Signed-off-by: Jia Jie Ho <ho.jia.jie@intel.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/configs/socfpga_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/socfpga_defconfig
++++ b/arch/arm/configs/socfpga_defconfig
+@@ -71,6 +71,7 @@ CONFIG_SCSI=y
+ CONFIG_BLK_DEV_SD=y
+ # CONFIG_SCSI_LOWLEVEL is not set
+ CONFIG_NETDEVICES=y
++CONFIG_ALTERA_TSE=m
+ CONFIG_E1000E=m
+ CONFIG_IGB=m
+ CONFIG_IXGBE=m
diff --git a/patches.socfpga/0086-ARM-dts-socfpga-Add-new-MCVEVK-manufacturer-compat.patch b/patches.socfpga/0086-ARM-dts-socfpga-Add-new-MCVEVK-manufacturer-compat.patch
new file mode 100644
index 0000000..f5c7e4e
--- /dev/null
+++ b/patches.socfpga/0086-ARM-dts-socfpga-Add-new-MCVEVK-manufacturer-compat.patch
@@ -0,0 +1,37 @@
+From 3bf20e590278aeae0493d36dead11207a5a3b6d7 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex@denx.de>
+Date: Mon, 19 Sep 2016 21:40:43 +0000
+Subject: [PATCH 086/103] ARM: dts: socfpga: Add new MCVEVK manufacturer compat
+
+The board is now manufactured by Aries Embedded GmbH, update compat string.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: Dinh Nguyen <dinguyen@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
++++ b/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
+@@ -18,7 +18,7 @@
+ #include "socfpga_cyclone5.dtsi"
+
+ / {
+- model = "DENX MCV";
++ model = "Aries/DENX MCV";
+ compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+ memory {
+--- a/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
+@@ -18,7 +18,7 @@
+ #include "socfpga_cyclone5_mcv.dtsi"
+
+ / {
+- model = "DENX MCV EVK";
++ model = "Aries/DENX MCV EVK";
+ compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+ aliases {
diff --git a/patches.socfpga/0087-ARM-dts-socfpga-Add-Macnica-sodia-board.patch b/patches.socfpga/0087-ARM-dts-socfpga-Add-Macnica-sodia-board.patch
new file mode 100644
index 0000000..f004121
--- /dev/null
+++ b/patches.socfpga/0087-ARM-dts-socfpga-Add-Macnica-sodia-board.patch
@@ -0,0 +1,162 @@
+From 3cd00779ac5363f30cccb685ae6ca56990d363b1 Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Date: Sat, 24 Sep 2016 23:59:45 +0000
+Subject: [PATCH 087/103] ARM: dts: socfpga: Add Macnica sodia board
+
+Add support for board based on the Altera Cyclone V SoC.
+This board has the following functions:
+ - 1 GiB of DRAM
+ - 1 Gigabit ethernet
+ - 1 SD card slot
+ - 1 USB gadget port
+ - QSPI NOR Flash
+ - I2C EEPROMs and I2C RTC
+ - DVI output
+ - Audio port
+
+This commit supports without QSPI, DVI and Audio.
+
+Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/Makefile | 1
+ arch/arm/boot/dts/socfpga_cyclone5_sodia.dts | 123 +++++++++++++++++++++++++++
+ 2 files changed, 124 insertions(+)
+ create mode 100644 arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -700,6 +700,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) += \
+ socfpga_cyclone5_de0_sockit.dtb \
+ socfpga_cyclone5_sockit.dtb \
+ socfpga_cyclone5_socrates.dtb \
++ socfpga_cyclone5_sodia.dtb \
+ socfpga_cyclone5_vining_fpga.dtb \
+ socfpga_vt.dtb
+ dtb-$(CONFIG_ARCH_SPEAR13XX) += \
+--- /dev/null
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
+@@ -0,0 +1,123 @@
++/*
++ * Copyright (C) 2016 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
++ *
++ * 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 "socfpga_cyclone5.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++
++/ {
++ model = "Altera SOCFPGA Cyclone V SoC Macnica Sodia board";
++ compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++
++ chosen {
++ bootargs = "earlyprintk";
++ stdout-path = "serial0:115200n8";
++ };
++
++ memory {
++ name = "memory";
++ device_type = "memory";
++ reg = <0x0 0x40000000>;
++ };
++
++ aliases {
++ ethernet0 = &gmac1;
++ };
++
++ regulator_3_3v: 3-3-v-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "3.3V";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
++ leds: gpio-leds {
++ compatible = "gpio-leds";
++
++ hps_led0 {
++ label = "hps:green:led0";
++ gpios = <&portb 12 GPIO_ACTIVE_LOW>;
++ };
++
++ hps_led1 {
++ label = "hps:green:led1";
++ gpios = <&portb 13 GPIO_ACTIVE_LOW>;
++ };
++
++ hps_led2 {
++ label = "hps:green:led2";
++ gpios = <&portb 14 GPIO_ACTIVE_LOW>;
++ };
++
++ hps_led3 {
++ label = "hps:green:led3";
++ gpios = <&portb 15 GPIO_ACTIVE_LOW>;
++ };
++ };
++};
++
++&gmac1 {
++ status = "okay";
++ phy-mode = "rgmii";
++ phy = <&phy0>;
++
++ mdio0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ phy0: ethernet-phy@0 {
++ reg = <0>;
++ rxd0-skew-ps = <0>;
++ rxd1-skew-ps = <0>;
++ rxd2-skew-ps = <0>;
++ rxd3-skew-ps = <0>;
++ rxdv-skew-ps = <0>;
++ rxc-skew-ps = <3000>;
++ txen-skew-ps = <0>;
++ txc-skew-ps = <3000>;
++ };
++ };
++};
++
++&gpio1 {
++ status = "okay";
++};
++
++&i2c0 {
++ status = "okay";
++
++ eeprom@51 {
++ compatible = "atmel,24c32";
++ reg = <0x51>;
++ pagesize = <32>;
++ };
++
++ rtc@68 {
++ compatible = "dallas,ds1339";
++ reg = <0x68>;
++ };
++};
++
++&mmc0 {
++ cd-gpios = <&portb 18 0>;
++ vmmc-supply = <®ulator_3_3v>;
++ vqmmc-supply = <®ulator_3_3v>;
++ status = "okay";
++};
++
++&usb1 {
++ status = "okay";
++};
diff --git a/patches.socfpga/0088-ARM-dts-socfpga-add-specific-compatible-strings-for-.patch b/patches.socfpga/0088-ARM-dts-socfpga-add-specific-compatible-strings-for-.patch
new file mode 100644
index 0000000..4a87d3b
--- /dev/null
+++ b/patches.socfpga/0088-ARM-dts-socfpga-add-specific-compatible-strings-for-.patch
@@ -0,0 +1,89 @@
+From d5b1b034ae10a0fcbd24a3af638558c93e17ca4a Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@kernel.org>
+Date: Tue, 1 Nov 2016 09:57:06 -0500
+Subject: [PATCH 088/103] ARM: dts: socfpga: add specific compatible strings
+ for boards
+
+Add a more specific board compatible entry for all of the SOCFPGA
+Cyclone 5 based boards.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+v3: Be a bit more specific with the c5 dk and sockit, use
+ "altr,socfpga-cyclone5-socdk" and "terasic,socfpga-cyclone5-sockit"
+v2: remove extra space and add a comma between compatible entries
+---
+ arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_sockit.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_sodia.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 2 +-
+ 6 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts
+@@ -18,7 +18,7 @@
+
+ / {
+ model = "Terasic DE-0(Atlas)";
+- compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++ compatible = "terasic,de0-atlas", "altr,socfpga-cyclone5", "altr,socfpga";
+
+ chosen {
+ bootargs = "earlyprintk";
+--- a/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
+@@ -19,7 +19,7 @@
+
+ / {
+ model = "Aries/DENX MCV EVK";
+- compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++ compatible = "denx,mcvevk", "altr,socfpga-cyclone5", "altr,socfpga";
+
+ aliases {
+ ethernet0 = &gmac0;
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -19,7 +19,7 @@
+
+ / {
+ model = "Altera SOCFPGA Cyclone V SoC Development Kit";
+- compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++ compatible = "altr,socfpga-cyclone5-socdk", "altr,socfpga-cyclone5", "altr,socfpga";
+
+ chosen {
+ bootargs = "earlyprintk";
+--- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
+@@ -19,7 +19,7 @@
+
+ / {
+ model = "Terasic SoCkit";
+- compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++ compatible = "terasic,socfpga-cyclone5-sockit", "altr,socfpga-cyclone5", "altr,socfpga";
+
+ chosen {
+ bootargs = "earlyprintk";
+--- a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
+@@ -21,7 +21,7 @@
+
+ / {
+ model = "Altera SOCFPGA Cyclone V SoC Macnica Sodia board";
+- compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++ compatible = "macnica,sodia", "altr,socfpga-cyclone5", "altr,socfpga";
+
+ chosen {
+ bootargs = "earlyprintk";
+--- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
+@@ -51,7 +51,7 @@
+
+ / {
+ model = "samtec VIN|ING FPGA";
+- compatible = "altr,socfpga-cyclone5", "altr,socfpga";
++ compatible = "samtec,vining", "altr,socfpga-cyclone5", "altr,socfpga";
+
+ chosen {
+ bootargs = "console=ttyS0,115200";
diff --git a/patches.socfpga/0089-ARM-dts-socfpga-Add-unit-name-to-memory-nodes.patch b/patches.socfpga/0089-ARM-dts-socfpga-Add-unit-name-to-memory-nodes.patch
new file mode 100644
index 0000000..c89c152
--- /dev/null
+++ b/patches.socfpga/0089-ARM-dts-socfpga-Add-unit-name-to-memory-nodes.patch
@@ -0,0 +1,138 @@
+From 053c4886aa63bf59091841b2a7635ce14921fb37 Mon Sep 17 00:00:00 2001
+From: Florian Vaussard <florian.vaussard@gmail.com>
+Date: Mon, 27 Feb 2017 10:38:39 -0600
+Subject: [PATCH 089/103] ARM: dts: socfpga: Add unit name to memory nodes
+
+Memory nodes in Arria5, Cyclone5 and Arria10 do not have a unit name.
+This will trigger several warnings like this one (when compiled with
+W=1):
+
+Node /memory has a reg or ranges property, but no unit name
+
+Add the corresponding unit name to each node.
+
+Signed-off-by: Florian Vaussard <florian.vaussard@heig-vd.ch>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 2 +-
+ arch/arm/boot/dts/socfpga_arria5_socdk.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_sockit.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_socrates.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_sodia.dts | 2 +-
+ arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 2 +-
+ arch/arm/boot/dts/socfpga_vt.dts | 2 +-
+ 10 files changed, 10 insertions(+), 10 deletions(-)
+
+--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+@@ -30,7 +30,7 @@
+ stdout-path = "serial0:115200n8";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+@@ -26,7 +26,7 @@
+ stdout-path = "serial0:115200n8";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts
+@@ -25,7 +25,7 @@
+ stdout-path = "serial0:115200n8";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
++++ b/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
+@@ -21,7 +21,7 @@
+ model = "Aries/DENX MCV";
+ compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1 GiB */
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+@@ -26,7 +26,7 @@
+ stdout-path = "serial0:115200n8";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
+@@ -26,7 +26,7 @@
+ stdout-path = "serial0:115200n8";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
+@@ -25,7 +25,7 @@
+ bootargs = "console=ttyS0,115200";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
+@@ -28,7 +28,7 @@
+ stdout-path = "serial0:115200n8";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>;
+--- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
+@@ -57,7 +57,7 @@
+ bootargs = "console=ttyS0,115200";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1GB */
+--- a/arch/arm/boot/dts/socfpga_vt.dts
++++ b/arch/arm/boot/dts/socfpga_vt.dts
+@@ -26,7 +26,7 @@
+ bootargs = "console=ttyS0,57600";
+ };
+
+- memory {
++ memory@0 {
+ name = "memory";
+ device_type = "memory";
+ reg = <0x0 0x40000000>; /* 1 GB */
diff --git a/patches.socfpga/0090-ARM-dts-socfpga-sodia-enable-qspi.patch b/patches.socfpga/0090-ARM-dts-socfpga-sodia-enable-qspi.patch
new file mode 100644
index 0000000..9d3cdf3
--- /dev/null
+++ b/patches.socfpga/0090-ARM-dts-socfpga-sodia-enable-qspi.patch
@@ -0,0 +1,41 @@
+From d59a294e24214c1d45314e38eac346256973f389 Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Date: Fri, 10 Feb 2017 11:21:33 -0600
+Subject: [PATCH 090/103] ARM: dts: socfpga: sodia: enable qspi
+
+Enable the qspi controller on sodia board and add the flash chip
+(n25q512a).
+
+Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+ arch/arm/boot/dts/socfpga_cyclone5_sodia.dts | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
++++ b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
+@@ -121,3 +121,24 @@
+ &usb1 {
+ status = "okay";
+ };
++
++&qspi {
++ status = "okay";
++
++ flash0: n25q512a@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "n25q512a";
++ reg = <0>;
++ spi-max-frequency = <100000000>;
++
++ m25p,fast-read;
++ cdns,page-size = <256>;
++ cdns,block-size = <16>;
++ cdns,read-delay = <4>;
++ cdns,tshsl-ns = <50>;
++ cdns,tsd2d-ns = <50>;
++ cdns,tchsh-ns = <4>;
++ cdns,tslch-ns = <4>;
++ };
++};
diff --git a/patches.socfpga/0091-ARM-dts-socfpga-add-qspi-node.patch b/patches.socfpga/0091-ARM-dts-socfpga-add-qspi-node.patch
new file mode 100644
index 0000000..f07477c
--- /dev/null
+++ b/patches.socfpga/0091-ARM-dts-socfpga-add-qspi-node.patch
@@ -0,0 +1,36 @@
+From 5420a09156d6bc2cb61aad87b1277c6c9e3ba788 Mon Sep 17 00:00:00 2001
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Tue, 18 Oct 2016 07:43:02 +0000
+Subject: [PATCH 091/103] ARM: dts: socfpga: add qspi node
+
+Add the qspi node to the socfpga dtsi file.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
+---
+ arch/arm/boot/dts/socfpga.dtsi | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/arch/arm/boot/dts/socfpga.dtsi
++++ b/arch/arm/boot/dts/socfpga.dtsi
+@@ -733,6 +733,20 @@
+ reg = <0xffff0000 0x10000>;
+ };
+
++ qspi: spi@ff705000 {
++ compatible = "cdns,qspi-nor";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0xff705000 0x1000>,
++ <0xffa00000 0x1000>;
++ interrupts = <0 151 4>;
++ cdns,fifo-depth = <128>;
++ cdns,fifo-width = <4>;
++ cdns,trigger-address = <0x00000000>;
++ clocks = <&qspi_clk>;
++ status = "disabled";
++ };
++
+ rst: rstmgr@ffd05000 {
+ #reset-cells = <1>;
+ compatible = "altr,rst-mgr";
diff --git a/patches.socfpga/0092-fpga-pr-ip-Core-driver-support-for-Altera-Partial-Re.patch b/patches.socfpga/0092-fpga-pr-ip-Core-driver-support-for-Altera-Partial-Re.patch
new file mode 100644
index 0000000..6d6a335
--- /dev/null
+++ b/patches.socfpga/0092-fpga-pr-ip-Core-driver-support-for-Altera-Partial-Re.patch
@@ -0,0 +1,302 @@
+From dee4f9e2e4dd5ee90ad2910be5546ff32f42aa55 Mon Sep 17 00:00:00 2001
+From: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Date: Thu, 23 Mar 2017 19:34:28 -0500
+Subject: [PATCH 092/103] fpga pr ip: Core driver support for Altera Partial
+ Reconfiguration IP.
+
+Adding the core functions necessary for a fpga-mgr driver
+for the Altera Partial IP component. It is intended for
+these functions to be used by the various bus implementations
+like the platform bus or the PCIe bus.
+
+Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 5
+ drivers/fpga/Makefile | 1
+ drivers/fpga/altera-pr-ip-core.c | 220 +++++++++++++++++++++++++++++++++
+ include/linux/fpga/altera-pr-ip-core.h | 29 ++++
+ 4 files changed, 255 insertions(+)
+ create mode 100644 drivers/fpga/altera-pr-ip-core.c
+ create mode 100644 include/linux/fpga/altera-pr-ip-core.h
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -83,6 +83,11 @@ config ALTERA_FREEZE_BRIDGE
+ isolate one region of the FPGA from the busses while that
+ region is being reprogrammed.
+
++config ALTERA_PR_IP_CORE
++ tristate "Altera Partial Reconfiguration IP Core"
++ help
++ Core driver support for Altera Partial Reconfiguration IP component
++
+ endif # FPGA
+
+ endmenu
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += so
+ obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o
+ obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o
+ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
++obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o
+
+ # FPGA Bridge Drivers
+ obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
+--- /dev/null
++++ b/drivers/fpga/altera-pr-ip-core.c
+@@ -0,0 +1,220 @@
++/*
++ * Driver for Altera Partial Reconfiguration IP Core
++ *
++ * Copyright (C) 2016-2017 Intel Corporation
++ *
++ * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation
++ * by Alan Tull <atull@opensource.altera.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++#include <linux/delay.h>
++#include <linux/fpga/altera-pr-ip-core.h>
++#include <linux/fpga/fpga-mgr.h>
++#include <linux/module.h>
++
++#define ALT_PR_DATA_OFST 0x00
++#define ALT_PR_CSR_OFST 0x04
++
++#define ALT_PR_CSR_PR_START BIT(0)
++#define ALT_PR_CSR_STATUS_SFT 2
++#define ALT_PR_CSR_STATUS_MSK (7 << ALT_PR_CSR_STATUS_SFT)
++#define ALT_PR_CSR_STATUS_NRESET (0 << ALT_PR_CSR_STATUS_SFT)
++#define ALT_PR_CSR_STATUS_PR_ERR (1 << ALT_PR_CSR_STATUS_SFT)
++#define ALT_PR_CSR_STATUS_CRC_ERR (2 << ALT_PR_CSR_STATUS_SFT)
++#define ALT_PR_CSR_STATUS_BAD_BITS (3 << ALT_PR_CSR_STATUS_SFT)
++#define ALT_PR_CSR_STATUS_PR_IN_PROG (4 << ALT_PR_CSR_STATUS_SFT)
++#define ALT_PR_CSR_STATUS_PR_SUCCESS (5 << ALT_PR_CSR_STATUS_SFT)
++
++struct alt_pr_priv {
++ void __iomem *reg_base;
++};
++
++static enum fpga_mgr_states alt_pr_fpga_state(struct fpga_manager *mgr)
++{
++ struct alt_pr_priv *priv = mgr->priv;
++ const char *err = "unknown";
++ enum fpga_mgr_states ret = FPGA_MGR_STATE_UNKNOWN;
++ u32 val;
++
++ val = readl(priv->reg_base + ALT_PR_CSR_OFST);
++
++ val &= ALT_PR_CSR_STATUS_MSK;
++
++ switch (val) {
++ case ALT_PR_CSR_STATUS_NRESET:
++ return FPGA_MGR_STATE_RESET;
++
++ case ALT_PR_CSR_STATUS_PR_ERR:
++ err = "pr error";
++ ret = FPGA_MGR_STATE_WRITE_ERR;
++ break;
++
++ case ALT_PR_CSR_STATUS_CRC_ERR:
++ err = "crc error";
++ ret = FPGA_MGR_STATE_WRITE_ERR;
++ break;
++
++ case ALT_PR_CSR_STATUS_BAD_BITS:
++ err = "bad bits";
++ ret = FPGA_MGR_STATE_WRITE_ERR;
++ break;
++
++ case ALT_PR_CSR_STATUS_PR_IN_PROG:
++ return FPGA_MGR_STATE_WRITE;
++
++ case ALT_PR_CSR_STATUS_PR_SUCCESS:
++ return FPGA_MGR_STATE_OPERATING;
++
++ default:
++ break;
++ }
++
++ dev_err(&mgr->dev, "encountered error code %d (%s) in %s()\n",
++ val, err, __func__);
++ return ret;
++}
++
++static int alt_pr_fpga_write_init(struct fpga_manager *mgr,
++ struct fpga_image_info *info,
++ const char *buf, size_t count)
++{
++ struct alt_pr_priv *priv = mgr->priv;
++ u32 val;
++
++ if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
++ dev_err(&mgr->dev, "%s Partial Reconfiguration flag not set\n",
++ __func__);
++ return -EINVAL;
++ }
++
++ val = readl(priv->reg_base + ALT_PR_CSR_OFST);
++
++ if (val & ALT_PR_CSR_PR_START) {
++ dev_err(&mgr->dev,
++ "%s Partial Reconfiguration already started\n",
++ __func__);
++ return -EINVAL;
++ }
++
++ writel(val | ALT_PR_CSR_PR_START, priv->reg_base + ALT_PR_CSR_OFST);
++
++ return 0;
++}
++
++static int alt_pr_fpga_write(struct fpga_manager *mgr, const char *buf,
++ size_t count)
++{
++ struct alt_pr_priv *priv = mgr->priv;
++ u32 *buffer_32 = (u32 *)buf;
++ size_t i = 0;
++
++ if (count <= 0)
++ return -EINVAL;
++
++ /* Write out the complete 32-bit chunks */
++ while (count >= sizeof(u32)) {
++ writel(buffer_32[i++], priv->reg_base);
++ count -= sizeof(u32);
++ }
++
++ /* Write out remaining non 32-bit chunks */
++ switch (count) {
++ case 3:
++ writel(buffer_32[i++] & 0x00ffffff, priv->reg_base);
++ break;
++ case 2:
++ writel(buffer_32[i++] & 0x0000ffff, priv->reg_base);
++ break;
++ case 1:
++ writel(buffer_32[i++] & 0x000000ff, priv->reg_base);
++ break;
++ case 0:
++ break;
++ default:
++ /* This will never happen */
++ return -EFAULT;
++ }
++
++ if (alt_pr_fpga_state(mgr) == FPGA_MGR_STATE_WRITE_ERR)
++ return -EIO;
++
++ return 0;
++}
++
++static int alt_pr_fpga_write_complete(struct fpga_manager *mgr,
++ struct fpga_image_info *info)
++{
++ u32 i = 0;
++
++ do {
++ switch (alt_pr_fpga_state(mgr)) {
++ case FPGA_MGR_STATE_WRITE_ERR:
++ return -EIO;
++
++ case FPGA_MGR_STATE_OPERATING:
++ dev_info(&mgr->dev,
++ "successful partial reconfiguration\n");
++ return 0;
++
++ default:
++ break;
++ }
++ udelay(1);
++ } while (info->config_complete_timeout_us > i++);
++
++ dev_err(&mgr->dev, "timed out waiting for write to complete\n");
++ return -ETIMEDOUT;
++}
++
++static const struct fpga_manager_ops alt_pr_ops = {
++ .state = alt_pr_fpga_state,
++ .write_init = alt_pr_fpga_write_init,
++ .write = alt_pr_fpga_write,
++ .write_complete = alt_pr_fpga_write_complete,
++};
++
++int alt_pr_register(struct device *dev, void __iomem *reg_base)
++{
++ struct alt_pr_priv *priv;
++ u32 val;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->reg_base = reg_base;
++
++ val = readl(priv->reg_base + ALT_PR_CSR_OFST);
++
++ dev_dbg(dev, "%s status=%d start=%d\n", __func__,
++ (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT,
++ (int)(val & ALT_PR_CSR_PR_START));
++
++ return fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv);
++}
++EXPORT_SYMBOL_GPL(alt_pr_register);
++
++int alt_pr_unregister(struct device *dev)
++{
++ dev_dbg(dev, "%s\n", __func__);
++
++ fpga_mgr_unregister(dev);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(alt_pr_unregister);
++
++MODULE_AUTHOR("Matthew Gerlach <matthew.gerlach@linux.intel.com>");
++MODULE_DESCRIPTION("Altera Partial Reconfiguration IP Core");
++MODULE_LICENSE("GPL v2");
+--- /dev/null
++++ b/include/linux/fpga/altera-pr-ip-core.h
+@@ -0,0 +1,29 @@
++/*
++ * Driver for Altera Partial Reconfiguration IP Core
++ *
++ * Copyright (C) 2016 Intel Corporation
++ *
++ * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation
++ * by Alan Tull <atull@opensource.altera.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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 _ALT_PR_IP_CORE_H
++#define _ALT_PR_IP_CORE_H
++#include <linux/io.h>
++
++int alt_pr_register(struct device *dev, void __iomem *reg_base);
++int alt_pr_unregister(struct device *dev);
++
++#endif /* _ALT_PR_IP_CORE_H */
diff --git a/patches.socfpga/0093-fpga-dt-bindings-for-Altera-Partial-Reconfiguration-.patch b/patches.socfpga/0093-fpga-dt-bindings-for-Altera-Partial-Reconfiguration-.patch
new file mode 100644
index 0000000..b394e1e
--- /dev/null
+++ b/patches.socfpga/0093-fpga-dt-bindings-for-Altera-Partial-Reconfiguration-.patch
@@ -0,0 +1,32 @@
+From 4d9e84bcd82101758a0c21563d7740c1be578631 Mon Sep 17 00:00:00 2001
+From: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Date: Thu, 23 Mar 2017 19:34:29 -0500
+Subject: [PATCH 093/103] fpga dt: bindings for Altera Partial Reconfiguration
+ IP.
+
+Device Tree bindings for Altera Partial Reconfiguration IP.
+
+Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/devicetree/bindings/fpga/altera-pr-ip.txt | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/fpga/altera-pr-ip.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt
+@@ -0,0 +1,12 @@
++Altera Arria10 Partial Reconfiguration IP
++
++Required properties:
++- compatible : should contain "altr,a10-pr-ip"
++- reg : base address and size for memory mapped io.
++
++Example:
++
++ fpga_mgr: fpga-mgr@ff20c000 {
++ compatible = "altr,a10-pr-ip";
++ reg = <0xff20c000 0x10>;
++ };
diff --git a/patches.socfpga/0094-fpga-pr-ip-Platform-driver-for-Altera-Partial-Reconf.patch b/patches.socfpga/0094-fpga-pr-ip-Platform-driver-for-Altera-Partial-Reconf.patch
new file mode 100644
index 0000000..0a14547
--- /dev/null
+++ b/patches.socfpga/0094-fpga-pr-ip-Platform-driver-for-Altera-Partial-Reconf.patch
@@ -0,0 +1,116 @@
+From 78ffcb1fd105ec0289d496df641c391d87e3c773 Mon Sep 17 00:00:00 2001
+From: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Date: Thu, 23 Mar 2017 19:34:30 -0500
+Subject: [PATCH 094/103] fpga pr ip: Platform driver for Altera Partial
+ Reconfiguration IP.
+
+This adds a platform bus driver for a fpga-mgr driver
+that uses the Altera Partial Reconfiguration IP component.
+
+Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 7 +++
+ drivers/fpga/Makefile | 1
+ drivers/fpga/altera-pr-ip-core-plat.c | 68 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 76 insertions(+)
+ create mode 100644 drivers/fpga/altera-pr-ip-core-plat.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -88,6 +88,13 @@ config ALTERA_PR_IP_CORE
+ help
+ Core driver support for Altera Partial Reconfiguration IP component
+
++config ALTERA_PR_IP_CORE_PLAT
++ tristate "Platform support of Altera Partial Reconfiguration IP Core"
++ depends on ALTERA_PR_IP_CORE && OF && HAS_IOMEM
++ help
++ Platform driver support for Altera Partial Reconfiguration IP
++ component
++
+ endif # FPGA
+
+ endmenu
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx
+ obj-$(CONFIG_FPGA_MGR_XILINX_SPI) += xilinx-spi.o
+ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
+ obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o
++obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o
+
+ # FPGA Bridge Drivers
+ obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
+--- /dev/null
++++ b/drivers/fpga/altera-pr-ip-core-plat.c
+@@ -0,0 +1,68 @@
++/*
++ * Driver for Altera Partial Reconfiguration IP Core
++ *
++ * Copyright (C) 2016-2017 Intel Corporation
++ *
++ * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation
++ * by Alan Tull <atull@opensource.altera.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/fpga/altera-pr-ip-core.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++
++static int alt_pr_platform_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ void __iomem *reg_base;
++ struct resource *res;
++
++ /* First mmio base is for register access */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ reg_base = devm_ioremap_resource(dev, res);
++
++ if (IS_ERR(reg_base))
++ return PTR_ERR(reg_base);
++
++ return alt_pr_register(dev, reg_base);
++}
++
++static int alt_pr_platform_remove(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++
++ return alt_pr_unregister(dev);
++}
++
++static const struct of_device_id alt_pr_of_match[] = {
++ { .compatible = "altr,a10-pr-ip", },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, alt_pr_of_match);
++
++static struct platform_driver alt_pr_platform_driver = {
++ .probe = alt_pr_platform_probe,
++ .remove = alt_pr_platform_remove,
++ .driver = {
++ .name = "alt_a10_pr_ip",
++ .of_match_table = alt_pr_of_match,
++ },
++};
++
++module_platform_driver(alt_pr_platform_driver);
++MODULE_AUTHOR("Matthew Gerlach <matthew.gerlach@linux.intel.com>");
++MODULE_DESCRIPTION("Altera Partial Reconfiguration IP Platform Driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0095-fpga-Add-support-for-Xilinx-LogiCORE-PR-Decoupler.patch b/patches.socfpga/0095-fpga-Add-support-for-Xilinx-LogiCORE-PR-Decoupler.patch
new file mode 100644
index 0000000..496db77
--- /dev/null
+++ b/patches.socfpga/0095-fpga-Add-support-for-Xilinx-LogiCORE-PR-Decoupler.patch
@@ -0,0 +1,219 @@
+From f978b7b1a45263dc1cfc46e6e0df91c608764910 Mon Sep 17 00:00:00 2001
+From: Moritz Fischer <mdf@kernel.org>
+Date: Fri, 24 Mar 2017 10:33:21 -0500
+Subject: [PATCH 095/103] fpga: Add support for Xilinx LogiCORE PR Decoupler
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds support for the Xilinx LogiCORE PR Decoupler
+soft-ip that does decoupling of PR regions in the FPGA
+fabric during partial reconfiguration.
+
+Signed-off-by: Moritz Fischer <mdf@kernel.org>
+Signed-off-by: Michal Simek <michal.simek@xilinx.com>
+Cc: Sören Brinkmann <soren.brinkmann@xilinx.com>
+Cc: linux-kernel@vger.kernel.org
+Cc: devicetree@vger.kernel.org
+Acked-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/Kconfig | 10 ++
+ drivers/fpga/Makefile | 1
+ drivers/fpga/xilinx-pr-decoupler.c | 161 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 172 insertions(+)
+ create mode 100644 drivers/fpga/xilinx-pr-decoupler.c
+
+--- a/drivers/fpga/Kconfig
++++ b/drivers/fpga/Kconfig
+@@ -95,6 +95,16 @@ config ALTERA_PR_IP_CORE_PLAT
+ Platform driver support for Altera Partial Reconfiguration IP
+ component
+
++config XILINX_PR_DECOUPLER
++ tristate "Xilinx LogiCORE PR Decoupler"
++ depends on FPGA_BRIDGE
++ depends on HAS_IOMEM
++ help
++ Say Y to enable drivers for Xilinx LogiCORE PR Decoupler.
++ The PR Decoupler exists in the FPGA fabric to isolate one
++ region of the FPGA from the busses while that region is
++ being reprogrammed during partial reconfig.
++
+ endif # FPGA
+
+ endmenu
+--- a/drivers/fpga/Makefile
++++ b/drivers/fpga/Makefile
+@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT)
+ obj-$(CONFIG_FPGA_BRIDGE) += fpga-bridge.o
+ obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE) += altera-hps2fpga.o altera-fpga2sdram.o
+ obj-$(CONFIG_ALTERA_FREEZE_BRIDGE) += altera-freeze-bridge.o
++obj-$(CONFIG_XILINX_PR_DECOUPLER) += xilinx-pr-decoupler.o
+
+ # High Level Interfaces
+ obj-$(CONFIG_FPGA_REGION) += fpga-region.o
+--- /dev/null
++++ b/drivers/fpga/xilinx-pr-decoupler.c
+@@ -0,0 +1,161 @@
++/*
++ * Copyright (c) 2017, National Instruments Corp.
++ * Copyright (c) 2017, Xilix Inc
++ *
++ * FPGA Bridge Driver for the Xilinx LogiCORE Partial Reconfiguration
++ * Decoupler IP Core.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/of_device.h>
++#include <linux/module.h>
++#include <linux/fpga/fpga-bridge.h>
++
++#define CTRL_CMD_DECOUPLE BIT(0)
++#define CTRL_CMD_COUPLE 0
++#define CTRL_OFFSET 0
++
++struct xlnx_pr_decoupler_data {
++ void __iomem *io_base;
++ struct clk *clk;
++};
++
++static inline void xlnx_pr_decoupler_write(struct xlnx_pr_decoupler_data *d,
++ u32 offset, u32 val)
++{
++ writel(val, d->io_base + offset);
++}
++
++static inline u32 xlnx_pr_decouple_read(const struct xlnx_pr_decoupler_data *d,
++ u32 offset)
++{
++ return readl(d->io_base + offset);
++}
++
++static int xlnx_pr_decoupler_enable_set(struct fpga_bridge *bridge, bool enable)
++{
++ int err;
++ struct xlnx_pr_decoupler_data *priv = bridge->priv;
++
++ err = clk_enable(priv->clk);
++ if (err)
++ return err;
++
++ if (enable)
++ xlnx_pr_decoupler_write(priv, CTRL_OFFSET, CTRL_CMD_COUPLE);
++ else
++ xlnx_pr_decoupler_write(priv, CTRL_OFFSET, CTRL_CMD_DECOUPLE);
++
++ clk_disable(priv->clk);
++
++ return 0;
++}
++
++static int xlnx_pr_decoupler_enable_show(struct fpga_bridge *bridge)
++{
++ const struct xlnx_pr_decoupler_data *priv = bridge->priv;
++ u32 status;
++ int err;
++
++ err = clk_enable(priv->clk);
++ if (err)
++ return err;
++
++ status = readl(priv->io_base);
++
++ clk_disable(priv->clk);
++
++ return !status;
++}
++
++static struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = {
++ .enable_set = xlnx_pr_decoupler_enable_set,
++ .enable_show = xlnx_pr_decoupler_enable_show,
++};
++
++static const struct of_device_id xlnx_pr_decoupler_of_match[] = {
++ { .compatible = "xlnx,pr-decoupler-1.00", },
++ { .compatible = "xlnx,pr-decoupler", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);
++
++static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
++{
++ struct xlnx_pr_decoupler_data *priv;
++ int err;
++ struct resource *res;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ priv->io_base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(priv->io_base))
++ return PTR_ERR(priv->io_base);
++
++ priv->clk = devm_clk_get(&pdev->dev, "aclk");
++ if (IS_ERR(priv->clk)) {
++ dev_err(&pdev->dev, "input clock not found\n");
++ return PTR_ERR(priv->clk);
++ }
++
++ err = clk_prepare_enable(priv->clk);
++ if (err) {
++ dev_err(&pdev->dev, "unable to enable clock\n");
++ return err;
++ }
++
++ clk_disable(priv->clk);
++
++ err = fpga_bridge_register(&pdev->dev, "Xilinx PR Decoupler",
++ &xlnx_pr_decoupler_br_ops, priv);
++
++ if (err) {
++ dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler");
++ clk_unprepare(priv->clk);
++ return err;
++ }
++
++ return 0;
++}
++
++static int xlnx_pr_decoupler_remove(struct platform_device *pdev)
++{
++ struct fpga_bridge *bridge = platform_get_drvdata(pdev);
++ struct xlnx_pr_decoupler_data *p = bridge->priv;
++
++ fpga_bridge_unregister(&pdev->dev);
++
++ clk_unprepare(p->clk);
++
++ return 0;
++}
++
++static struct platform_driver xlnx_pr_decoupler_driver = {
++ .probe = xlnx_pr_decoupler_probe,
++ .remove = xlnx_pr_decoupler_remove,
++ .driver = {
++ .name = "xlnx_pr_decoupler",
++ .of_match_table = of_match_ptr(xlnx_pr_decoupler_of_match),
++ },
++};
++
++module_platform_driver(xlnx_pr_decoupler_driver);
++
++MODULE_DESCRIPTION("Xilinx Partial Reconfiguration Decoupler");
++MODULE_AUTHOR("Moritz Fischer <mdf@kernel.org>");
++MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>");
++MODULE_LICENSE("GPL v2");
diff --git a/patches.socfpga/0096-fpga-altera-hps2fpga-disable-unprepare-clock-on-erro.patch b/patches.socfpga/0096-fpga-altera-hps2fpga-disable-unprepare-clock-on-erro.patch
new file mode 100644
index 0000000..d117a93
--- /dev/null
+++ b/patches.socfpga/0096-fpga-altera-hps2fpga-disable-unprepare-clock-on-erro.patch
@@ -0,0 +1,51 @@
+From fa2e7c7a675e9523bd558009e966661e0ba50ddd Mon Sep 17 00:00:00 2001
+From: Tobias Klauser <tklauser@distanz.ch>
+Date: Mon, 24 Apr 2017 16:34:20 -0500
+Subject: [PATCH 096/103] fpga altera-hps2fpga: disable/unprepare clock on
+ error in alt_fpga_bridge_probe()
+
+If either _alt_hps2fpga_enable_set() or fpga_bridge_register() fail in
+alt_fpga_bridge_probe(), the clock remains enabled and prepared. Also,
+in the error path for _alt_hps2fpga_enable_set() a call to
+fpga_bridge_unregister() is made even though the bridge was not
+registered yet.
+
+Remove the unnecessary call to fpga_bridge_unregister() and call
+clk_disable_unprepare() in both error paths in order to make sure the
+clock gets properly disabled and unprepared.
+
+Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
+Acked-by: Moritz Fischer <mdf@kernel.org>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/altera-hps2fpga.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/fpga/altera-hps2fpga.c
++++ b/drivers/fpga/altera-hps2fpga.c
+@@ -181,15 +181,18 @@ static int alt_fpga_bridge_probe(struct
+ (enable ? "enabling" : "disabling"));
+
+ ret = _alt_hps2fpga_enable_set(priv, enable);
+- if (ret) {
+- fpga_bridge_unregister(&pdev->dev);
+- return ret;
+- }
++ if (ret)
++ goto err;
+ }
+ }
+
+- return fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
+- priv);
++ ret = fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
++ priv);
++err:
++ if (ret)
++ clk_disable_unprepare(priv->clk);
++
++ return ret;
+ }
+
+ static int alt_fpga_bridge_remove(struct platform_device *pdev)
diff --git a/patches.socfpga/0097-fpga-region-release-FPGA-region-reference-in-error-p.patch b/patches.socfpga/0097-fpga-region-release-FPGA-region-reference-in-error-p.patch
new file mode 100644
index 0000000..4466666
--- /dev/null
+++ b/patches.socfpga/0097-fpga-region-release-FPGA-region-reference-in-error-p.patch
@@ -0,0 +1,40 @@
+From d5363219287e11386f82638a6bd4ad78a8ba7071 Mon Sep 17 00:00:00 2001
+From: Tobias Klauser <tklauser@distanz.ch>
+Date: Mon, 24 Apr 2017 16:34:21 -0500
+Subject: [PATCH 097/103] fpga: region: release FPGA region reference in error
+ path
+
+If fpga_region_get_manager() fails in fpga_region_program_fpga(), a
+reference to the fpga_manager instance previously acquired through
+fpga_region_get() is retained. Make sure to properly release it in the
+error case by using a separate jump label which will call
+fpga_region_put() in before returning.
+
+Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
+Acked-by: Moritz Fischer <mdf@kernel.org>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/fpga-region.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/fpga/fpga-region.c
++++ b/drivers/fpga/fpga-region.c
+@@ -245,7 +245,8 @@ static int fpga_region_program_fpga(stru
+ mgr = fpga_region_get_manager(region);
+ if (IS_ERR(mgr)) {
+ pr_err("failed to get fpga region manager\n");
+- return PTR_ERR(mgr);
++ ret = PTR_ERR(mgr);
++ goto err_put_region;
+ }
+
+ ret = fpga_region_get_bridges(region, overlay);
+@@ -281,6 +282,7 @@ err_put_br:
+ fpga_bridges_put(®ion->bridge_list);
+ err_put_mgr:
+ fpga_mgr_put(mgr);
++err_put_region:
+ fpga_region_put(region);
+
+ return ret;
diff --git a/patches.socfpga/0098-fpga-fr-br-update-supported-version-numbers.patch b/patches.socfpga/0098-fpga-fr-br-update-supported-version-numbers.patch
new file mode 100644
index 0000000..13a3209
--- /dev/null
+++ b/patches.socfpga/0098-fpga-fr-br-update-supported-version-numbers.patch
@@ -0,0 +1,82 @@
+From 1ac2b755e3a514fb74fbe7574042364c97a8e572 Mon Sep 17 00:00:00 2001
+From: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Date: Mon, 24 Apr 2017 16:34:22 -0500
+Subject: [PATCH 098/103] fpga fr br: update supported version numbers
+
+The value in the version register of the altera freeze bridge
+controller changed from the beta value of 2 to the
+value of 0xad000003 in the official release of the IP.
+This patch supports the old and new version numbers, and the
+driver's probe function will fail if neither of the supported
+versions is found.
+
+Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
+Reviewed-by: Moritz Fischer <mdf@kernel.org>
+Signed-off-by: Alan Tull <atull@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/fpga/altera-freeze-bridge.c | 30 +++++++++++++++++++-----------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+--- a/drivers/fpga/altera-freeze-bridge.c
++++ b/drivers/fpga/altera-freeze-bridge.c
+@@ -28,6 +28,7 @@
+ #define FREEZE_CSR_REG_VERSION 12
+
+ #define FREEZE_CSR_SUPPORTED_VERSION 2
++#define FREEZE_CSR_OFFICIAL_VERSION 0xad000003
+
+ #define FREEZE_CSR_STATUS_FREEZE_REQ_DONE BIT(0)
+ #define FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE BIT(1)
+@@ -218,6 +219,7 @@ static int altera_freeze_br_probe(struct
+ {
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
++ void __iomem *base_addr;
+ struct altera_freeze_br_data *priv;
+ struct resource *res;
+ u32 status, revision;
+@@ -225,26 +227,32 @@ static int altera_freeze_br_probe(struct
+ if (!np)
+ return -ENODEV;
+
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ base_addr = devm_ioremap_resource(dev, res);
++ if (IS_ERR(base_addr))
++ return PTR_ERR(base_addr);
++
++ revision = readl(base_addr + FREEZE_CSR_REG_VERSION);
++ if ((revision != FREEZE_CSR_SUPPORTED_VERSION) &&
++ (revision != FREEZE_CSR_OFFICIAL_VERSION)) {
++ dev_err(dev,
++ "%s unexpected revision 0x%x != 0x%x != 0x%x\n",
++ __func__, revision, FREEZE_CSR_SUPPORTED_VERSION,
++ FREEZE_CSR_OFFICIAL_VERSION);
++ return -EINVAL;
++ }
++
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- priv->base_addr = devm_ioremap_resource(dev, res);
+- if (IS_ERR(priv->base_addr))
+- return PTR_ERR(priv->base_addr);
+-
+- status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
++ status = readl(base_addr + FREEZE_CSR_STATUS_OFFSET);
+ if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)
+ priv->enable = 1;
+
+- revision = readl(priv->base_addr + FREEZE_CSR_REG_VERSION);
+- if (revision != FREEZE_CSR_SUPPORTED_VERSION)
+- dev_warn(dev,
+- "%s Freeze Controller unexpected revision %d != %d\n",
+- __func__, revision, FREEZE_CSR_SUPPORTED_VERSION);
++ priv->base_addr = base_addr;
+
+ return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME,
+ &altera_freeze_br_br_ops, priv);
diff --git a/patches.socfpga/0099-ARM-dts-socfpga-Add-NAND-device-tree-for-Arria10.patch b/patches.socfpga/0099-ARM-dts-socfpga-Add-NAND-device-tree-for-Arria10.patch
new file mode 100644
index 0000000..b0255ad
--- /dev/null
+++ b/patches.socfpga/0099-ARM-dts-socfpga-Add-NAND-device-tree-for-Arria10.patch
@@ -0,0 +1,84 @@
+From 969f7218e1e460db033b6c1c04300a47c0cab279 Mon Sep 17 00:00:00 2001
+From: Graham Moore <grmoore@opensource.altera.com>
+Date: Tue, 7 Jul 2015 09:58:36 -0500
+Subject: [PATCH 099/103] ARM: dts: socfpga: Add NAND device tree for Arria10
+
+Add socfpga_arria10_socdk_nand.dts board file for supporting NAND.
+
+Signed-off-by: Graham Moore <grmoore@opensource.altera.com>
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+---
+v2: move nand dts node to socfpga_arria10.dtsi
+---
+ arch/arm/boot/dts/Makefile | 1
+ arch/arm/boot/dts/socfpga_arria10.dtsi | 13 +++++++++
+ arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts | 31 +++++++++++++++++++++++
+ 3 files changed, 45 insertions(+)
+ create mode 100644 arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -693,6 +693,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
+ sh73a0-kzm9g.dtb
+ dtb-$(CONFIG_ARCH_SOCFPGA) += \
+ socfpga_arria5_socdk.dtb \
++ socfpga_arria10_socdk_nand.dtb \
+ socfpga_arria10_socdk_qspi.dtb \
+ socfpga_arria10_socdk_sdmmc.dtb \
+ socfpga_cyclone5_mcvevk.dtb \
+--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
+@@ -631,6 +631,19 @@
+ status = "disabled";
+ };
+
++ nand: nand@ffb90000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "denali,denali-nand-dt", "altr,socfpga-denali-nand";
++ reg = <0xffb90000 0x72000>,
++ <0xffb80000 0x10000>;
++ reg-names = "nand_data", "denali_reg";
++ interrupts = <0 99 4>;
++ dma-mask = <0xffffffff>;
++ clocks = <&nand_clk>;
++ status = "disabled";
++ };
++
+ ocram: sram@ffe00000 {
+ compatible = "mmio-sram";
+ reg = <0xffe00000 0x40000>;
+--- /dev/null
++++ b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
+@@ -0,0 +1,31 @@
++/*
++ * Copyright (C) 2015 Altera Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ */
++
++/dts-v1/;
++#include "socfpga_arria10_socdk.dtsi"
++
++&nand {
++ status = "okay";
++
++ partition@nand-boot {
++ label = "Boot and fpga data";
++ reg = <0x0 0x1C00000>;
++ };
++ partition@nand-rootfs {
++ label = "Root Filesystem - JFFS2";
++ reg = <0x1C00000 0x6400000>;
++ };
++};
diff --git a/patches.socfpga/0100-dt-bindings-reset-Add-reset-manager-offsets-for-Stra.patch b/patches.socfpga/0100-dt-bindings-reset-Add-reset-manager-offsets-for-Stra.patch
new file mode 100644
index 0000000..8998406
--- /dev/null
+++ b/patches.socfpga/0100-dt-bindings-reset-Add-reset-manager-offsets-for-Stra.patch
@@ -0,0 +1,127 @@
+From 5cfbeefdedaa7850b4e4cd121df2352947af0556 Mon Sep 17 00:00:00 2001
+From: Richard Gong <richard.gong@intel.com>
+Date: Thu, 1 Jun 2017 09:23:59 -0500
+Subject: [PATCH 100/103] dt-bindings: reset: Add reset manager offsets for
+ Stratix10
+
+There are several changes in reset manager offsets from Arria10 to
+Stratix10. This patch is based on one from Arria10 and adds offset
+updates for Stratix10
+
+Signed-off-by: Richard Gong <richard.gong@intel.com>
+---
+ include/dt-bindings/reset/altr,rst-mgr-s10.h | 108 +++++++++++++++++++++++++++
+ 1 file changed, 108 insertions(+)
+ create mode 100644 include/dt-bindings/reset/altr,rst-mgr-s10.h
+
+--- /dev/null
++++ b/include/dt-bindings/reset/altr,rst-mgr-s10.h
+@@ -0,0 +1,108 @@
++/*
++ * Copyright (C) 2016 Intel Corporation. All rights reserved
++ * Copyright (C) 2016 Altera Corporation. All rights reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ *
++ * derived from Steffen Trumtrar's "altr,rst-mgr-a10.h"
++ */
++
++#ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_S10_H
++#define _DT_BINDINGS_RESET_ALTR_RST_MGR_S10_H
++
++/* MPUMODRST */
++#define CPU0_RESET 0
++#define CPU1_RESET 1
++#define CPU2_RESET 2
++#define CPU3_RESET 3
++
++/* PER0MODRST */
++#define EMAC0_RESET 32
++#define EMAC1_RESET 33
++#define EMAC2_RESET 34
++#define USB0_RESET 35
++#define USB1_RESET 36
++#define NAND_RESET 37
++/* 38 is empty */
++#define SDMMC_RESET 39
++#define EMAC0_OCP_RESET 40
++#define EMAC1_OCP_RESET 41
++#define EMAC2_OCP_RESET 42
++#define USB0_OCP_RESET 43
++#define USB1_OCP_RESET 44
++#define NAND_OCP_RESET 45
++/* 46 is empty */
++#define SDMMC_OCP_RESET 47
++#define DMA_RESET 48
++#define SPIM0_RESET 49
++#define SPIM1_RESET 50
++#define SPIS0_RESET 51
++#define SPIS1_RESET 52
++#define DMA_OCP_RESET 53
++#define EMAC_PTP_RESET 54
++/* 55 is empty*/
++#define DMAIF0_RESET 56
++#define DMAIF1_RESET 57
++#define DMAIF2_RESET 58
++#define DMAIF3_RESET 59
++#define DMAIF4_RESET 60
++#define DMAIF5_RESET 61
++#define DMAIF6_RESET 62
++#define DMAIF7_RESET 63
++
++/* PER1MODRST */
++#define WATCHDOG0_RESET 64
++#define WATCHDOG1_RESET 65
++#define WATCHDOG2_RESET 66
++#define WATCHDOG3_RESET 67
++#define L4SYSTIMER0_RESET 68
++#define L4SYSTIMER1_RESET 69
++#define SPTIMER0_RESET 70
++#define SPTIMER1_RESET 71
++#define I2C0_RESET 72
++#define I2C1_RESET 73
++#define I2C2_RESET 74
++#define I2C3_RESET 75
++#define I2C4_RESET 76
++/* 77-79 is empty */
++#define UART0_RESET 80
++#define UART1_RESET 81
++/* 82-87 is empty */
++#define GPIO0_RESET 88
++#define GPIO1_RESET 89
++
++/* BRGMODRST */
++#define SOC2FPGA_RESET 96
++#define LWHPS2FPGA_RESET 97
++#define FPGA2SOC_RESET 98
++#define F2SSDRAM0_RESET 99
++#define F2SSDRAM1_RESET 100
++#define F2SSDRAM2_RESET 101
++#define DDRSCH_RESET 102
++
++/* COLDMODRST */
++#define CPUPO0_RESET 160
++#define CPUPO1_RESET 161
++#define CPUPO2_RESET 162
++#define CPUPO3_RESET 163
++/* 164-167 is empty */
++#define L2_RESET 168
++
++/* DBGMODRST */
++#define DBG_RESET 224
++#define CSDAP_RESET 225
++
++/* TAPMODRST */
++#define TAP_RESET 256
++
++#endif
diff --git a/patches.socfpga/0101-nios2-add-screen_info.patch b/patches.socfpga/0101-nios2-add-screen_info.patch
new file mode 100644
index 0000000..6e33cf1
--- /dev/null
+++ b/patches.socfpga/0101-nios2-add-screen_info.patch
@@ -0,0 +1,35 @@
+From b3e0ba2525523283d68e8a8f7a464faf8662a632 Mon Sep 17 00:00:00 2001
+From: Ley Foon Tan <ley.foon.tan@intel.com>
+Date: Wed, 7 Dec 2016 15:44:19 +0800
+Subject: [PATCH 101/103] nios2: add screen_info
+
+Fix build error when enable VGA console.
+
+drivers/video/console/vgacon.c:586: undefined reference to `screen_info'
+
+Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
+---
+ arch/nios2/kernel/setup.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/nios2/kernel/setup.c
++++ b/arch/nios2/kernel/setup.c
+@@ -18,6 +18,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/initrd.h>
+ #include <linux/of_fdt.h>
++#include <linux/screen_info.h>
+
+ #include <asm/mmu_context.h>
+ #include <asm/sections.h>
+@@ -36,6 +37,10 @@ static struct pt_regs fake_regs = { 0, 0
+ 0, 0, 0, 0, 0, 0,
+ 0};
+
++#ifdef CONFIG_VT
++struct screen_info screen_info;
++#endif
++
+ /* Copy a short hook instruction sequence to the exception address */
+ static inline void copy_exception_handler(unsigned int addr)
+ {
diff --git a/patches.socfpga/0102-nios2-switch-to-RAW_COPY_USER.patch b/patches.socfpga/0102-nios2-switch-to-RAW_COPY_USER.patch
new file mode 100644
index 0000000..09391d9
--- /dev/null
+++ b/patches.socfpga/0102-nios2-switch-to-RAW_COPY_USER.patch
@@ -0,0 +1,108 @@
+From 0b5d6273491a3b5dc69b794b0e6c678884f68157 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Wed, 22 Mar 2017 13:08:32 -0400
+Subject: [PATCH 102/103] nios2: switch to RAW_COPY_USER
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+---
+ arch/nios2/Kconfig | 1 +
+ arch/nios2/include/asm/uaccess.h | 31 ++++++-------------------------
+ arch/nios2/mm/uaccess.c | 16 ++++++++--------
+ 3 files changed, 15 insertions(+), 33 deletions(-)
+
+--- a/arch/nios2/Kconfig
++++ b/arch/nios2/Kconfig
+@@ -16,6 +16,7 @@ config NIOS2
+ select SPARSE_IRQ
+ select USB_ARCH_HAS_HCD if USB_SUPPORT
+ select CPU_NO_EFFICIENT_FFS
++ select ARCH_HAS_RAW_COPY_USER
+
+ config GENERIC_CSUM
+ def_bool y
+--- a/arch/nios2/include/asm/uaccess.h
++++ b/arch/nios2/include/asm/uaccess.h
+@@ -95,36 +95,17 @@ static inline unsigned long __must_check
+ return __clear_user(to, n);
+ }
+
+-extern long __copy_from_user(void *to, const void __user *from,
+- unsigned long n);
+-extern long __copy_to_user(void __user *to, const void *from, unsigned long n);
+-
+-static inline long copy_from_user(void *to, const void __user *from,
+- unsigned long n)
+-{
+- unsigned long res = n;
+- if (access_ok(VERIFY_READ, from, n))
+- res = __copy_from_user(to, from, n);
+- if (unlikely(res))
+- memset(to + (n - res), 0, res);
+- return res;
+-}
+-
+-static inline long copy_to_user(void __user *to, const void *from,
+- unsigned long n)
+-{
+- if (!access_ok(VERIFY_WRITE, to, n))
+- return n;
+- return __copy_to_user(to, from, n);
+-}
++extern unsigned long
++raw_copy_from_user(void *to, const void __user *from, unsigned long n);
++extern unsigned long
++raw_copy_to_user(void __user *to, const void *from, unsigned long n);
++#define INLINE_COPY_FROM_USER
++#define INLINE_COPY_TO_USER
+
+ extern long strncpy_from_user(char *__to, const char __user *__from,
+ long __len);
+ extern long strnlen_user(const char __user *s, long n);
+
+-#define __copy_from_user_inatomic __copy_from_user
+-#define __copy_to_user_inatomic __copy_to_user
+-
+ /* Optimized macros */
+ #define __get_user_asm(val, insn, addr, err) \
+ { \
+--- a/arch/nios2/mm/uaccess.c
++++ b/arch/nios2/mm/uaccess.c
+@@ -10,9 +10,9 @@
+ #include <linux/export.h>
+ #include <linux/uaccess.h>
+
+-asm(".global __copy_from_user\n"
+- " .type __copy_from_user, @function\n"
+- "__copy_from_user:\n"
++asm(".global raw_copy_from_user\n"
++ " .type raw_copy_from_user, @function\n"
++ "raw_copy_from_user:\n"
+ " movi r2,7\n"
+ " mov r3,r4\n"
+ " bge r2,r6,1f\n"
+@@ -65,12 +65,12 @@ asm(".global __copy_from_user\n"
+ ".word 7b,13b\n"
+ ".previous\n"
+ );
+-EXPORT_SYMBOL(__copy_from_user);
++EXPORT_SYMBOL(raw_copy_from_user);
+
+ asm(
+- " .global __copy_to_user\n"
+- " .type __copy_to_user, @function\n"
+- "__copy_to_user:\n"
++ " .global raw_copy_to_user\n"
++ " .type raw_copy_to_user, @function\n"
++ "raw_copy_to_user:\n"
+ " movi r2,7\n"
+ " mov r3,r4\n"
+ " bge r2,r6,1f\n"
+@@ -127,7 +127,7 @@ asm(
+ ".word 11b,13b\n"
+ ".word 12b,13b\n"
+ ".previous\n");
+-EXPORT_SYMBOL(__copy_to_user);
++EXPORT_SYMBOL(raw_copy_to_user);
+
+ long strncpy_from_user(char *__to, const char __user *__from, long __len)
+ {
diff --git a/patches.socfpga/0103-nios2-use-generic-strncpy_from_user-and-strnlen_user.patch b/patches.socfpga/0103-nios2-use-generic-strncpy_from_user-and-strnlen_user.patch
new file mode 100644
index 0000000..8701cfa
--- /dev/null
+++ b/patches.socfpga/0103-nios2-use-generic-strncpy_from_user-and-strnlen_user.patch
@@ -0,0 +1,88 @@
+From 1e114cbc9496ee8376e0ad899890a1eff7e58230 Mon Sep 17 00:00:00 2001
+From: Ley Foon Tan <ley.foon.tan@intel.com>
+Date: Mon, 8 May 2017 17:14:14 +0800
+Subject: [PATCH 103/103] nios2: use generic strncpy_from_user() and
+ strnlen_user()
+
+This change enables the generic strncpy_from_user() and strnlen_user()
+
+Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
+---
+ arch/nios2/Kconfig | 2 ++
+ arch/nios2/include/asm/uaccess.h | 7 +++++--
+ arch/nios2/mm/uaccess.c | 33 ---------------------------------
+ 3 files changed, 7 insertions(+), 35 deletions(-)
+
+--- a/arch/nios2/Kconfig
++++ b/arch/nios2/Kconfig
+@@ -6,6 +6,8 @@ config NIOS2
+ select GENERIC_CPU_DEVICES
+ select GENERIC_IRQ_PROBE
+ select GENERIC_IRQ_SHOW
++ select GENERIC_STRNCPY_FROM_USER
++ select GENERIC_STRNLEN_USER
+ select HAVE_ARCH_TRACEHOOK
+ select HAVE_ARCH_KGDB
+ select IRQ_DOMAIN
+--- a/arch/nios2/include/asm/uaccess.h
++++ b/arch/nios2/include/asm/uaccess.h
+@@ -64,6 +64,8 @@ extern int fixup_exception(struct pt_reg
+
+ # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
+
++#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
++
+ /*
+ * Zero Userspace
+ */
+@@ -103,8 +105,9 @@ raw_copy_to_user(void __user *to, const
+ #define INLINE_COPY_TO_USER
+
+ extern long strncpy_from_user(char *__to, const char __user *__from,
+- long __len);
+-extern long strnlen_user(const char __user *s, long n);
++ long __len);
++extern __must_check long strlen_user(const char __user *str);
++extern __must_check long strnlen_user(const char __user *s, long n);
+
+ /* Optimized macros */
+ #define __get_user_asm(val, insn, addr, err) \
+--- a/arch/nios2/mm/uaccess.c
++++ b/arch/nios2/mm/uaccess.c
+@@ -128,36 +128,3 @@ asm(
+ ".word 12b,13b\n"
+ ".previous\n");
+ EXPORT_SYMBOL(raw_copy_to_user);
+-
+-long strncpy_from_user(char *__to, const char __user *__from, long __len)
+-{
+- int l = strnlen_user(__from, __len);
+- int is_zt = 1;
+-
+- if (l > __len) {
+- is_zt = 0;
+- l = __len;
+- }
+-
+- if (l == 0 || copy_from_user(__to, __from, l))
+- return -EFAULT;
+-
+- if (is_zt)
+- l--;
+- return l;
+-}
+-
+-long strnlen_user(const char __user *s, long n)
+-{
+- long i;
+-
+- for (i = 0; i < n; i++) {
+- char c;
+-
+- if (get_user(c, s + i) == -EFAULT)
+- return 0;
+- if (c == 0)
+- return i + 1;
+- }
+- return n + 1;
+-}
diff --git a/series b/series
index 228a079..c607364 100644
--- a/series
+++ b/series
@@ -857,6 +857,112 @@
patches.renesas/0286-ARM-dts-r8a7791-Drop-_clk-suffix-from-external-CAN-c.patch
#############################################################################
+# SoCFPGA patches
+patches.socfpga/0001-ARM-dts-socfpga-enable-arm-shared-override-in-the-pl.patch
+patches.socfpga/0002-ARM-socfpga_defconfig-Enable-HIGHMEM.patch
+patches.socfpga/0003-ARM-dts-socfpga-enable-qspi-on-the-Cyclone5-devkit.patch
+patches.socfpga/0004-ARM-dts-socfpga-Add-QSPI-node-for-the-Arria10.patch
+patches.socfpga/0005-ARM-dts-socfpga-Enable-QSPI-in-Arria10-devkit.patch
+patches.socfpga/0006-ARM-dts-socfpga-Enable-QSPI-on-the-Cyclone5-sockit.patch
+patches.socfpga/0007-ARM-dts-socfpga-Enable-QSPI-on-the-Arria5-devkit.patch
+patches.socfpga/0008-ARM-socfpga_defconfig-enable-FS-configs-to-support-A.patch
+patches.socfpga/0009-dt-bindings-Add-Macnica-Americas-vendor-prefix.patch
+patches.socfpga/0010-dt-bindings-Add-vendor-prefix-for-Terasic-Inc.patch
+patches.socfpga/0011-dt-bindings-Add-vendor-prefix-for-Samtec.patch
+patches.socfpga/0012-ARM-dts-socfpga-enable-GPIO-and-LEDs-for-Cyclone5-an.patch
+patches.socfpga/0013-ARM-dts-socfpga-set-desired-i2c-clock-on-Cyclone5-an.patch
+patches.socfpga/0014-ARM-dts-socfpga-Add-Rohm-DH2228FV-DAC.patch
+patches.socfpga/0015-ARM-dts-socfpga-enable-CAN-on-Cyclone5-devkit.patch
+patches.socfpga/0016-ARM-dts-socfpga-enable-watchdog-timer-on-Arria5-and-.patch
+patches.socfpga/0017-ARM-dts-socfpga-add-the-LTC2977-power-monitor-on-Arr.patch
+patches.socfpga/0018-ARM-dts-socfpga-add-fpga-manager-node-for-Arria10.patch
+patches.socfpga/0019-ARM-dts-socfpga-fpga-manager-data-is-32-bits.patch
+patches.socfpga/0020-ARM-dts-socfpga-add-fpga-region-support-on-Arria10.patch
+patches.socfpga/0021-ARM-dts-socfpga-add-missing-compatible-string-for-SD.patch
+patches.socfpga/0022-ARM-dts-watchdog0-cannot-reliably-trigger-reset.patch
+patches.socfpga/0023-MAINTAINERS-socfpga-update-email-for-Dinh-Nguyen.patch
+patches.socfpga/0024-of-overlay-add-of-overlay-notifications.patch
+patches.socfpga/0025-fpga-add-method-to-get-fpga-manager-from-device.patch
+patches.socfpga/0026-doc-fpga-mgr-add-fpga-image-info-to-api.patch
+patches.socfpga/0027-fpga-add-bindings-document-for-fpga-region.patch
+patches.socfpga/0028-fpga-mgr-add-fpga-image-information-struct.patch
+patches.socfpga/0029-add-sysfs-document-for-fpga-bridge-class.patch
+patches.socfpga/0030-fpga-add-fpga-bridge-framework.patch
+patches.socfpga/0031-fpga-fpga-region-device-tree-control-for-FPGA.patch
+patches.socfpga/0032-ARM-socfpga-fpga-bridge-driver-support.patch
+patches.socfpga/0033-fpga-add-altera-freeze-bridge-support.patch
+patches.socfpga/0034-fpga-manager-Add-Socfpga-Arria10-support.patch
+patches.socfpga/0035-ARM-socfpga-checking-the-wrong-variable.patch
+patches.socfpga/0036-fpga-Add-COMPILE_TEST-to-all-drivers.patch
+patches.socfpga/0037-fpga-zynq-Add-missing-n-to-messages.patch
+patches.socfpga/0038-fpga-zynq-Remove-priv-dev.patch
+patches.socfpga/0039-fpga-zynq-Fix-incorrect-ISR-state-on-bootup.patch
+patches.socfpga/0040-fpga-Clarify-how-write_init-works-streaming-modes.patch
+patches.socfpga/0041-fpga-zynq-Check-for-errors-after-completing-DMA.patch
+patches.socfpga/0042-fpga-zynq-Check-the-bitstream-for-validity.patch
+patches.socfpga/0043-fpga-Add-scatterlist-based-programming.patch
+patches.socfpga/0044-fpga-zynq-Use-the-scatterlist-interface.patch
+patches.socfpga/0045-fpga-fix-sparse-warnings-in-fpga-mgr-and-fpga-bridge.patch
+patches.socfpga/0046-fpga-Add-flag-to-indicate-bitstream-needs-decrypting.patch
+patches.socfpga/0047-fpga-zynq-Add-support-for-encrypted-bitstreams.patch
+patches.socfpga/0048-fpga-region-Add-fpga-region-property-encrypted-fpga-.patch
+patches.socfpga/0049-FPGA-Add-TS-7300-FPGA-manager.patch
+patches.socfpga/0050-Documentation-Add-binding-document-for-Lattice-iCE40.patch
+patches.socfpga/0051-fpga-Add-support-for-Lattice-iCE40-FPGAs.patch
+patches.socfpga/0052-fpga-bridge-Replace-open-coded-list_for_each-list_en.patch
+patches.socfpga/0053-fpga-altera_freeze_bridge-Constify-ops.patch
+patches.socfpga/0054-dt-bindings-fpga-add-xilinx-slave-serial-binding-des.patch
+patches.socfpga/0055-fpga-manager-Add-Xilinx-slave-serial-SPI-driver.patch
+patches.socfpga/0056-ARM-socfpga-add-bindings-document-for-fpga-bridge-dr.patch
+patches.socfpga/0057-ARM-socfpga-add-bindings-doc-for-arria10-fpga-manage.patch
+patches.socfpga/0058-add-bindings-document-for-altera-freeze-bridge.patch
+patches.socfpga/0059-MAINTAINERS-add-git-url-for-fpga.patch
+patches.socfpga/0060-ARM-dts-socfpga-add-base-fpga-region-and-fpga-bridge.patch
+patches.socfpga/0061-fpga-add-config-complete-timeout.patch
+patches.socfpga/0062-MAINTAINERS-Add-file-patterns-for-fpga-device-tree-b.patch
+patches.socfpga/0063-MAINTAINERS-fpga-update-email-and-directory-paths.patch
+patches.socfpga/0064-spi-Add-Flag-to-Enable-Slave-Select-with-GPIO-Chip-S.patch
+patches.socfpga/0065-spi-dw-Set-GPIO_SS-flag-to-toggle-Slave-Select-on-GP.patch
+patches.socfpga/0066-ARM-dts-socfpga-Add-SPI-Master1-for-Arria10-SR-chip.patch
+patches.socfpga/0067-ARM-dts-socfpga-Add-Devkit-A10-SR-fields-for-Arria10.patch
+patches.socfpga/0068-ARM-dts-socfpga-Enable-GPIO-parent-for-Arria10-SR-ch.patch
+patches.socfpga/0069-ARM-dts-socfpga-Add-LED-framework-to-A10-SR-GPIO.patch
+patches.socfpga/0070-EDAC-altera-Disable-IRQs-while-injecting-SDRAM-error.patch
+patches.socfpga/0071-gpio-altera-a10sr-Add-A10-System-Resource-Chip-GPIO-.patch
+patches.socfpga/0072-dt-bindings-mfd-Add-Altera-Arria10-System-Resource-C.patch
+patches.socfpga/0073-ARM-dts-Add-EMAC-AXI-settings-for-Arria10.patch
+patches.socfpga/0074-MAINTAINERS-EDAC-Update-email-for-Thor-Thayer.patch
+patches.socfpga/0075-gpio-altera-a10sr-Set-gpio_chip-parent-property.patch
+patches.socfpga/0076-dt-bindings-reset-a10sr-Add-Arria10-SR-Reset-Control.patch
+patches.socfpga/0077-reset-Add-Altera-Arria10-SR-Reset-Controller.patch
+patches.socfpga/0078-ARM-dts-socfpga-Add-Devkit-A10-SR-Reset-Controller.patch
+patches.socfpga/0079-EDAC-altera-Fix-peripheral-warnings-for-Cyclone5.patch
+patches.socfpga/0080-mfd-altr_a10sr-Add-Arria10-DevKit-Reset-Controller.patch
+patches.socfpga/0081-dt-bindings-mfd-Add-Altera-Arria10-SR-Reset-Controll.patch
+patches.socfpga/0082-ARM-socfpga-defconfig-enable-qspi.patch
+patches.socfpga/0083-ARM-socfpga-updates-for-socfpga_defconfig.patch
+patches.socfpga/0084-ARM-socfpga_defconfig-update-defconfig-for-SoCFPGA.patch
+patches.socfpga/0085-ARM-socfpga-updates-for-socfpga_defconfig.patch
+patches.socfpga/0086-ARM-dts-socfpga-Add-new-MCVEVK-manufacturer-compat.patch
+patches.socfpga/0087-ARM-dts-socfpga-Add-Macnica-sodia-board.patch
+patches.socfpga/0088-ARM-dts-socfpga-add-specific-compatible-strings-for-.patch
+patches.socfpga/0089-ARM-dts-socfpga-Add-unit-name-to-memory-nodes.patch
+patches.socfpga/0090-ARM-dts-socfpga-sodia-enable-qspi.patch
+patches.socfpga/0091-ARM-dts-socfpga-add-qspi-node.patch
+patches.socfpga/0092-fpga-pr-ip-Core-driver-support-for-Altera-Partial-Re.patch
+patches.socfpga/0093-fpga-dt-bindings-for-Altera-Partial-Reconfiguration-.patch
+patches.socfpga/0094-fpga-pr-ip-Platform-driver-for-Altera-Partial-Reconf.patch
+patches.socfpga/0095-fpga-Add-support-for-Xilinx-LogiCORE-PR-Decoupler.patch
+patches.socfpga/0096-fpga-altera-hps2fpga-disable-unprepare-clock-on-erro.patch
+patches.socfpga/0097-fpga-region-release-FPGA-region-reference-in-error-p.patch
+patches.socfpga/0098-fpga-fr-br-update-supported-version-numbers.patch
+patches.socfpga/0099-ARM-dts-socfpga-Add-NAND-device-tree-for-Arria10.patch
+patches.socfpga/0100-dt-bindings-reset-Add-reset-manager-offsets-for-Stra.patch
+patches.socfpga/0101-nios2-add-screen_info.patch
+patches.socfpga/0102-nios2-switch-to-RAW_COPY_USER.patch
+patches.socfpga/0103-nios2-use-generic-strncpy_from_user-and-strnlen_user.patch
+
+#############################################################################
# Misc patches
##############################################################################