diff --git a/cores/axis_rp_adc_v1_0/core_config.tcl b/cores/axis_rp_adc_v1_0/core_config.tcl
index c61fb615ceb8d23657ddcf52b43bf52e5fa3b70b..7b59ee3efed5d773344bb5fe2866051db7f7de42 100644
--- a/cores/axis_rp_adc_v1_0/core_config.tcl
+++ b/cores/axis_rp_adc_v1_0/core_config.tcl
@@ -1,4 +1,4 @@
-set display_name {AXI4-Stream Red Pitaya ADC}
+set display_name {AXI4-Stream Red Pitaya ADC v1.0}
 
 set core [ipx::current_core]
 
diff --git a/cores/axis_rp_adc_v3_0/core_config.tcl b/cores/axis_rp_adc_v3_0/core_config.tcl
index c61fb615ceb8d23657ddcf52b43bf52e5fa3b70b..e01ad25776f5d08985e89ed780d049c99981bb10 100644
--- a/cores/axis_rp_adc_v3_0/core_config.tcl
+++ b/cores/axis_rp_adc_v3_0/core_config.tcl
@@ -1,4 +1,4 @@
-set display_name {AXI4-Stream Red Pitaya ADC}
+set display_name {AXI4-Stream Red Pitaya ADC v3.0}
 
 set core [ipx::current_core]
 
diff --git a/patches/cma.c b/patches/cma.c
new file mode 100644
index 0000000000000000000000000000000000000000..621210743df0156c7261ffba1f64744bc7a0f0e4
--- /dev/null
+++ b/patches/cma.c
@@ -0,0 +1,96 @@
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-map-ops.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, u32)
+
+static struct device *dma_device = NULL;
+static size_t dma_size = 0;
+static void *cpu_addr = NULL;
+static dma_addr_t dma_addr;
+
+static void cma_free(void)
+{
+  if(!cpu_addr) return;
+  dma_free_coherent(dma_device, dma_size, cpu_addr, dma_addr);
+  cpu_addr = NULL;
+}
+
+static long cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+  long rc;
+  u32 buffer;
+
+  if(cmd != CMA_ALLOC) return -ENOTTY;
+
+  rc = copy_from_user(&buffer, (void __user *)arg, sizeof(buffer));
+  if(rc) return rc;
+
+  cma_free();
+
+  dma_size = buffer;
+  cpu_addr = dma_alloc_coherent(dma_device, dma_size, &dma_addr, GFP_KERNEL);
+
+  if(IS_ERR_OR_NULL(cpu_addr))
+  {
+    rc = PTR_ERR(cpu_addr);
+    if(rc == 0) rc = -ENOMEM;
+    cpu_addr = NULL;
+    return rc;
+  }
+
+  buffer = dma_addr;
+  return copy_to_user((void __user *)arg, &buffer, sizeof(buffer));
+}
+
+static int cma_mmap(struct file *file, struct vm_area_struct *vma)
+{
+  return dma_mmap_coherent(dma_device, vma, cpu_addr, dma_addr, dma_size);
+}
+
+static int cma_release(struct inode *inode, struct file *file)
+{
+  cma_free();
+  return 0;
+}
+
+static struct file_operations cma_fops =
+{
+  .unlocked_ioctl = cma_ioctl,
+  .mmap = cma_mmap,
+  .release = cma_release
+};
+
+struct miscdevice cma_device =
+{
+  .minor = MISC_DYNAMIC_MINOR,
+  .name = "cma",
+  .fops = &cma_fops
+};
+
+static int __init cma_init(void)
+{
+  int rc;
+
+  rc = misc_register(&cma_device);
+  if(rc) return rc;
+
+  dma_device = cma_device.this_device;
+
+  dma_device->dma_ops = &arm_coherent_dma_ops;
+  dma_device->coherent_dma_mask = DMA_BIT_MASK(32);
+
+  return 0;
+}
+
+static void __exit cma_exit(void)
+{
+  cma_free();
+  misc_deregister(&cma_device);
+}
+
+module_init(cma_init);
+module_exit(cma_exit);
+MODULE_LICENSE("MIT");
diff --git a/patches/devicetree.patch b/patches/devicetree.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fc16466a0c4bfdde90d537e80901fbe747e8173e
--- /dev/null
+++ b/patches/devicetree.patch
@@ -0,0 +1,147 @@
+diff -rupN pl.dtsi.old pl.dtsi
+--- pl.dtsi.old
++++ pl.dtsi
+@@ -15,7 +15,7 @@
+ 			#interrupt-cells = <2>;
+ 			clock-names = "s_axi_aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,axi-intc-4.1", "xlnx,xps-intc-1.00.a";
++      compatible = "generic-uio";
+ 			interrupt-controller ;
+ 			interrupt-names = "irq";
+ 			interrupt-parent = <&intc>;
+@@ -32,19 +32,19 @@
+ 		cfg_0: axi_cfg_register@40001000 {
+ 			clock-names = "aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,axi-cfg-register-1.0";
++      compatible = "generic-uio";
+ 			reg = <0x40001000 0x1000>;
+ 		};
+ 		sts_0: axi_sts_register@40002000 {
+ 			clock-names = "aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,axi-sts-register-1.0";
++      compatible = "generic-uio";
+ 			reg = <0x40002000 0x1000>;
+ 		};
+ 		xadc_wiz_0: xadc_wiz@40003000 {
+ 			clock-names = "s_axi_aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,xadc-wiz-3.3", "xlnx,axi-xadc-1.00.a";
++      compatible = "generic-uio";
+ 			reg = <0x40003000 0x1000>;
+ 			xlnx,alarm-limit-r0 = <0xb5ed>;
+ 			xlnx,alarm-limit-r1 = <0x57e4>;
+@@ -126,5 +126,17 @@
+ 			xlnx,vaux8 = <0x1>;
+ 			xlnx,vaux9 = <0x1>;
+ 		};
+-	};
++		hst0_reader_0: axi_bram_reader@40010000 {
++			clock-names = "aclk";
++			clocks = <&misc_clk_0>;
++      compatible = "generic-uio";
++			reg = <0x40010000 0x10000>;
++		};
++		hst1_reader_1: axi_bram_reader@40020000 {
++			clock-names = "aclk";
++			clocks = <&misc_clk_0>;
++      compatible = "generic-uio";
++			reg = <0x40020000 0x10000>;
++		};
++  };
+ };
+diff -rupN pcw.dtsi.old pcw.dtsi
+--- pcw.dtsi.old
++++ pcw.dtsi
+@@ -26,6 +26,19 @@
+ 	clock-frequency = <400000>;
+ 	status = "okay";
+ };
++&i2c0 {
++	eep@50 {
++		compatible = "24c64";
++ 		size = <8192>;
++ 		pagesize = <32>;
++		reg = <0x50>;
++	};
++  bmp180@77{
++    compatible = "bosch,bmp280";
++    reg = <0x77>;
++    status = "okay";
++  };
++};
+ &intc {
+ 	num_cpus = <2>;
+ 	num_interrupts = <96>;
+@@ -45,6 +51,11 @@
+ 	is-decoded-cs = <0>;
+ 	num-cs = <1>;
+ 	status = "okay";
++	spidev@0 {
++		compatible = "spidev";
++		reg = <0x0>;
++		spi-max-frequency = <10000000>;
++	};
+ };
+ &uart0 {
+ 	device_type = "serial";
+@@ -57,11 +68,33 @@
+ 	status = "okay";
+ };
+ &usb0 {
++	dr_mode = "host";
+-	phy_type = "ulpi";
++	usb-phy = <&usb_phy0>;
+ 	status = "okay";
+-	usb-reset = <&gpio0 48 0>;
++	xlnx,phy-reset-gpio = <&gpio0 48 0>;
+ };
+ &clkc {
+ 	fclk-enable = <0x0>;
+ 	ps-clk-frequency = <33333333>;
+ };
++&adc {
++	xlnx,channels {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		channel@0 {
++			reg = <0>;
++		};
++		channel@1 {
++			reg = <1>;
++		};
++		channel@2 {
++			reg = <2>;
++		};
++		channel@9 {
++			reg = <9>;
++		};
++		channel@10 {
++			reg = <10>;
++		};
++	};
++};
+diff -rupN system-top.dts.old system-top.dts
+--- system-top.dts.old
++++ system-top.dts
+@@ -14,6 +14,18 @@
+ 		bootargs = "console=ttyPS0,115200 earlyprintk earlycon";
+ 		stdout-path = "serial0:115200n8";
+ 	};
++	usb_phy0: phy0 {
++		#phy-cells = <0>;
++		compatible = "ulpi-phy";
++		reg = <0xe0002000 0x1000>;
++		view-port = <0x0170>;
++		drv-vbus;
++	};
++	pps {
++		compatible = "pps-gpio";
++		gpios = <&gpio0 54 0>;
++		capture-clear;
++	};
+ 	aliases {
+ 		ethernet0 = &gem0;
+ 		i2c0 = &i2c0;
diff --git a/patches/linux-5.10.patch b/patches/linux-5.10.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f37550adb0d9daa8bbb5ba74dd6b79a316365496
--- /dev/null
+++ b/patches/linux-5.10.patch
@@ -0,0 +1,494 @@
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/common.c linux-5.10/arch/arm/mach-zynq/common.c
+--- old/linux-5.10/arch/arm/mach-zynq/common.c
++++ linux-5.10/arch/arm/mach-zynq/common.c
+@@ -95,6 +95,7 @@ static void __init zynq_init_late(void)
+ {
+ 	zynq_core_pm_init();
+ 	zynq_pm_late_init();
++	zynq_prefetch_init();
+ }
+ 
+ /**
+@@ -186,8 +187,13 @@ static const char * const zynq_dt_match[
+ 
+ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+ 	/* 64KB way size, 8-way associativity, parity disabled */
+-	.l2c_aux_val    = 0x00400000,
++#ifdef CONFIG_XILINX_PREFETCH
++	.l2c_aux_val	= 0x30400000,
++	.l2c_aux_mask	= 0xcfbfffff,
++#else
++	.l2c_aux_val	= 0x00400000,
+ 	.l2c_aux_mask	= 0xffbfffff,
++#endif
+ 	.smp		= smp_ops(zynq_smp_ops),
+ 	.map_io		= zynq_map_io,
+ 	.init_irq	= zynq_irq_init,
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/common.h linux-5.10/arch/arm/mach-zynq/common.h
+--- old/linux-5.10/arch/arm/mach-zynq/common.h
++++ linux-5.10/arch/arm/mach-zynq/common.h
+@@ -15,6 +15,7 @@ extern void zynq_slcr_cpu_stop(int cpu);
+ extern void zynq_slcr_cpu_start(int cpu);
+ extern bool zynq_slcr_cpu_state_read(int cpu);
+ extern void zynq_slcr_cpu_state_write(int cpu, bool die);
++extern u32 zynq_slcr_get_ocm_config(void);
+ extern u32 zynq_slcr_get_device_id(void);
+ 
+ #ifdef CONFIG_SMP
+@@ -29,6 +30,22 @@ extern void __iomem *zynq_scu_base;
+ 
+ void zynq_pm_late_init(void);
+ 
++static inline void zynq_prefetch_init(void)
++{
++	/*
++	 * Enable prefetching in aux control register. L2 prefetch must
++	 * only be enabled if the slave supports it (PL310 does)
++	 */
++	asm volatile ("mrc   p15, 0, r1, c1, c0, 1\n"
++#ifdef CONFIG_XILINX_PREFETCH
++		      "orr   r1, r1, #6\n"
++#else
++		      "bic   r1, r1, #6\n"
++#endif
++		      "mcr   p15, 0, r1, c1, c0, 1\n"
++		      : : : "r1");
++}
++
+ static inline void zynq_core_pm_init(void)
+ {
+ 	/* A9 clock gating */
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/Kconfig linux-5.10/arch/arm/mach-zynq/Kconfig
+--- old/linux-5.10/arch/arm/mach-zynq/Kconfig
++++ linux-5.10/arch/arm/mach-zynq/Kconfig
+@@ -16,3 +16,19 @@ config ARCH_ZYNQ
+ 	select SOC_BUS
+ 	help
+ 	  Support for Xilinx Zynq ARM Cortex A9 Platform
++
++if ARCH_ZYNQ
++
++menu "Xilinx Specific Options"
++
++config XILINX_PREFETCH
++	bool "Cache Prefetch"
++	default y
++	help
++	  This option turns on L1 & L2 cache prefetching to get the best performance
++	  in many cases. This may not always be the best performance depending on
++	  the usage.
++
++endmenu
++
++endif
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/Makefile linux-5.10/arch/arm/mach-zynq/Makefile
+--- old/linux-5.10/arch/arm/mach-zynq/Makefile
++++ linux-5.10/arch/arm/mach-zynq/Makefile
+@@ -4,5 +4,5 @@
+ #
+ 
+ # Common support
+-obj-y				:= common.o slcr.o pm.o
++obj-y				:= common.o slcr.o zynq_ocm.o pm.o
+ obj-$(CONFIG_SMP)		+= headsmp.o platsmp.o
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/platsmp.c linux-5.10/arch/arm/mach-zynq/platsmp.c
+--- old/linux-5.10/arch/arm/mach-zynq/platsmp.c
++++ linux-5.10/arch/arm/mach-zynq/platsmp.c
+@@ -115,6 +115,7 @@ static void __init zynq_smp_prepare_cpus
+ static void zynq_secondary_init(unsigned int cpu)
+ {
+ 	zynq_core_pm_init();
++	zynq_prefetch_init();
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/slcr.c linux-5.10/arch/arm/mach-zynq/slcr.c
+--- old/linux-5.10/arch/arm/mach-zynq/slcr.c
++++ linux-5.10/arch/arm/mach-zynq/slcr.c
+@@ -20,6 +20,7 @@
+ #define SLCR_REBOOT_STATUS_OFFSET	0x258 /* PS Reboot Status */
+ #define SLCR_PSS_IDCODE			0x530 /* PS IDCODE */
+ #define SLCR_L2C_RAM			0xA1C /* L2C_RAM in AR#54190 */
++#define SLCR_OCM_CFG_OFFSET		0x910 /* OCM Address Mapping */
+ 
+ #define SLCR_UNLOCK_MAGIC		0xDF0D
+ #define SLCR_A9_CPU_CLKSTOP		0x10
+@@ -116,6 +117,19 @@ static struct notifier_block zynq_slcr_r
+ };
+ 
+ /**
++ * zynq_slcr_get_ocm_config - Get SLCR OCM config
++ *
++ * return:	OCM config bits
++ */
++u32 zynq_slcr_get_ocm_config(void)
++{
++	u32 ret;
++
++	zynq_slcr_read(&ret, SLCR_OCM_CFG_OFFSET);
++	return ret;
++}
++
++/**
+  * zynq_slcr_cpu_start - Start cpu
+  * @cpu:	cpu number
+  */
+diff -rupN old/linux-5.10/drivers/char/Kconfig linux-5.10/drivers/char/Kconfig
+--- old/linux-5.10/drivers/char/Kconfig
++++ linux-5.10/drivers/char/Kconfig
+@@ -471,6 +471,14 @@ config ADI
+ 	  and SSM (Silicon Secured Memory).  Intended consumers of this
+ 	  driver include crash and makedumpfile.
+ 
++config DEVCMA
++	bool "/dev/cma virtual device support"
++	default y
++
++config XILINX_DEVCFG
++	tristate "Xilinx Device Configuration"
++	depends on ARCH_ZYNQ
++
+ endmenu
+ 
+ config RANDOM_TRUST_CPU
+diff -rupN old/linux-5.10/drivers/char/Makefile linux-5.10/drivers/char/Makefile
+--- old/linux-5.10/drivers/char/Makefile
++++ linux-5.10/drivers/char/Makefile
+@@ -47,3 +47,5 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
+ obj-$(CONFIG_XILLYBUS)		+= xillybus/
+ obj-$(CONFIG_POWERNV_OP_PANEL)	+= powernv-op-panel.o
+ obj-$(CONFIG_ADI)		+= adi.o
++obj-$(CONFIG_DEVCMA)		+= cma.o
++obj-$(CONFIG_XILINX_DEVCFG)	+= xilinx_devcfg.o
+diff -rupN old/linux-5.10/drivers/net/phy/intel-xway.c linux-5.10/drivers/net/phy/intel-xway.c
+--- old/linux-5.10/drivers/net/phy/intel-xway.c
++++ linux-5.10/drivers/net/phy/intel-xway.c
+@@ -180,6 +180,12 @@ static int xway_gphy_config_init(struct
+ 	if (err)
+ 		return err;
+ 
++	/* Set SGMII RX & TX timing skew to 2 ns & 2.5 ns respectively. */
++	/* Set MII power supply to 2V5. */
++	err = phy_write(phydev, 0x17, 0x4D00);
++	if (err)
++		return err;
++
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCH,
+ 		      XWAY_MMD_LEDCH_NACS_NONE |
+ 		      XWAY_MMD_LEDCH_SBF_F02HZ |
+@@ -189,20 +195,16 @@ static int xway_gphy_config_init(struct
+ 		      XWAY_MMD_LEDCH_SCAN_NONE);
+ 
+ 	/**
+-	 * In most cases only one LED is connected to this phy, so
+-	 * configure them all to constant on and pulse mode. LED3 is
+-	 * only available in some packages, leave it in its reset
+-	 * configuration.
++	 * Set LED0 blinking on RX/TX.
++	 * Set LED1 blinking on link speed: slow=10M, fast=100M, on=1G.
+ 	 */
+-	ledxh = XWAY_MMD_LEDxH_BLINKF_NONE | XWAY_MMD_LEDxH_CON_LINK10XX;
+-	ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT |
+-		XWAY_MMD_LEDxL_BLINKS_NONE;
+-	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0H, ledxh);
++	ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT;
++	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0H, 0);
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0L, ledxl);
++	ledxh = XWAY_MMD_LEDxH_CON_LINK1000 | XWAY_MMD_LEDxH_BLINKF_LINK100;
++	ledxl = XWAY_MMD_LEDxH_CON_LINK10;
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1H, ledxh);
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1L, ledxl);
+-	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh);
+-	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl);
+ 
+ 	return 0;
+ }
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/Kconfig linux-5.10/drivers/net/wireless/realtek/Kconfig
+--- old/linux-5.10/drivers/net/wireless/realtek/Kconfig
++++ linux-5.10/drivers/net/wireless/realtek/Kconfig
+@@ -13,8 +13,9 @@ config WLAN_VENDOR_REALTEK
+ if WLAN_VENDOR_REALTEK
+ 
+ source "drivers/net/wireless/realtek/rtl818x/Kconfig"
+-source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
+ source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
+ source "drivers/net/wireless/realtek/rtw88/Kconfig"
++source "drivers/net/wireless/realtek/rtl8188eu/Kconfig"
++source "drivers/net/wireless/realtek/rtl8192cu/Kconfig"
+ 
+ endif # WLAN_VENDOR_REALTEK
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/Makefile linux-5.10/drivers/net/wireless/realtek/Makefile
+--- old/linux-5.10/drivers/net/wireless/realtek/Makefile
++++ linux-5.10/drivers/net/wireless/realtek/Makefile
+@@ -5,7 +5,8 @@
+ 
+ obj-$(CONFIG_RTL8180)		+= rtl818x/
+ obj-$(CONFIG_RTL8187)		+= rtl818x/
+-obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
+ obj-$(CONFIG_RTL8XXXU)		+= rtl8xxxu/
+ obj-$(CONFIG_RTW88)		+= rtw88/
++obj-$(CONFIG_RTL8188EU)		+= rtl8188eu/
++obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
+ 
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig
+--- old/linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig
++++ linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig
+@@ -1,6 +1,6 @@
+ config RTL8188EU
+ 	tristate "Realtek 8188E USB WiFi"
+ 	depends on USB
+-	---help---
++	help
+ 	  Help message of RTL8188EU
+ 
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig
+--- old/linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig	1970-01-01 00:00:00.000000000 +0000
++++ linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig
+@@ -0,0 +1,9 @@
++config RTL8192CU
++	tristate "Realtek 8192CU USB WiFi"
++	depends on MAC80211 && USB
++	select CFG80211_WEXT
++	select WIRELESS_EXT
++	select WEXT_PRIV
++	help
++	  This option adds the Realtek RTL8192CU USB device.
++
+diff -rupN old/linux-5.10/drivers/pps/clients/pps-gpio.c linux-5.10/drivers/pps/clients/pps-gpio.c
+--- old/linux-5.10/drivers/pps/clients/pps-gpio.c
++++ linux-5.10/drivers/pps/clients/pps-gpio.c
+@@ -145,6 +145,8 @@ static int pps_gpio_setup(struct platfor
+ 
+ 	if (of_property_read_bool(np, "assert-falling-edge"))
+ 		data->assert_falling_edge = true;
++	if (of_get_property(np, "capture-clear", NULL))
++		data->capture_clear = true;
+ 	return 0;
+ }
+ 
+diff -rupN old/linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c
+--- old/linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c
++++ linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c
+@@ -30,6 +30,7 @@ static const struct ci_hdrc_platform_dat
+ 
+ static const struct ci_hdrc_platform_data ci_zynq_pdata = {
+ 	.capoffset	= DEF_CAPOFFSET,
++	.flags		= CI_HDRC_PHY_VBUS_CONTROL,
+ };
+ 
+ static const struct ci_hdrc_platform_data ci_zevio_pdata = {
+@@ -64,6 +65,9 @@ static int ci_hdrc_usb2_probe(struct pla
+ 	if (match && match->data) {
+ 		/* struct copy */
+ 		*ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
++		ci_pdata->usb_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
++		if (IS_ERR(ci_pdata->usb_phy))
++			return PTR_ERR(ci_pdata->usb_phy);
+ 	}
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+diff -rupN old/linux-5.10/drivers/usb/chipidea/host.c linux-5.10/drivers/usb/chipidea/host.c
+--- old/linux-5.10/drivers/usb/chipidea/host.c
++++ linux-5.10/drivers/usb/chipidea/host.c
+@@ -57,6 +57,14 @@ static int ehci_ci_portpower(struct usb_
+ 		priv->enabled = enable;
+ 	}
+ 
++	if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
++			ci->usb_phy && ci->usb_phy->set_vbus) {
++		if (enable)
++			ci->usb_phy->set_vbus(ci->usb_phy, 1);
++		else
++			ci->usb_phy->set_vbus(ci->usb_phy, 0);
++	}
++
+ 	if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
+ 		/*
+ 		 * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
+diff -rupN old/linux-5.10/drivers/usb/chipidea/otg_fsm.c linux-5.10/drivers/usb/chipidea/otg_fsm.c
+--- old/linux-5.10/drivers/usb/chipidea/otg_fsm.c
++++ linux-5.10/drivers/usb/chipidea/otg_fsm.c
+@@ -471,6 +471,11 @@ static void ci_otg_drv_vbus(struct otg_f
+ 				return;
+ 			}
+ 		}
++
++		if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
++				ci->usb_phy && ci->usb_phy->set_vbus)
++			ci->usb_phy->set_vbus(ci->usb_phy, 1);
++
+ 		/* Disable data pulse irq */
+ 		hw_write_otgsc(ci, OTGSC_DPIE, 0);
+ 
+@@ -480,6 +485,10 @@ static void ci_otg_drv_vbus(struct otg_f
+ 		if (ci->platdata->reg_vbus)
+ 			regulator_disable(ci->platdata->reg_vbus);
+ 
++		if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
++				ci->usb_phy && ci->usb_phy->set_vbus)
++			ci->usb_phy->set_vbus(ci->usb_phy, 0);
++
+ 		fsm->a_bus_drop = 1;
+ 		fsm->a_bus_req = 0;
+ 	}
+diff -rupN old/linux-5.10/drivers/usb/phy/phy-ulpi.c linux-5.10/drivers/usb/phy/phy-ulpi.c
+--- old/linux-5.10/drivers/usb/phy/phy-ulpi.c
++++ linux-5.10/drivers/usb/phy/phy-ulpi.c
+@@ -13,9 +13,16 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/export.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/io.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
+ #include <linux/usb.h>
+ #include <linux/usb/otg.h>
+ #include <linux/usb/ulpi.h>
++#include <linux/usb/phy.h>
+ 
+ 
+ struct ulpi_info {
+@@ -39,6 +46,13 @@ static struct ulpi_info ulpi_ids[] = {
+ 	ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
+ };
+ 
++struct ulpi_phy {
++	struct usb_phy	*usb_phy;
++	void __iomem *regs;
++	unsigned int vp_offset;
++	unsigned int flags;
++};
++
+ static int ulpi_set_otg_flags(struct usb_phy *phy)
+ {
+ 	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
+@@ -240,6 +254,23 @@ static int ulpi_set_vbus(struct usb_otg
+ 	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
+ }
+ 
++static int usbphy_set_vbus(struct usb_phy *phy, int on)
++{
++	unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
++
++	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
++
++	if (on) {
++		if (phy->flags & ULPI_OTG_DRVVBUS)
++			flags |= ULPI_OTG_CTRL_DRVVBUS;
++
++		if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
++			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
++	}
++
++	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
++}
++
+ static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg,
+ 			  struct usb_phy_io_ops *ops,
+ 			  unsigned int flags)
+@@ -249,6 +280,7 @@ static void otg_ulpi_init(struct usb_phy
+ 	phy->io_ops	= ops;
+ 	phy->otg	= otg;
+ 	phy->init	= ulpi_init;
++	phy->set_vbus	= usbphy_set_vbus;
+ 
+ 	otg->usb_phy	= phy;
+ 	otg->set_host	= ulpi_set_host;
+@@ -301,3 +333,83 @@ devm_otg_ulpi_create(struct device *dev,
+ 	return phy;
+ }
+ EXPORT_SYMBOL_GPL(devm_otg_ulpi_create);
++
++static int ulpi_phy_probe(struct platform_device *pdev)
++{
++	struct device_node *np = pdev->dev.of_node;
++	struct resource *res;
++	struct ulpi_phy *uphy;
++	bool flag;
++	int ret;
++
++	uphy = devm_kzalloc(&pdev->dev, sizeof(*uphy), GFP_KERNEL);
++	if (!uphy)
++		return -ENOMEM;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
++		return -ENODEV;
++	}
++
++	uphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
++	if (!uphy->regs) {
++		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
++		return -EFAULT;
++	}
++
++	if (IS_ERR(uphy->regs))
++		return PTR_ERR(uphy->regs);
++
++	if (of_property_read_u32(np, "view-port", &uphy->vp_offset))
++		dev_dbg(&pdev->dev, "Missing view-port property\n");
++
++	if (IS_ERR(uphy->regs)) {
++		dev_err(&pdev->dev, "view-port register not specified\n");
++		return PTR_ERR(uphy->regs);
++	}
++
++	flag = of_property_read_bool(np, "drv-vbus");
++	if (flag)
++		uphy->flags |= ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT;
++
++	uphy->usb_phy = otg_ulpi_create(&ulpi_viewport_access_ops, uphy->flags);
++
++	uphy->usb_phy->dev = &pdev->dev;
++
++	uphy->usb_phy->io_priv = uphy->regs + uphy->vp_offset;
++
++	ret = usb_add_phy_dev(uphy->usb_phy);
++	if (ret < 0)
++		return ret;
++
++	return 0;
++}
++
++static int ulpi_phy_remove(struct platform_device *pdev)
++{
++	struct ulpi_phy *uphy = platform_get_drvdata(pdev);
++
++	usb_remove_phy(uphy->usb_phy);
++
++	return 0;
++}
++
++static const struct of_device_id ulpi_phy_table[] = {
++	{ .compatible = "ulpi-phy" },
++	{ },
++};
++MODULE_DEVICE_TABLE(of, ulpi_phy_table);
++
++static struct platform_driver ulpi_phy_driver = {
++	.probe		= ulpi_phy_probe,
++	.remove		= ulpi_phy_remove,
++	.driver		= {
++		.name	= "ulpi-phy",
++		.of_match_table = ulpi_phy_table,
++	},
++};
++module_platform_driver(ulpi_phy_driver);
++
++MODULE_DESCRIPTION("ULPI PHY driver");
++MODULE_LICENSE("GPL v2");
+diff -rupN old/linux-5.10/include/linux/usb/chipidea.h linux-5.10/include/linux/usb/chipidea.h
+--- old/linux-5.10/include/linux/usb/chipidea.h
++++ linux-5.10/include/linux/usb/chipidea.h
+@@ -62,6 +62,7 @@ struct ci_hdrc_platform_data {
+ #define CI_HDRC_REQUIRES_ALIGNED_DMA	BIT(13)
+ #define CI_HDRC_IMX_IS_HSIC		BIT(14)
+ #define CI_HDRC_PMQOS			BIT(15)
++#define CI_HDRC_PHY_VBUS_CONTROL	BIT(16)
+ 	enum usb_dr_mode	dr_mode;
+ #define CI_HDRC_CONTROLLER_RESET_EVENT		0
+ #define CI_HDRC_CONTROLLER_STOPPED_EVENT	1
diff --git a/patches/u-boot-2021.04.patch b/patches/u-boot-2021.04.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c9223599e86eb6b4f48407080ca17a51b89424d3
--- /dev/null
+++ b/patches/u-boot-2021.04.patch
@@ -0,0 +1,43 @@
+diff -rupN old/u-boot-2021.04/arch/arm/dts/Makefile u-boot-2021.04/arch/arm/dts/Makefile
+--- old/u-boot-2021.04/arch/arm/dts/Makefile
++++ u-boot-2021.04/arch/arm/dts/Makefile
+@@ -286,7 +286,8 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
+ 	zynq-zturn.dtb \
+ 	zynq-zturn-v5.dtb \
+ 	zynq-zybo.dtb \
+-	zynq-zybo-z7.dtb
++	zynq-zybo-z7.dtb \
++	zynq-red-pitaya.dtb
+ dtb-$(CONFIG_ARCH_ZYNQMP) += \
+ 	avnet-ultra96-rev1.dtb			\
+ 	avnet-ultrazedev-cc-v1.0-ultrazedev-som-v1.0.dtb	\
+diff -rupN old/u-boot-2021.04/board/xilinx/zynq/board.c u-boot-2021.04/board/xilinx/zynq/board.c
+--- old/u-boot-2021.04/board/xilinx/zynq/board.c
++++ u-boot-2021.04/board/xilinx/zynq/board.c
+@@ -37,12 +37,12 @@ int board_late_init(void)
+ 	const char *mode;
+ 	char *new_targets;
+ 	char *env_targets;
+-
++/*
+ 	if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
+ 		debug("Saved variables - Skipping\n");
+ 		return 0;
+ 	}
+-
++*/
+ 	if (!CONFIG_IS_ENABLED(ENV_VARS_UBOOT_RUNTIME_CONFIG))
+ 		return 0;
+ 
+diff -rupN old/u-boot-2021.04/common/main.c u-boot-2021.04/common/main.c
+--- old/u-boot-2021.04/common/main.c
++++ u-boot-2021.04/common/main.c
+@@ -61,6 +61,8 @@ void main_loop(void)
+ 	if (cli_process_fdt(&s))
+ 		cli_secure_boot_cmd(s);
+ 
++	env_set("sdboot", "echo Importing environment from SD... && mmcinfo && load mmc 0 0x2000000 uEnv.txt && env import -t 0x2000000 ${filesize} && boot");
++
+ 	autoboot_command(s);
+ 
+ 	cli_loop();
diff --git a/patches/xilinx_devcfg.c b/patches/xilinx_devcfg.c
new file mode 100644
index 0000000000000000000000000000000000000000..ea36195621022c59a3f49ba02d4ea3e672489d56
--- /dev/null
+++ b/patches/xilinx_devcfg.c
@@ -0,0 +1,2160 @@
+/*
+ * Xilinx Zynq Device Config driver
+ *
+ * Copyright (c) 2011 - 2013 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/cdev.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#define DRIVER_NAME "xdevcfg"
+#define XDEVCFG_DEVICES 1
+
+/* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(xdevcfg_mutex);
+
+/* Constant Definitions */
+#define XDCFG_CTRL_OFFSET		0x00 /* Control Register */
+#define XDCFG_LOCK_OFFSET		0x04 /* Lock Register */
+#define XDCFG_INT_STS_OFFSET		0x0C /* Interrupt Status Register */
+#define XDCFG_INT_MASK_OFFSET		0x10 /* Interrupt Mask Register */
+#define XDCFG_STATUS_OFFSET		0x14 /* Status Register */
+#define XDCFG_DMA_SRC_ADDR_OFFSET	0x18 /* DMA Source Address Register */
+#define XDCFG_DMA_DEST_ADDR_OFFSET	0x1C /* DMA Destination Address Reg */
+#define XDCFG_DMA_SRC_LEN_OFFSET	0x20 /* DMA Source Transfer Length */
+#define XDCFG_DMA_DEST_LEN_OFFSET	0x24 /* DMA Destination Transfer */
+#define XDCFG_UNLOCK_OFFSET		0x34 /* Unlock Register */
+#define XDCFG_MCTRL_OFFSET		0x80 /* Misc. Control Register */
+
+/* Control Register Bit definitions */
+#define XDCFG_CTRL_PCFG_PROG_B_MASK	0x40000000 /* Program signal to
+						    * Reset FPGA
+						    */
+#define XDCFG_CTRL_PCAP_PR_MASK		0x08000000 /* Enable PCAP for PR */
+#define XDCFG_CTRL_PCAP_MODE_MASK	0x04000000 /* Enable PCAP */
+#define XDCFG_CTRL_PCAP_RATE_EN_MASK  0x02000000 /* Enable PCAP Quad Rate */
+#define XDCFG_CTRL_PCFG_AES_EN_MASK	0x00000E00 /* AES Enable Mask */
+#define XDCFG_CTRL_SEU_EN_MASK		0x00000100 /* SEU Enable Mask */
+#define XDCFG_CTRL_SPNIDEN_MASK		0x00000040 /* Secure Non Invasive
+						    *  Debug Enable
+						    */
+#define XDCFG_CTRL_SPIDEN_MASK		0x00000020 /* Secure Invasive
+						    *  Debug Enable
+						    */
+#define XDCFG_CTRL_NIDEN_MASK		0x00000010 /* Non-Invasive Debug
+						    *  Enable
+						    */
+#define XDCFG_CTRL_DBGEN_MASK		0x00000008 /* Invasive Debug
+						    *  Enable
+						    */
+#define XDCFG_CTRL_DAP_EN_MASK		0x00000007 /* DAP Enable Mask */
+
+/* Lock register bit definitions */
+
+#define XDCFG_LOCK_AES_EN_MASK		0x00000008 /* Lock AES_EN update */
+#define XDCFG_LOCK_SEU_MASK		0x00000004 /* Lock SEU_En update */
+#define XDCFG_LOCK_DBG_MASK		0x00000001 /* This bit locks
+						    *  security config
+						    *  including: DAP_En,
+						    *  DBGEN,NIDEN, SPNIEN
+						    */
+
+/* Miscellaneous Control Register bit definitions */
+#define XDCFG_MCTRL_PCAP_LPBK_MASK	0x00000010 /* Internal PCAP loopback */
+
+/* Status register bit definitions */
+#define XDCFG_STATUS_PCFG_INIT_MASK	0x00000010 /* FPGA init status */
+
+/* Interrupt Status/Mask Register Bit definitions */
+#define XDCFG_IXR_DMA_DONE_MASK		0x00002000 /* DMA Command Done */
+#define XDCFG_IXR_D_P_DONE_MASK		0x00001000 /* DMA and PCAP Cmd Done */
+#define XDCFG_IXR_PCFG_DONE_MASK	0x00000004 /* FPGA programmed */
+#define XDCFG_IXR_ERROR_FLAGS_MASK	0x00F0F860
+#define XDCFG_IXR_ALL_MASK		0xF8F7F87F
+/* Miscellaneous constant values */
+#define XDCFG_DMA_INVALID_ADDRESS	0xFFFFFFFF  /* Invalid DMA address */
+
+static const char * const fclk_name[] = {
+	"fclk0",
+	"fclk1",
+	"fclk2",
+	"fclk3"
+};
+#define NUMFCLKS ARRAY_SIZE(fclk_name)
+
+/**
+ * struct xdevcfg_drvdata - Device Configuration driver structure
+ *
+ * @dev: Pointer to the device structure
+ * @cdev: Instance of the cdev structure
+ * @devt: Pointer to the dev_t structure
+ * @class: Pointer to device class
+ * @fclk_class: Pointer to fclk device class
+ * @dma_done: The dma_done status bit for the DMA command completion
+ * @error_status: The error status captured during the DMA transfer
+ * @irq: Interrupt number
+ * @clk: Peripheral clock for devcfg
+ * @fclk: Array holding references to the FPGA clocks
+ * @fclk_exported: Flag inidcating whether an FPGA clock is exported
+ * @is_open: The status bit to indicate whether the device is opened
+ * @sem: Instance for the mutex
+ * @lock: Instance of spinlock
+ * @base_address: The virtual device base address of the device registers
+ * @ep107: Flags is used to identify the platform
+ * @endian_swap: Flags is used to identify the endianness format
+ * @residue_buf: Array holding stragglers from last time (0 to 3 bytes)
+ * @residue_len: stragglers length in bytes
+ * @is_partial_bitstream: Status bit to indicate partial/full bitstream
+ */
+struct xdevcfg_drvdata {
+	struct device *dev;
+	struct cdev cdev;
+	dev_t devt;
+	struct class *class;
+	struct class *fclk_class;
+	int irq;
+	struct clk *clk;
+	struct clk *fclk[NUMFCLKS];
+	u8 fclk_exported[NUMFCLKS];
+	bool dma_done;
+	int error_status;
+	bool is_open;
+	struct mutex sem;
+	spinlock_t lock;
+	void __iomem *base_address;
+	int ep107;
+	bool is_partial_bitstream;
+	bool endian_swap;
+	char residue_buf[3];
+	int residue_len;
+};
+
+/**
+ * struct fclk_data - FPGA clock data
+ * @clk: Pointer to clock
+ * @enabled: Flag indicating enable status of the clock
+ * @rate_rnd: Rate to be rounded for round rate operation
+ */
+struct fclk_data {
+	struct clk *clk;
+	int enabled;
+	unsigned long rate_rnd;
+};
+
+/* Register read/write access routines */
+#define xdevcfg_writereg(offset, val)	__raw_writel(val, offset)
+#define xdevcfg_readreg(offset)		__raw_readl(offset)
+
+#define SLCR_FPGA_RST_CTRL_OFFSET	0x240 /* FPGA Software Reset Control */
+#define SLCR_LVL_SHFTR_EN_OFFSET	0x900 /* Level Shifters Enable */
+
+static struct regmap *zynq_slcr_regmap;
+
+/**
+ * zynq_slcr_write - Write to a register in SLCR block
+ *
+ * @val:	Value to write to the register
+ * @offset:	Register offset in SLCR block
+ *
+ * Return:	a negative value on error, 0 on success
+ */
+static int zynq_slcr_write(u32 val, u32 offset)
+{
+	return regmap_write(zynq_slcr_regmap, offset, val);
+}
+
+/**
+ * zynq_slcr_init_preload_fpga - Disable communication from the PL to PS.
+ */
+static void zynq_slcr_init_preload_fpga(void)
+{
+	/* Assert FPGA top level output resets */
+	zynq_slcr_write(0xF, SLCR_FPGA_RST_CTRL_OFFSET);
+
+	/* Disable level shifters */
+	zynq_slcr_write(0, SLCR_LVL_SHFTR_EN_OFFSET);
+
+	/* Enable output level shifters */
+	zynq_slcr_write(0xA, SLCR_LVL_SHFTR_EN_OFFSET);
+}
+
+/**
+ * zynq_slcr_init_postload_fpga - Re-enable communication from the PL to PS.
+ */
+static void zynq_slcr_init_postload_fpga(void)
+{
+	/* Enable level shifters */
+	zynq_slcr_write(0xf, SLCR_LVL_SHFTR_EN_OFFSET);
+
+	/* Deassert AXI interface resets */
+	zynq_slcr_write(0, SLCR_FPGA_RST_CTRL_OFFSET);
+}
+
+/**
+ * xdevcfg_reset_pl - Reset the programmable logic.
+ * @base_address:	The base address of the device.
+ *
+ * Must be called with PCAP clock enabled
+ */
+static void xdevcfg_reset_pl(void __iomem *base_address)
+{
+	/*
+	 * Create a rising edge on PCFG_INIT. PCFG_INIT follows PCFG_PROG_B,
+	 * so we need to * poll it after setting PCFG_PROG_B to make sure that
+	 * the rising edge happens.
+	 */
+	xdevcfg_writereg(base_address + XDCFG_CTRL_OFFSET,
+			(xdevcfg_readreg(base_address + XDCFG_CTRL_OFFSET) &
+			 ~XDCFG_CTRL_PCFG_PROG_B_MASK));
+	while (xdevcfg_readreg(base_address + XDCFG_STATUS_OFFSET) &
+			XDCFG_STATUS_PCFG_INIT_MASK)
+		;
+
+	usleep_range(5000, 5100);
+	xdevcfg_writereg(base_address + XDCFG_CTRL_OFFSET,
+			(xdevcfg_readreg(base_address + XDCFG_CTRL_OFFSET) |
+			 XDCFG_CTRL_PCFG_PROG_B_MASK));
+	while (!(xdevcfg_readreg(base_address + XDCFG_STATUS_OFFSET) &
+				XDCFG_STATUS_PCFG_INIT_MASK))
+		;
+}
+
+/**
+ * xdevcfg_irq - The main interrupt handler.
+ * @irq:	The interrupt number.
+ * @data:	Pointer to the driver data structure.
+ * returns: IRQ_HANDLED after the interrupt is handled.
+ **/
+static irqreturn_t xdevcfg_irq(int irq, void *data)
+{
+	u32 intr_status;
+	struct xdevcfg_drvdata *drvdata = data;
+
+	spin_lock(&drvdata->lock);
+
+	intr_status = xdevcfg_readreg(drvdata->base_address +
+					XDCFG_INT_STS_OFFSET);
+
+	/* Clear the interrupts */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+				intr_status);
+
+	if ((intr_status & XDCFG_IXR_D_P_DONE_MASK) ==
+				XDCFG_IXR_D_P_DONE_MASK)
+		drvdata->dma_done = 1;
+
+	if ((intr_status & XDCFG_IXR_ERROR_FLAGS_MASK) ==
+			XDCFG_IXR_ERROR_FLAGS_MASK)
+		drvdata->error_status = 1;
+
+	spin_unlock(&drvdata->lock);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xdevcfg_write - The is the driver write function.
+ *
+ * @file:	Pointer to the file structure.
+ * @buf:	Pointer to the bitstream location.
+ * @count:	The number of bytes to be written.
+ * @ppos:	Pointer to the offset value
+ * returns:	Success or error status.
+ **/
+static ssize_t
+xdevcfg_write(struct file *file, const char __user *buf, size_t count,
+		loff_t *ppos)
+{
+	char *kbuf;
+	int status;
+	unsigned long timeout;
+	u32 intr_reg, dma_len;
+	dma_addr_t dma_addr;
+	u32 transfer_length = 0;
+	struct xdevcfg_drvdata *drvdata = file->private_data;
+	size_t user_count = count;
+	int i;
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	status = mutex_lock_interruptible(&drvdata->sem);
+
+	if (status)
+		goto err_clk;
+
+	dma_len = count + drvdata->residue_len;
+	kbuf = dma_alloc_coherent(drvdata->dev, dma_len, &dma_addr, GFP_KERNEL);
+	if (!kbuf) {
+		status = -ENOMEM;
+		goto err_unlock;
+	}
+
+	/* Collect stragglers from last time (0 to 3 bytes) */
+	memcpy(kbuf, drvdata->residue_buf, drvdata->residue_len);
+
+	/* Fetch user data, appending to stragglers */
+	if (copy_from_user(kbuf + drvdata->residue_len, buf, count)) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	/* Include stragglers in total bytes to be handled */
+	count += drvdata->residue_len;
+
+	/* First block contains a header */
+	if (*ppos == 0 && count > 4) {
+		/* Look for sync word */
+		for (i = 0; i < count - 4; i++) {
+			if (memcmp(kbuf + i, "\x66\x55\x99\xAA", 4) == 0) {
+				pr_debug("Found normal sync word\n");
+				drvdata->endian_swap = 0;
+				break;
+			}
+			if (memcmp(kbuf + i, "\xAA\x99\x55\x66", 4) == 0) {
+				pr_debug("Found swapped sync word\n");
+				drvdata->endian_swap = 1;
+				break;
+			}
+		}
+		/* Remove the header, aligning the data on word boundary */
+		if (i != count - 4) {
+			count -= i;
+			memmove(kbuf, kbuf + i, count);
+		}
+	}
+
+	/* Save stragglers for next time */
+	drvdata->residue_len = count % 4;
+	count -= drvdata->residue_len;
+	memcpy(drvdata->residue_buf, kbuf + count, drvdata->residue_len);
+
+	/* Fixup endianess of the data */
+	if (drvdata->endian_swap) {
+		for (i = 0; i < count; i += 4) {
+			u32 *p = (u32 *)&kbuf[i];
+			*p = swab32(*p);
+		}
+	}
+
+	/* Enable DMA and error interrupts */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+				XDCFG_IXR_ALL_MASK);
+
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				(u32) (~(XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK)));
+
+	drvdata->dma_done = 0;
+	drvdata->error_status = 0;
+
+	/* Initiate DMA write command */
+	if (count < 0x1000)
+		xdevcfg_writereg(drvdata->base_address +
+			XDCFG_DMA_SRC_ADDR_OFFSET, (u32)(dma_addr + 1));
+	else
+		xdevcfg_writereg(drvdata->base_address +
+			XDCFG_DMA_SRC_ADDR_OFFSET, (u32) dma_addr);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_ADDR_OFFSET,
+				(u32)XDCFG_DMA_INVALID_ADDRESS);
+	/* Convert number of bytes to number of words.  */
+	if (count % 4)
+		transfer_length	= (count / 4 + 1);
+	else
+		transfer_length	= count / 4;
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_SRC_LEN_OFFSET,
+				transfer_length);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_LEN_OFFSET, 0);
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (!READ_ONCE(drvdata->dma_done)) {
+		if (time_after(jiffies, timeout)) {
+			status = -ETIMEDOUT;
+			goto error;
+		}
+	}
+
+	if (READ_ONCE(drvdata->error_status))
+		status = drvdata->error_status;
+
+	/* Disable the DMA and error interrupts */
+	intr_reg = xdevcfg_readreg(drvdata->base_address +
+					XDCFG_INT_MASK_OFFSET);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				intr_reg | (XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK));
+
+	/* If we didn't write correctly, then bail out. */
+	if (status) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	*ppos += user_count;
+	status = user_count;
+
+error:
+	dma_free_coherent(drvdata->dev, dma_len, kbuf, dma_addr);
+err_unlock:
+	mutex_unlock(&drvdata->sem);
+err_clk:
+	clk_disable(drvdata->clk);
+	return status;
+}
+
+
+/**
+ * xdevcfg_read - The is the driver read function.
+ * @file:	Pointer to the file structure.
+ * @buf:	Pointer to the bitstream location.
+ * @count:	The number of bytes read.
+ * @ppos:	Pointer to the offsetvalue
+ * returns:	Success or error status.
+ */
+static ssize_t
+xdevcfg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	u32 *kbuf;
+	int status;
+	unsigned long timeout;
+	dma_addr_t dma_addr;
+	struct xdevcfg_drvdata *drvdata = file->private_data;
+	u32 intr_reg;
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	status = mutex_lock_interruptible(&drvdata->sem);
+	if (status)
+		goto err_clk;
+
+	/* Get new data from the ICAP, and return was requested. */
+	kbuf = dma_alloc_coherent(drvdata->dev, count, &dma_addr, GFP_KERNEL);
+	if (!kbuf) {
+		status = -ENOMEM;
+		goto err_unlock;
+	}
+
+	drvdata->dma_done = 0;
+	drvdata->error_status = 0;
+
+	/* Enable DMA and error interrupts */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+				XDCFG_IXR_ALL_MASK);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				(u32) (~(XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK)));
+	/* Initiate DMA read command */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_SRC_ADDR_OFFSET,
+				(u32)XDCFG_DMA_INVALID_ADDRESS);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_ADDR_OFFSET,
+				(u32)dma_addr);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_SRC_LEN_OFFSET, 0);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_LEN_OFFSET,
+				count / 4);
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (!drvdata->dma_done) {
+		if (time_after(jiffies, timeout)) {
+			status = -ETIMEDOUT;
+			goto error;
+		}
+	}
+
+	if (drvdata->error_status)
+		status = drvdata->error_status;
+
+	/* Disable and clear DMA and error interrupts */
+	intr_reg = xdevcfg_readreg(drvdata->base_address +
+					XDCFG_INT_MASK_OFFSET);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				intr_reg | (XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK));
+
+
+	/* If we didn't read correctly, then bail out. */
+	if (status) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	/* If we fail to return the data to the user, then bail out. */
+	if (copy_to_user(buf, kbuf, count)) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	status = count;
+error:
+	dma_free_coherent(drvdata->dev, count, kbuf, dma_addr);
+err_unlock:
+	mutex_unlock(&drvdata->sem);
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+static void xdevcfg_enable_partial(struct xdevcfg_drvdata *drvdata)
+{
+	u32 reg = xdevcfg_readreg(drvdata->base_address + XDCFG_CTRL_OFFSET);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+			 reg | XDCFG_CTRL_PCAP_PR_MASK);
+}
+
+static void xdevcfg_disable_partial(struct xdevcfg_drvdata *drvdata)
+{
+	u32 reg = xdevcfg_readreg(drvdata->base_address + XDCFG_CTRL_OFFSET);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+			 reg & ~XDCFG_CTRL_PCAP_PR_MASK);
+}
+
+/**
+ * xdevcfg_open - The is the driver open function.
+ * @inode:	Pointer to the inode structure of this device.
+ * @file:	Pointer to the file structure.
+ * returns:	Success or error status.
+ */
+static int xdevcfg_open(struct inode *inode, struct file *file)
+{
+	struct xdevcfg_drvdata *drvdata;
+	int status;
+
+	drvdata = container_of(inode->i_cdev, struct xdevcfg_drvdata, cdev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	status = mutex_lock_interruptible(&drvdata->sem);
+	if (status)
+		goto err_clk;
+
+	if (drvdata->is_open) {
+		status = -EBUSY;
+		goto error;
+	}
+
+	file->private_data = drvdata;
+	drvdata->is_open = 1;
+	drvdata->endian_swap = 0;
+	drvdata->residue_len = 0;
+
+	/*
+	 * If is_partial_bitstream is set, then PROG_B is not asserted
+	 * (xdevcfg_reset_pl function) and also zynq_slcr_init_preload_fpga and
+	 * zynq_slcr_init_postload_fpga functions are not invoked.
+	 */
+	if (drvdata->is_partial_bitstream)
+		xdevcfg_enable_partial(drvdata);
+	else
+		zynq_slcr_init_preload_fpga();
+
+	/*
+	 * Only do the reset of the PL for Zynq as it causes problems on the
+	 * EP107 and the issue is not understood, but not worth investigating
+	 * as the emulation platform is very different than silicon and not a
+	 * complete implementation. Also, do not reset if it is a partial
+	 * bitstream.
+	 */
+	if ((!drvdata->ep107) && (!drvdata->is_partial_bitstream))
+		xdevcfg_reset_pl(drvdata->base_address);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+			XDCFG_IXR_PCFG_DONE_MASK);
+
+error:
+	mutex_unlock(&drvdata->sem);
+err_clk:
+	clk_disable(drvdata->clk);
+	return status;
+}
+
+/**
+ * xdevcfg_release - The is the driver release function.
+ * @inode:	Pointer to the inode structure of this device.
+ * @file:	Pointer to the file structure.
+ * returns:	Success.
+ */
+static int xdevcfg_release(struct inode *inode, struct file *file)
+{
+	struct xdevcfg_drvdata *drvdata = file->private_data;
+
+	if (drvdata->is_partial_bitstream)
+		xdevcfg_disable_partial(drvdata);
+	else
+		zynq_slcr_init_postload_fpga();
+
+	if (drvdata->residue_len)
+		dev_info(drvdata->dev, "Did not transfer last %d bytes\n",
+			 drvdata->residue_len);
+
+	drvdata->is_open = 0;
+
+	return 0;
+}
+
+static const struct file_operations xdevcfg_fops = {
+	.owner = THIS_MODULE,
+	.write = xdevcfg_write,
+	.read = xdevcfg_read,
+	.open = xdevcfg_open,
+	.release = xdevcfg_release,
+};
+
+/*
+ * The following functions are the routines provided to the user to
+ * set/get the status bit value in the control/lock registers.
+ */
+
+/**
+ * xdevcfg_set_dap_en - This function sets the DAP bits in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	negative error if the string could not be converted
+ *		or the size of the buffer.
+ */
+static ssize_t xdevcfg_set_dap_en(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_unlock;
+
+	if (mask_bit > 7) {
+		status = -EINVAL;
+		goto err_unlock;
+	}
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+			(ctrl_reg_status |
+			 (((u32)mask_bit) & XDCFG_CTRL_DAP_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_unlock:
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_dap_en_status - The function returns the DAP_EN bits status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_dap_en_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 dap_en_status;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	dap_en_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET) & XDCFG_CTRL_DAP_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", dap_en_status);
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_dap, 0644, xdevcfg_show_dap_en_status,
+				xdevcfg_set_dap_en);
+
+/**
+ * xdevcfg_set_dbgen - This function sets the DBGEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_dbgen(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_DBGEN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_DBGEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_dbgen_status - The function returns the DBGEN bit status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_dbgen_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 dbgen_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	dbgen_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET) & XDCFG_CTRL_DBGEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (dbgen_status >> 3));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_dbg_in, 0644, xdevcfg_show_dbgen_status,
+				xdevcfg_set_dbgen);
+
+/**
+ * xdevcfg_set_niden - This function sets the NIDEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_niden(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_NIDEN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_NIDEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_niden_status - The function returns the NIDEN bit status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_niden_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 niden_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	niden_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET) & XDCFG_CTRL_NIDEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (niden_status >> 4));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_dbg_nonin, 0644, xdevcfg_show_niden_status,
+			xdevcfg_set_niden);
+
+/**
+ * xdevcfg_set_spiden - This function sets the SPIDEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_spiden(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_SPIDEN_MASK));
+	else
+
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_SPIDEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_spiden_status - The function returns the SPIDEN bit status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_spiden_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 spiden_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	spiden_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_SPIDEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (spiden_status >> 5));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_sec_dbg_in, 0644, xdevcfg_show_spiden_status,
+				xdevcfg_set_spiden);
+
+/**
+ * xdevcfg_set_spniden - This function sets the SPNIDEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or the size of buffer
+ */
+static ssize_t xdevcfg_set_spniden(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_SPNIDEN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_SPNIDEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_spniden_status - The function returns the SPNIDEN bit status
+ * in the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_spniden_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 spniden_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	spniden_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_SPNIDEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (spniden_status >> 6));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_sec_dbg_nonin, 0644, xdevcfg_show_spniden_status,
+					xdevcfg_set_spniden);
+
+/**
+ * xdevcfg_set_seu - This function sets the SEU_EN bit in the
+ * control register with the given value
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_seu(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_SEU_EN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_SEU_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_seu_status - The function returns the SEU_EN bit status
+ * in the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_seu_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 seu_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	seu_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_SEU_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (seu_status > 8));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_seu, 0644, xdevcfg_show_seu_status, xdevcfg_set_seu);
+
+/**
+ * xdevcfg_set_aes - This function sets the AES_EN bits in the
+ * control register with either all 1s or all 0s.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ *
+ * The user must send only one bit in the buffer to notify whether he wants to
+ * either set or reset these bits.
+ */
+static ssize_t xdevcfg_set_aes(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status < 0)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status |
+				 XDCFG_CTRL_PCFG_AES_EN_MASK |
+				 XDCFG_CTRL_PCAP_RATE_EN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status &
+				 ~(XDCFG_CTRL_PCFG_AES_EN_MASK |
+				 XDCFG_CTRL_PCAP_RATE_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_aes_status - The function returns the AES_EN bit status
+ * in the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_aes_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 aes_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	aes_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_PCFG_AES_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (aes_status >> 9));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_aes, 0644, xdevcfg_show_aes_status, xdevcfg_set_aes);
+
+/**
+ * xdevcfg_set_aes_en_lock - This function sets the LOCK_AES_EN bit in the
+ * lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_aes_en_lock(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 aes_en_lock_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	aes_en_lock_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_LOCK_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(aes_en_lock_status | XDCFG_LOCK_AES_EN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(aes_en_lock_status &
+				 (~XDCFG_LOCK_AES_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_aes_en_lock_status - The function returns the LOCK_AES_EN bit
+ * status in the lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_aes_en_lock_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 aes_en_lock_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	aes_en_lock_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_LOCK_OFFSET) & XDCFG_LOCK_AES_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (aes_en_lock_status >> 3));
+
+	return status;
+}
+
+static DEVICE_ATTR(aes_en_lock, 0644, xdevcfg_show_aes_en_lock_status,
+				xdevcfg_set_aes_en_lock);
+
+/**
+ * xdevcfg_set_seu_lock - This function sets the LOCK_SEU bit in the
+ * lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_seu_lock(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 seu_lock_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	seu_lock_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_LOCK_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(seu_lock_status | XDCFG_LOCK_SEU_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(seu_lock_status  & (~XDCFG_LOCK_SEU_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_seu_lock_status - The function returns the LOCK_SEU bit
+ * status in the lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_seu_lock_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 seu_lock_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	seu_lock_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_LOCK_OFFSET) & XDCFG_LOCK_SEU_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (seu_lock_status >> 2));
+
+	return status;
+}
+
+static DEVICE_ATTR(seu_lock, 0644, xdevcfg_show_seu_lock_status,
+					xdevcfg_set_seu_lock);
+
+/**
+ * xdevcfg_set_dbg_lock - This function sets the LOCK_DBG bit in the
+ * lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_dbg_lock(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 lock_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	lock_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_LOCK_OFFSET);
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(lock_reg_status | XDCFG_LOCK_DBG_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(lock_reg_status & (~XDCFG_LOCK_DBG_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_dbg_lock_status - The function returns the LOCK_DBG bit
+ * status in the lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_dbg_lock_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 dbg_lock_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	dbg_lock_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_LOCK_OFFSET) & XDCFG_LOCK_DBG_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", dbg_lock_status);
+
+	return status;
+}
+
+static DEVICE_ATTR(dbg_lock, 0644, xdevcfg_show_dbg_lock_status,
+				xdevcfg_set_dbg_lock);
+
+/**
+ * xdevcfg_show_prog_done_status - The function returns the PROG_DONE bit
+ * status in the interrupt status register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_prog_done_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 prog_done_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	prog_done_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_INT_STS_OFFSET) & XDCFG_IXR_PCFG_DONE_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (prog_done_status >> 2));
+
+	return status;
+}
+
+static DEVICE_ATTR(prog_done, 0644, xdevcfg_show_prog_done_status,
+				NULL);
+
+/**
+ * xdevcfg_set_is_partial_bitstream - This function sets the
+ * is_partial_bitstream variable. If is_partial_bitstream is set,
+ * then PROG_B is not asserted (xdevcfg_reset_pl) and also
+ * zynq_slcr_init_preload_fpga and zynq_slcr_init_postload_fpga functions
+ * are not invoked.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_is_partial_bitstream(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		return status;
+
+	if (mask_bit > 1)
+		return -EINVAL;
+
+	if (mask_bit)
+		drvdata->is_partial_bitstream = 1;
+	else
+		drvdata->is_partial_bitstream = 0;
+
+	return size;
+}
+
+/**
+ * xdevcfg_show_is_partial_bitstream_status - The function returns the
+ * value of is_partial_bitstream variable.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_is_partial_bitstream_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = sprintf(buf, "%d\n", drvdata->is_partial_bitstream);
+
+	return status;
+}
+
+static DEVICE_ATTR(is_partial_bitstream, 0644,
+				xdevcfg_show_is_partial_bitstream_status,
+				xdevcfg_set_is_partial_bitstream);
+
+static const struct attribute *xdevcfg_attrs[] = {
+	&dev_attr_prog_done.attr, /* PCFG_DONE bit in Intr Status register */
+	&dev_attr_dbg_lock.attr, /* Debug lock bit in Lock register */
+	&dev_attr_seu_lock.attr, /* SEU lock bit in Lock register */
+	&dev_attr_aes_en_lock.attr, /* AES EN lock bit in Lock register */
+	&dev_attr_enable_aes.attr, /* AES EN bit in Control register */
+	&dev_attr_enable_seu.attr, /* SEU EN bit in Control register */
+	&dev_attr_enable_sec_dbg_nonin.attr, /*SPNIDEN bit in Control register*/
+	&dev_attr_enable_sec_dbg_in.attr, /*SPIDEN bit in Control register */
+	&dev_attr_enable_dbg_nonin.attr, /* NIDEN bit in Control register */
+	&dev_attr_enable_dbg_in.attr, /* DBGEN bit in Control register */
+	&dev_attr_enable_dap.attr, /* DAP_EN bits in Control register */
+	&dev_attr_is_partial_bitstream.attr, /* Flag for partial bitstream */
+	NULL,
+};
+
+
+static const struct attribute_group xdevcfg_attr_group = {
+	.attrs = (struct attribute **) xdevcfg_attrs,
+};
+
+static ssize_t fclk_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->enabled);
+}
+
+static ssize_t fclk_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long enable;
+	int ret;
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	ret = kstrtoul(buf, 0, &enable);
+	if (ret)
+		return -EINVAL;
+
+	enable = !!enable;
+	if (enable == pdata->enabled)
+		return count;
+
+	if (enable)
+		ret = clk_enable(pdata->clk);
+	else
+		clk_disable(pdata->clk);
+
+	if (ret)
+		return ret;
+
+	pdata->enabled = enable;
+	return count;
+}
+
+static DEVICE_ATTR(enable, 0644, fclk_enable_show, fclk_enable_store);
+
+static ssize_t fclk_set_rate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%lu\n", clk_get_rate(pdata->clk));
+}
+
+static ssize_t fclk_set_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	unsigned long rate;
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	ret = kstrtoul(buf, 0, &rate);
+	if (ret)
+		return -EINVAL;
+
+	rate = clk_round_rate(pdata->clk, rate);
+	ret = clk_set_rate(pdata->clk, rate);
+
+	return ret ? ret : count;
+}
+
+static DEVICE_ATTR(set_rate, 0644, fclk_set_rate_show, fclk_set_rate_store);
+
+static ssize_t fclk_round_rate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%lu => %lu\n", pdata->rate_rnd,
+			clk_round_rate(pdata->clk, pdata->rate_rnd));
+}
+
+static ssize_t fclk_round_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	unsigned long rate;
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	ret = kstrtoul(buf, 0, &rate);
+	if (ret)
+		return -EINVAL;
+
+	pdata->rate_rnd = rate;
+
+	return count;
+}
+
+static DEVICE_ATTR(round_rate, 0644, fclk_round_rate_show,
+		fclk_round_rate_store);
+
+static const struct attribute *fclk_ctrl_attrs[] = {
+	&dev_attr_enable.attr,
+	&dev_attr_set_rate.attr,
+	&dev_attr_round_rate.attr,
+	NULL,
+};
+
+static const struct attribute_group fclk_ctrl_attr_grp = {
+	.attrs = (struct attribute **)fclk_ctrl_attrs,
+};
+
+static ssize_t xdevcfg_fclk_export_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	int i, ret;
+	struct device *subdev;
+	struct fclk_data *fdata;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (!strncmp(buf, fclk_name[i], strlen(fclk_name[i])))
+			break;
+	}
+
+	if (i < NUMFCLKS && !drvdata->fclk_exported[i]) {
+		drvdata->fclk_exported[i] = 1;
+		subdev = device_create(drvdata->fclk_class, dev, MKDEV(0, 0),
+				NULL, fclk_name[i]);
+		if (IS_ERR(subdev))
+			return PTR_ERR(subdev);
+		ret = clk_prepare(drvdata->fclk[i]);
+		if (ret)
+			return ret;
+		fdata = kzalloc(sizeof(*fdata), GFP_KERNEL);
+		if (!fdata) {
+			ret = -ENOMEM;
+			goto err_unprepare;
+		}
+		fdata->clk = drvdata->fclk[i];
+		dev_set_drvdata(subdev, fdata);
+		ret = sysfs_create_group(&subdev->kobj, &fclk_ctrl_attr_grp);
+		if (ret)
+			goto err_free;
+	} else {
+		return -EINVAL;
+	}
+
+	return size;
+
+err_free:
+	kfree(fdata);
+err_unprepare:
+	clk_unprepare(drvdata->fclk[i]);
+
+	return ret;
+}
+
+static ssize_t xdevcfg_fclk_export_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int i;
+	ssize_t count = 0;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (!drvdata->fclk_exported[i])
+			count += scnprintf(buf + count, PAGE_SIZE - count,
+					"%s\n", fclk_name[i]);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(fclk_export, 0644, xdevcfg_fclk_export_show,
+		xdevcfg_fclk_export_store);
+
+static int match_fclk(struct device *dev, const void *data)
+{
+	struct fclk_data *fdata = dev_get_drvdata(dev);
+
+	return fdata->clk == data;
+}
+
+static ssize_t xdevcfg_fclk_unexport_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	int i;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (!strncmp(buf, fclk_name[i], strlen(fclk_name[i])))
+			break;
+	}
+
+	if (i < NUMFCLKS && drvdata->fclk_exported[i]) {
+		struct fclk_data *fdata;
+		struct device *subdev;
+
+		drvdata->fclk_exported[i] = 0;
+		subdev = class_find_device(drvdata->fclk_class, NULL,
+				drvdata->fclk[i], match_fclk);
+		fdata = dev_get_drvdata(subdev);
+		if (fdata->enabled)
+			clk_disable(fdata->clk);
+		clk_unprepare(fdata->clk);
+		kfree(fdata);
+		device_unregister(subdev);
+		put_device(subdev);
+	} else {
+		return -EINVAL;
+	}
+
+	return size;
+}
+
+static ssize_t xdevcfg_fclk_unexport_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int i;
+	ssize_t count = 0;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (drvdata->fclk_exported[i])
+			count += scnprintf(buf + count, PAGE_SIZE - count,
+					"%s\n", fclk_name[i]);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(fclk_unexport, 0644, xdevcfg_fclk_unexport_show,
+		xdevcfg_fclk_unexport_store);
+
+static const struct attribute *fclk_exp_attrs[] = {
+	&dev_attr_fclk_export.attr,
+	&dev_attr_fclk_unexport.attr,
+	NULL,
+};
+
+static const struct attribute_group fclk_exp_attr_grp = {
+	.attrs = (struct attribute **)fclk_exp_attrs,
+};
+
+static void xdevcfg_fclk_init(struct device *dev)
+{
+	int i;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		drvdata->fclk[i] = clk_get(dev, fclk_name[i]);
+		if (IS_ERR(drvdata->fclk[i])) {
+			dev_warn(dev, "fclk not found\n");
+			return;
+		}
+	}
+
+	drvdata->fclk_class = class_create(THIS_MODULE, "fclk");
+	if (IS_ERR(drvdata->fclk_class)) {
+		dev_warn(dev, "failed to create fclk class\n");
+		return;
+	}
+
+	if (sysfs_create_group(&dev->kobj, &fclk_exp_attr_grp))
+		dev_warn(dev, "failed to create sysfs entries\n");
+}
+
+static void xdevcfg_fclk_remove(struct device *dev)
+{
+	int i;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (drvdata->fclk_exported[i]) {
+			struct fclk_data *fdata;
+			struct device *subdev;
+
+			drvdata->fclk_exported[i] = 0;
+			subdev = class_find_device(drvdata->fclk_class, NULL,
+					drvdata->fclk[i], match_fclk);
+			fdata = dev_get_drvdata(subdev);
+			if (fdata->enabled)
+				clk_disable(fdata->clk);
+			clk_unprepare(fdata->clk);
+			kfree(fdata);
+			device_unregister(subdev);
+			put_device(subdev);
+
+		}
+	}
+
+	class_destroy(drvdata->fclk_class);
+	sysfs_remove_group(&dev->kobj, &fclk_exp_attr_grp);
+
+}
+
+/**
+ * xdevcfg_drv_probe -  Probe call for the device.
+ *
+ * @pdev:	handle to the platform device structure.
+ *
+ * Returns: 0 on success, negative error otherwise.
+ *
+ * It does all the memory allocation and registration for the device.
+ */
+static int xdevcfg_drv_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct xdevcfg_drvdata *drvdata;
+	dev_t devt;
+	int retval;
+	u32 ctrlreg;
+	struct device_node *np;
+	const void *prop;
+	int size;
+	struct device *dev;
+
+	zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr");
+	if (IS_ERR(zynq_slcr_regmap)) {
+		pr_err("%s: failed to find zynq-slcr\n", __func__);
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drvdata->base_address = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(drvdata->base_address))
+		return PTR_ERR(drvdata->base_address);
+
+	drvdata->irq = platform_get_irq(pdev, 0);
+	retval = devm_request_irq(&pdev->dev, drvdata->irq, &xdevcfg_irq,
+				0, dev_name(&pdev->dev), drvdata);
+	if (retval) {
+		dev_err(&pdev->dev, "No IRQ available");
+		return retval;
+	}
+
+	platform_set_drvdata(pdev, drvdata);
+	spin_lock_init(&drvdata->lock);
+	mutex_init(&drvdata->sem);
+	drvdata->is_open = 0;
+	drvdata->is_partial_bitstream = 0;
+	drvdata->dma_done = 0;
+	drvdata->error_status = 0;
+	dev_info(&pdev->dev, "ioremap %pa to %p\n",
+		 &res->start, drvdata->base_address);
+
+	drvdata->clk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(drvdata->clk)) {
+		dev_err(&pdev->dev, "input clock not found\n");
+		return PTR_ERR(drvdata->clk);
+	}
+
+	retval = clk_prepare_enable(drvdata->clk);
+	if (retval) {
+		dev_err(&pdev->dev, "unable to enable clock\n");
+		return retval;
+	}
+
+	/*
+	 * Figure out from the device tree if this is running on the EP107
+	 * emulation platform as it doesn't match the silicon exactly and the
+	 * driver needs to work accordingly.
+	 */
+	np = of_get_next_parent(pdev->dev.of_node);
+	np = of_get_next_parent(np);
+	prop = of_get_property(np, "compatible", &size);
+
+	if (prop != NULL) {
+		if ((strcmp((const char *)prop, "xlnx,zynq-ep107")) == 0)
+			drvdata->ep107 = 1;
+		else
+			drvdata->ep107 = 0;
+	}
+
+	/* Unlock the device */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_UNLOCK_OFFSET,
+				0x757BDF0D);
+
+	/*
+	 * Set the configuration register with the following options
+	 *  - Reset FPGA
+	 *  - Enable the PCAP interface
+	 *  - Set the throughput rate for maximum speed
+	 *  - Set the CPU in user mode
+	 */
+	ctrlreg = xdevcfg_readreg(drvdata->base_address + XDCFG_CTRL_OFFSET);
+	ctrlreg &= ~XDCFG_CTRL_PCAP_PR_MASK;
+	ctrlreg |= XDCFG_CTRL_PCFG_PROG_B_MASK | XDCFG_CTRL_PCAP_MODE_MASK;
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET, ctrlreg);
+
+	/* Ensure internal PCAP loopback is disabled */
+	ctrlreg = xdevcfg_readreg(drvdata->base_address + XDCFG_MCTRL_OFFSET);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_MCTRL_OFFSET,
+				(~XDCFG_MCTRL_PCAP_LPBK_MASK &
+				ctrlreg));
+
+
+	retval = alloc_chrdev_region(&devt, 0, XDEVCFG_DEVICES, DRIVER_NAME);
+	if (retval < 0)
+		goto failed5;
+
+	drvdata->devt = devt;
+
+	cdev_init(&drvdata->cdev, &xdevcfg_fops);
+	drvdata->cdev.owner = THIS_MODULE;
+	retval = cdev_add(&drvdata->cdev, devt, 1);
+	if (retval) {
+		dev_err(&pdev->dev, "cdev_add() failed\n");
+		goto failed6;
+	}
+
+	drvdata->class = class_create(THIS_MODULE, DRIVER_NAME);
+	if (IS_ERR(drvdata->class)) {
+		dev_err(&pdev->dev, "failed to create class\n");
+		goto failed6;
+	}
+
+	dev = device_create(drvdata->class, &pdev->dev, devt, drvdata,
+			DRIVER_NAME);
+	if (IS_ERR(dev)) {
+		dev_err(&pdev->dev, "unable to create device\n");
+		goto failed7;
+	}
+
+	drvdata->dev = &pdev->dev;
+
+	/* create sysfs files for the device */
+	retval = sysfs_create_group(&(pdev->dev.kobj), &xdevcfg_attr_group);
+	if (retval) {
+		dev_err(&pdev->dev, "Failed to create sysfs attr group\n");
+		cdev_del(&drvdata->cdev);
+		goto failed8;
+	}
+
+	xdevcfg_fclk_init(&pdev->dev);
+
+	clk_disable(drvdata->clk);
+
+	return 0;		/* Success */
+
+failed8:
+	device_destroy(drvdata->class, drvdata->devt);
+failed7:
+	class_destroy(drvdata->class);
+failed6:
+	/* Unregister char driver */
+	unregister_chrdev_region(devt, XDEVCFG_DEVICES);
+failed5:
+	clk_disable_unprepare(drvdata->clk);
+
+	return retval;
+}
+
+/**
+ * xdevcfg_drv_remove -  Remove call for the device.
+ *
+ * @pdev:	handle to the platform device structure.
+ *
+ * Returns: 0 or error status.
+ *
+ * Unregister the device after releasing the resources.
+ */
+static int xdevcfg_drv_remove(struct platform_device *pdev)
+{
+	struct xdevcfg_drvdata *drvdata;
+
+	drvdata = platform_get_drvdata(pdev);
+
+	if (!drvdata)
+		return -ENODEV;
+
+	unregister_chrdev_region(drvdata->devt, XDEVCFG_DEVICES);
+
+	sysfs_remove_group(&pdev->dev.kobj, &xdevcfg_attr_group);
+
+	xdevcfg_fclk_remove(&pdev->dev);
+	device_destroy(drvdata->class, drvdata->devt);
+	class_destroy(drvdata->class);
+	cdev_del(&drvdata->cdev);
+	clk_unprepare(drvdata->clk);
+
+	return 0;		/* Success */
+}
+
+static const struct of_device_id xdevcfg_of_match[] = {
+	{ .compatible = "xlnx,zynq-devcfg-1.0", },
+	{ /* end of table */}
+};
+MODULE_DEVICE_TABLE(of, xdevcfg_of_match);
+
+/* Driver Structure */
+static struct platform_driver xdevcfg_platform_driver = {
+	.probe = xdevcfg_drv_probe,
+	.remove = xdevcfg_drv_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
+		.of_match_table = xdevcfg_of_match,
+	},
+};
+
+module_platform_driver(xdevcfg_platform_driver);
+
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("Xilinx Device Config Driver");
+MODULE_LICENSE("GPL");
diff --git a/patches/xilinx_zynq_defconfig b/patches/xilinx_zynq_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..72063935e48964cb82df90dff70144db9743ac8f
--- /dev/null
+++ b/patches/xilinx_zynq_defconfig
@@ -0,0 +1,396 @@
+CONFIG_LOCALVERSION="-xilinx"
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_BUG is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_754327=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_BIG_LITTLE=y
+CONFIG_BL_SWITCHER=y
+CONFIG_HIGHMEM=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_ZYNQ_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_SYN_COOKIES=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_CAN=y
+CONFIG_CAN_XILINXCAN=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIE_XILINX=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_PL353=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_XILINX_TRAFGEN=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_MACB=y
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_E1000E=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_R8169=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_AXI_EMAC=y
+CONFIG_MARVELL_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_INTEL_XWAY_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_INPUT_SPARSEKMAP=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_XILINX_DEVCFG=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_CADENCE=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE=y
+CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQ_QSPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+CONFIG_GPIO_ZYNQ=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_UCD9200=y
+CONFIG_BMP280=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_CADENCE_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_ADV7604=y
+CONFIG_DRM=y
+CONFIG_DRM_XLNX=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_ADI=y
+CONFIG_SND_SOC_ADI_AXI_I2S=y
+CONFIG_SND_SOC_ADI_AXI_SPDIF=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_STORAGE=y
+CONFIG_USB_UAS=m
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_ULPI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_XILINX=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_ZERO=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=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_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_EDAC=y
+CONFIG_EDAC_SYNOPSYS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_DMADEVICES=y
+CONFIG_PL330_DMA=y
+CONFIG_XILINX_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_UIO_XILINX_APM=y
+CONFIG_COMMON_CLK_SI570=y
+CONFIG_REMOTEPROC=y
+CONFIG_ZYNQ_REMOTEPROC=m
+CONFIG_MEMORY=y
+CONFIG_IIO=y
+CONFIG_XILINX_XADC=y
+CONFIG_XILINX_INTC=y
+CONFIG_RAS=y
+CONFIG_EXT3_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DMA_CMA=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_FTRACE is not set
+CONFIG_OVERLAY_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SYN_COOKIES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RTL8188EU=m
+CONFIG_RTL8192CU=m
+CONFIG_RT2X00=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_RT55XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_MT7601U=m
+CONFIG_ATH9K_HTC=m
+CONFIG_B43=m
+CONFIG_BRCMFMAC=m
+CONFIG_BRCMFMAC_USB=y
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_MBIM=m
+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
+CONFIG_USB_NET_QMI_WWAN=m
+CONFIG_NAMESPACES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_MACVLAN=m
+CONFIG_TUN=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_UDL=m
+CONFIG_FUSE_FS=m
+CONFIG_SPI_SPIDEV=m
+CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ULPI_BUS=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_ACL=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_STAGING=y
+CONFIG_FB_TFT=m
+CONFIG_FB_TFT_AGM1264K_FL=m
+CONFIG_FB_TFT_BD663474=m
+CONFIG_FB_TFT_HX8340BN=m
+CONFIG_FB_TFT_HX8347D=m
+CONFIG_FB_TFT_HX8353D=m
+CONFIG_FB_TFT_HX8357D=m
+CONFIG_FB_TFT_ILI9163=m
+CONFIG_FB_TFT_ILI9320=m
+CONFIG_FB_TFT_ILI9325=m
+CONFIG_FB_TFT_ILI9340=m
+CONFIG_FB_TFT_ILI9341=m
+CONFIG_FB_TFT_ILI9481=m
+CONFIG_FB_TFT_ILI9486=m
+CONFIG_FB_TFT_PCD8544=m
+CONFIG_FB_TFT_RA8875=m
+CONFIG_FB_TFT_S6D02A1=m
+CONFIG_FB_TFT_S6D1121=m
+CONFIG_FB_TFT_SSD1289=m
+CONFIG_FB_TFT_SSD1306=m
+CONFIG_FB_TFT_SSD1331=m
+CONFIG_FB_TFT_SSD1351=m
+CONFIG_FB_TFT_ST7735R=m
+CONFIG_FB_TFT_ST7789V=m
+CONFIG_FB_TFT_TINYLCD=m
+CONFIG_FB_TFT_TLS8204=m
+CONFIG_FB_TFT_UC1611=m
+CONFIG_FB_TFT_UC1701=m
+CONFIG_FB_TFT_UPD161704=m
+CONFIG_FB_TFT_WATTEROTT=m
+CONFIG_FB_FLEX=m
+CONFIG_FB_TFT_FBTFT_DEVICE=m
+CONFIG_USB_ACM=m
+CONFIG_USB_TMC=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=8
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_SERIAL=m
+CONFIG_USB_F_OBEX=m
+CONFIG_USB_F_NCM=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_EEM=m
+CONFIG_USB_F_SUBSET=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_FS=m
+CONFIG_USB_F_UAC1=m
+CONFIG_USB_F_UAC2=m
+CONFIG_USB_F_UVC=m
+CONFIG_USB_F_MIDI=m
+CONFIG_USB_F_HID=m
+CONFIG_USB_F_PRINTER=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_RNDIS=y
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_WEBCAM=m
diff --git a/patches/zynq-red-pitaya.dts b/patches/zynq-red-pitaya.dts
new file mode 100644
index 0000000000000000000000000000000000000000..1c6ceb9dfd064193c954d9241b118a3c4f97370b
--- /dev/null
+++ b/patches/zynq-red-pitaya.dts
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright (C) 2011 - 2015 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ */
+/dts-v1/;
+#include "zynq-7000.dtsi"
+
+/ {
+	model = "Red Pitaya Board";
+	compatible = "xlnx,zynq-red-pitaya", "xlnx,zynq-7000";
+
+	aliases {
+		ethernet0 = &gem0;
+		serial0 = &uart0;
+		mmc0 = &sdhci0;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "";
+		stdout-path = "serial0:115200n8";
+	};
+
+	usb_phy0: phy0 {
+		#phy-cells = <0>;
+		compatible = "usb-nop-xceiv";
+	};
+};
+
+&clkc {
+	ps-clk-frequency = <33333333>;
+};
+
+&gem0 {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy>;
+
+	ethernet_phy: ethernet-phy@1 {
+		reg = <1>;
+		device_type = "ethernet-phy";
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	eeprom@50 {
+		compatible = "24c64";
+		reg = <0x50>;
+	};
+   bmp180@77{
+     compatible = "bosch,bmp280";
+     reg = <0x77>;
+     };
+};
+
+&sdhci0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+	usb-phy = <&usb_phy0>;
+};
diff --git a/patches/zynq_ocm.c b/patches/zynq_ocm.c
new file mode 100644
index 0000000000000000000000000000000000000000..324b7c125bf5681ecff2bb5f6f090bcd293ffc44
--- /dev/null
+++ b/patches/zynq_ocm.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 Xilinx
+ *
+ * Based on "Generic on-chip SRAM allocation driver"
+ *
+ * Copyright (C) 2012 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/genalloc.h>
+
+#include "common.h"
+
+#define ZYNQ_OCM_HIGHADDR	0xfffc0000
+#define ZYNQ_OCM_LOWADDR	0x0
+#define ZYNQ_OCM_BLOCK_SIZE	0x10000
+#define ZYNQ_OCM_BLOCKS		4
+#define ZYNQ_OCM_GRANULARITY	32
+
+#define ZYNQ_OCM_PARITY_CTRL	0x0
+#define ZYNQ_OCM_PARITY_ENABLE	0x1e
+
+#define ZYNQ_OCM_PARITY_ERRADDRESS	0x4
+
+#define ZYNQ_OCM_IRQ_STS		0x8
+#define ZYNQ_OCM_IRQ_STS_ERR_MASK	0x7
+
+struct zynq_ocm_dev {
+	void __iomem *base;
+	int irq;
+	struct gen_pool *pool;
+	struct resource res[ZYNQ_OCM_BLOCKS];
+};
+
+/**
+ * zynq_ocm_irq_handler - Interrupt service routine of the OCM controller
+ * @irq:	IRQ number
+ * @data:	Pointer to the zynq_ocm_dev structure
+ *
+ * Return:	IRQ_HANDLED when handled; IRQ_NONE otherwise.
+ */
+static irqreturn_t zynq_ocm_irq_handler(int irq, void *data)
+{
+	u32 sts;
+	u32 err_addr;
+	struct zynq_ocm_dev *zynq_ocm = data;
+
+	/* check status */
+	sts = readl(zynq_ocm->base + ZYNQ_OCM_IRQ_STS);
+	if (sts & ZYNQ_OCM_IRQ_STS_ERR_MASK) {
+		/* check error address */
+		err_addr = readl(zynq_ocm->base + ZYNQ_OCM_PARITY_ERRADDRESS);
+		pr_err("%s: OCM err intr generated at 0x%04x (stat: 0x%08x).",
+		       __func__, err_addr, sts & ZYNQ_OCM_IRQ_STS_ERR_MASK);
+		return IRQ_HANDLED;
+	}
+	pr_warn("%s: Interrupt generated by OCM, but no error is found.",
+		__func__);
+
+	return IRQ_NONE;
+}
+
+/**
+ * zynq_ocm_probe - Probe method for the OCM driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ *
+ * Return:	0 on success and error value on failure
+ */
+static int zynq_ocm_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct zynq_ocm_dev *zynq_ocm;
+	u32 i, ocm_config, curr;
+	struct resource *res;
+
+	ocm_config = zynq_slcr_get_ocm_config();
+
+	zynq_ocm = devm_kzalloc(&pdev->dev, sizeof(*zynq_ocm), GFP_KERNEL);
+	if (!zynq_ocm)
+		return -ENOMEM;
+
+	zynq_ocm->pool = devm_gen_pool_create(&pdev->dev,
+					      ilog2(ZYNQ_OCM_GRANULARITY),
+					      NUMA_NO_NODE, NULL);
+	if (!zynq_ocm->pool)
+		return -ENOMEM;
+
+	curr = 0; /* For storing current struct resource for OCM */
+	for (i = 0; i < ZYNQ_OCM_BLOCKS; i++) {
+		u32 base, start, end;
+
+		/* Setup base address for 64kB OCM block */
+		if (ocm_config & BIT(i))
+			base = ZYNQ_OCM_HIGHADDR;
+		else
+			base = ZYNQ_OCM_LOWADDR;
+
+		/* Calculate start and end block addresses */
+		start = i * ZYNQ_OCM_BLOCK_SIZE + base;
+		end = start + (ZYNQ_OCM_BLOCK_SIZE - 1);
+
+		/* Concatenate OCM blocks together to get bigger pool */
+		if (i > 0 && start == (zynq_ocm->res[curr - 1].end + 1)) {
+			zynq_ocm->res[curr - 1].end = end;
+		} else {
+#ifdef CONFIG_SMP
+			/*
+			 * OCM block if placed at 0x0 has special meaning
+			 * for SMP because jump trampoline is added there.
+			 * Ensure that this address won't be allocated.
+			 */
+			if (!base) {
+				u32 trampoline_code_size =
+					&zynq_secondary_trampoline_end -
+					&zynq_secondary_trampoline;
+				dev_dbg(&pdev->dev,
+					"Allocate reset vector table %dB\n",
+					trampoline_code_size);
+				/* postpone start offset */
+				start += trampoline_code_size;
+			}
+#endif
+			/* First resource is always initialized */
+			zynq_ocm->res[curr].start = start;
+			zynq_ocm->res[curr].end = end;
+			zynq_ocm->res[curr].flags = IORESOURCE_MEM;
+			curr++; /* Increment curr value */
+		}
+		dev_dbg(&pdev->dev, "OCM block %d, start %x, end %x\n",
+			i, start, end);
+	}
+
+	/*
+	 * Separate pool allocation from OCM block detection to ensure
+	 * the biggest possible pool.
+	 */
+	for (i = 0; i < ZYNQ_OCM_BLOCKS; i++) {
+		unsigned long size;
+		void __iomem *virt_base;
+
+		/* Skip all zero size resources */
+		if (zynq_ocm->res[i].end == 0)
+			break;
+		dev_dbg(&pdev->dev, "OCM resources %d, start %x, end %x\n",
+			i, zynq_ocm->res[i].start, zynq_ocm->res[i].end);
+		size = resource_size(&zynq_ocm->res[i]);
+		virt_base = devm_ioremap_resource(&pdev->dev,
+						  &zynq_ocm->res[i]);
+		if (IS_ERR(virt_base))
+			return PTR_ERR(virt_base);
+
+		ret = gen_pool_add_virt(zynq_ocm->pool,
+					(unsigned long)virt_base,
+					zynq_ocm->res[i].start, size, -1);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Gen pool failed\n");
+			return ret;
+		}
+		dev_info(&pdev->dev, "ZYNQ OCM pool: %ld KiB @ 0x%p\n",
+			 size / 1024, virt_base);
+	}
+
+	/* Get OCM config space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	zynq_ocm->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(zynq_ocm->base))
+		return PTR_ERR(zynq_ocm->base);
+
+	/* Allocate OCM parity IRQ */
+	zynq_ocm->irq = platform_get_irq(pdev, 0);
+	if (zynq_ocm->irq < 0) {
+		dev_err(&pdev->dev, "irq resource not found\n");
+		return zynq_ocm->irq;
+	}
+	ret = devm_request_irq(&pdev->dev, zynq_ocm->irq, zynq_ocm_irq_handler,
+			       0, pdev->name, zynq_ocm);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "request_irq failed\n");
+		return ret;
+	}
+
+	/* Enable parity errors */
+	writel(ZYNQ_OCM_PARITY_ENABLE, zynq_ocm->base + ZYNQ_OCM_PARITY_CTRL);
+
+	platform_set_drvdata(pdev, zynq_ocm);
+
+	return 0;
+}
+
+/**
+ * zynq_ocm_remove - Remove method for the OCM driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees all resources allocated to
+ * the device.
+ *
+ * Return:	0 on success and error value on failure
+ */
+static int zynq_ocm_remove(struct platform_device *pdev)
+{
+	struct zynq_ocm_dev *zynq_ocm = platform_get_drvdata(pdev);
+
+	if (gen_pool_avail(zynq_ocm->pool) < gen_pool_size(zynq_ocm->pool))
+		dev_dbg(&pdev->dev, "removed while SRAM allocated\n");
+
+	return 0;
+}
+
+static struct of_device_id zynq_ocm_dt_ids[] = {
+	{ .compatible = "xlnx,zynq-ocmc-1.0" },
+	{ /* end of table */ }
+};
+
+static struct platform_driver zynq_ocm_driver = {
+	.driver = {
+		.name = "zynq-ocm",
+		.of_match_table = zynq_ocm_dt_ids,
+	},
+	.probe = zynq_ocm_probe,
+	.remove = zynq_ocm_remove,
+};
+
+static int __init zynq_ocm_init(void)
+{
+	return platform_driver_register(&zynq_ocm_driver);
+}
+
+arch_initcall(zynq_ocm_init);
diff --git a/patches/zynq_red_pitaya.h b/patches/zynq_red_pitaya.h
new file mode 100644
index 0000000000000000000000000000000000000000..2be3bd17d46527f12d4f8ec1e060f24d4272dac9
--- /dev/null
+++ b/patches/zynq_red_pitaya.h
@@ -0,0 +1,16 @@
+#ifndef __CONFIG_ZYNQ_RED_PITAYA_H
+#define __CONFIG_ZYNQ_RED_PITAYA_H
+
+#include <configs/zynq-common.h>
+
+#undef CONFIG_SYS_I2C_EEPROM_ADDR_LEN
+#undef CONFIG_SYS_I2C_EEPROM_ADDR
+#undef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS
+#undef CONFIG_SYS_EEPROM_SIZE
+
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		2
+#define CONFIG_SYS_I2C_EEPROM_ADDR		0x50
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS	5
+#define CONFIG_SYS_EEPROM_SIZE			8192 /* Bytes */
+
+#endif /* __CONFIG_ZYNQ_RED_PITAYA_H */
diff --git a/patches/zynq_red_pitaya_defconfig b/patches/zynq_red_pitaya_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..6b6197b2750e68e1107a02975ebe6dad68af6955
--- /dev/null
+++ b/patches/zynq_red_pitaya_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_SYS_TEXT_BASE=0x4000000
+CONFIG_SYS_CUSTOM_LDSCRIPT=y
+CONFIG_SYS_LDSCRIPT="arch/arm/mach-zynq/u-boot.lds"
+CONFIG_DEFAULT_DEVICE_TREE="zynq-red-pitaya"
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_CMD_MMC=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_EEPROM=y
+CONFIG_ENV_OFFSET=0x1800
+CONFIG_ENV_SIZE=0x400
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_CADENCE=y
+CONFIG_SYS_I2C_EEPROM_ADDR=0x50
+CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ZYNQ=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_ZYNQ_GEM=y
+CONFIG_ZYNQ_SERIAL=y