浏览代码

Add project directory

U-DESKTOP-M040OEH\slavs 1 周之前
父节点
当前提交
889f99463c

+ 145 - 0
Makefile

@@ -0,0 +1,145 @@
+# 'make' builds everything
+# 'make clean' deletes everything except source files and Makefile
+#
+# You need to set NAME, PART and PROC for your project.
+# NAME is the base name for most of the generated files.
+
+# solves problem with awk while building linux kernel
+# solution taken from http://www.googoolia.com/wp/2015/04/21/awk-symbol-lookup-error-awk-undefined-symbol-mpfr_z_sub/
+LD_LIBRARY_PATH =
+
+NAME = led_blinker
+PART = xc7z010clg400-1
+PROC = ps7_cortexa9_0
+
+FILES = $(wildcard cores/*.v)
+CORES = $(FILES:.v=)
+
+VIVADO = vivado -nolog -nojournal -mode batch
+XSCT = xsct
+RM = rm -rf
+
+INITRAMFS_TAG = 3.22
+LINUX_TAG = 6.12
+DTREE_TAG = xilinx_v2025.1
+
+INITRAMFS_DIR = tmp/initramfs-$(INITRAMFS_TAG)
+LINUX_DIR = tmp/linux-$(LINUX_TAG)
+DTREE_DIR = tmp/device-tree-xlnx-$(DTREE_TAG)
+
+LINUX_TAR = tmp/linux-$(LINUX_TAG).tar.xz
+DTREE_TAR = tmp/device-tree-xlnx-$(DTREE_TAG).tar.gz
+
+INITRAMFS_URL = https://dl-cdn.alpinelinux.org/alpine/v$(INITRAMFS_TAG)/releases/armv7/netboot/initramfs-lts
+LINUX_URL = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$(LINUX_TAG).52.tar.xz
+DTREE_URL = https://github.com/Xilinx/device-tree-xlnx/archive/$(DTREE_TAG).tar.gz
+
+SSBL_URL = https://github.com/pavel-demin/ssbl/releases/latest/download/ssbl.elf
+
+RTL8188_TAR = tmp/rtl8188eu-main.tar.gz
+RTL8188_URL = https://github.com/pavel-demin/rtl8188eu/archive/main.tar.gz
+
+.PRECIOUS: tmp/cores/% tmp/%.xpr tmp/%.xsa tmp/%.bit tmp/%.fsbl/executable.elf tmp/%.tree/system-top.dts
+
+all: tmp/$(NAME).bit boot.bin boot-rootfs.bin
+
+cores: $(addprefix tmp/, $(CORES))
+
+xpr: tmp/$(NAME).xpr
+
+bit: tmp/$(NAME).bit
+
+$(LINUX_TAR):
+	mkdir -p $(@D)
+	curl -L $(LINUX_URL) -o $@
+
+$(DTREE_TAR):
+	mkdir -p $(@D)
+	curl -L $(DTREE_URL) -o $@
+
+$(RTL8188_TAR):
+	mkdir -p $(@D)
+	curl -L $(RTL8188_URL) -o $@
+
+$(INITRAMFS_DIR):
+	mkdir -p $@
+	curl -L $(INITRAMFS_URL) | gunzip | cpio -id --directory=$@
+	patch -d $@ -p 0 < patches/initramfs.patch
+	rm -rf $@/etc/modprobe.d $@/lib/firmware $@/lib/modules $@/var
+
+$(LINUX_DIR): $(LINUX_TAR) $(RTL8188_TAR)
+	mkdir -p $@
+	tar -Jxf $< --strip-components=1 --directory=$@
+	mkdir -p $@/drivers/net/wireless/realtek/rtl8188eu
+	tar -zxf $(RTL8188_TAR) --strip-components=1 --directory=$@/drivers/net/wireless/realtek/rtl8188eu
+	patch -d tmp -p 0 < patches/linux-$(LINUX_TAG).patch
+	cp patches/cma.c $@/drivers/char
+	cp patches/xilinx_devcfg.c $@/drivers/char
+	cp patches/xilinx_zynq_defconfig $@/arch/arm/configs
+
+$(DTREE_DIR): $(DTREE_TAR)
+	mkdir -p $@
+	tar -zxf $< --strip-components=1 --directory=$@
+
+tmp/ssbl.elf:
+	mkdir -p $(@D)
+	curl -L $(SSBL_URL) -o $@
+
+zImage.bin: $(LINUX_DIR)
+	make -C $< mrproper
+	make -C $< ARCH=arm -j $(shell nproc 2> /dev/null || echo 1) \
+	  CROSS_COMPILE=arm-linux-gnueabihf- LOADADDR=0x8000 \
+	  xilinx_zynq_defconfig zImage modules
+	cp $</arch/arm/boot/zImage $@
+
+initrd.bin: $(INITRAMFS_DIR)
+	cd $< && find . | sort | cpio -o -H newc | gzip -9 -n > ../../$@
+	truncate -s 4M $@
+
+boot.bin: tmp/$(NAME).fsbl/executable.elf tmp/ssbl.elf initrd.dtb zImage.bin initrd.bin
+	echo "img:{[bootloader] tmp/$(NAME).fsbl/executable.elf tmp/ssbl.elf [load=0x2000000] initrd.dtb [load=0x2008000] zImage.bin [load=0x3000000] initrd.bin}" > tmp/boot.bif
+	bootgen -image tmp/boot.bif -w -o $@
+
+boot-rootfs.bin: tmp/$(NAME).fsbl/executable.elf tmp/ssbl.elf rootfs.dtb zImage.bin
+	echo "img:{[bootloader] tmp/$(NAME).fsbl/executable.elf tmp/ssbl.elf [load=0x2000000] rootfs.dtb [load=0x2008000] zImage.bin}" > tmp/boot-rootfs.bif
+	bootgen -image tmp/boot-rootfs.bif -w -o $@
+
+initrd.dtb: tmp/$(NAME).tree/system-top.dts
+	dtc -I dts -O dtb -o $@ -i tmp/$(NAME).tree -i dts dts/initrd.dts
+
+rootfs.dtb: tmp/$(NAME).tree/system-top.dts
+	dtc -I dts -O dtb -o $@ -i tmp/$(NAME).tree -i dts dts/rootfs.dts
+
+tmp/cores/%: cores/%.v
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/core.tcl -tclargs $* $(PART)
+
+tmp/%.xpr: projects/% $(addprefix tmp/, $(CORES))
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/project.tcl -tclargs $* $(PART)
+
+tmp/%.xsa: tmp/%.xpr
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/hwdef.tcl -tclargs $*
+
+tmp/%.bit: tmp/%.xpr
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/bitstream.tcl -tclargs $*
+
+tmp/%.fsbl/executable.elf: tmp/%.xsa
+	mkdir -p $(@D)
+	$(XSCT) scripts/fsbl.tcl $* $(PROC)
+	cp patches/red_pitaya_fsbl_hooks.c $(@D)
+	patch $(@D)/fsbl_hooks.c patches/fsbl.patch
+	make -C $(@D)
+
+tmp/%.tree/system-top.dts: tmp/%.xsa $(DTREE_DIR)
+	mkdir -p $(@D)
+	$(XSCT) scripts/devicetree.tcl $* $(PROC) $(DTREE_DIR)
+	sed -i 's|#include|/include/|' $@
+
+clean:
+	$(RM) zImage.bin initrd.bin boot.bin boot-rootfs.bin initrd.dtb rootfs.dtb tmp
+	$(RM) .Xil usage_statistics_webtalk.html usage_statistics_webtalk.xml
+	$(RM) vivado*.jou vivado*.log
+	$(RM) webtalk*.jou webtalk*.log

+ 22 - 0
helpers/bazaar-mcpha.sh

@@ -0,0 +1,22 @@
+project=mcpha
+
+cp -a projects/$project/bazaar $project
+
+arm-linux-gnueabihf-gcc -shared -Wall -fPIC -Os -s $project/src/main.c -o $project/controllerhf.so
+
+server=mcpha-server
+arm-linux-gnueabihf-gcc -static -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard projects/$project/server/$server.c -lm -lpthread -o $project/$server
+
+server=pha-server
+arm-linux-gnueabihf-gcc -static -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard projects/$project/server/$server.c -lpthread -o $project/$server
+
+cp tmp/$project.bit $project
+
+version=1.0-`date +%Y%m%d`
+revision=`git log -n1 --pretty=%h`
+
+sed -i "s/REVISION/$revision/; s/VERSION/$version/" $project/info/info.json
+
+zip -r $project-$version.zip $project
+
+rm -rf $project

+ 19 - 0
helpers/bazaar.sh

@@ -0,0 +1,19 @@
+project=$1
+server=$2
+
+cp -a projects/$project/bazaar $project
+
+arm-linux-gnueabihf-gcc -shared -Wall -fPIC -Os -s $project/src/main.c -o $project/controllerhf.so
+
+arm-linux-gnueabihf-gcc -static -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard projects/$project/server/$server.c -D_GNU_SOURCE -lm -lpthread -o $project/$server
+
+cp tmp/$project.bit $project
+
+version=1.0-`date +%Y%m%d`
+revision=`git log -n1 --pretty=%h`
+
+sed -i "s/REVISION/$revision/; s/VERSION/$version/" $project/info/info.json
+
+zip -r $project-$version.zip $project
+
+rm -rf $project

+ 17 - 0
helpers/build-all.sh

@@ -0,0 +1,17 @@
+source /opt/Xilinx/2025.1/Vitis/settings64.sh
+
+JOBS=`nproc 2> /dev/null || echo 1`
+
+make -j $JOBS cores
+
+make NAME=led_blinker all
+
+PRJS="sdr_receiver sdr_receiver_hpsdr sdr_receiver_wide sdr_transceiver sdr_transceiver_ft8 sdr_transceiver_hpsdr sdr_transceiver_wide sdr_transceiver_wspr mcpha pulsed_nmr scanner vna playground template"
+
+printf "%s\n" $PRJS | xargs -n 1 -P $JOBS -I {} make NAME={} bit
+
+PRJS="led_blinker_122_88 sdr_receiver_122_88 sdr_receiver_hpsdr_122_88 sdr_receiver_wide_122_88 sdr_transceiver_122_88 sdr_transceiver_ft8_122_88 sdr_transceiver_hpsdr_122_88 sdr_transceiver_wspr_122_88 pulsed_nmr_122_88 vna_122_88"
+
+printf "%s\n" $PRJS | xargs -n 1 -P $JOBS -I {} make NAME={} PART=xc7z020clg400-1 bit
+
+sudo sh scripts/alpine.sh

+ 6 - 0
helpers/build-bazaar.sh

@@ -0,0 +1,6 @@
+source helpers/bazaar.sh sdr_receiver_hpsdr sdr-receiver-hpsdr
+source helpers/bazaar.sh sdr_transceiver sdr-transceiver
+source helpers/bazaar.sh sdr_transceiver_hpsdr sdr-transceiver-hpsdr
+source helpers/bazaar.sh vna vna
+
+source helpers/bazaar-mcpha.sh

+ 9 - 0
helpers/build-cores.tcl

@@ -0,0 +1,9 @@
+set files [glob -nocomplain cores/*.v]
+
+set part_name xc7z010clg400-1
+
+foreach file_name $files {
+  set core_name [file rootname [file tail $file_name]]
+  set argv [list $core_name $part_name]
+  source scripts/core.tcl
+}

+ 8 - 0
helpers/build-debian.sh

@@ -0,0 +1,8 @@
+source /opt/Xilinx/2025.1/Vitis/settings64.sh
+
+DATE=`date +%Y%m%d`
+
+make NAME=led_blinker all
+
+sudo sh scripts/image.sh scripts/debian.sh red-pitaya-debian-13-armhf-$DATE.img 2048
+zip red-pitaya-debian-13-armhf-$DATE.zip red-pitaya-debian-13-armhf-$DATE.img

+ 121 - 0
helpers/build-nginx.sh

@@ -0,0 +1,121 @@
+apt-get install libpcre3-dev libluajit-5.1-dev libcurl4-openssl-dev libssl-dev libboost-regex1.55-dev libboost-system1.55-dev libboost-thread1.55-dev libcrypto++-dev zlib1g-dev
+
+curl -L https://github.com/RedPitaya/RedPitaya/archive/v0.95-1.tar.gz -o RedPitaya-0.95-1.tar.gz
+tar -zxf RedPitaya-0.95-1.tar.gz
+cd RedPitaya-0.95-1
+
+cat <<- EOF_CAT > patches/lua-nginx-module.patch
+diff -rupN lua-nginx-module.old/config lua-nginx-module.new/config
+--- lua-nginx-module.old/config
++++ lua-nginx-module.new/config
+@@ -295,8 +311,8 @@ fi
+ NGX_DTRACE_PROVIDERS="$NGX_DTRACE_PROVIDERS $ngx_addon_dir/dtrace/ngx_lua_provider.d"
+ NGX_TAPSET_SRCS="$NGX_TAPSET_SRCS $ngx_addon_dir/tapset/ngx_lua.stp"
+
+-USE_MD5=YES
+-USE_SHA1=YES
++USE_MD5=NO
++USE_SHA1=NO
+
+ CORE_INCS="$CORE_INCS $ngx_addon_dir/src/api"
+
+diff -rupN lua-nginx-module.old/src/ngx_http_lua_socket_tcp.c lua-nginx-module.new/src/ngx_http_lua_socket_tcp.c
+--- lua-nginx-module.old/src/ngx_http_lua_socket_tcp.c
++++ lua-nginx-module.new/src/ngx_http_lua_socket_tcp.c
+@@ -3146,8 +3146,7 @@ ngx_http_lua_req_socket(lua_State *L)
+     }
+
+     lua_settop(L, 1);
+-    lua_pushnil(L);
+-    return 2;
++    return 1;
+ }
+
+
+EOF_CAT
+
+make Bazaar/tools/libjson
+make Bazaar/nginx/ngx_ext_modules/ws_server/websocketpp
+make Bazaar/nginx/ngx_ext_modules/lua-nginx-module
+make Bazaar/nginx/nginx-1.5.3
+
+make -C shared
+
+patch -d Bazaar/nginx/ngx_ext_modules/ws_server/rp_sdk -p1 <<- EOF_PATCH
+diff -rupN rp_sdk.old/Makefile rp_sdk.new/Makefile
+--- rp_sdk.old/Makefile
++++ rp_sdk.new/Makefile
+@@ -22,7 +22,7 @@ CRYPTO_DIR=../../../../tools/cryptopp
+ CRYPTO_INSTALL_DIR=../../../../tools/build
+
+ CXX=\$(CROSS_COMPILE)g++
+-CXXFLAGS=-c -Wall -O0 -static -std=c++11 -fPIC -I\$(LIBJSON_DIR) -I\$(CRYPTO_INSTALL_DIR)/include/cryptopp -DNDEBUG
++CXXFLAGS=-c -Wall -O0 -static -std=c++11 -fPIC -I\$(LIBJSON_DIR) -I/usr/include/crypto++ -DNDEBUG
+ ifeq (\$(ALWAYS_PURCHASED),true)
+ CXXFLAGS+=-DALWAYS_PURCHASED
+ endif
+@@ -51,9 +51,7 @@ \$(CRYPTO_LIB):
+ 	make -C \$(CRYPTO_DIR) CXX=\${CROSS_COMPILE}g++ PREFIX=../build install
+
+ \$(LIB): \$(OBJECTS)
+-	mkdir -p \$(OBJDIR)/cryptopp
+-	cd \$(OBJDIR)/cryptopp; ar -x \$(CURRENT_DIR)/\$(CRYPTO_LIB)
+-	ar rc \$(LIB) objs/cryptopp/*.o \$(OBJECTS)
++	ar rc \$(LIB) \$(OBJECTS)
+
+ \$(SDKOBJDIR)/%.o: %.cpp
+ 	mkdir -p \$(dir \$@)
+EOF_PATCH
+
+make -C Bazaar/nginx/ngx_ext_modules/ws_server/rp_sdk librp_sdk.a
+
+patch -d Bazaar/nginx/ngx_ext_modules/ws_server/websocketpp/websocketpp -p1 <<- EOF_PATCH
+diff -rupN websocketpp.old/transport/asio/endpoint.hpp websocketpp.new/transport/asio/endpoint.hpp
+--- websocketpp.old/transport/asio/endpoint.hpp
++++ websocketpp.new/transport/asio/endpoint.hpp
+@@ -95,7 +95,7 @@ public:
+     explicit endpoint()
+       : m_io_service(NULL)
+       , m_external_io_service(false)
+-      , m_listen_backlog(0)
++      , m_listen_backlog(boost::asio::socket_base::max_connections)
+       , m_reuse_addr(false)
+       , m_state(UNINITIALIZED)
+     {
+EOF_PATCH
+
+make -C Bazaar/nginx/ngx_ext_modules/ws_server
+
+cd Bazaar/nginx/nginx-1.5.3
+./configure `cat ../configure_withouts.txt` --add-module=../ngx_ext_modules/lua-nginx-module --add-module=../ngx_ext_modules/ngx_http_rp_module
+make
+cp objs/nginx /opt/redpitaya/sbin/nginx
+strip /opt/redpitaya/sbin/nginx
+cd -
+
+patch -d Applications/scopegenpro/src -p1 <<- EOF_PATCH
+diff -rupN src.old/Makefile src.new/Makefile
+--- src.old/Makefile
++++ src.new/Makefile
+@@ -3,7 +3,7 @@ RM=rm
+
+ CXXSOURCES=main.cpp
+
+-RP_API=../../../api/lib
++RP_API=/opt/redpitaya/lib
+ RP_SDK=../../../Bazaar/nginx/ngx_ext_modules/ws_server/rp_sdk
+
+ INCLUDE = -I\$(RP_SDK)
+@@ -14,7 +14,7 @@ COMMON_FLAGS+=-Wall -fPIC -lstdc++ -Os -s
+ CXXFLAGS+=\$(COMMON_FLAGS) -std=c++11 \$(INCLUDE)
+ LDFLAGS =-shared \$(COMMON_FLAGS) -L\$(RP_SDK)/lib
+ LDFLAGS+= -Wl,--whole-archive
+-LDFLAGS+=-L\$(RP_SDK) -lrp_sdk
++LDFLAGS+=-L\$(RP_SDK) -lrp_sdk -lcryptopp
+ LDFLAGS+=-L\$(RP_API) -lrpapp -lrp
+ LDFLAGS+= -Wl,--no-whole-archive
+
+EOF_PATCH
+
+make -C Applications/scopegenpro/src
+cp Applications/scopegenpro/controllerhf.so /opt/redpitaya/www/apps/scopegenpro/controllerhf.so

+ 11 - 0
helpers/build-project.sh

@@ -0,0 +1,11 @@
+source /opt/Xilinx/2025.1/Vitis/settings64.sh
+
+JOBS=`nproc 2> /dev/null || echo 1`
+
+make -j $JOBS cores
+
+make NAME=led_blinker all
+
+make NAME=$1 bit
+
+sudo sh scripts/alpine-project.sh $1

+ 8 - 0
helpers/dds-mem.py

@@ -0,0 +1,8 @@
+import numpy as np
+
+a = 2**23 - 2
+
+x = (np.arange(2048) + 0.5) / 4096
+lut = np.round(a * np.cos(np.pi * x)).astype(np.uint32)
+
+print("\n".join([format(v, "06x") for v in lut]))

+ 115 - 0
helpers/fpga-bit-to-bin.py

@@ -0,0 +1,115 @@
+#!/usr/bin/python3
+
+# copied from https://github.com/topic-embedded-products/meta-topic/blob/master/recipes-bsp/fpga/fpga-bit-to-bin/fpga-bit-to-bin.py
+
+import argparse
+import struct
+
+
+def flip32(data):
+    sl = struct.Struct("<I")
+    sb = struct.Struct(">I")
+    try:
+        b = buffer(data)
+    except NameError:
+        # Python 3 does not have 'buffer'
+        b = data
+    d = bytearray(len(data))
+    for offset in range(0, len(data), 4):
+        sb.pack_into(d, offset, sl.unpack_from(b, offset)[0])
+    return d
+
+
+parser = argparse.ArgumentParser(description="Convert FPGA bit files to raw bin format suitable for flashing")
+parser.add_argument("-f", "--flip", dest="flip", action="store_true", default=False, help="Flip 32-bit endianess (needed for Zynq)")
+parser.add_argument("bitfile", help="Input bit file name")
+parser.add_argument("binfile", help="Output bin file name")
+args = parser.parse_args()
+
+short = struct.Struct(">H")
+ulong = struct.Struct(">I")
+
+bitfile = open(args.bitfile, "rb")
+
+l = short.unpack(bitfile.read(2))[0]
+if l != 9:
+    raise Exception("Missing <0009> header (0x%x), not a bit file" % l)
+bitfile.read(l)
+l = short.unpack(bitfile.read(2))[0]
+d = bitfile.read(l)
+if d != b"a":
+    raise Exception("Missing <a> header, not a bit file")
+
+l = short.unpack(bitfile.read(2))[0]
+d = bitfile.read(l)
+print("Design name: %s" % d)
+
+# If bitstream is a partial bitstream, get some information from filename and header
+if b"PARTIAL=TRUE" in d:
+    print("Partial bitstream")
+    partial = True
+
+    # Get node_nr from filename (last (group of) digits)
+    for i in range(len(args.bitfile) - 1, 0, -1):
+        if args.bitfile[i].isdigit():
+            pos_end = i + 1
+            for j in range(i - 1, 0, -1):
+                if not args.bitfile[j].isdigit():
+                    pos_start = j + 1
+                    break
+            break
+    if pos_end != 0 and pos_end != 0:
+        node_nr = int(args.bitfile[pos_start:pos_end])
+    else:
+        node_nr = 0
+    print("NodeID: %s" % node_nr)
+
+    # Get 16 least significant bits of UserID in design name
+    pos_start = d.find(b"UserID=")
+    if pos_start != -1:
+        pos_end = d.find(b";", pos_start)
+        pos_start = pos_end - 4
+        userid = int(d[pos_start:pos_end], 16)
+        print("UserID: 0x%x" % userid)
+
+else:
+    print("Full bitstream")
+    partial = False
+    node_nr = 0
+
+KEYNAMES = {b"b": "Partname", b"c": "Date", b"d": "Time"}
+
+while 1:
+    k = bitfile.read(1)
+    if not k:
+        bitfile.close()
+        raise Exception("unexpected EOF")
+    elif k == b"e":
+        l = ulong.unpack(bitfile.read(4))[0]
+        print("Found binary data: %s" % l)
+        d = bitfile.read(l)
+        if args.flip:
+            print("Flipping data...")
+            d = flip32(d)
+        # Open bin file
+        binfile = open(args.binfile, "wb")
+        # Write header if it is a partial
+        if partial:
+            binfile.write(struct.pack("B", 0))
+            binfile.write(struct.pack("B", node_nr))
+            binfile.write(struct.pack(">H", userid))
+        # Write the converted bit-2-bin data
+        print("Writing data...")
+        binfile.write(d)
+        binfile.close()
+        break
+    elif k in KEYNAMES:
+        l = short.unpack(bitfile.read(2))[0]
+        d = bitfile.read(l)
+        print(KEYNAMES[k], d)
+    else:
+        print("Unexpected key: %s" % k)
+        l = short.unpack(bitfile.read(2))[0]
+        d = bitfile.read(l)
+
+bitfile.close()

+ 33 - 0
helpers/sdr-receiver-ecosystem.sh

@@ -0,0 +1,33 @@
+ecosystem=ecosystem-0.95-1-6deb253
+
+rm -rf ${ecosystem}-sdr-receiver
+
+test -f ${ecosystem}.zip || curl -O http://downloads.redpitaya.com/downloads/${ecosystem}.zip
+
+unzip -d ${ecosystem}-sdr-receiver ${ecosystem}.zip
+
+arm-linux-gnueabihf-gcc -static projects/sdr_receiver/server/sdr-receiver.c -lm -o ${ecosystem}-sdr-receiver/bin/sdr-receiver
+cp tmp/sdr_receiver.bit ${ecosystem}-sdr-receiver
+
+rm -f ${ecosystem}-sdr-receiver/u-boot.scr
+cp ${ecosystem}-sdr-receiver/u-boot.scr.buildroot ${ecosystem}-sdr-receiver/u-boot.scr
+
+cat <<- EOF_CAT >> ${ecosystem}-sdr-receiver/etc/network/config
+
+PATH=\$PATH:\$PATH_REDPITAYA/sbin:\$PATH_REDPITAYA/bin
+
+EOF_CAT
+
+cat <<- EOF_CAT >> ${ecosystem}-sdr-receiver/sbin/discovery.sh
+
+# start SDR receiver
+
+cat /opt/redpitaya/sdr_receiver.bit > /dev/xdevcfg
+
+/opt/redpitaya/bin/sdr-receiver &
+
+EOF_CAT
+
+cd ${ecosystem}-sdr-receiver
+zip -r ../${ecosystem}-sdr-receiver.zip .
+cd ..

+ 99 - 0
patches/cma.c

@@ -0,0 +1,99 @@
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/dma-map-ops.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, u32)
+
+static unsigned long cma_size = 0;
+static struct page *cma_page = NULL;
+static struct page **cma_pages = NULL;
+
+static void cma_free(void)
+{
+  if(cma_pages)
+  {
+    kfree(cma_pages);
+    cma_pages = NULL;
+  }
+
+  if(cma_page)
+  {
+    dma_release_from_contiguous(NULL, cma_page, cma_size);
+    cma_page = NULL;
+  }
+}
+
+static long cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+  int i;
+  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();
+
+  cma_size = PAGE_ALIGN(buffer) >> PAGE_SHIFT;
+
+  cma_pages = kmalloc_array(cma_size, sizeof(struct page *), GFP_KERNEL);
+
+  if(!cma_pages) return -ENOMEM;
+
+  cma_page = dma_alloc_from_contiguous(NULL, cma_size, 0, false);
+
+  if(!cma_page)
+  {
+    cma_free();
+    return -ENOMEM;
+  }
+
+  for(i = 0; i < cma_size; ++i) cma_pages[i] = &cma_page[i];
+
+  buffer = page_to_phys(cma_page);
+  return copy_to_user((void __user *)arg, &buffer, sizeof(buffer));
+}
+
+static int cma_mmap(struct file *file, struct vm_area_struct *vma)
+{
+  if(!cma_pages) return -ENXIO;
+  vm_flags_set(vma, VM_MIXEDMAP);
+  return vm_map_pages(vma, cma_pages, cma_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)
+{
+  return misc_register(&cma_device);
+}
+
+static void __exit cma_exit(void)
+{
+  cma_free();
+  misc_deregister(&cma_device);
+}
+
+module_init(cma_init);
+module_exit(cma_exit);
+MODULE_LICENSE("MIT");

+ 18 - 0
patches/fsbl.patch

@@ -0,0 +1,18 @@
+--- fsbl_hooks.c.old
++++ fsbl_hooks.c
+@@ -34,6 +34,7 @@
+ 
+ /************************** Function Prototypes ******************************/
+ 
++u32 SetMacAddress();
+ 
+ /******************************************************************************
+ * This function is the hook which will be called  before the bitstream download.
+@@ -112,6 +113,7 @@ u32 FsblHookBeforeHandoff(void)
+ 	 * Errors to be stored in the status variable and returned
+ 	 */
+ 	fsbl_printf(DEBUG_INFO,"In FsblHookBeforeHandoff function \r\n");
++	Status = SetMacAddress();
+ 
+ 	return (Status);
+ }

+ 16 - 0
patches/initramfs.patch

@@ -0,0 +1,16 @@
+--- init.old
++++ init
+@@ -827,10 +827,9 @@ fi
+ 
+ # locate boot media and mount it
+ ebegin "Mounting boot media"
+-$MOCK nlplug-findfs $cryptopts -p /sbin/mdev ${KOPT_debug_init:+-d} \
+-	${KOPT_usbdelay:+-t $(( $KOPT_usbdelay * 1000 ))} \
+-	${KOPT_uevent_buf_size:+-U $KOPT_uevent_buf_size} \
+-	$repoopts -a "$ROOT"/tmp/apkovls
++mkdir -p /media/mmcblk0p1
++mount -o ro /dev/mmcblk0p1 /media/mmcblk0p1
++ls /media/mmcblk0p1/*.apkovl.tar.gz > /tmp/apkovls
+ eend $?
+ 
+ # Setup network interfaces

+ 425 - 0
patches/linux-6.1.patch

@@ -0,0 +1,425 @@
+diff -rupN old/linux-6.1/arch/arm/mach-zynq/common.c linux-6.1/arch/arm/mach-zynq/common.c
+--- old/linux-6.1/arch/arm/mach-zynq/common.c
++++ linux-6.1/arch/arm/mach-zynq/common.c
+@@ -96,6 +96,7 @@ static void __init zynq_init_late(void)
+ {
+ 	zynq_core_pm_init();
+ 	zynq_pm_late_init();
++	zynq_prefetch_init();
+ }
+
+ /**
+@@ -187,8 +188,13 @@ static const char * const zynq_dt_match[
+
+ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+ 	/* 64KB way size, 8-way associativity, parity disabled */
++#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-6.1/arch/arm/mach-zynq/common.h linux-6.1/arch/arm/mach-zynq/common.h
+--- old/linux-6.1/arch/arm/mach-zynq/common.h
++++ linux-6.1/arch/arm/mach-zynq/common.h
+@@ -29,6 +29,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-6.1/arch/arm/mach-zynq/Kconfig linux-6.1/arch/arm/mach-zynq/Kconfig
+--- old/linux-6.1/arch/arm/mach-zynq/Kconfig
++++ linux-6.1/arch/arm/mach-zynq/Kconfig
+@@ -15,3 +15,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-6.1/arch/arm/mach-zynq/platsmp.c linux-6.1/arch/arm/mach-zynq/platsmp.c
+--- old/linux-6.1/arch/arm/mach-zynq/platsmp.c
++++ linux-6.1/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-6.1/drivers/char/Kconfig linux-6.1/drivers/char/Kconfig
+--- old/linux-6.1/drivers/char/Kconfig
++++ linux-6.1/drivers/char/Kconfig
+@@ -459,4 +459,12 @@ config RANDOM_TRUST_BOOTLOADER
+ 	  believe its RNG facilities may be faulty. This may also be configured
+ 	  at boot time with "random.trust_bootloader=on/off".
+
++config DEVCMA
++	bool "/dev/cma virtual device support"
++	default y
++
++config XILINX_DEVCFG
++	tristate "Xilinx Device Configuration"
++	depends on ARCH_ZYNQ
++
+ endmenu
+diff -rupN old/linux-6.1/drivers/char/Makefile linux-6.1/drivers/char/Makefile
+--- old/linux-6.1/drivers/char/Makefile
++++ linux-6.1/drivers/char/Makefile
+@@ -45,3 +45,5 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
+ obj-$(CONFIG_XILLYBUS_CLASS)	+= 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-6.1/drivers/net/phy/intel-xway.c linux-6.1/drivers/net/phy/intel-xway.c
+--- old/linux-6.1/drivers/net/phy/intel-xway.c
++++ linux-6.1/drivers/net/phy/intel-xway.c
+@@ -252,6 +252,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 |
+@@ -261,20 +267,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);
+
+ 	err = xway_gphy_rgmii_init(phydev);
+ 	if (err)
+diff -rupN old/linux-6.1/drivers/net/wireless/realtek/Kconfig linux-6.1/drivers/net/wireless/realtek/Kconfig
+--- old/linux-6.1/drivers/net/wireless/realtek/Kconfig
++++ linux-6.1/drivers/net/wireless/realtek/Kconfig
+@@ -13,9 +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/rtw89/Kconfig"
++source "drivers/net/wireless/realtek/rtl8188eu/Kconfig"
+
+ endif # WLAN_VENDOR_REALTEK
+diff -rupN old/linux-6.1/drivers/net/wireless/realtek/Makefile linux-6.1/drivers/net/wireless/realtek/Makefile
+--- old/linux-6.1/drivers/net/wireless/realtek/Makefile
++++ linux-6.1/drivers/net/wireless/realtek/Makefile
+@@ -5,8 +5,8 @@
+
+ obj-$(CONFIG_RTL8180)		+= rtl818x/
+ obj-$(CONFIG_RTL8187)		+= rtl818x/
+-obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
+ obj-$(CONFIG_RTL8XXXU)		+= rtl8xxxu/
+ obj-$(CONFIG_RTW88)		+= rtw88/
+ obj-$(CONFIG_RTW89)		+= rtw89/
++obj-$(CONFIG_RTL8188EU)		+= rtl8188eu/
+
+diff -rupN old/linux-6.1/drivers/pps/clients/pps-gpio.c linux-6.1/drivers/pps/clients/pps-gpio.c
+--- old/linux-6.1/drivers/pps/clients/pps-gpio.c
++++ linux-6.1/drivers/pps/clients/pps-gpio.c
+@@ -113,6 +113,9 @@ static int pps_gpio_setup(struct device
+ 	data->assert_falling_edge =
+ 		device_property_read_bool(dev, "assert-falling-edge");
+
++	data->capture_clear =
++		device_property_read_bool(dev, "capture-clear");
++
+ 	data->echo_pin = devm_gpiod_get_optional(dev, "echo", GPIOD_OUT_LOW);
+ 	if (IS_ERR(data->echo_pin))
+ 		return dev_err_probe(dev, PTR_ERR(data->echo_pin),
+diff -rupN old/linux-6.1/drivers/usb/chipidea/ci_hdrc_usb2.c linux-6.1/drivers/usb/chipidea/ci_hdrc_usb2.c
+--- old/linux-6.1/drivers/usb/chipidea/ci_hdrc_usb2.c
++++ linux-6.1/drivers/usb/chipidea/ci_hdrc_usb2.c
+@@ -65,6 +65,10 @@ 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-6.1/drivers/usb/chipidea/core.c linux-6.1/drivers/usb/chipidea/core.c
+--- old/linux-6.1/drivers/usb/chipidea/core.c
++++ linux-6.1/drivers/usb/chipidea/core.c
+@@ -326,7 +326,8 @@ static int _ci_usb_phy_init(struct ci_hd
+
+ 		ret = phy_power_on(ci->phy);
+ 		if (ret) {
+-			phy_exit(ci->phy);
++			if (phy_exit(ci->phy) < 0)
++				dev_dbg(ci->dev, "phy exit failed\r\n");
+ 			return ret;
+ 		}
+ 	} else {
+@@ -343,12 +344,20 @@ static int _ci_usb_phy_init(struct ci_hd
+  */
+ static void ci_usb_phy_exit(struct ci_hdrc *ci)
+ {
++	int ret;
++
+ 	if (ci->platdata->flags & CI_HDRC_OVERRIDE_PHY_CONTROL)
+ 		return;
+
+ 	if (ci->phy) {
+-		phy_power_off(ci->phy);
+-		phy_exit(ci->phy);
++		ret = phy_power_off(ci->phy);
++		if (ret < 0)
++			dev_dbg(ci->dev, "phy poweroff failed\r\n");
++
++		ret = phy_exit(ci->phy);
++		if (ret < 0)
++			dev_dbg(ci->dev, "phy exit failed\r\n");
++
+ 	} else {
+ 		usb_phy_shutdown(ci->usb_phy);
+ 	}
+@@ -711,13 +720,16 @@ static int ci_get_platdata(struct device
+ 	if (usb_get_maximum_speed(dev) == USB_SPEED_FULL)
+ 		platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
+
+-	of_property_read_u32(dev->of_node, "phy-clkgate-delay-us",
+-				     &platdata->phy_clkgate_delay_us);
++	if (of_property_read_u32(dev->of_node, "phy-clkgate-delay-us",
++				 &platdata->phy_clkgate_delay_us))
++		dev_dbg(dev, "Missing phy-clkgate-delay-us property\n");
+
+ 	platdata->itc_setting = 1;
+
+-	of_property_read_u32(dev->of_node, "itc-setting",
+-					&platdata->itc_setting);
++	if (of_property_read_u32(dev->of_node, "itc-setting",
++				 &platdata->itc_setting))
++		dev_dbg(dev, "Missing itc-setting property\n");
++
+
+ 	ret = of_property_read_u32(dev->of_node, "ahb-burst-config",
+ 				&platdata->ahb_burst_config);
+diff -rupN old/linux-6.1/drivers/usb/phy/Kconfig linux-6.1/drivers/usb/phy/Kconfig
+--- old/linux-6.1/drivers/usb/phy/Kconfig
++++ linux-6.1/drivers/usb/phy/Kconfig
+@@ -174,6 +174,7 @@ config USB_TEGRA_PHY
+ config USB_ULPI
+ 	bool "Generic ULPI Transceiver Driver"
+ 	depends on ARM || ARM64 || COMPILE_TEST
++	depends on USB_PHY
+ 	select USB_ULPI_VIEWPORT
+ 	help
+ 	  Enable this to support ULPI connected USB OTG transceivers which
+diff -rupN old/linux-6.1/drivers/usb/phy/phy-ulpi.c linux-6.1/drivers/usb/phy/phy-ulpi.c
+--- old/linux-6.1/drivers/usb/phy/phy-ulpi.c
++++ linux-6.1/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");

+ 279 - 0
patches/linux-6.12.patch

@@ -0,0 +1,279 @@
+diff -rupN old/linux-6.12/drivers/char/Kconfig linux-6.12/drivers/char/Kconfig
+--- old/linux-6.12/drivers/char/Kconfig
++++ linux-6.12/drivers/char/Kconfig
+@@ -422,4 +422,12 @@ 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
+diff -rupN old/linux-6.12/drivers/char/Makefile linux-6.12/drivers/char/Makefile
+--- old/linux-6.12/drivers/char/Makefile
++++ linux-6.12/drivers/char/Makefile
+@@ -43,3 +43,5 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
+ obj-$(CONFIG_XILLYBUS_CLASS)	+= 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-6.12/drivers/net/phy/intel-xway.c linux-6.12/drivers/net/phy/intel-xway.c
+--- old/linux-6.12/drivers/net/phy/intel-xway.c
++++ linux-6.12/drivers/net/phy/intel-xway.c
+@@ -252,6 +252,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 |
+@@ -261,20 +267,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);
+ 
+ 	err = xway_gphy_rgmii_init(phydev);
+ 	if (err)
+diff -rupN old/linux-6.12/drivers/net/wireless/realtek/Kconfig linux-6.12/drivers/net/wireless/realtek/Kconfig
+--- old/linux-6.12/drivers/net/wireless/realtek/Kconfig
++++ linux-6.12/drivers/net/wireless/realtek/Kconfig
+@@ -13,9 +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/rtw89/Kconfig"
++source "drivers/net/wireless/realtek/rtl8188eu/Kconfig"
+ 
+ endif # WLAN_VENDOR_REALTEK
+diff -rupN old/linux-6.12/drivers/net/wireless/realtek/Makefile linux-6.12/drivers/net/wireless/realtek/Makefile
+--- old/linux-6.12/drivers/net/wireless/realtek/Makefile
++++ linux-6.12/drivers/net/wireless/realtek/Makefile
+@@ -5,8 +5,8 @@
+ 
+ obj-$(CONFIG_RTL8180)		+= rtl818x/
+ obj-$(CONFIG_RTL8187)		+= rtl818x/
+-obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
+ obj-$(CONFIG_RTL8XXXU)		+= rtl8xxxu/
+ obj-$(CONFIG_RTW88)		+= rtw88/
+ obj-$(CONFIG_RTW89)		+= rtw89/
++obj-$(CONFIG_RTL8188EU)		+= rtl8188eu/
+ 
+diff -rupN old/linux-6.12/drivers/pps/clients/pps-gpio.c linux-6.12/drivers/pps/clients/pps-gpio.c
+--- old/linux-6.12/drivers/pps/clients/pps-gpio.c
++++ linux-6.12/drivers/pps/clients/pps-gpio.c
+@@ -113,6 +113,9 @@ static int pps_gpio_setup(struct device
+ 	data->assert_falling_edge =
+ 		device_property_read_bool(dev, "assert-falling-edge");
+ 
++	data->capture_clear =
++		device_property_read_bool(dev, "capture-clear");
++
+ 	data->echo_pin = devm_gpiod_get_optional(dev, "echo", GPIOD_OUT_LOW);
+ 	if (IS_ERR(data->echo_pin))
+ 		return dev_err_probe(dev, PTR_ERR(data->echo_pin),
+diff -rupN old/linux-6.12/drivers/usb/chipidea/ci_hdrc_usb2.c linux-6.12/drivers/usb/chipidea/ci_hdrc_usb2.c
+--- old/linux-6.12/drivers/usb/chipidea/ci_hdrc_usb2.c
++++ linux-6.12/drivers/usb/chipidea/ci_hdrc_usb2.c
+@@ -62,9 +62,18 @@ static int ci_hdrc_usb2_probe(struct pla
+ 	}
+ 
+ 	data = device_get_match_data(&pdev->dev);
+-	if (data)
++	if (data) {
+ 		/* struct copy */
+ 		*ci_pdata = *data;
++		if (of_device_is_compatible(pdev->dev.of_node,
++					    "xlnx,zynq-usb-2.20a")) {
++			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);
+ 	if (!priv)
+diff -rupN old/linux-6.12/drivers/usb/phy/Kconfig linux-6.12/drivers/usb/phy/Kconfig
+--- old/linux-6.12/drivers/usb/phy/Kconfig
++++ linux-6.12/drivers/usb/phy/Kconfig
+@@ -160,7 +160,7 @@ config USB_TEGRA_PHY
+ 
+ config USB_ULPI
+ 	bool "Generic ULPI Transceiver Driver"
+-	depends on ARM || ARM64 || COMPILE_TEST
++	depends on ARM || ARM64 || COMPILE_TEST || USB_PHY
+ 	select USB_ULPI_VIEWPORT
+ 	help
+ 	  Enable this to support ULPI connected USB OTG transceivers which
+diff -rupN old/linux-6.12/drivers/usb/phy/phy-ulpi.c linux-6.12/drivers/usb/phy/phy-ulpi.c
+--- old/linux-6.12/drivers/usb/phy/phy-ulpi.c
++++ linux-6.12/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/io.h>
++#include <linux/of.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,69 @@ 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;
++	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 (IS_ERR(uphy->regs))
++		return PTR_ERR(uphy->regs);
++
++	if (of_property_read_bool(np, "external-drv-vbus") ||
++	    of_property_read_bool(np, "drv-vbus"))
++		uphy->flags |= ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT;
++
++	ret = of_property_read_u32(np, "view-port", &uphy->vp_offset);
++	if (ret)
++		return ret;
++
++	uphy->usb_phy = otg_ulpi_create(&ulpi_viewport_access_ops, uphy->flags);
++	if (!uphy->usb_phy) {
++		dev_err(&pdev->dev, "Failed to create ULPI OTG\n");
++		return -ENOMEM;
++	}
++
++	uphy->usb_phy->dev = &pdev->dev;
++	uphy->usb_phy->io_priv = uphy->regs + uphy->vp_offset;
++	return usb_add_phy_dev(uphy->usb_phy);
++}
++
++static void ulpi_phy_remove(struct platform_device *pdev)
++{
++	struct ulpi_phy *uphy = platform_get_drvdata(pdev);
++
++	usb_remove_phy(uphy->usb_phy);
++}
++
++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");

+ 287 - 0
patches/linux-6.6.patch

@@ -0,0 +1,287 @@
+diff -rupN old/linux-6.6/drivers/char/Kconfig linux-6.6/drivers/char/Kconfig
+--- old/linux-6.6/drivers/char/Kconfig
++++ linux-6.6/drivers/char/Kconfig
+@@ -422,4 +422,12 @@ 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
+diff -rupN old/linux-6.6/drivers/char/Makefile linux-6.6/drivers/char/Makefile
+--- old/linux-6.6/drivers/char/Makefile
++++ linux-6.6/drivers/char/Makefile
+@@ -44,3 +44,5 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
+ obj-$(CONFIG_XILLYBUS_CLASS)	+= 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-6.6/drivers/net/phy/intel-xway.c linux-6.6/drivers/net/phy/intel-xway.c
+--- old/linux-6.6/drivers/net/phy/intel-xway.c
++++ linux-6.6/drivers/net/phy/intel-xway.c
+@@ -252,6 +252,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 |
+@@ -261,20 +267,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);
+ 
+ 	err = xway_gphy_rgmii_init(phydev);
+ 	if (err)
+diff -rupN old/linux-6.6/drivers/net/wireless/realtek/Kconfig linux-6.6/drivers/net/wireless/realtek/Kconfig
+--- old/linux-6.6/drivers/net/wireless/realtek/Kconfig
++++ linux-6.6/drivers/net/wireless/realtek/Kconfig
+@@ -13,9 +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/rtw89/Kconfig"
++source "drivers/net/wireless/realtek/rtl8188eu/Kconfig"
+ 
+ endif # WLAN_VENDOR_REALTEK
+diff -rupN old/linux-6.6/drivers/net/wireless/realtek/Makefile linux-6.6/drivers/net/wireless/realtek/Makefile
+--- old/linux-6.6/drivers/net/wireless/realtek/Makefile
++++ linux-6.6/drivers/net/wireless/realtek/Makefile
+@@ -5,8 +5,8 @@
+ 
+ obj-$(CONFIG_RTL8180)		+= rtl818x/
+ obj-$(CONFIG_RTL8187)		+= rtl818x/
+-obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
+ obj-$(CONFIG_RTL8XXXU)		+= rtl8xxxu/
+ obj-$(CONFIG_RTW88)		+= rtw88/
+ obj-$(CONFIG_RTW89)		+= rtw89/
++obj-$(CONFIG_RTL8188EU)		+= rtl8188eu/
+ 
+diff -rupN old/linux-6.6/drivers/pps/clients/pps-gpio.c linux-6.6/drivers/pps/clients/pps-gpio.c
+--- old/linux-6.6/drivers/pps/clients/pps-gpio.c
++++ linux-6.6/drivers/pps/clients/pps-gpio.c
+@@ -113,6 +113,9 @@ static int pps_gpio_setup(struct device
+ 	data->assert_falling_edge =
+ 		device_property_read_bool(dev, "assert-falling-edge");
+ 
++	data->capture_clear =
++		device_property_read_bool(dev, "capture-clear");
++
+ 	data->echo_pin = devm_gpiod_get_optional(dev, "echo", GPIOD_OUT_LOW);
+ 	if (IS_ERR(data->echo_pin))
+ 		return dev_err_probe(dev, PTR_ERR(data->echo_pin),
+diff -rupN old/linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c
+--- old/linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c
++++ linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c
+@@ -65,6 +65,14 @@ static int ci_hdrc_usb2_probe(struct pla
+ 	if (match && match->data) {
+ 		/* struct copy */
+ 		*ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
++		if (of_device_is_compatible(pdev->dev.of_node,
++					    "xlnx,zynq-usb-2.20a")) {
++			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-6.6/drivers/usb/chipidea/udc.c linux-6.6/drivers/usb/chipidea/udc.c
+--- old/linux-6.6/drivers/usb/chipidea/udc.c
++++ linux-6.6/drivers/usb/chipidea/udc.c
+@@ -688,7 +688,8 @@ static int _hardware_dequeue(struct ci_h
+ 		if ((TD_STATUS_ACTIVE & tmptoken) != 0) {
+ 			int n = hw_ep_bit(hwep->num, hwep->dir);
+ 
+-			if (ci->rev == CI_REVISION_24)
++			if (ci->rev == CI_REVISION_24 ||
++			    ci->rev == CI_REVISION_22)
+ 				if (!hw_read(ci, OP_ENDPTSTAT, BIT(n)))
+ 					reprime_dtd(ci, hwep, node);
+ 			hwreq->req.status = -EALREADY;
+diff -rupN old/linux-6.6/drivers/usb/phy/Kconfig linux-6.6/drivers/usb/phy/Kconfig
+--- old/linux-6.6/drivers/usb/phy/Kconfig
++++ linux-6.6/drivers/usb/phy/Kconfig
+@@ -160,7 +160,7 @@ config USB_TEGRA_PHY
+ 
+ config USB_ULPI
+ 	bool "Generic ULPI Transceiver Driver"
+-	depends on ARM || ARM64 || COMPILE_TEST
++	depends on ARM || ARM64 || COMPILE_TEST || USB_PHY
+ 	select USB_ULPI_VIEWPORT
+ 	help
+ 	  Enable this to support ULPI connected USB OTG transceivers which
+diff -rupN old/linux-6.6/drivers/usb/phy/phy-ulpi.c linux-6.6/drivers/usb/phy/phy-ulpi.c
+--- old/linux-6.6/drivers/usb/phy/phy-ulpi.c
++++ linux-6.6/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/io.h>
++#include <linux/of.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,69 @@ 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;
++	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 (IS_ERR(uphy->regs))
++		return PTR_ERR(uphy->regs);
++
++	if (of_property_read_bool(np, "external-drv-vbus") ||
++	    of_property_read_bool(np, "drv-vbus"))
++		uphy->flags |= ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT;
++
++	ret = of_property_read_u32(np, "view-port", &uphy->vp_offset);
++	if (ret)
++		return ret;
++
++	uphy->usb_phy = otg_ulpi_create(&ulpi_viewport_access_ops, uphy->flags);
++	if (!uphy->usb_phy) {
++		dev_err(&pdev->dev, "Failed to create ULPI OTG\n");
++		return -ENOMEM;
++	}
++
++	uphy->usb_phy->dev = &pdev->dev;
++	uphy->usb_phy->io_priv = uphy->regs + uphy->vp_offset;
++	return usb_add_phy_dev(uphy->usb_phy);
++}
++
++static void ulpi_phy_remove(struct platform_device *pdev)
++{
++	struct ulpi_phy *uphy = platform_get_drvdata(pdev);
++
++	usb_remove_phy(uphy->usb_phy);
++}
++
++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_new	= 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");

+ 58 - 0
patches/red_pitaya_fsbl_hooks.c

@@ -0,0 +1,58 @@
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "xiicps.h"
+#include "xemacps.h"
+
+u32 SetMacAddress()
+{
+  XIicPs Iic;
+  XIicPs_Config *IicConfig;
+  XEmacPs Emac;
+  XEmacPs_Config *EmacConfig;
+  u32 Status, i;
+  u8 Buffer[1024];
+  char *Pointer;
+
+  Buffer[0] = 0x18;
+  Buffer[1] = 0;
+
+  IicConfig = XIicPs_LookupConfig(XPAR_PS7_I2C_0_DEVICE_ID);
+  if(IicConfig == NULL) return XST_FAILURE;
+
+  Status = XIicPs_CfgInitialize(&Iic, IicConfig, IicConfig->BaseAddress);
+  if(Status != XST_SUCCESS) return XST_FAILURE;
+
+  Status = XIicPs_SetSClk(&Iic, 100000);
+  if(Status != XST_SUCCESS) return XST_FAILURE;
+
+  Status = XIicPs_MasterSendPolled(&Iic, Buffer, 2, 0x50);
+  if(Status != XST_SUCCESS) return XST_FAILURE;
+
+  while(XIicPs_BusIsBusy(&Iic));
+
+  Status = XIicPs_MasterRecvPolled(&Iic, Buffer, 1024, 0x50);
+  if(Status != XST_SUCCESS) return XST_FAILURE;
+
+  Pointer = memmem(Buffer, 1024, "ethaddr=", 8);
+  if(Pointer == NULL) return XST_FAILURE;
+
+  Pointer += 7;
+  for(i = 0; i < 6; ++i)
+  {
+    Buffer[i] = strtol(Pointer + 1, &Pointer, 16);
+  }
+
+  EmacConfig = XEmacPs_LookupConfig(XPAR_PS7_ETHERNET_0_DEVICE_ID);
+  if(EmacConfig == NULL) return XST_FAILURE;
+
+  Status = XEmacPs_CfgInitialize(&Emac, EmacConfig, EmacConfig->BaseAddress);
+  if(Status != XST_SUCCESS) return XST_FAILURE;
+
+  Status = XEmacPs_SetMacAddress(&Emac, Buffer, 1);
+  if(Status != XST_SUCCESS) return XST_FAILURE;
+
+  return Status;
+}

+ 14 - 0
patches/remoteproc.dts

@@ -0,0 +1,14 @@
+/include/ "system.dts"
+
+/ {
+	test: remoteproc@0 {
+		compatible = "xlnx,zynq_remoteproc";
+		reg = < 0x1E000000 0x2000000 >;
+		interrupt-parent = <&intc>;
+		interrupts = < 0 37 0 0 38 0 >;
+		firmware = "app_cpu1.elf";
+		ipino = <8>;
+		vring0 = <9>;
+		vring1 = <10>;
+	};
+};

+ 37 - 0
patches/remoteproc.patch

@@ -0,0 +1,37 @@
+--- old/linux-xlnx-xilinx-v2015.1/drivers/remoteproc/zynq_remoteproc.c
++++ linux-xlnx-xilinx-v2015.1/drivers/remoteproc/zynq_remoteproc.c
+@@ -62,6 +62,25 @@ struct zynq_rproc_pdata {
+ static struct platform_device *remoteprocdev;
+ static struct work_struct workqueue;
+ 
++ssize_t up_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++	struct rproc *rproc = container_of(dev, struct rproc, dev);
++	if(buf[0] == '0') { // want to shut down
++		rproc_shutdown(rproc);
++	} else { // bring up
++		rproc_boot(rproc);
++	}
++	return count;
++}
++
++static ssize_t up_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	struct rproc *rproc = container_of(dev, struct rproc, dev);
++	return sprintf(buf, "%d\n", rproc->state);
++}
++
++static DEVICE_ATTR_RW(up);
++
+ static void handle_event(struct work_struct *work)
+ {
+ 	struct zynq_rproc_pdata *local = platform_get_drvdata(remoteprocdev);
+@@ -308,6 +327,8 @@ static int zynq_remoteproc_probe(struct
+ 			goto rproc_fault;
+ 		}
+ 
++		ret = device_create_file(&local->rproc->dev, &dev_attr_up);
++
+ 		return ret;
+ 	} else
+ 		ret = -ENODEV;

+ 164 - 0
patches/standalone_v5_0.patch

@@ -0,0 +1,164 @@
+diff -brupN old/ps7_cortexa9_1/libsrc/standalone_v5_0/src/asm_vectors.S ps7_cortexa9_1/libsrc/standalone_v5_0/src/asm_vectors.S
+--- old/ps7_cortexa9_1/libsrc/standalone_v5_0/src/asm_vectors.S
++++ ps7_cortexa9_1/libsrc/standalone_v5_0/src/asm_vectors.S
+@@ -55,6 +55,7 @@
+ *
+ ******************************************************************************/
+ #include "xil_errata.h"
++#include "xparameters.h"
+ 
+ #define __ARM_NEON__ 1
+ 
+@@ -63,6 +64,10 @@
+ 
+ .globl _boot
+ .globl _vector_table
++.globl _cpu0_catch
++.globl _cpu1_catch
++.globl OKToRun
++.globl EndlessLoop0
+ 
+ .globl FIQInterrupt
+ .globl IRQInterrupt
+@@ -85,6 +90,20 @@ _vector_table:
+ 	B	FIQHandler
+ 
+ 
++#if XPAR_CPU_ID==0
++_cpu0_catch:
++.word	OKToRun		/* fixed addr for caught cpu- */
++_cpu1_catch:
++.word	EndlessLoop0	/* fixed addr for caught cpu- */
++
++#elif XPAR_CPU_ID==1
++_cpu0_catch:
++.word	EndlessLoop0
++_cpu1_catch:
++.word	OKToRun
++#endif
++
++
+ IRQHandler:					/* IRQ vector handler */
+ 
+ 	stmdb	sp!,{r0-r3,r12,lr}		/* state save from compiled code*/
+diff -brupN old/ps7_cortexa9_1/libsrc/standalone_v5_0/src/boot.S ps7_cortexa9_1/libsrc/standalone_v5_0/src/boot.S
+--- old/ps7_cortexa9_1/libsrc/standalone_v5_0/src/boot.S
++++ ps7_cortexa9_1/libsrc/standalone_v5_0/src/boot.S
+@@ -79,6 +77,11 @@
+ .global __undef_stack
+ .global _vector_table
+ 
++.globl _cpu0_catch
++.globl _cpu1_catch
++.globl OKToRun
++.globl EndlessLoop0
++
+ .set PSS_L2CC_BASE_ADDR, 0xF8F02000
+ .set PSS_SLCR_BASE_ADDR, 0xF8000000
+ 
+@@ -137,26 +139,27 @@
+ _prestart:
+ _boot:
+ 
+-#if XPAR_CPU_ID==0
+-/* only allow cpu0 through */
++/* Test which processor is running and jump to the catch address */
+ 	mrc	p15,0,r1,c0,c0,5
+ 	and	r1, r1, #0xf
+ 	cmp	r1, #0
+-	beq	OKToRun
++	bne	NotCpu0
++	ldr	r0, =_cpu0_catch
++	b cpuxCont
++NotCpu0:
++	cmp	r1, #1
++	bne	EndlessLoop0
++	ldr	r0, =_cpu1_catch
++	b cpuxCont
+ EndlessLoop0:
+ 	wfe
+ 	b	EndlessLoop0
+ 
+-#elif XPAR_CPU_ID==1
+-/* only allow cpu1 through */
+-	mrc	p15,0,r1,c0,c0,5
+-	and	r1, r1, #0xf
+-	cmp	r1, #1
+-	beq	OKToRun
+-EndlessLoop1:
+-	wfe
+-	b	EndlessLoop1
+-#endif
++/* Jump to address pointed to by cpux_catch */
++cpuxCont:
++	ldr lr, [r0]
++	bx	lr
++
+ 
+ OKToRun:
+ 	mrc     p15, 0, r0, c0, c0, 0		/* Get the revision */
+@@ -251,18 +254,42 @@ shareable_loop:
+ 	bge	shareable_loop			/* loop till 1G is covered */
+ #endif
+ 
+-	/* In case of AMP, map virtual address 0x20000000 to 0x00000000  and mark it as non-cacheable */
++//	/* In case of AMP, map virtual address 0x20000000 to 0x00000000  and mark it as non-cacheable */
++//#if USE_AMP==1
++//	ldr	r3, =0x1ff			/* 512 entries to cover 512MB DDR */
++//	ldr	r0, =TblBase			/* MMU Table address in memory */
++//	add	r0, r0, #0x800			/* Address of entry in MMU table, for 0x20000000 */
++//	ldr	r2, =0x0c02			/* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */
++//mmu_loop:
++//	str	r2, [r0]			/* write the entry to MMU table */
++//	add	r0, r0, #0x4			/* next entry in the table */
++//	add	r2, r2, #0x100000		/* next section */
++//	subs	r3, r3, #1
++//	bge	mmu_loop			/* loop till 512MB is covered */
++//#endif
++
++	/* In case of AMP, mark address 0x00000000 - 0x1dffffff DDR as unassigned/reserved */
++	/* and address 0x1e000000 - 0x1fffffff DDR as inner cached only */
+ #if USE_AMP==1
+-	ldr	r3, =0x1ff			/* 512 entries to cover 512MB DDR */
++	ldr	r3, =0x1df			/* 480 entries to cover 480MB DDR */
+ 	ldr	r0, =TblBase			/* MMU Table address in memory */
+-	add	r0, r0, #0x800			/* Address of entry in MMU table, for 0x20000000 */
+-	ldr	r2, =0x0c02			/* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */
++	ldr	r2, =0x0000			/* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */
+ mmu_loop:
+ 	str	r2, [r0]			/* write the entry to MMU table */
+ 	add	r0, r0, #0x4			/* next entry in the table */
+ 	add	r2, r2, #0x100000		/* next section */
+ 	subs	r3, r3, #1
+-	bge	mmu_loop			/* loop till 512MB is covered */
++	bge	mmu_loop			/* loop till 480MB is covered */
++
++	ldr	r3, =0x01f			/* 32 entries to cover 32MB DDR */
++	movw	r2, #0x4de6			/* S=b0 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b1 */
++	movt	r2, #0x1e00			/* S=b0, Section start for address 0x1e000000 */
++mmu_loop1:
++	str	r2, [r0]			/* write the entry to MMU table */
++	add	r0, r0, #0x4			/* next entry in the table */
++	add	r2, r2, #0x100000		/* next section */
++	subs	r3, r3, #1
++	bge	mmu_loop1			/* loop till 32MB is covered */
+ #endif
+ 
+ 	mrs	r0, cpsr			/* get the current PSR */
+diff -brupN old/ps7_cortexa9_1/libsrc/standalone_v5_0/src/xtime_l.c ps7_cortexa9_1/libsrc/standalone_v5_0/src/xtime_l.c
+--- old/ps7_cortexa9_1/libsrc/standalone_v5_0/src/xtime_l.c
++++ ps7_cortexa9_1/libsrc/standalone_v5_0/src/xtime_l.c	
+@@ -80,6 +80,13 @@
+ ****************************************************************************/
+ void XTime_SetTime(XTime Xtime_Global)
+ {
++#ifdef USE_AMP
++	if(Xil_In32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET) & (u32)0x1) {
++		// Timer is already enabled so don't reset it
++		return;
++	}
++#endif
++
+ 	/* Disable Global Timer */
+ 	Xil_Out32((u32)GLOBAL_TMR_BASEADDR + (u32)GTIMER_CONTROL_OFFSET, (u32)0x0);
+ 

+ 12 - 0
patches/uio.dts

@@ -0,0 +1,12 @@
+/include/ "system.dts"
+
+/ {
+	chosen {
+		bootargs = "uio_pdrv_genirq.of_id=generic-uio console=ttyPS0,115200 root=/dev/mmcblk0p2 ro rootfstype=ext4 earlyprintk rootwait";
+	};
+
+	uio0: uio@40000000 {
+		compatible = "generic-uio";
+		reg = <0x40000000 0x1000>;
+	};
+};

+ 2156 - 0
patches/xilinx_devcfg.c

@@ -0,0 +1,2156 @@
+/*
+ * 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("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(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.
+ *
+ * Unregister the device after releasing the resources.
+ */
+static void xdevcfg_drv_remove(struct platform_device *pdev)
+{
+	struct xdevcfg_drvdata *drvdata;
+
+	drvdata = platform_get_drvdata(pdev);
+
+	if (!drvdata)
+		return;
+
+	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);
+}
+
+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");

+ 343 - 0
patches/xilinx_zynq_defconfig

@@ -0,0 +1,343 @@
+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_EXPERT=y
+# CONFIG_BUG is not set
+CONFIG_PERF_EVENTS=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_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_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIE_XILINX=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_FW_LOADER_COMPRESS=y
+CONFIG_FW_LOADER_COMPRESS_ZSTD=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_PL35X=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_OVERLAY=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+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_CAN_XILINXCAN=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_I2C_XILINX=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_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_TPG=y
+CONFIG_VIDEO_ADV7604=y
+CONFIG_DRM=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=y
+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_COMMON_CLK_SI570=y
+CONFIG_REMOTEPROC=y
+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_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_FTRACE is not set
+CONFIG_OVERLAY_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RTL8188EU=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_NETLINK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_IPV4=y
+CONFIG_NFT_CT=m
+CONFIG_NFT_MASQ=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_COMPAT=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_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_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_DFS_UPCALL=y
+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