--- /dev/null
+#
+# Copyright (C) 2013-2021 OpenWrt.org
+# Copyright (C) 2017 Yousong Zhou
+# Copyright (C) 2021 Zoltan Herpai
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_VERSION:=2020.04
+
+PKG_HASH:=fe732aaf037d9cc3c0909bad8362af366ae964bbdac6913a34081ff4ad565372
+
+PKG_MAINTAINER:=Zoltan HERPAI <wigyori@uid0.hu>
+
+include $(INCLUDE_DIR)/u-boot.mk
+include $(INCLUDE_DIR)/package.mk
+
+define U-Boot/Default
+ BUILD_TARGET:=suniv
+ UBOOT_IMAGE:=u-boot-sunxi-with-spl.bin
+ UENV:=default
+ HIDDEN:=1
+endef
+
+define U-Boot/licheepi_nano
+ NAME:=LicheePi Nano
+ BUILD_DEVICES:=licheepi-nano
+endef
+
+UBOOT_TARGETS := \
+ licheepi_nano
+
+UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(STAGING_DIR_IMAGE)
+ $(CP) $(PKG_BUILD_DIR)/$(UBOOT_IMAGE) $(STAGING_DIR_IMAGE)/$(BUILD_DEVICES)-u-boot-with-spl.bin
+ mkimage -C none -A arm -T script -d uEnv-$(UENV).txt \
+ $(STAGING_DIR_IMAGE)/$(BUILD_DEVICES)-boot.scr
+endef
+
+define Package/u-boot/install/default
+endef
+
+$(eval $(call BuildPackage/U-Boot))
--- /dev/null
+From 1dcc6c61ee650b26b94da4f4d6030d54706d87fe Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Thu, 18 Jan 2018 23:11:20 +0800
+Subject: [PATCH 01/29] arm: arm926ejs: start.S: port save_boot_params support
+ from armv7 code
+
+The ARMv7 start code has support for saving some boot params at the
+entry point, which is used by some SoCs to return to BROM.
+
+Port this to ARM926EJ-S start code.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/cpu/arm926ejs/start.S | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S
+index ff592ba810..9011afed3f 100644
+--- a/arch/arm/cpu/arm926ejs/start.S
++++ b/arch/arm/cpu/arm926ejs/start.S
+@@ -17,6 +17,7 @@
+ #include <asm-offsets.h>
+ #include <config.h>
+ #include <common.h>
++#include <linux/linkage.h>
+
+ /*
+ *************************************************************************
+@@ -32,8 +33,13 @@
+ */
+
+ .globl reset
++ .globl save_boot_params_ret
++ .type save_boot_params_ret,%function
+
+ reset:
++ /* Allow the board to save important registers */
++ b save_boot_params
++save_boot_params_ret:
+ /*
+ * set the cpu to SVC32 mode
+ */
+@@ -110,3 +116,16 @@ flush_dcache:
+ #endif
+ mov pc, lr /* back to my caller */
+ #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
++
++/*************************************************************************
++ *
++ * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
++ * __attribute__((weak));
++ *
++ * Stack pointer is not yet initialized at this moment
++ * Don't save anything to stack even if compiled with -O0
++ *
++ *************************************************************************/
++WEAK(save_boot_params)
++ b save_boot_params_ret /* back to my caller */
++ENDPROC(save_boot_params)
+--
+2.20.1
+
--- /dev/null
+From 3fb67784930f20b3ec271a4277c2875a66717769 Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Thu, 18 Jan 2018 23:14:48 +0800
+Subject: [PATCH 02/29] arm: arm926ej-s: add sunxi code
+
+Some Allwinner SoCs use ARM926EJ-S core.
+
+Add Allwinner/sunXi specific code to ARM926EJ-S CPU dircetory.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/cpu/arm926ejs/Makefile | 1 +
+ arch/arm/cpu/arm926ejs/sunxi/Makefile | 16 +++
+ arch/arm/cpu/arm926ejs/sunxi/config.mk | 6 +
+ arch/arm/cpu/arm926ejs/sunxi/fel_utils.S | 38 +++++++
+ arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S | 68 +++++++++++
+ arch/arm/cpu/arm926ejs/sunxi/start.c | 1 +
+ arch/arm/cpu/arm926ejs/sunxi/timer.c | 113 +++++++++++++++++++
+ arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds | 63 +++++++++++
+ 8 files changed, 306 insertions(+)
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/Makefile
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/config.mk
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/fel_utils.S
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/start.c
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/timer.c
+ create mode 100644 arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
+
+diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
+index b051025bb0..5b709a216e 100644
+--- a/arch/arm/cpu/arm926ejs/Makefile
++++ b/arch/arm/cpu/arm926ejs/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_MX25) += mx25/
+ obj-$(CONFIG_MX27) += mx27/
+ obj-$(if $(filter mxs,$(SOC)),y) += mxs/
+ obj-$(if $(filter spear,$(SOC)),y) += spear/
++obj-$(CONFIG_ARCH_SUNXI) += sunxi/
+
+ # some files can only build in ARM or THUMB2, not THUMB1
+
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/Makefile b/arch/arm/cpu/arm926ejs/sunxi/Makefile
+new file mode 100644
+index 0000000000..61b9864f6a
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/Makefile
+@@ -0,0 +1,16 @@
++#
++# (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
++#
++# Based on some other Makefile
++# (C) Copyright 2000-2003
++# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++#
++# SPDX-License-Identifier: GPL-2.0+
++#
++obj-y += timer.o
++obj-y += lowlevel_init.o
++
++ifdef CONFIG_SPL_BUILD
++obj-y += fel_utils.o
++CFLAGS_fel_utils.o := -marm
++endif
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/config.mk b/arch/arm/cpu/arm926ejs/sunxi/config.mk
+new file mode 100644
+index 0000000000..76ffec9df6
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/config.mk
+@@ -0,0 +1,6 @@
++# Build a combined spl + u-boot image
++ifdef CONFIG_SPL
++ifndef CONFIG_SPL_BUILD
++ALL-y += u-boot-sunxi-with-spl.bin
++endif
++endif
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S b/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S
+new file mode 100644
+index 0000000000..ca91377008
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S
+@@ -0,0 +1,38 @@
++/*
++ * Utility functions for FEL mode.
++ *
++ * Copyright (c) 2015 Google, Inc
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#include <asm-offsets.h>
++#include <config.h>
++#include <asm/system.h>
++#include <linux/linkage.h>
++
++ENTRY(save_boot_params)
++ ldr r0, =fel_stash
++ str sp, [r0, #0]
++ str lr, [r0, #4]
++ mrs lr, cpsr @ Read CPSR
++ str lr, [r0, #8]
++ mrc p15, 0, lr, c1, c0, 0 @ Read CP15 SCTLR Register
++ str lr, [r0, #12]
++ mrc p15, 0, lr, c1, c0, 0 @ Read CP15 Control Register
++ str lr, [r0, #16]
++ b save_boot_params_ret
++ENDPROC(save_boot_params)
++
++ENTRY(return_to_fel)
++ mov sp, r0
++ mov lr, r1
++ ldr r0, =fel_stash
++ ldr r1, [r0, #16]
++ mcr p15, 0, r1, c1, c0, 0 @ Write CP15 Control Register
++ ldr r1, [r0, #12]
++ mcr p15, 0, r1, c1, c0, 0 @ Write CP15 SCTLR Register
++ ldr r1, [r0, #8]
++ msr cpsr, r1 @ Write CPSR
++ bx lr
++ENDPROC(return_to_fel)
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S b/arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S
+new file mode 100644
+index 0000000000..2bfd907026
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S
+@@ -0,0 +1,68 @@
++/*
++ * A lowlevel_init function that sets up the stack to call a C function to
++ * perform further init.
++ *
++ * Based on lowlevel_init.S in armv7 directory, which is:
++ * (C) Copyright 2010 Texas Instruments, <www.ti.com>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#include <asm-offsets.h>
++#include <config.h>
++#include <linux/linkage.h>
++
++.pushsection .text.s_init, "ax"
++WEAK(s_init)
++ bx lr
++ENDPROC(s_init)
++.popsection
++
++.pushsection .text.lowlevel_init, "ax"
++WEAK(lowlevel_init)
++ /*
++ * Setup a temporary stack. Global data is not available yet.
++ */
++#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
++ ldr sp, =CONFIG_SPL_STACK
++#else
++ ldr sp, =CONFIG_SYS_INIT_SP_ADDR
++#endif
++ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
++#ifdef CONFIG_SPL_DM
++ mov r9, #0
++#else
++ /*
++ * Set up global data for boards that still need it. This will be
++ * removed soon.
++ */
++#ifdef CONFIG_SPL_BUILD
++ ldr r9, =gdata
++#else
++ sub sp, sp, #GD_SIZE
++ bic sp, sp, #7
++ mov r9, sp
++#endif
++#endif
++ /*
++ * Save the old lr(passed in ip) and the current lr to stack
++ */
++ push {ip, lr}
++
++ /*
++ * Call the very early init function. This should do only the
++ * absolute bare minimum to get started. It should not:
++ *
++ * - set up DRAM
++ * - use global_data
++ * - clear BSS
++ * - try to start a console
++ *
++ * For boards with SPL this should be empty since SPL can do all of
++ * this init in the SPL board_init_f() function which is called
++ * immediately after this.
++ */
++ bl s_init
++ pop {ip, pc}
++ENDPROC(lowlevel_init)
++.popsection
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/start.c b/arch/arm/cpu/arm926ejs/sunxi/start.c
+new file mode 100644
+index 0000000000..6b392fa835
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/start.c
+@@ -0,0 +1 @@
++/* Intentionally empty. Only needed to get FEL SPL link line right */
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/timer.c b/arch/arm/cpu/arm926ejs/sunxi/timer.c
+new file mode 100644
+index 0000000000..36263896d8
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/timer.c
+@@ -0,0 +1,113 @@
++/*
++ * (C) Copyright 2007-2011
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ * Tom Cubie <tangliang@allwinnertech.com>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#include <common.h>
++#include <asm/io.h>
++#include <asm/arch/timer.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#define TIMER_MODE (0x0 << 7) /* continuous mode */
++#define TIMER_DIV (0x0 << 4) /* pre scale 1 */
++#define TIMER_SRC (0x1 << 2) /* osc24m */
++#define TIMER_RELOAD (0x1 << 1) /* reload internal value */
++#define TIMER_EN (0x1 << 0) /* enable timer */
++
++#define TIMER_CLOCK (24 * 1000 * 1000)
++#define COUNT_TO_USEC(x) ((x) / 24)
++#define USEC_TO_COUNT(x) ((x) * 24)
++#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ)
++#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ)
++
++#define TIMER_LOAD_VAL 0xffffffff
++
++#define TIMER_NUM 0 /* we use timer 0 */
++
++/* read the 32-bit timer */
++static ulong read_timer(void)
++{
++ struct sunxi_timer_reg *timers =
++ (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
++ struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
++
++ /*
++ * The hardware timer counts down, therefore we invert to
++ * produce an incrementing timer.
++ */
++ return ~readl(&timer->val);
++}
++
++/* init timer register */
++int timer_init(void)
++{
++ struct sunxi_timer_reg *timers =
++ (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
++ struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
++ writel(TIMER_LOAD_VAL, &timer->inter);
++ writel(TIMER_MODE | TIMER_DIV | TIMER_SRC | TIMER_RELOAD | TIMER_EN,
++ &timer->ctl);
++
++ return 0;
++}
++
++/* timer without interrupts */
++ulong get_timer(ulong base)
++{
++ return get_timer_masked() - base;
++}
++
++ulong get_timer_masked(void)
++{
++ /* current tick value */
++ ulong now = TICKS_TO_HZ(read_timer());
++
++ if (now >= gd->arch.lastinc) /* normal (non rollover) */
++ gd->arch.tbl += (now - gd->arch.lastinc);
++ else {
++ /* rollover */
++ gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL)
++ - gd->arch.lastinc) + now;
++ }
++ gd->arch.lastinc = now;
++
++ return gd->arch.tbl;
++}
++
++/* delay x useconds */
++void __udelay(unsigned long usec)
++{
++ long tmo = USEC_TO_COUNT(usec);
++ ulong now, last = read_timer();
++
++ while (tmo > 0) {
++ now = read_timer();
++ if (now > last) /* normal (non rollover) */
++ tmo -= now - last;
++ else /* rollover */
++ tmo -= TIMER_LOAD_VAL - last + now;
++ last = now;
++ }
++}
++
++/*
++ * This function is derived from PowerPC code (read timebase as long long).
++ * On ARM it just returns the timer value.
++ */
++unsigned long long get_ticks(void)
++{
++ return get_timer(0);
++}
++
++/*
++ * This function is derived from PowerPC code (timebase clock frequency).
++ * On ARM it returns the number of timer ticks per second.
++ */
++ulong get_tbclk(void)
++{
++ return CONFIG_SYS_HZ;
++}
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
+new file mode 100644
+index 0000000000..1b667807db
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
+@@ -0,0 +1,63 @@
++/*
++ * (C) Copyright 2018
++ * Icenowy Zheng <icenowy@aosc.io>
++ *
++ * Based on arch/arm/cpu/armv7/sunxi/u-boot-spl.lds:
++ *
++ * (C) Copyright 2012
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ * Tom Cubie <tangliang@allwinnertech.com>
++ *
++ * Based on omap-common/u-boot-spl.lds:
++ *
++ * (C) Copyright 2002
++ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
++ *
++ * (C) Copyright 2010
++ * Texas Instruments, <www.ti.com>
++ * Aneesh V <aneesh@ti.com>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
++ LENGTH = CONFIG_SPL_MAX_SIZE }
++MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
++ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
++
++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
++OUTPUT_ARCH(arm)
++ENTRY(_start)
++SECTIONS
++{
++ .text :
++ {
++ __start = .;
++ *(.vectors)
++ arch/arm/cpu/arm926ejs/start.o (.text)
++ *(.text*)
++ } > .sram
++
++ . = ALIGN(4);
++ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
++
++ . = ALIGN(4);
++ .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
++
++ . = ALIGN(4);
++ .u_boot_list : {
++ KEEP(*(SORT(.u_boot_list*)));
++ } > .sram
++
++ . = ALIGN(4);
++ __image_copy_end = .;
++ _end = .;
++
++ .bss :
++ {
++ . = ALIGN(4);
++ __bss_start = .;
++ *(.bss*)
++ . = ALIGN(4);
++ __bss_end = .;
++ } > .sdram
++}
+--
+2.20.1
+
--- /dev/null
+From a2800766ac52b835fa2dcf6fad395cf42f32ae69 Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Thu, 18 Jan 2018 23:18:57 +0800
+Subject: [PATCH 03/29] sunxi: add support for suniv architecture
+
+Add support for the suniv architecture, which is newer ARM9 SoCs by
+Allwinner. The design of it seems to be a mixture of sun3i, sun4i and
+sun6i.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/dts/suniv-f1c100s.dtsi | 6 +
+ arch/arm/dts/suniv.dtsi | 183 +++++++
+ arch/arm/include/asm/arch-sunxi/clock.h | 2 +-
+ arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 21 +
+ arch/arm/include/asm/arch-sunxi/cpu_sun4i.h | 8 +
+ arch/arm/include/asm/arch-sunxi/dram.h | 2 +
+ arch/arm/include/asm/arch-sunxi/dram_suniv.h | 47 ++
+ arch/arm/include/asm/arch-sunxi/gpio.h | 1 +
+ arch/arm/mach-sunxi/Kconfig | 14 +-
+ arch/arm/mach-sunxi/Makefile | 2 +
+ arch/arm/mach-sunxi/board.c | 7 +-
+ arch/arm/mach-sunxi/clock.c | 3 +-
+ arch/arm/mach-sunxi/clock_sun6i.c | 47 +-
+ arch/arm/mach-sunxi/cpu_info.c | 2 +
+ arch/arm/mach-sunxi/dram_helpers.c | 4 +
+ arch/arm/mach-sunxi/dram_suniv.c | 496 ++++++++++++++++++
+ board/sunxi/board.c | 4 +-
+ include/configs/suniv.h | 17 +
+ include/configs/sunxi-common.h | 64 ++-
+ include/dt-bindings/clock/suniv-ccu.h | 69 +++
+ include/dt-bindings/reset/suniv-ccu.h | 37 ++
+ 21 files changed, 1011 insertions(+), 25 deletions(-)
+ create mode 100644 arch/arm/dts/suniv-f1c100s.dtsi
+ create mode 100644 arch/arm/dts/suniv.dtsi
+ create mode 100644 arch/arm/include/asm/arch-sunxi/dram_suniv.h
+ create mode 100644 arch/arm/mach-sunxi/dram_suniv.c
+ create mode 100644 include/configs/suniv.h
+ create mode 100644 include/dt-bindings/clock/suniv-ccu.h
+ create mode 100644 include/dt-bindings/reset/suniv-ccu.h
+
+diff --git a/arch/arm/dts/suniv-f1c100s.dtsi b/arch/arm/dts/suniv-f1c100s.dtsi
+new file mode 100644
+index 0000000000..f084bc8dd1
+--- /dev/null
++++ b/arch/arm/dts/suniv-f1c100s.dtsi
+@@ -0,0 +1,6 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR X11)
++/*
++ * Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
++ */
++
++#include "suniv.dtsi"
+diff --git a/arch/arm/dts/suniv.dtsi b/arch/arm/dts/suniv.dtsi
+new file mode 100644
+index 0000000000..5bca082d2e
+--- /dev/null
++++ b/arch/arm/dts/suniv.dtsi
+@@ -0,0 +1,183 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR X11)
++/*
++ * Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
++ */
++
++#include <dt-bindings/clock/suniv-ccu.h>
++#include <dt-bindings/reset/suniv-ccu.h>
++
++/ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ interrupt-parent = <&intc>;
++
++ clocks {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ osc24M: clk-24M {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <24000000>;
++ clock-output-names = "osc24M";
++ };
++
++ osc32k: clk-32k {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <32768>;
++ clock-output-names = "osc32k";
++ };
++
++ fake100M: clk-100M {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <100000000>;
++ clock-output-names = "fake-100M";
++ };
++ };
++
++ cpus {
++ #address-cells = <0>;
++ #size-cells = <0>;
++
++ cpu {
++ compatible = "arm,arm926ej-s";
++ device_type = "cpu";
++ };
++ };
++
++ soc {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ sram-controller@1c00000 {
++ compatible = "allwinner,sun4i-a10-sram-controller";
++ reg = <0x01c00000 0x30>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ sram_d: sram@10000 {
++ compatible = "mmio-sram";
++ reg = <0x00010000 0x1000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0 0x00010000 0x1000>;
++
++ otg_sram: sram-section@0 {
++ compatible = "allwinner,sun4i-a10-sram-d";
++ reg = <0x0000 0x1000>;
++ status = "disabled";
++ };
++ };
++ };
++
++ ccu: clock@1c20000 {
++ compatible = "allwinner,suniv-ccu";
++ reg = <0x01c20000 0x400>;
++ clocks = <&osc24M>, <&osc32k>;
++ clock-names = "hosc", "losc";
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ };
++
++ intc: interrupt-controller@1c20400 {
++ compatible = "allwinner,suniv-ic";
++ reg = <0x01c20400 0x400>;
++ interrupt-controller;
++ #interrupt-cells = <1>;
++ };
++
++ pio: pinctrl@1c20800 {
++ compatible = "allwinner,suniv-pinctrl";
++ reg = <0x01c20800 0x400>;
++ interrupts = <38>, <39>, <40>;
++ clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
++ clock-names = "apb", "hosc", "losc";
++ gpio-controller;
++ interrupt-controller;
++ #interrupt-cells = <3>;
++ #gpio-cells = <3>;
++
++ uart0_pins_a: uart-pins-pe {
++ pins = "PE0", "PE1";
++ function = "uart0";
++ };
++ };
++
++ timer@1c20c00 {
++ compatible = "allwinner,sun4i-a10-timer";
++ reg = <0x01c20c00 0x90>;
++ interrupts = <13>;
++ clocks = <&osc24M>;
++ };
++
++ wdt: watchdog@1c20ca0 {
++ compatible = "allwinner,sun6i-a31-wdt";
++ reg = <0x01c20ca0 0x20>;
++ };
++
++ uart0: serial@1c25000 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x01c25000 0x400>;
++ interrupts = <1>;
++ reg-shift = <2>;
++ reg-io-width = <4>;
++ clocks = <&ccu CLK_BUS_UART0>;
++ resets = <&ccu RST_BUS_UART0>;
++ status = "disabled";
++ };
++
++ uart1: serial@1c25400 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x01c25400 0x400>;
++ interrupts = <2>;
++ reg-shift = <2>;
++ reg-io-width = <4>;
++ clocks = <&ccu CLK_BUS_UART1>;
++ resets = <&ccu RST_BUS_UART1>;
++ status = "disabled";
++ };
++
++ uart2: serial@1c25800 {
++ compatible = "snps,dw-apb-uart";
++ reg = <0x01c25800 0x400>;
++ interrupts = <3>;
++ reg-shift = <2>;
++ reg-io-width = <4>;
++ clocks = <&ccu CLK_BUS_UART2>;
++ resets = <&ccu RST_BUS_UART2>;
++ status = "disabled";
++ };
++
++ usb_otg: usb@1c13000 {
++ compatible = "allwinner,suniv-musb";
++ reg = <0x01c13000 0x0400>;
++ clocks = <&ccu CLK_BUS_OTG>;
++ resets = <&ccu RST_BUS_OTG>;
++ interrupts = <26>;
++ interrupt-names = "mc";
++ phys = <&usbphy 0>;
++ phy-names = "usb";
++ extcon = <&usbphy 0>;
++ allwinner,sram = <&otg_sram 1>;
++ status = "disabled";
++ };
++
++ usbphy: phy@1c13400 {
++ compatible = "allwinner,suniv-usb-phy";
++ reg = <0x01c13400 0x10>;
++ reg-names = "phy_ctrl";
++ clocks = <&ccu CLK_USB_PHY0>;
++ clock-names = "usb0_phy";
++ resets = <&ccu RST_USB_PHY0>;
++ reset-names = "usb0_reset";
++ #phy-cells = <1>;
++ status = "disabled";
++ };
++ };
++};
+diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
+index 5994130e6b..97b45d34ba 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock.h
++++ b/arch/arm/include/asm/arch-sunxi/clock.h
+@@ -19,7 +19,7 @@
+ #elif defined(CONFIG_MACH_SUN50I_H6)
+ #include <asm/arch/clock_sun50i_h6.h>
+ #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
+- defined(CONFIG_MACH_SUN50I)
++ defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
+ #include <asm/arch/clock_sun6i.h>
+ #elif defined(CONFIG_MACH_SUN9I)
+ #include <asm/arch/clock_sun9i.h>
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+index ee387127f3..0d6168c430 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+@@ -168,6 +168,14 @@ struct sunxi_ccm_reg {
+ u32 pll_lock_ctrl; /* 0x320 PLL lock control, R40 only */
+ };
+
++/* apb1 bit field */
++#ifdef CONFIG_MACH_SUNIV
++#define APB1_GATE_UART_SHIFT (20)
++#define APB1_GATE_UART_MASK (0x7 << APB1_GATE_UART_SHIFT)
++#define APB1_GATE_TWI_SHIFT (16)
++#define APB1_GATE_TWI_MASK (0x7 << APB1_GATE_TWI_SHIFT)
++#endif
++
+ /* apb2 bit field */
+ #define APB2_CLK_SRC_LOSC (0x0 << 24)
+ #define APB2_CLK_SRC_OSC24M (0x1 << 24)
+@@ -226,7 +234,12 @@ struct sunxi_ccm_reg {
+ #define CCM_PLL5_CTRL_SIGMA_DELTA_EN (0x1 << 24)
+ #define CCM_PLL5_CTRL_EN (0x1 << 31)
+
++#if !defined(CONFIG_MACH_SUNIV)
+ #define PLL6_CFG_DEFAULT 0x90041811 /* 600 MHz */
++#else
++/* suniv pll6 doesn't have postdiv 2, so k is set to 0 */
++#define PLL6_CFG_DEFAULT 0x90041800
++#endif
+
+ #define CCM_PLL6_CTRL_N_SHIFT 8
+ #define CCM_PLL6_CTRL_N_MASK (0x1f << CCM_PLL6_CTRL_N_SHIFT)
+@@ -488,6 +501,14 @@ struct sunxi_ccm_reg {
+ #define AHB_RESET_OFFSET_EPHY 2
+ #define AHB_RESET_OFFSET_LVDS 0
+
++/* apb1 reset */
++#ifdef CONFIG_MACH_SUNIV
++#define APB1_RESET_UART_SHIFT (20)
++#define APB1_RESET_UART_MASK (0x7 << APB1_RESET_UART_SHIFT)
++#define APB1_RESET_TWI_SHIFT (16)
++#define APB1_RESET_TWI_MASK (0x7 << APB1_RESET_TWI_SHIFT)
++#endif
++
+ /* apb2 reset */
+ #define APB2_RESET_UART_SHIFT (16)
+ #define APB2_RESET_UART_MASK (0xff << APB2_RESET_UART_SHIFT)
+diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+index 02ce73954d..bfc5a7692a 100644
+--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
++++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+@@ -111,6 +111,12 @@ defined(CONFIG_MACH_SUN50I)
+
+ #define SUNXI_SJTAG_BASE 0x01c23c00
+
++#ifdef CONFIG_MACH_SUNIV
++#define SUNXI_UART0_BASE 0x01c25000
++#define SUNXI_UART1_BASE 0x01c25400
++#define SUNXI_UART2_BASE 0x01c25800
++#endif
++
+ #define SUNXI_TP_BASE 0x01c25000
+ #define SUNXI_PMU_BASE 0x01c25400
+
+@@ -118,9 +124,11 @@ defined(CONFIG_MACH_SUN50I)
+ #define SUNXI_CPUCFG_BASE 0x01c25c00
+ #endif
+
++#ifndef CONFIG_MACH_SUNIV
+ #define SUNXI_UART0_BASE 0x01c28000
+ #define SUNXI_UART1_BASE 0x01c28400
+ #define SUNXI_UART2_BASE 0x01c28800
++#endif
+ #define SUNXI_UART3_BASE 0x01c28c00
+ #define SUNXI_UART4_BASE 0x01c29000
+ #define SUNXI_UART5_BASE 0x01c29400
+diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
+index 8002b7efdc..523dd71cc9 100644
+--- a/arch/arm/include/asm/arch-sunxi/dram.h
++++ b/arch/arm/include/asm/arch-sunxi/dram.h
+@@ -29,6 +29,8 @@
+ #include <asm/arch/dram_sun9i.h>
+ #elif defined(CONFIG_MACH_SUN50I_H6)
+ #include <asm/arch/dram_sun50i_h6.h>
++#elif defined(CONFIG_MACH_SUNIV)
++#include <asm/arch/dram_suniv.h>
+ #else
+ #include <asm/arch/dram_sun4i.h>
+ #endif
+diff --git a/arch/arm/include/asm/arch-sunxi/dram_suniv.h b/arch/arm/include/asm/arch-sunxi/dram_suniv.h
+new file mode 100644
+index 0000000000..088eb5b9eb
+--- /dev/null
++++ b/arch/arm/include/asm/arch-sunxi/dram_suniv.h
+@@ -0,0 +1,47 @@
++/*
++ * suniv DRAM controller register definition
++ *
++ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
++ *
++ * Based on xboot's arch/arm32/mach-f1c100s/sys-dram.c, which is:
++ *
++ * Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#define PIO_SDRAM_DRV (0x2c0)
++#define PIO_SDRAM_PULL (0x2c4)
++
++#define DRAM_SCONR (0x00)
++#define DRAM_STMG0R (0x04)
++#define DRAM_STMG1R (0x08)
++#define DRAM_SCTLR (0x0c)
++#define DRAM_SREFR (0x10)
++#define DRAM_SEXTMR (0x14)
++#define DRAM_DDLYR (0x24)
++#define DRAM_DADRR (0x28)
++#define DRAM_DVALR (0x2c)
++#define DRAM_DRPTR0 (0x30)
++#define DRAM_DRPTR1 (0x34)
++#define DRAM_DRPTR2 (0x38)
++#define DRAM_DRPTR3 (0x3c)
++#define DRAM_SEFR (0x40)
++#define DRAM_MAE (0x44)
++#define DRAM_ASPR (0x48)
++#define DRAM_SDLY0 (0x4C)
++#define DRAM_SDLY1 (0x50)
++#define DRAM_SDLY2 (0x54)
++#define DRAM_MCR0 (0x100)
++#define DRAM_MCR1 (0x104)
++#define DRAM_MCR2 (0x108)
++#define DRAM_MCR3 (0x10c)
++#define DRAM_MCR4 (0x110)
++#define DRAM_MCR5 (0x114)
++#define DRAM_MCR6 (0x118)
++#define DRAM_MCR7 (0x11c)
++#define DRAM_MCR8 (0x120)
++#define DRAM_MCR9 (0x124)
++#define DRAM_MCR10 (0x128)
++#define DRAM_MCR11 (0x12c)
++#define DRAM_BWCR (0x140)
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
+index a646ea6a3c..88018ae568 100644
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -177,6 +177,7 @@ enum sunxi_gpio_number {
+ #define SUNXI_GPD_LVDS0 3
+ #define SUNXI_GPD_PWM 2
+
++#define SUNIV_GPE_UART0 5
+ #define SUN5I_GPE_SDC2 3
+ #define SUN8I_GPE_TWI2 3
+ #define SUN50I_GPE_TWI2 3
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index 16d41b83af..8a9258b32d 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -1,7 +1,8 @@
+ if ARCH_SUNXI
+
+ config SPL_LDSCRIPT
+- default "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" if !ARM64
++ default "arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds" if MACH_SUNIV
++ default "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" if !ARM64 && !MACH_SUNIV
+
+ config IDENT_STRING
+ default " Allwinner Technology"
+@@ -150,6 +151,12 @@ choice
+ prompt "Sunxi SoC Variant"
+ optional
+
++config MACH_SUNIV
++ bool "suniv (Allwinner F1C100s/F1C200s/F1C600/R6)"
++ select CPU_ARM926EJS
++ select SUNXI_GEN_SUN6I
++ select SUPPORT_SPL
++
+ config MACH_SUN4I
+ bool "sun4i (Allwinner A10)"
+ select CPU_V7A
+@@ -533,6 +540,7 @@ config DRAM_ODT_CORRECTION
+ endif
+
+ config SYS_CLK_FREQ
++ default 408000000 if MACH_SUNIV
+ default 1008000000 if MACH_SUN4I
+ default 1008000000 if MACH_SUN5I
+ default 1008000000 if MACH_SUN6I
+@@ -543,6 +551,7 @@ config SYS_CLK_FREQ
+ default 888000000 if MACH_SUN50I_H6
+
+ config SYS_CONFIG_NAME
++ default "suniv" if MACH_SUNIV
+ default "sun4i" if MACH_SUN4I
+ default "sun5i" if MACH_SUN5I
+ default "sun6i" if MACH_SUN6I
+@@ -767,7 +776,7 @@ config VIDEO_SUNXI
+
+ config VIDEO_HDMI
+ bool "HDMI output support"
+- depends on VIDEO_SUNXI && !MACH_SUN8I
++ depends on VIDEO_SUNXI && !MACH_SUN8I && !MACH_SUNIV
+ default y
+ ---help---
+ Say Y here to add support for outputting video over HDMI.
+@@ -982,6 +991,7 @@ config GMAC_TX_DELAY
+ Set the GMAC Transmit Clock Delay Chain value.
+
+ config SPL_STACK_R_ADDR
++ default 0x81e00000 if MACH_SUNIV
+ default 0x4fe00000 if MACH_SUN4I
+ default 0x4fe00000 if MACH_SUN5I
+ default 0x4fe00000 if MACH_SUN6I
+diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
+index d129f33479..5fca0073f3 100644
+--- a/arch/arm/mach-sunxi/Makefile
++++ b/arch/arm/mach-sunxi/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_SUN6I_P2WI) += p2wi.o
+ obj-$(CONFIG_SUN6I_PRCM) += prcm.o
+ obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o
+ obj-$(CONFIG_SUN8I_RSB) += rsb.o
++obj-$(CONFIG_MACH_SUNIV) += clock_sun6i.o
+ obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o
+ obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o
+ obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o
+@@ -29,6 +30,7 @@ obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
+ obj-$(CONFIG_MACH_SUN50I_H6) += clock_sun50i_h6.o
+
+ ifdef CONFIG_SPL_BUILD
++obj-$(CONFIG_MACH_SUNIV) += dram_suniv.o
+ obj-$(CONFIG_DRAM_SUN4I) += dram_sun4i.o
+ obj-$(CONFIG_DRAM_SUN6I) += dram_sun6i.o
+ obj-$(CONFIG_DRAM_SUN8I_A23) += dram_sun8i_a23.o
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index aa1d2230c9..35cd16bb44 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -83,6 +83,10 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUNXI_GPF_UART0);
+ #endif
+ sunxi_gpio_set_pull(SUNXI_GPF(4), 1);
++#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUNIV)
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(0), SUNIV_GPE_UART0);
++ sunxi_gpio_set_cfgpin(SUNXI_GPE(1), SUNIV_GPE_UART0);
++ sunxi_gpio_set_pull(SUNXI_GPE(1), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 1 && (defined(CONFIG_MACH_SUN4I) || \
+ defined(CONFIG_MACH_SUN7I) || \
+ defined(CONFIG_MACH_SUN8I_R40))
+@@ -199,7 +203,8 @@ void s_init(void)
+ /* No H3 BSP, boot0 seems to not modify SUNXI_SRAMC_BASE + 0x44 */
+ #endif
+
+-#if !defined(CONFIG_ARM_CORTEX_CPU_IS_UP) && !defined(CONFIG_ARM64)
++#if !defined(CONFIG_ARM_CORTEX_CPU_IS_UP) && !defined(CONFIG_ARM64) && \
++ !defined(CONFIG_MACH_SUNIV)
+ /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
+ asm volatile(
+ "mrc p15, 0, r0, c1, c0, 1\n"
+diff --git a/arch/arm/mach-sunxi/clock.c b/arch/arm/mach-sunxi/clock.c
+index f591affebf..636b3b6b02 100644
+--- a/arch/arm/mach-sunxi/clock.c
++++ b/arch/arm/mach-sunxi/clock.c
+@@ -36,7 +36,8 @@ int clock_init(void)
+ }
+
+ /* These functions are shared between various SoCs so put them here. */
+-#if defined CONFIG_SUNXI_GEN_SUN6I && !defined CONFIG_MACH_SUN9I
++#if defined CONFIG_SUNXI_GEN_SUN6I && !defined CONFIG_MACH_SUN9I && \
++ !defined CONFIG_MACH_SUNIV
+ int clock_twi_onoff(int port, int state)
+ {
+ struct sunxi_ccm_reg *const ccm =
+diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
+index 6ca38f73d9..64b2d54d71 100644
+--- a/arch/arm/mach-sunxi/clock_sun6i.c
++++ b/arch/arm/mach-sunxi/clock_sun6i.c
+@@ -21,7 +21,8 @@ void clock_init_safe(void)
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+-#if !defined(CONFIG_MACH_SUNXI_H3_H5) && !defined(CONFIG_MACH_SUN50I)
++#if !defined(CONFIG_MACH_SUNXI_H3_H5) && !defined(CONFIG_MACH_SUN50I) && \
++ !defined(CONFIG_MACH_SUNIV)
+ struct sunxi_prcm_reg * const prcm =
+ (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
+@@ -47,9 +48,11 @@ void clock_init_safe(void)
+
+ writel(AHB1_ABP1_DIV_DEFAULT, &ccm->ahb1_apb1_div);
+
++#ifndef CONFIG_MACH_SUNIV
+ writel(MBUS_CLK_DEFAULT, &ccm->mbus0_clk_cfg);
+ if (IS_ENABLED(CONFIG_MACH_SUN6I))
+ writel(MBUS_CLK_DEFAULT, &ccm->mbus1_clk_cfg);
++#endif
+
+ #if defined(CONFIG_MACH_SUN8I_R40) && defined(CONFIG_SUNXI_AHCI)
+ setbits_le32(&ccm->sata_pll_cfg, CCM_SATA_PLL_DEFAULT);
+@@ -85,6 +88,7 @@ void clock_init_uart(void)
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
++#ifndef CONFIG_MACH_SUNIV
+ /* uart clock source is apb2 */
+ writel(APB2_CLK_SRC_OSC24M|
+ APB2_CLK_RATE_N_1|
+@@ -100,6 +104,24 @@ void clock_init_uart(void)
+ setbits_le32(&ccm->apb2_reset_cfg,
+ 1 << (APB2_RESET_UART_SHIFT +
+ CONFIG_CONS_INDEX - 1));
++#else
++ /* suniv doesn't have apb2, so uart clock source is apb1 */
++ writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg);
++ while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_CTRL_LOCK))
++ ;
++
++ writel(AHB1_ABP1_DIV_DEFAULT, &ccm->ahb1_apb1_div);
++
++ /* open the clock for uart */
++ setbits_le32(&ccm->apb1_gate,
++ CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT +
++ CONFIG_CONS_INDEX - 1));
++
++ /* deassert uart reset */
++ setbits_le32(&ccm->apb1_reset_cfg,
++ 1 << (APB1_RESET_UART_SHIFT +
++ CONFIG_CONS_INDEX - 1));
++#endif
+ #else
+ /* enable R_PIO and R_UART clocks, and de-assert resets */
+ prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_UART);
+@@ -123,10 +145,15 @@ void clock_set_pll1(unsigned int clk)
+ }
+
+ /* Switch to 24MHz clock while changing PLL1 */
++#ifndef CONFIG_MACH_SUNIV
+ writel(AXI_DIV_3 << AXI_DIV_SHIFT |
+ ATB_DIV_2 << ATB_DIV_SHIFT |
+ CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_axi_cfg);
++#else
++ writel(CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
++ &ccm->cpu_axi_cfg);
++#endif
+
+ /*
+ * sun6i: PLL1 rate = ((24000000 * n * k) >> 0) / m (p is ignored)
+@@ -135,13 +162,27 @@ void clock_set_pll1(unsigned int clk)
+ writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) |
+ CCM_PLL1_CTRL_N(clk / (24000000 * k / m)) |
+ CCM_PLL1_CTRL_K(k) | CCM_PLL1_CTRL_M(m), &ccm->pll1_cfg);
++#ifndef CONFIG_MACH_SUNIV
+ sdelay(200);
++#else
++ do {
++ /* ARM926EJ-S code do not have sdelay */
++ volatile int i = 200;
++
++ while (i > 0) i--;
++ } while(0);
++#endif
+
+ /* Switch CPU to PLL1 */
++#ifndef CONFIG_MACH_SUNIV
+ writel(AXI_DIV_3 << AXI_DIV_SHIFT |
+ ATB_DIV_2 << ATB_DIV_SHIFT |
+ CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_axi_cfg);
++#else
++ writel(CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
++ &ccm->cpu_axi_cfg);
++#endif
+ }
+ #endif
+
+@@ -315,7 +356,11 @@ unsigned int clock_get_pll6(void)
+ uint32_t rval = readl(&ccm->pll6_cfg);
+ int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
+ int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1;
++#ifndef CONFIG_MACH_SUNIV
+ return 24000000 * n * k / 2;
++#else
++ return 24000000 * n * k;
++#endif
+ }
+
+ unsigned int clock_get_mipi_pll(void)
+diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
+index ae4745bfec..b201df82d7 100644
+--- a/arch/arm/mach-sunxi/cpu_info.c
++++ b/arch/arm/mach-sunxi/cpu_info.c
+@@ -56,6 +56,8 @@ int print_cpuinfo(void)
+ {
+ #ifdef CONFIG_MACH_SUN4I
+ puts("CPU: Allwinner A10 (SUN4I)\n");
++#elif defined CONFIG_MACH_SUNIV
++ puts("CPU: Allwinner F Series (SUNIV)\n");
+ #elif defined CONFIG_MACH_SUN5I
+ u32 val = readl(SUNXI_SID_BASE + 0x08);
+ switch ((val >> 12) & 0xf) {
+diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
+index 520b597fcc..2c873192e6 100644
+--- a/arch/arm/mach-sunxi/dram_helpers.c
++++ b/arch/arm/mach-sunxi/dram_helpers.c
+@@ -26,7 +26,10 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val)
+
+ /*
+ * Test if memory at offset offset matches memory at begin of DRAM
++ *
++ * Note: dsb() is not available on ARMv5 in Thumb mode
+ */
++#ifndef CONFIG_MACH_SUNIV
+ bool mctl_mem_matches(u32 offset)
+ {
+ /* Try to write different values to RAM at two addresses */
+@@ -37,3 +40,4 @@ bool mctl_mem_matches(u32 offset)
+ return readl(CONFIG_SYS_SDRAM_BASE) ==
+ readl((ulong)CONFIG_SYS_SDRAM_BASE + offset);
+ }
++#endif
+diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
+new file mode 100644
+index 0000000000..40aebf6eba
+--- /dev/null
++++ b/arch/arm/mach-sunxi/dram_suniv.c
+@@ -0,0 +1,496 @@
++/*
++ * suniv DRAM initialization
++ *
++ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
++ *
++ * Based on xboot's arch/arm32/mach-f1c100s/sys-dram.c, which is:
++ *
++ * Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#include <common.h>
++#include <asm/io.h>
++#include <asm/arch/clock.h>
++#include <asm/arch/dram.h>
++#include <asm/arch/gpio.h>
++
++#define SDR_T_CAS (0x2)
++#define SDR_T_RAS (0x8)
++#define SDR_T_RCD (0x3)
++#define SDR_T_RP (0x3)
++#define SDR_T_WR (0x3)
++#define SDR_T_RFC (0xd)
++#define SDR_T_XSR (0xf9)
++#define SDR_T_RC (0xb)
++#define SDR_T_INIT (0x8)
++#define SDR_T_INIT_REF (0x7)
++#define SDR_T_WTR (0x2)
++#define SDR_T_RRD (0x2)
++#define SDR_T_XP (0x0)
++
++enum dram_type
++{
++ DRAM_TYPE_SDR = 0,
++ DRAM_TYPE_DDR = 1,
++ /* Not supported yet. */
++ DRAM_TYPE_MDDR = 2,
++};
++
++struct dram_para
++{
++ u32 size; /* dram size (unit: MByte) */
++ u32 clk; /* dram work clock (unit: MHz) */
++ u32 access_mode; /* 0: interleave mode 1: sequence mode */
++ u32 cs_num; /* dram chip count 1: one chip 2: two chip */
++ u32 ddr8_remap; /* for 8bits data width DDR 0: normal 1: 8bits */
++ enum dram_type sdr_ddr;
++ u32 bwidth; /* dram bus width */
++ u32 col_width; /* column address width */
++ u32 row_width; /* row address width */
++ u32 bank_size; /* dram bank count */
++ u32 cas; /* dram cas */
++};
++
++struct dram_para suniv_dram_para = {
++ .size = 32,
++ .clk = 156,
++ .access_mode = 1,
++ .cs_num = 1,
++ .ddr8_remap = 0,
++ .sdr_ddr = DRAM_TYPE_DDR,
++ .bwidth = 16,
++ .col_width = 10,
++ .row_width = 13,
++ .bank_size = 4,
++ .cas = 0x3,
++};
++
++static int dram_initial(void)
++{
++ unsigned int time = 0xffffff;
++
++ setbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR, 0x1);
++ while((readl(SUNXI_DRAMC_BASE + DRAM_SCTLR) & 0x1) && time--)
++ {
++ if(time == 0)
++ return 0;
++ }
++ return 1;
++}
++
++static int dram_delay_scan(void)
++{
++ unsigned int time = 0xffffff;
++
++ setbits_le32(SUNXI_DRAMC_BASE + DRAM_DDLYR, 0x1);
++ while((readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) & 0x1) && time--)
++ {
++ if(time == 0)
++ return 0;
++ }
++ return 1;
++}
++
++static void dram_set_autofresh_cycle(u32 clk)
++{
++ u32 val = 0;
++ u32 row = 0;
++ u32 temp = 0;
++
++ row = readl(SUNXI_DRAMC_BASE + DRAM_SCONR);
++ row &= 0x1e0;
++ row >>= 0x5;
++
++ if(row == 0xc)
++ {
++ if(clk >= 1000000)
++ {
++ temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
++ while(temp >= (10000000 >> 6))
++ {
++ temp -= (10000000 >> 6);
++ val++;
++ }
++ }
++ else
++ {
++ val = (clk * 499) >> 6;
++ }
++ }
++ else if(row == 0xb)
++ {
++ if(clk >= 1000000)
++ {
++ temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
++ while(temp >= (10000000 >> 7))
++ {
++ temp -= (10000000 >> 7);
++ val++;
++ }
++ }
++ else
++ {
++ val = (clk * 499) >> 5;
++ }
++ }
++ writel(val, SUNXI_DRAMC_BASE + DRAM_SREFR);
++}
++
++static int dram_para_setup(struct dram_para * para)
++{
++ u32 val = 0;
++
++ val = (para->ddr8_remap) | (0x1 << 1) |
++ ((para->bank_size >> 2) << 3) |
++ ((para->cs_num >> 1) << 4) |
++ ((para->row_width - 1) << 5) |
++ ((para->col_width - 1) << 9) |
++ ((para->sdr_ddr ? (para->bwidth >> 4) : (para->bwidth >> 5)) << 13) |
++ (para->access_mode << 15) |
++ (para->sdr_ddr << 16);
++
++ writel(val, SUNXI_DRAMC_BASE + DRAM_SCONR);
++ setbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR, 0x1 << 19);
++ return dram_initial();
++}
++
++static u32 dram_check_delay(u32 bwidth)
++{
++ u32 dsize;
++ int i,j;
++ u32 num = 0;
++ u32 dflag = 0;
++
++ dsize = ((bwidth == 16) ? 4 : 2);
++ for(i = 0; i < dsize; i++)
++ {
++ if(i == 0)
++ dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR0);
++ else if(i == 1)
++ dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR1);
++ else if(i == 2)
++ dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR2);
++ else if(i == 3)
++ dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR3);
++
++ for(j = 0; j < 32; j++)
++ {
++ if(dflag & 0x1)
++ num++;
++ dflag >>= 1;
++ }
++ }
++ return num;
++}
++
++static int sdr_readpipe_scan(void)
++{
++ u32 k = 0;
++
++ for(k = 0; k < 32; k++)
++ {
++ writel(k, CONFIG_SYS_SDRAM_BASE + 4 * k);
++ }
++ for(k = 0; k < 32; k++)
++ {
++ if(readl(CONFIG_SYS_SDRAM_BASE + 4 * k) != k)
++ return 0;
++ }
++ return 1;
++}
++
++static u32 sdr_readpipe_select(void)
++{
++ u32 value = 0;
++ u32 i = 0;
++ for(i = 0; i < 8; i++)
++ {
++ clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
++ 0x7 << 6, i << 6);
++ if(sdr_readpipe_scan())
++ {
++ value = i;
++ return value;
++ }
++ }
++ return value;
++}
++
++static u32 dram_check_type(struct dram_para * para)
++{
++ u32 times = 0;
++ int i;
++
++ for(i = 0; i < 8; i++)
++ {
++ clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
++ 0x7 << 6, i << 6);
++ dram_delay_scan();
++ if(readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) & 0x30)
++ times++;
++ }
++
++ if(times == 8)
++ {
++ para->sdr_ddr = DRAM_TYPE_SDR;
++ return 0;
++ }
++ else
++ {
++ para->sdr_ddr = DRAM_TYPE_DDR;
++ return 1;
++ }
++}
++
++static u32 dram_scan_readpipe(struct dram_para * para)
++{
++ u32 rp_best = 0, rp_val = 0;
++ u32 readpipe[8];
++ int i;
++
++ if(para->sdr_ddr == DRAM_TYPE_DDR)
++ {
++ for(i = 0; i < 8; i++)
++ {
++ clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
++ 0x7 << 6, i << 6);
++ dram_delay_scan();
++ readpipe[i] = 0;
++ if((((readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) >> 4) & 0x3) == 0x0) &&
++ (((readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) >> 4) & 0x1) == 0x0))
++ {
++ readpipe[i] = dram_check_delay(para->bwidth);
++ }
++ if(rp_val < readpipe[i])
++ {
++ rp_val = readpipe[i];
++ rp_best = i;
++ }
++ }
++ clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
++ 0x7 << 6, rp_best << 6);
++ dram_delay_scan();
++ }
++ else
++ {
++ clrbits_le32(SUNXI_DRAMC_BASE + DRAM_SCONR,
++ (0x1 << 16) | (0x3 << 13));
++ rp_best = sdr_readpipe_select();
++ clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
++ 0x7 << 6, rp_best << 6);
++ }
++ return 0;
++}
++
++static u32 dram_get_dram_size(struct dram_para * para)
++{
++ u32 colflag = 10, rowflag = 13;
++ u32 val1 = 0;
++ u32 count = 0;
++ u32 addr1, addr2;
++ int i;
++
++ para->col_width = colflag;
++ para->row_width = rowflag;
++ dram_para_setup(para);
++ dram_scan_readpipe(para);
++ for(i = 0; i < 32; i++)
++ {
++ *((u8 *)(CONFIG_SYS_SDRAM_BASE + 0x200 + i)) = 0x11;
++ *((u8 *)(CONFIG_SYS_SDRAM_BASE + 0x600 + i)) = 0x22;
++ }
++ for(i = 0; i < 32; i++)
++ {
++ val1 = *((u8 *)(CONFIG_SYS_SDRAM_BASE + 0x200 + i));
++ if(val1 == 0x22)
++ count++;
++ }
++ if(count == 32)
++ {
++ colflag = 9;
++ }
++ else
++ {
++ colflag = 10;
++ }
++ count = 0;
++ para->col_width = colflag;
++ para->row_width = rowflag;
++ dram_para_setup(para);
++ if(colflag == 10)
++ {
++ addr1 = CONFIG_SYS_SDRAM_BASE + 0x400000;
++ addr2 = CONFIG_SYS_SDRAM_BASE + 0xc00000;
++ }
++ else
++ {
++ addr1 = CONFIG_SYS_SDRAM_BASE + 0x200000;
++ addr2 = CONFIG_SYS_SDRAM_BASE + 0x600000;
++ }
++ for(i = 0; i < 32; i++)
++ {
++ *((u8 *)(addr1 + i)) = 0x33;
++ *((u8 *)(addr2 + i)) = 0x44;
++ }
++ for(i = 0; i < 32; i++)
++ {
++ val1 = *((u8 *)(addr1 + i));
++ if(val1 == 0x44)
++ {
++ count++;
++ }
++ }
++ if(count == 32)
++ {
++ rowflag = 12;
++ }
++ else
++ {
++ rowflag = 13;
++ }
++ para->col_width = colflag;
++ para->row_width = rowflag;
++ if(para->row_width != 13)
++ {
++ para->size = 16;
++ }
++ else if(para->col_width == 10)
++ {
++ para->size = 64;
++ }
++ else
++ {
++ para->size = 32;
++ }
++ dram_set_autofresh_cycle(para->clk);
++ para->access_mode = 0;
++ dram_para_setup(para);
++
++ return 0;
++}
++
++static void simple_dram_check(void)
++{
++ volatile u32 *dram = (u32*) CONFIG_SYS_SDRAM_BASE;
++ int i;
++
++ for(i = 0; i < 0x40; i++)
++ {
++ dram[i] = i;
++ }
++
++ for(i = 0; i < 0x40; i++)
++ {
++ if (dram[i] != i) {
++ printf("DRAM initialization failed: dram[0x%x] != 0x%x.", i, dram[i]);
++ while(1) {}
++ }
++ }
++
++ for(i = 0; i < 0x10000; i += 0x40)
++ {
++ dram[i] = i;
++ }
++
++ for(i = 0; i < 0x10000; i += 0x40)
++ {
++ if (dram[i] != i) {
++ printf("DRAM initialization failed: dram[0x%x] != 0x%x.", i, dram[i]);
++ while(1) {}
++ }
++ }
++}
++
++static void do_dram_init(struct dram_para * para)
++{
++ struct sunxi_ccm_reg * const ccm =
++ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
++ u32 val;
++ u8 m; /* PLL_DDR clock factor */
++
++ sunxi_gpio_set_cfgpin(SUNXI_GPB(3), 0x7);
++ udelay(5000);
++ /* TODO: dig out what's them... some analog register? */
++ if(((para->cas) >> 3) & 0x1)
++ {
++ setbits_le32(SUNXI_PIO_BASE + 0x2c4, (0x1 << 23) | (0x20 << 17));
++ }
++
++ if((para->clk >= 144) && (para->clk <= 180))
++ {
++ writel(0xaaa, SUNXI_PIO_BASE + 0x2c0);
++ }
++ if(para->clk >= 180)
++ {
++ writel(0xfff, SUNXI_PIO_BASE + 0x2c0);
++ }
++
++ if(para->cas & BIT(4))
++ {
++ writel(0xd1303333, &ccm->pll5_pattern_cfg);
++ }
++ else if(para->cas & BIT(5))
++ {
++ writel(0xcce06666, &ccm->pll5_pattern_cfg);
++ }
++ else if(para->cas & BIT(6))
++ {
++ writel(0xc8909999, &ccm->pll5_pattern_cfg);
++ }
++ else if(para->cas & BIT(7))
++ {
++ writel(0xc440cccc, &ccm->pll5_pattern_cfg);
++ }
++
++ if((para->clk) <= 96)
++ m = 2;
++ else
++ m = 1;
++
++ val = CCM_PLL5_CTRL_EN | CCM_PLL5_CTRL_UPD |
++ CCM_PLL5_CTRL_N((para->clk * 2) / (24 / m)) |
++ CCM_PLL5_CTRL_K(1) | CCM_PLL5_CTRL_M(m);
++ if(para->cas & GENMASK(7, 4))
++ {
++ val |= CCM_PLL5_CTRL_SIGMA_DELTA_EN;
++ }
++ writel(val, &ccm->pll5_cfg);
++ setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_UPD);
++ mctl_await_completion(&ccm->pll5_cfg, BIT(28), BIT(28));
++ udelay(5000);
++
++ setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_MCTL));
++ clrbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_RESET_OFFSET_MCTL));
++ udelay(50);
++ setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_RESET_OFFSET_MCTL));
++
++ clrsetbits_le32(SUNXI_PIO_BASE + 0x2c4, (1 << 16),
++ ((para->sdr_ddr == DRAM_TYPE_DDR) << 16));
++
++ val = (SDR_T_CAS << 0) | (SDR_T_RAS << 3) | (SDR_T_RCD << 7) |
++ (SDR_T_RP << 10) | (SDR_T_WR << 13) | (SDR_T_RFC << 15) |
++ (SDR_T_XSR << 19) | (SDR_T_RC << 28);
++ writel(val, SUNXI_DRAMC_BASE + DRAM_STMG0R);
++ val = (SDR_T_INIT << 0) | (SDR_T_INIT_REF << 16) | (SDR_T_WTR << 20) |
++ (SDR_T_RRD << 22) | (SDR_T_XP << 25);
++ writel(val, SUNXI_DRAMC_BASE + DRAM_STMG1R);
++ dram_para_setup(para);
++ dram_check_type(para);
++
++ clrsetbits_le32(SUNXI_PIO_BASE + 0x2c4, (1 << 16),
++ ((para->sdr_ddr == DRAM_TYPE_DDR) << 16));
++
++ dram_set_autofresh_cycle(para->clk);
++ dram_scan_readpipe(para);
++ dram_get_dram_size(para);
++ simple_dram_check();
++}
++
++unsigned long sunxi_dram_init(void)
++{
++ do_dram_init(&suniv_dram_para);
++
++ return suniv_dram_para.size * 1024 * 1024;
++}
+diff --git a/board/sunxi/board.c b/board/sunxi/board.c
+index b9450a0e36..48ef12e514 100644
+--- a/board/sunxi/board.c
++++ b/board/sunxi/board.c
+@@ -221,7 +221,7 @@ int board_init(void)
+
+ gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
+
+-#ifndef CONFIG_ARM64
++#if !defined(CONFIG_ARM64) && !defined(CONFIG_MACH_SUNIV)
+ asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
+ debug("id_pfr1: 0x%08x\n", id_pfr1);
+ /* Generic Timer Extension available? */
+@@ -248,7 +248,7 @@ int board_init(void)
+ #endif
+ }
+ }
+-#endif /* !CONFIG_ARM64 */
++#endif /* !CONFIG_ARM64 && !CONFIG_MACH_SUNIV */
+
+ ret = axp_gpio_init();
+ if (ret)
+diff --git a/include/configs/suniv.h b/include/configs/suniv.h
+new file mode 100644
+index 0000000000..e6aca3ec4b
+--- /dev/null
++++ b/include/configs/suniv.h
+@@ -0,0 +1,17 @@
++/*
++ * Configuration settings for new Allwinner F-series (suniv) CPU
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++#define CONFIG_SUNXI_USB_PHYS 1
++
++/*
++ * Include common sunxi configuration where most the settings are
++ */
++#include <configs/sunxi-common.h>
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
+index 0ef289fd64..cb427004b6 100644
+--- a/include/configs/sunxi-common.h
++++ b/include/configs/sunxi-common.h
+@@ -38,7 +38,12 @@
+ /* Serial & console */
+ #define CONFIG_SYS_NS16550_SERIAL
+ /* ns16550 reg in the low bits of cpu reg */
++#ifndef CONFIG_MACH_SUNIV
+ #define CONFIG_SYS_NS16550_CLK 24000000
++#else
++/* suniv doesn't have apb2 and uart is connected to apb1 */
++#define CONFIG_SYS_NS16550_CLK 100000000
++#endif
+ #ifndef CONFIG_DM_SERIAL
+ # define CONFIG_SYS_NS16550_REG_SIZE -4
+ # define CONFIG_SYS_NS16550_COM1 SUNXI_UART0_BASE
+@@ -67,6 +72,16 @@
+ * we get warnings if the Kconfig value mismatches. */
+ #define CONFIG_SPL_STACK_R_ADDR 0x2fe00000
+ #define CONFIG_SPL_BSS_START_ADDR 0x2ff80000
++#elif defined(CONFIG_MACH_SUNIV)
++#define SDRAM_OFFSET(x) 0x8##x
++#define CONFIG_SYS_SDRAM_BASE 0x80000000
++#define CONFIG_SYS_LOAD_ADDR 0x81000000 /* default load address */
++#define CONFIG_SYS_TEXT_BASE 0x81700000
++/* Note SPL_STACK_R_ADDR is set through Kconfig, we include it here
++ * since it needs to fit in with the other values. By also #defining it
++ * we get warnings if the Kconfig value mismatches. */
++#define CONFIG_SPL_STACK_R_ADDR 0x81e00000
++#define CONFIG_SPL_BSS_START_ADDR 0x81f80000
+ #else
+ #define SDRAM_OFFSET(x) 0x4##x
+ #define CONFIG_SYS_SDRAM_BASE 0x40000000
+@@ -144,12 +159,15 @@
+ #define CONFIG_SYS_MMC_MAX_DEVICE 4
+ #endif
+
+-#ifndef CONFIG_MACH_SUN8I_V3S
+-/* 64MB of malloc() pool */
+-#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (64 << 20))
+-#else
++#if defined(CONFIG_MACH_SUN8I_V3S)
+ /* 2MB of malloc() pool */
+ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (2 << 20))
++#elif defined(CONFIG_MACH_SUNIV)
++/* 1MB of malloc() pool */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (1 << 20))
++#else
++/* 64MB of malloc() pool */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (64 << 20))
+ #endif
+
+ /*
+@@ -301,19 +319,7 @@ extern int soft_i2c_gpio_scl;
+ #define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(FE00000))
+
+ #else
+-/*
+- * 160M RAM (256M minimum minus 64MB heap + 32MB for u-boot, stack, fb, etc.
+- * 32M uncompressed kernel, 16M compressed kernel, 1M fdt,
+- * 1M script, 1M pxe and the ramdisk at the end.
+- */
+-#ifndef CONFIG_MACH_SUN8I_V3S
+-#define BOOTM_SIZE __stringify(0xa000000)
+-#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(2000000))
+-#define FDT_ADDR_R __stringify(SDRAM_OFFSET(3000000))
+-#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(3100000))
+-#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(3200000))
+-#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(3300000))
+-#else
++#if defined(CONFIG_MACH_SUN8I_V3S)
+ /*
+ * 64M RAM minus 2MB heap + 16MB for u-boot, stack, fb, etc.
+ * 16M uncompressed kernel, 8M compressed kernel, 1M fdt,
+@@ -325,6 +331,30 @@ extern int soft_i2c_gpio_scl;
+ #define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(1900000))
+ #define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(1A00000))
+ #define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(1B00000))
++#elif defined(CONFIG_MACH_SUNIV)
++/*
++ * 32M RAM minus 1MB heap + 8MB for u-boot, stack, fb, etc.
++ * 8M uncompressed kernel, 4M compressed kernel, 512K fdt,
++ * 512K script, 512K pxe and the ramdisk at the end.
++ */
++#define BOOTM_SIZE __stringify(0x1700000)
++#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(0500000))
++#define FDT_ADDR_R __stringify(SDRAM_OFFSET(0C00000))
++#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(0C50000))
++#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(0D00000))
++#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(0D50000))
++#else
++/*
++ * 160M RAM (256M minimum minus 64MB heap + 32MB for u-boot, stack, fb, etc.
++ * 32M uncompressed kernel, 16M compressed kernel, 1M fdt,
++ * 1M script, 1M pxe and the ramdisk at the end.
++ */
++#define BOOTM_SIZE __stringify(0xa000000)
++#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(2000000))
++#define FDT_ADDR_R __stringify(SDRAM_OFFSET(3000000))
++#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(3100000))
++#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(3200000))
++#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(3300000))
+ #endif
+ #endif
+
+diff --git a/include/dt-bindings/clock/suniv-ccu.h b/include/dt-bindings/clock/suniv-ccu.h
+new file mode 100644
+index 0000000000..9c22d70b2c
+--- /dev/null
++++ b/include/dt-bindings/clock/suniv-ccu.h
+@@ -0,0 +1,69 @@
++/*
++ * Copyright (c) 2018 Icenowy Zheng <icenowy@aosc.xyz>
++ *
++ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++ */
++
++#ifndef _DT_BINDINGS_CLK_SUNIV_H_
++#define _DT_BINDINGS_CLK_SUNIV_H_
++
++#define CLK_CPU 11
++
++#define CLK_BUS_MMC0 14
++#define CLK_BUS_MMC1 15
++#define CLK_BUS_DRAM 16
++#define CLK_BUS_SPI0 17
++#define CLK_BUS_SPI1 18
++#define CLK_BUS_OTG 19
++#define CLK_BUS_VE 20
++#define CLK_BUS_LCD 21
++#define CLK_BUS_DEINTERLACE 22
++#define CLK_BUS_CSI 23
++#define CLK_BUS_TVD 24
++#define CLK_BUS_TVE 25
++#define CLK_BUS_DE_BE 26
++#define CLK_BUS_DE_FE 27
++#define CLK_BUS_CODEC 28
++#define CLK_BUS_SPDIF 29
++#define CLK_BUS_IR 30
++#define CLK_BUS_RSB 31
++#define CLK_BUS_I2S0 32
++#define CLK_BUS_I2C0 33
++#define CLK_BUS_I2C1 34
++#define CLK_BUS_I2C2 35
++#define CLK_BUS_PIO 36
++#define CLK_BUS_UART0 37
++#define CLK_BUS_UART1 38
++#define CLK_BUS_UART2 39
++
++#define CLK_MMC0 40
++#define CLK_MMC0_SAMPLE 41
++#define CLK_MMC0_OUTPUT 42
++#define CLK_MMC1 43
++#define CLK_MMC1_SAMPLE 44
++#define CLK_MMC1_OUTPUT 45
++#define CLK_I2S 46
++#define CLK_SPDIF 47
++
++#define CLK_USB_PHY0 48
++
++#define CLK_DRAM_VE 49
++#define CLK_DRAM_CSI 50
++#define CLK_DRAM_DEINTERLACE 51
++#define CLK_DRAM_TVD 52
++#define CLK_DRAM_DE_FE 53
++#define CLK_DRAM_DE_BE 54
++
++#define CLK_DE_BE 55
++#define CLK_DE_FE 56
++#define CLK_TCON 57
++#define CLK_DEINTERLACE 58
++#define CLK_TVE2_CLK 59
++#define CLK_TVE1_CLK 60
++#define CLK_TVD 61
++#define CLK_CSI 62
++#define CLK_VE 63
++#define CLK_CODEC 64
++#define CLK_AVS 65
++
++#endif
+diff --git a/include/dt-bindings/reset/suniv-ccu.h b/include/dt-bindings/reset/suniv-ccu.h
+new file mode 100644
+index 0000000000..993f6b5381
+--- /dev/null
++++ b/include/dt-bindings/reset/suniv-ccu.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.xyz>
++ *
++ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++ */
++
++#ifndef _DT_BINDINGS_RST_SUNIV_H_
++#define _DT_BINDINGS_RST_SUNIV_H_
++
++#define RST_USB_PHY0 0
++#define RST_BUS_MMC0 1
++#define RST_BUS_MMC1 2
++#define RST_BUS_DRAM 3
++#define RST_BUS_SPI0 4
++#define RST_BUS_SPI1 5
++#define RST_BUS_OTG 6
++#define RST_BUS_VE 7
++#define RST_BUS_LCD 8
++#define RST_BUS_DEINTERLACE 9
++#define RST_BUS_CSI 10
++#define RST_BUS_TVD 11
++#define RST_BUS_TVE 12
++#define RST_BUS_DE_BE 13
++#define RST_BUS_DE_FE 14
++#define RST_BUS_CODEC 15
++#define RST_BUS_SPDIF 16
++#define RST_BUS_IR 17
++#define RST_BUS_RSB 18
++#define RST_BUS_I2S0 19
++#define RST_BUS_I2C0 20
++#define RST_BUS_I2C1 21
++#define RST_BUS_I2C2 22
++#define RST_BUS_UART0 23
++#define RST_BUS_UART1 24
++#define RST_BUS_UART2 25
++
++#endif /* _DT_BINDINGS_RST_SUNIV_H_ */
+--
+2.20.1
+
--- /dev/null
+From 42174df1977bd0e1052eacd6c7094db630d15cca Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Thu, 18 Jan 2018 23:37:02 +0800
+Subject: [PATCH 04/29] sunxi: suniv: add support for Lichee Pi Nano
+
+Lichee Pi Nano is a board based on F1C100s.
+
+Add support for it.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/dts/suniv-f1c100s-licheepi-nano.dts | 43 ++++++++++++++++++++
+ configs/licheepi_nano_defconfig | 9 ++++
+ 2 files changed, 52 insertions(+)
+ create mode 100644 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+ create mode 100644 configs/licheepi_nano_defconfig
+
+diff --git a/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+new file mode 100644
+index 0000000000..d54cded8e3
+--- /dev/null
++++ b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+@@ -0,0 +1,43 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR X11)
++/*
++ * Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
++ */
++
++/dts-v1/;
++#include "suniv-f1c100s.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++ model = "Lichee Pi Nano";
++ compatible = "licheepi,licheepi-nano", "allwinner,suniv-f1c100s",
++ "allwinner,suniv";
++
++ aliases {
++ serial0 = &uart0;
++ };
++
++ chosen {
++ stdout-path = "serial0:115200n8";
++ };
++};
++
++&otg_sram {
++ status = "okay";
++};
++
++&uart0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins_a>;
++ status = "okay";
++};
++
++&usb_otg {
++ dr_mode = "otg";
++ status = "okay";
++};
++
++&usbphy {
++ usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>; /* PE2 */
++ status = "okay";
++};
+diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig
+new file mode 100644
+index 0000000000..6e455baadf
+--- /dev/null
++++ b/configs/licheepi_nano_defconfig
+@@ -0,0 +1,9 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_MACH_SUNIV=y
++CONFIG_DRAM_CLK=156
++CONFIG_DRAM_ZQ=0
++# CONFIG_VIDEO_SUNXI is not set
++CONFIG_DEFAULT_DEVICE_TREE="suniv-f1c100s-licheepi-nano"
++CONFIG_SPL=y
++# CONFIG_SPL_DM_SERIAL is not set
+--
+2.20.1
+
+--- u-boot-2019.04/arch/arm/dts/Makefile.old 2019-04-09 03:40:40.000000000 +0200
++++ u-boot-2019.04/arch/arm/dts/Makefile 2021-01-19 23:38:54.383599354 +0100
+@@ -485,6 +485,8 @@
+ sun9i-a80-optimus.dtb \
+ sun9i-a80-cubieboard4.dtb \
+ sun9i-a80-cx-a99.dtb
++dtb-$(CONFIG_MACH_SUNIV) += \
++ suniv-f1c100s-licheepi-nano.dtb
+
+ dtb-$(CONFIG_VF610) += vf500-colibri.dtb \
+ vf610-colibri.dtb \
--- /dev/null
+From 2d6e643e5d0e42dd5d6a0c56ca66c6d1055b4e8d Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Fri, 19 Jan 2018 23:26:58 +0800
+Subject: [PATCH] sunxi: suniv: add boot sequence for SPL to try
+
+The BROM of suniv do not pass the info of boot media to SPL.
+
+Add boot sequence for SPL to try again for the available boot media.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/mach-sunxi/board.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index 35cd16bb44a..d20cf2dc38f 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -271,10 +271,32 @@ uint32_t sunxi_get_boot_device(void)
+ return sector;
+ }
+
++
++#ifndef CONFIG_MACH_SUNIV
+ u32 spl_boot_device(void)
+ {
+ return sunxi_get_boot_device();
+ }
++#else
++/*
++ * suniv BROM do not pass the boot media type to SPL, so we try with the
++ * boot sequence in BROM: mmc0->spinor->fail.
++ */
++void board_boot_order(u32 *spl_boot_list)
++{
++ /*
++ * See the comments above in sunxi_get_boot_device() for infomation
++ * about FEL boot.
++ */
++ if (!is_boot0_magic(SPL_ADDR + 4)) {
++ spl_boot_list[0] = BOOT_DEVICE_BOARD;
++ return;
++ }
++
++ spl_boot_list[0] = BOOT_DEVICE_MMC1;
++ spl_boot_list[1] = BOOT_DEVICE_SPI;
++}
++#endif
+
+ void board_init_f(ulong dummy)
+ {
--- /dev/null
+From ffa272ca154c1fb1d035f102551c1fbbdce45f9f Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Fri, 19 Jan 2018 23:51:29 +0800
+Subject: [PATCH 06/29] sunxi: spi-spl: add support for SUNIV
+
+The suniv SoC come with a sun6i-style SPI controller at the base address
+of sun4i SPI controller. The module clock of the SPI controller is also
+missing.
+
+Add support for it.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+--- u-boot-2020.04/arch/arm/mach-sunxi/spl_spi_sunxi.c.orig 2020-04-13 17:02:18.000000000 +0200
++++ u-boot-2020.04/arch/arm/mach-sunxi/spl_spi_sunxi.c 2021-01-21 18:20:58.405677129 +0100
+@@ -85,6 +85,7 @@
+
+ #define SPI0_CLK_DIV_BY_2 0x1000
+ #define SPI0_CLK_DIV_BY_4 0x1001
++#define SPI0_CLK_DIV_BY_32 0x100f
+
+ /*****************************************************************************/
+
+@@ -151,11 +152,17 @@
+ if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+ setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
+
++#ifndef CONFIG_MACH_SUNIV
+ /* Divide by 4 */
+ writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ?
+ SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL));
+ /* 24MHz from OSC24M */
+ writel((1 << 31), CCM_SPI0_CLK);
++#else
++ /* Divide by 32, clock source is AHB clock 200MHz */
++ writel(SPI0_CLK_DIV_BY_32, IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ?
++ SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL);
++#endif
+
+ if (is_sun6i_gen_spi()) {
+ /* Enable SPI in the master mode and do a soft reset */
+@@ -185,8 +192,10 @@
+ clrbits_le32(base + SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
+ SUN4I_CTL_ENABLE);
+
++#ifndef CONFIG_MACH_SUNIV
+ /* Disable the SPI0 clock */
+ writel(0, CCM_SPI0_CLK);
++#endif
+
+ /* Close the SPI0 gate */
+ if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+@@ -208,6 +217,19 @@
+ IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+ pin_function = SUN50I_GPC_SPI0;
+
++ if (IS_ENABLED(CONFIG_MACH_SUNIV))
++ pin_function = SUNIV_GPC_SPI0;
++
++ /*
++ * suniv comes with a sun6i-style SPI controller at the
++ * sun4i SPI base address
++ */
++ if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) &&
++ !IS_ENABLED(CONFIG_MACH_SUNIV))
++ spi0_base = 0x01c68000;
++ else
++ spi0_base = 0x01c05000;
++
+ spi0_pinmux_setup(pin_function);
+ spi0_enable_clock();
+ }
+--- u-boot-2020.04/arch/arm/mach-sunxi/Kconfig.orig 2021-01-21 18:22:23.275147206 +0100
++++ u-boot-2020.04/arch/arm/mach-sunxi/Kconfig 2021-01-21 18:25:42.245215848 +0100
+@@ -1004,7 +1004,7 @@
+
+ config SPL_SPI_SUNXI
+ bool "Support for SPI Flash on Allwinner SoCs in SPL"
+- depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6
++ depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 || MACH_SUNIV
+ help
+ Enable support for SPI Flash. This option allows SPL to read from
+ sunxi SPI Flash. It uses the same method as the boot ROM, so does
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
+index 88018ae5689..43088e2f547 100644
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -169,6 +169,7 @@ enum sunxi_gpio_number {
+ #define SUNXI_GPC_NAND 2
+ #define SUNXI_GPC_SPI0 3
+ #define SUNXI_GPC_SDC2 3
++#define SUNIV_GPC_SPI0 2
+ #define SUN6I_GPC_SDC3 4
+ #define SUN50I_GPC_SPI0 4
+
--- /dev/null
+From 315c1010ff3861f2f3018004847f7a7f49a06c31 Mon Sep 17 00:00:00 2001
+From: "S.J.R. van Schaik" <stephan@synkhronix.com>
+Date: Fri, 10 Feb 2017 12:04:17 +0000
+Subject: [PATCH 07/29] sunxi: add missing AHB_GATE_OFFSET_SPIx defines for
+ sun6i/sun9i
+
+Added missing AHB_GATE_OFFSET_SPIx defines to enable/disable clock gating for
+SPI on the sun6i and sun9i platforms.
+
+Signed-off-by: S.J.R. van Schaik <stephan@whiteboxsystems.nl>
+---
+ arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 ++
+ arch/arm/include/asm/arch-sunxi/clock_sun9i.h | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+index 0d6168c430..6b9458f895 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+@@ -323,6 +323,8 @@ struct sunxi_ccm_reg {
+ #define AHB_GATE_OFFSET_USB0 25
+ #define AHB_GATE_OFFSET_SATA 24
+ #endif
++#define AHB_GATE_OFFSET_SPI1 21
++#define AHB_GATE_OFFSET_SPI0 20
+ #define AHB_GATE_OFFSET_MCTL 14
+ #define AHB_GATE_OFFSET_GMAC 17
+ #define AHB_GATE_OFFSET_NAND0 13
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
+index 530e0dd73b..181cb5194c 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
+@@ -194,6 +194,10 @@ struct sunxi_ccm_reg {
+
+ /* ahb gate1 field */
+ #define AHB_GATE_OFFSET_DMA 24
++#define AHB_GATE_OFFSET_SPI3 23
++#define AHB_GATE_OFFSET_SPI2 22
++#define AHB_GATE_OFFSET_SPI1 21
++#define AHB_GATE_OFFSET_SPI0 20
+
+ /* apb1_gate fields */
+ #define APB1_GATE_UART_SHIFT 16
+--
+2.20.1
+
--- /dev/null
+From 10ca61bb6b41dd7a645a3fd03717d9125cb3963f Mon Sep 17 00:00:00 2001
+From: "S.J.R. van Schaik" <stephan@synkhronix.com>
+Date: Fri, 10 Feb 2017 11:24:37 +0000
+Subject: [PATCH 08/29] sunxi: add SPI register definitions for sun4i/sun7i
+
+Introduces SPI registers for sun4i/sun7i by adding struct sunxi_spi_regs
+and flags.
+
+Signed-off-by: S.J.R. van Schaik <stephan@whiteboxsystems.nl>
+---
+ arch/arm/include/asm/arch-sunxi/spi.h | 29 +++++++++++
+ arch/arm/include/asm/arch-sunxi/spi_sun4i.h | 53 +++++++++++++++++++++
+ 2 files changed, 82 insertions(+)
+ create mode 100644 arch/arm/include/asm/arch-sunxi/spi.h
+ create mode 100644 arch/arm/include/asm/arch-sunxi/spi_sun4i.h
+
+diff --git a/arch/arm/include/asm/arch-sunxi/spi.h b/arch/arm/include/asm/arch-sunxi/spi.h
+new file mode 100644
+index 0000000000..66301b24d5
+--- /dev/null
++++ b/arch/arm/include/asm/arch-sunxi/spi.h
+@@ -0,0 +1,29 @@
++/*
++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V.
++ * S.J.R. van Schaik <stephan@whiteboxsystems.nl>
++ * M.B.W. Wajer <merlijn@whiteboxsystems.nl>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#ifndef _SUNXI_SPI_H
++#define _SUNXI_SPI_H
++
++#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
++ defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I)
++#include <asm/arch/spi_sun6i.h>
++#else
++#include <asm/arch/spi_sun4i.h>
++#endif
++
++#define SUNXI_SPI_BURST_CNT(cnt) ((cnt) & 0xffffff)
++#define SUNXI_SPI_XMIT_CNT(cnt) ((cnt) & 0xffffff)
++
++#define SUNXI_SPI_CLK_CTL_CDR2_MASK 0xff
++#define SUNXI_SPI_CLK_CTL_CDR2(div) ((div) & SUNXI_SPI_CLK_CTL_CDR2_MASK)
++#define SUNXI_SPI_CLK_CTL_CDR1_MASK 0xf
++#define SUNXI_SPI_CLK_CTL_CDR1(div) \
++ (((div) & SUNXI_SPI_CLK_CTL_CDR1_MASK) << 8)
++#define SUNXI_SPI_CLK_CTL_DRS BIT(12)
++
++#endif /* _SUNXI_SPI_H */
+diff --git a/arch/arm/include/asm/arch-sunxi/spi_sun4i.h b/arch/arm/include/asm/arch-sunxi/spi_sun4i.h
+new file mode 100644
+index 0000000000..c94519651f
+--- /dev/null
++++ b/arch/arm/include/asm/arch-sunxi/spi_sun4i.h
+@@ -0,0 +1,53 @@
++/*
++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V.
++ * S.J.R. van Schaik <stephan@whiteboxsystems.nl>
++ * M.B.W. Wajer <merlijn@whiteboxsystems.nl>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#ifndef _SUNXI_SPI_SUN4I_H
++#define _SUNXI_SPI_SUN4I_H
++
++struct sunxi_spi_regs {
++ uint32_t rx_data; /* 0x00 */
++ uint32_t tx_data; /* 0x04 */
++ union {
++ uint32_t glb_ctl;
++ uint32_t xfer_ctl;
++ uint32_t fifo_ctl;
++ uint32_t burst_ctl;
++ }; /* 0x08 */
++ uint32_t int_ctl; /* 0x0c */
++ uint32_t int_sta; /* 0x10 */
++ uint32_t dma_ctl; /* 0x14 */
++ uint32_t wait; /* 0x18 */
++ uint32_t clk_ctl; /* 0x1c */
++ uint32_t burst_cnt; /* 0x20 */
++ uint32_t xmit_cnt; /* 0x24 */
++ uint32_t fifo_sta; /* 0x28 */
++};
++
++#define SUNXI_SPI_CTL_SRST 0
++
++#define SUNXI_SPI_CTL_ENABLE BIT(0)
++#define SUNXI_SPI_CTL_MASTER BIT(1)
++#define SUNXI_SPI_CTL_CPHA BIT(2)
++#define SUNXI_SPI_CTL_CPOL BIT(3)
++#define SUNXI_SPI_CTL_CS_ACTIVE_LOW BIT(4)
++#define SUNXI_SPI_CTL_TF_RST BIT(8)
++#define SUNXI_SPI_CTL_RF_RST BIT(9)
++#define SUNXI_SPI_CTL_XCH BIT(10)
++#define SUNXI_SPI_CTL_CS_MASK 0x3000
++#define SUNXI_SPI_CTL_CS(cs) (((cs) << 12) & SUNXI_SPI_CTL_CS_MASK)
++#define SUNXI_SPI_CTL_DHB BIT(15)
++#define SUNXI_SPI_CTL_CS_MANUAL BIT(16)
++#define SUNXI_SPI_CTL_CS_LEVEL BIT(17)
++#define SUNXI_SPI_CTL_TP BIT(18)
++
++#define SUNXI_SPI_FIFO_RF_CNT_MASK 0x7f
++#define SUNXI_SPI_FIFO_RF_CNT_BITS 0
++#define SUNXI_SPI_FIFO_TF_CNT_MASK 0x7f
++#define SUNXI_SPI_FIFO_TF_CNT_BITS 16
++
++#endif /* _SUNXI_SPI_SUN4I_H */
+--
+2.20.1
+
--- /dev/null
+From f4c5f2f12c027600c3dc15f14c495e9a9449522f Mon Sep 17 00:00:00 2001
+From: "S.J.R. van Schaik" <stephan@synkhronix.com>
+Date: Fri, 10 Feb 2017 11:25:56 +0000
+Subject: [PATCH 09/29] sunxi: add SPI register definitions for
+ sun6i/sun8i/sun9i/sun50i
+
+Introduces SPI registers for sun6i/sun8i/sun9i/sun50i by adding struct
+sunxi_spi_regs and flags.
+
+Signed-off-by: S.J.R. van Schaik <stephan@whiteboxsystems.nl>
+---
+ arch/arm/include/asm/arch-sunxi/spi_sun6i.h | 56 +++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+ create mode 100644 arch/arm/include/asm/arch-sunxi/spi_sun6i.h
+
+diff --git a/arch/arm/include/asm/arch-sunxi/spi_sun6i.h b/arch/arm/include/asm/arch-sunxi/spi_sun6i.h
+new file mode 100644
+index 0000000000..d9241848f9
+--- /dev/null
++++ b/arch/arm/include/asm/arch-sunxi/spi_sun6i.h
+@@ -0,0 +1,56 @@
++/*
++ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V.
++ * S.J.R. van Schaik <stephan@whiteboxsystems.nl>
++ * M.B.W. Wajer <merlijn@whiteboxsystems.nl>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#ifndef _SUNXI_SPI_SUN6I_H
++#define _SUNXI_SPI_SUN6I_H
++
++struct sunxi_spi_regs {
++ uint32_t unused0[1];
++ uint32_t glb_ctl; /* 0x04 */
++ uint32_t xfer_ctl; /* 0x08 */
++ uint32_t unused1[1];
++ uint32_t int_ctl; /* 0x10 */
++ uint32_t int_sta; /* 0x14 */
++ uint32_t fifo_ctl; /* 0x18 */
++ uint32_t fifo_sta; /* 0x1c */
++ uint32_t wait; /* 0x20 */
++ uint32_t clk_ctl; /* 0x24 */
++ uint32_t unused2[2];
++ uint32_t burst_cnt; /* 0x30 */
++ uint32_t xmit_cnt; /* 0x34 */
++ uint32_t burst_ctl; /* 0x38 */
++ uint32_t unused3[113];
++ uint32_t tx_data; /* 0x200 */
++ uint32_t unused4[63];
++ uint32_t rx_data; /* 0x300 */
++};
++
++#define SUNXI_SPI_CTL_ENABLE BIT(0)
++#define SUNXI_SPI_CTL_MASTER BIT(1)
++#define SUNXI_SPI_CTL_TP BIT(7)
++#define SUNXI_SPI_CTL_SRST BIT(31)
++
++#define SUNXI_SPI_CTL_CPHA BIT(0)
++#define SUNXI_SPI_CTL_CPOL BIT(1)
++#define SUNXI_SPI_CTL_CS_ACTIVE_LOW BIT(2)
++#define SUNXI_SPI_CTL_CS_MASK 0x30
++#define SUNXI_SPI_CTL_CS(cs) (((cs) << 4) & SUNXI_SPI_CTL_CS_MASK)
++#define SUNXI_SPI_CTL_CS_MANUAL BIT(6)
++#define SUNXI_SPI_CTL_CS_LEVEL BIT(7)
++#define SUNXI_SPI_CTL_DHB BIT(8)
++#define SUNXI_SPI_CTL_XCH BIT(31)
++
++#define SUNXI_SPI_CTL_RF_RST BIT(15)
++#define SUNXI_SPI_CTL_TF_RST BIT(31)
++
++#define SUNXI_SPI_FIFO_RF_CNT_MASK 0x7f
++#define SUNXI_SPI_FIFO_RF_CNT_BITS 0
++#define SUNXI_SPI_FIFO_TF_CNT_MASK 0x7f
++#define SUNXI_SPI_FIFO_TF_CNT_BITS 16
++
++#endif /* _SUNXI_SPI_SUN6I_H */
+--
+2.20.1
+
--- /dev/null
+From 9a0ca4a595f8129904432b67ad1fb7ee815f3d67 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Sun, 12 Feb 2017 14:53:16 +0000
+Subject: [PATCH 10/29] introduce and use sunxi_gpio_setup_dt_pins()
+
+---
+ arch/arm/include/asm/arch-sunxi/gpio.h | 3 ++
+ arch/arm/mach-sunxi/pinmux.c | 61 ++++++++++++++++++++++++++
+ 2 files changed, 64 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
+index 43088e2f54..723c553a8c 100644
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -250,4 +250,7 @@ int axp_gpio_init(void);
+ static inline int axp_gpio_init(void) { return 0; }
+ #endif
+
++int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
++ const char * mux_name, int mux_sel);
++
+ #endif /* _SUNXI_GPIO_H */
+diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
+index 642483f06c..6ffba3910b 100644
+--- a/arch/arm/mach-sunxi/pinmux.c
++++ b/arch/arm/mach-sunxi/pinmux.c
+@@ -8,6 +8,9 @@
+ #include <common.h>
+ #include <asm/io.h>
+ #include <asm/arch/gpio.h>
++#include <fdtdec.h>
++#include <fdt_support.h>
++#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+ void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
+ {
+@@ -68,3 +71,61 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
+
+ return 0;
+ }
++
++int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
++ const char * mux_name, int mux_sel)
++{
++ int drive, pull, pin, i;
++ const char *pin_name;
++ int offset;
++
++ offset = fdtdec_lookup_phandle(fdt_blob, node, "pinctrl-0");
++ if (offset < 0)
++ return offset;
++
++ drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
++ "drive-strength", 0);
++ if (drive) {
++ if (drive <= 10)
++ drive = SUN4I_PINCTRL_10_MA;
++ else if (drive <= 20)
++ drive = SUN4I_PINCTRL_20_MA;
++ else if (drive <= 30)
++ drive = SUN4I_PINCTRL_30_MA;
++ else
++ drive = SUN4I_PINCTRL_40_MA;
++ } else {
++ drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
++ "allwinner,drive", 4);
++ }
++
++ if (fdt_get_property(fdt_blob, offset, "bias-pull-up", NULL))
++ pull = SUN4I_PINCTRL_PULL_UP;
++ else if (fdt_get_property(fdt_blob, offset, "bias-disable", NULL))
++ pull = SUN4I_PINCTRL_NO_PULL;
++ else if (fdt_get_property(fdt_blob, offset, "bias-pull-down", NULL))
++ pull = SUN4I_PINCTRL_PULL_DOWN;
++ else
++ pull = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
++ "allwinner,pull", 0);
++
++ for (i = 0; ; i++) {
++ pin_name = fdt_stringlist_get(fdt_blob, offset,
++ "allwinner,pins", i, NULL);
++ if (!pin_name) {
++ pin_name = fdt_stringlist_get(fdt_blob, offset,
++ "pins", i, NULL);
++ if (!pin_name)
++ break;
++ }
++ pin = sunxi_name_to_gpio(pin_name);
++ if (pin < 0)
++ continue;
++
++ sunxi_gpio_set_cfgpin(pin, mux_sel);
++ sunxi_gpio_set_drv(pin, drive);
++ sunxi_gpio_set_pull(pin, pull);
++ }
++
++ return i;
++}
+--
+2.20.1
+
--- /dev/null
+From 40715e23667d0ce5bfe81dae029ca99564031681 Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sat, 20 Jan 2018 12:19:12 +0800
+Subject: [PATCH 11/29] sunxi: add SPI Flash block size for env storage
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ include/configs/sunxi-common.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
+index cb427004b6..6d754269cc 100644
+--- a/include/configs/sunxi-common.h
++++ b/include/configs/sunxi-common.h
+@@ -157,6 +157,8 @@
+ #define CONFIG_SYS_MMC_ENV_DEV 0
+ #endif
+ #define CONFIG_SYS_MMC_MAX_DEVICE 4
++#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
++#define CONFIG_ENV_SECT_SIZE 0x1000
+ #endif
+
+ #if defined(CONFIG_MACH_SUN8I_V3S)
+--
+2.20.1
+
--- /dev/null
+From 052334272e5268769a43689b636f895e524033ff Mon Sep 17 00:00:00 2001
+From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Date: Wed, 1 Mar 2017 22:29:06 +0100
+Subject: [PATCH 12/29] spi: sunxi_spi: Add DM SPI driver for A31/A80/A64
+
+This adds a rewrite of the SPI driver we had in use for the A31-uQ7
+(sun6i), A80-Q7 (sun9i) and A64-uQ7 (sun50i) boards, which includes
+support for:
+ * cs-gpios (i.e. GPIOs as additional chip-selects)
+
+Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 +
+ drivers/spi/Kconfig | 14 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/sun6i_spi.c | 539 ++++++++++++++++++
+ 4 files changed, 556 insertions(+)
+ create mode 100644 drivers/spi/sun6i_spi.c
+
+diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+index 6b9458f895..5ecdf58bd5 100644
+--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
++++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+@@ -473,6 +473,8 @@ struct sunxi_ccm_reg {
+ #ifdef CONFIG_MACH_SUN8I_R40
+ #define AHB_RESET_OFFSET_SATA 24
+ #endif
++#define AHB_RESET_OFFSET_SPI1 21
++#define AHB_RESET_OFFSET_SPI0 20
+ #define AHB_RESET_OFFSET_GMAC 17
+ #define AHB_RESET_OFFSET_MCTL 14
+ #define AHB_RESET_OFFSET_MMC3 11
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 8588866489..2d2f447a54 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -282,6 +282,20 @@ config STM32_SPI
+ SoCs. This uses driver model and requires a device tree binding to
+ operate.
+
++config SUN6I_SPI
++ bool "Allwinner (sun6i+) SPI driver"
++ help
++ Enable the SPI driver for new Allwinner SoCs.
++
++ This driver can be used to access the SPI NOR flash on for
++ communciation with SPI peripherals platforms embedding the
++ Allwinner SoC. This driver supports the device-model (only)
++ and has support for GPIOs as additional chip-selects.
++
++ For recent platforms (e.g. sun50i), dual-IO receive mode is
++ also supported, when configured for a SPI-NOR flash in the
++ device tree.
++
+ config TEGRA114_SPI
+ bool "nVidia Tegra114 SPI driver"
+ help
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index ae4f2958f8..ed49f39c34 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -50,6 +50,7 @@ obj-$(CONFIG_PL022_SPI) += pl022_spi.o
+ obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o
+ obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o
+ obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
++obj-$(CONFIG_SUN6I_SPI) += sun6i_spi.o
+ obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o
+ obj-$(CONFIG_SPI_SUNXI) += spi-sunxi.o
+ obj-$(CONFIG_SH_SPI) += sh_spi.o
+diff --git a/drivers/spi/sun6i_spi.c b/drivers/spi/sun6i_spi.c
+new file mode 100644
+index 0000000000..750c4d8819
+--- /dev/null
++++ b/drivers/spi/sun6i_spi.c
+@@ -0,0 +1,539 @@
++/*
++ * SPI driver for Allwinner sunxi SoCs
++ *
++ * Copyright (C) 2015-2017 Theobroma Systems Design und Consulting GmbH
++ *
++ * 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 <common.h>
++#ifdef CONFIG_DM_GPIO
++#include <asm/gpio.h>
++#endif
++#include <asm/io.h>
++#include <asm/arch/clock.h>
++#include <dm.h>
++#include <errno.h>
++#include <fdtdec.h>
++#include <wait_bit.h>
++#include <reset.h>
++#include <spi.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++struct sunxi_spi_platdata {
++ void *base;
++ unsigned int max_hz;
++
++ /* We could do with a single delay counter, but it won't do harm
++ to have two, as the same is the case for most other driver. */
++ uint deactivate_delay_us; /* Delay to wait after deactivate */
++ uint activate_delay_us; /* Delay to wait after activate */
++
++#if defined(CONFIG_DM_GPIO)
++ int cs_gpios_num;
++ struct gpio_desc *cs_gpios;
++#endif
++};
++
++struct sunxi_spi_driverdata {
++ unsigned int fifo_depth;
++};
++
++struct sunxi_spi_privdata {
++ ulong last_transaction_us; /* Time of last transaction end */
++ unsigned int hz_requested; /* last requested bitrate */
++ unsigned int hz_actual; /* currently set bitrate */
++};
++
++struct sunxi_spi_reg {
++ u8 _rsvd[0x4];
++ u32 GCR; /* SPI Global Control register */
++ u32 TCR; /* SPI Transfer Control register */
++ u8 _rsvd1[0x4];
++ u32 IER; /* SPI Interrupt Control register */
++ u32 ISR; /* SPI Interrupt Status register */
++ u32 FCR; /* SPI FIFO Control register */
++ u32 FSR; /* SPI FIFO Status register */
++ u32 WCR; /* SPI Wait Clock Counter register */
++ u32 CCR; /* SPI Clock Rate Control register */
++ u8 _rsvd2[0x8];
++ u32 MBC; /* SPI Burst Counter register */
++ u32 MTC; /* SPI Transmit Counter register */
++ u32 BCC; /* SPI Burst Control register */
++ u8 _rsvd3[0x4c];
++ u32 NDMA_MODE_CTL;
++ u8 _rsvd4[0x174];
++ u32 TXD; /* SPI TX Data register */
++ u8 _rsvd5[0xfc];
++ u32 RXD; /* SPI RX Data register */
++};
++
++
++#define GCR_MASTER BIT(1)
++#define GCR_EN BIT(0)
++
++#define TCR_XCH BIT(31)
++#define TCR_SDC BIT(11)
++#define TCR_DHB BIT(8)
++#define TCR_SSSEL_SHIFT (4)
++#define TCR_SSSEL_MASK (0x3 << TCR_SSSEL_SHIFT)
++#define TCR_SSLEVEL BIT(7)
++#define TCR_SSOWNER BIT(6)
++#define TCR_CPOL BIT(1)
++#define TCR_CPHA BIT(0)
++
++#define FCR_RX_FIFO_RST BIT(31)
++#define FCR_TX_FIFO_RST BIT(15)
++
++#define BCC_STC_MASK (0x00FFFFFF)
++
++#define CCTL_SEL_CDR1 0
++#define CCTL_SEL_CDR2 BIT(12)
++#define CDR1(n) ((n & 0xf) << 8)
++#define CDR2(n) (((n/2) - 1) & 0xff)
++
++static int sunxi_spi_cs_activate(struct udevice *dev, unsigned cs)
++{
++ struct udevice *bus = dev->parent;
++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus);
++ struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base;
++ struct sunxi_spi_privdata *priv = dev_get_priv(bus);
++ int ret = 0;
++
++ debug("%s (%s): cs %d cs_gpios_num %d cs_gpios %p\n",
++ dev->name, __func__, cs, plat->cs_gpios_num, plat->cs_gpios);
++
++ /* If it's too soon to do another transaction, wait... */
++ if (plat->deactivate_delay_us && priv->last_transaction_us) {
++ ulong delay_us;
++ delay_us = timer_get_us() - priv->last_transaction_us;
++ if (delay_us < plat->deactivate_delay_us)
++ udelay(plat->deactivate_delay_us - delay_us);
++ }
++
++#if defined(CONFIG_DM_GPIO)
++ /* Use GPIOs as chip selects? */
++ if (plat->cs_gpios) {
++ /* Guard against out-of-bounds accesses */
++ if (!(cs < plat->cs_gpios_num))
++ return -ENOENT;
++
++ if (dm_gpio_is_valid(&plat->cs_gpios[cs])) {
++ ret = dm_gpio_set_value(&plat->cs_gpios[cs], 1);
++ goto done;
++ }
++ }
++#endif
++ /* The hardware can control up to 4 CS, however not all of
++ them will be going to pads. We don't try to second-guess
++ the DT or higher-level drivers though and just test against
++ the hard limit. */
++
++ if (!(cs < 4))
++ return -ENOENT;
++
++ /* Control the positional CS output */
++ clrsetbits_le32(&spi->TCR, TCR_SSSEL_MASK, cs << TCR_SSSEL_SHIFT);
++ clrsetbits_le32(&spi->TCR, TCR_SSLEVEL, TCR_SSOWNER);
++
++done:
++ /* We'll delay, even it this is an error return... */
++ if (plat->activate_delay_us)
++ udelay(plat->activate_delay_us);
++
++ return ret;
++}
++
++static void sunxi_spi_cs_deactivate(struct udevice *dev, unsigned cs)
++{
++ struct udevice *bus = dev->parent;
++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus);
++ struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base;
++ struct sunxi_spi_privdata *priv = dev_get_priv(bus);
++
++#if defined(CONFIG_DM_GPIO)
++ /* Use GPIOs as chip selects? */
++ if (plat->cs_gpios) {
++ if (dm_gpio_is_valid(&plat->cs_gpios[cs])) {
++ dm_gpio_set_value(&plat->cs_gpios[cs], 0);
++ return;
++ }
++ }
++#endif
++
++ /* We have only the hardware chip select, so use those */
++ setbits_le32(&spi->TCR, TCR_SSLEVEL | TCR_SSOWNER);
++
++ /* Remember time of this transaction for the next delay */
++ if (plat->deactivate_delay_us)
++ priv->last_transaction_us = timer_get_us();
++}
++
++static inline uint8_t *spi_fill_writefifo(struct sunxi_spi_reg *spi,
++ uint8_t *dout, int cnt)
++{
++ debug("%s: dout = %p, cnt = %d\n", __func__, dout, cnt);
++
++ if (dout) {
++ int i;
++
++ for (i = 0; i < cnt; i++)
++ writeb(dout[i], &spi->TXD);
++
++ dout += cnt;
++ }
++
++ return dout;
++}
++
++static inline uint8_t *spi_drain_readfifo(struct sunxi_spi_reg *spi,
++ uint8_t *din, int cnt)
++{
++ debug("%s: din = %p, cnt = %d\n", __func__, din, cnt);
++
++ if (din) {
++ int i;
++
++ for (i = 0; i < cnt; i++)
++ din[i] = readb(&spi->RXD);
++
++ din += cnt;
++ }
++
++ return din;
++}
++
++static int sunxi_spi_xfer(struct udevice *dev, unsigned int bitlen,
++ const void *out, void *in, unsigned long flags)
++{
++ struct udevice *bus = dev->parent;
++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus);
++ struct sunxi_spi_privdata *priv = dev_get_priv(bus);
++ struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base;
++ struct sunxi_spi_driverdata *data =
++ (struct sunxi_spi_driverdata *)dev_get_driver_data(dev->parent);
++ struct dm_spi_slave_platdata *slave = dev_get_parent_platdata(dev);
++ uint8_t *dout = (uint8_t *)out;
++ uint8_t *din = (uint8_t *)in;
++ int fifo_depth = data->fifo_depth;
++ unsigned int n_bytes = DIV_ROUND_UP(bitlen, 8);
++ int ret = 0;
++ /*
++ * We assume that 1ms (for any delays within the module to
++ * start the transfer) + 2x the time to transfer a full FIFO
++ * (for the data- and bitrate-dependent part) is a reasonable
++ * timeout to detect the module being stuck.
++ */
++ ulong timeout_ms =
++ (DIV_ROUND_UP(fifo_depth * 16000, priv->hz_actual)) + 1;
++
++ debug("%s (%s): regs %p bitlen %d din %p flags %lx fifo_depth %d\n",
++ dev->name, __func__, spi, bitlen, din, flags, fifo_depth);
++
++ if (flags & SPI_XFER_BEGIN) {
++ ret = sunxi_spi_cs_activate(dev, slave->cs);
++ if (ret < 0) {
++ printf("%s: failed to activate chip-select %d\n",
++ dev->name, slave->cs);
++ return ret;
++ }
++ }
++
++ /* Reset FIFO */
++ writel(FCR_RX_FIFO_RST | FCR_TX_FIFO_RST, &spi->FCR);
++ /* Wait until the FIFO reset autoclears */
++ ret = wait_for_bit(dev->name, &spi->FCR,
++ FCR_RX_FIFO_RST | FCR_TX_FIFO_RST,
++ false, 10, true);
++ if (ret < 0) {
++ printf("%s: failed to reset FIFO within 10ms\n", bus->name);
++ return ret;
++ }
++
++ /* Set the discard burst bits depending on whether we are receiving */
++ clrbits_le32(&spi->TCR, TCR_DHB);
++ if (!din)
++ setbits_le32(&spi->TCR, TCR_DHB);
++
++ /* Transfer in blocks of FIFO_DEPTH */
++ while (n_bytes > 0) {
++ int cnt = (n_bytes < fifo_depth) ? n_bytes : fifo_depth;
++ int txcnt = dout ? cnt : 0;
++
++ /* We need to set up the transfer counters in every
++ iteration, as the hardware block counts those down
++ to 0 and leaves the 0 in the register (i.e. there's
++ no shadow register within the controller that these
++ values are copied into). */
++
++ /* master burst counter: total length (tx + rx + dummy) */
++ writel(cnt, &spi->MBC);
++ /* master transmit counter: tx */
++ writel(txcnt, &spi->MTC);
++ /* burst control counter: single-mode tx */
++ clrsetbits_le32(&spi->BCC, BCC_STC_MASK, txcnt & BCC_STC_MASK);
++
++ dout = spi_fill_writefifo(spi, dout, txcnt);
++
++ /* Start transfer ... */
++ setbits_le32(&spi->TCR, TCR_XCH);
++ /* ... and wait until it finshes. */
++ ret = wait_for_bit(dev->name, &spi->TCR, TCR_XCH,
++ false, timeout_ms, true);
++ if (ret < 0) {
++ printf("%s: stuck in XCH for %ld ms\n",
++ bus->name, timeout_ms);
++ goto fail;
++ }
++
++ din = spi_drain_readfifo(spi, din, cnt);
++
++ n_bytes -= cnt;
++ }
++
++ fail:
++ if (flags & SPI_XFER_END)
++ sunxi_spi_cs_deactivate(dev, slave->cs);
++
++ return 0;
++};
++
++static int sunxi_spi_ofdata_to_platdata(struct udevice *dev)
++{
++ struct sunxi_spi_platdata *plat = dev_get_platdata(dev);
++ const void *blob = gd->fdt_blob;
++ int node = dev_of_offset(dev);
++ fdt_addr_t addr;
++ fdt_size_t size;
++
++ debug("%s: %p\n", __func__, dev);
++
++ addr = fdtdec_get_addr_size_auto_noparent(blob, node, "reg", 0,
++ &size, false);
++ if (addr == FDT_ADDR_T_NONE) {
++ debug("%s: failed to find base address\n", dev->name);
++ return -ENODEV;
++ }
++ plat->base = (void *)addr;
++ plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
++ plat->activate_delay_us = fdtdec_get_int(blob, node,
++ "spi-activate_delay", 0);
++ plat->deactivate_delay_us = fdtdec_get_int(blob, node,
++ "spi-deactivate-delay", 0);
++
++#if defined(CONFIG_DM_GPIO)
++ plat->cs_gpios_num = gpio_get_list_count(dev, "cs-gpios");
++ if (plat->cs_gpios_num > 0) {
++ int i;
++
++ plat->cs_gpios = calloc(plat->cs_gpios_num,
++ sizeof(struct gpio_desc));
++ if (!plat->cs_gpios)
++ return -ENOMEM;
++
++ for (i = 0; i < plat->cs_gpios_num; ++i)
++ gpio_request_by_name(dev, "cs-gpios", i,
++ &plat->cs_gpios[i], 0);
++ }
++#endif
++ return 0;
++}
++
++static int sunxi_spi_probe(struct udevice *dev)
++{
++ unsigned int pin_func = SUNXI_GPC_SPI0;
++ int ret;
++
++ if (IS_ENABLED(CONFIG_MACH_SUN50I))
++ pin_func = SUN50I_GPC_SPI0;
++
++ if (IS_ENABLED(CONFIG_MACH_SUNIV))
++ pin_func = SUNIV_GPC_SPI0;
++
++ ret = sunxi_gpio_setup_dt_pins(gd->fdt_blob, dev_of_offset(dev),
++ NULL, pin_func);
++
++ if (ret < 0) {
++ printf("SPI: pinctrl node not found.\n");
++ } else if (!ret) {
++ printf("SPI: pinctrl node not valid.\n");
++ }
++
++ return (ret <= 0) ? -EINVAL : 0;
++}
++
++static int sunxi_spi_claim_bus(struct udevice *dev)
++{
++ struct sunxi_spi_platdata *plat = dev_get_platdata(dev->parent);
++ struct spi_slave *spi_slave = dev_get_parent_priv(dev);
++ struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base;
++
++ debug("%s: %p %p\n", __func__, dev, dev->parent);
++
++ /* Enable in master-mode */
++ setbits_le32(&spi->GCR, GCR_MASTER | GCR_EN);
++ /* All CS control is manual and set them to inactive */
++ clrbits_le32(&spi->TCR, TCR_SSSEL_MASK);
++ setbits_le32(&spi->TCR, TCR_SSOWNER);
++ /* Apply polarity and phase from the mode bits */
++ if (spi_slave->mode & SPI_CPOL)
++ setbits_le32(&spi->TCR, TCR_CPOL);
++ if (spi_slave->mode & SPI_CPHA)
++ setbits_le32(&spi->TCR, TCR_CPHA);
++
++#if defined(DM_GPIO)
++ /* Set all cs-gpios to inactive */
++ for (i = 0; i < plat->cs_gpios_num; ++i)
++ if (dm_gpio_is_valid(&plat->cs_gpios[i]))
++ dm_gpio_set_value(&plat->cs_gpios[i], 0);
++#endif
++
++
++ return 0;
++}
++
++static int sunxi_spi_release_bus(struct udevice *dev)
++{
++ struct sunxi_spi_platdata *plat = dev_get_platdata(dev->parent);
++ struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base;
++
++ clrbits_le32(&spi->GCR, GCR_EN);
++
++ return 0;
++}
++
++static int sunxi_spi_set_speed(struct udevice *bus, unsigned int hz)
++{
++ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
++ struct sunxi_spi_platdata *plat = dev_get_platdata(bus);
++ struct sunxi_spi_reg *spi = (struct sunxi_spi_reg *)plat->base;
++ struct sunxi_spi_privdata *priv = dev_get_priv(bus);
++ unsigned sclk_shift, hz_ahb, hz_sclk, target_freq;
++
++ debug("%s: %p, %d\n", __func__, bus, hz);
++
++ if (plat->max_hz && (hz > plat->max_hz)) {
++ debug("%s: selected speed (%d) exceeds maximum of %d\n",
++ bus->name, hz, plat->max_hz);
++ hz = plat->max_hz;
++ }
++
++ /* If the last request was for the same speed, we're done */
++ if (priv->hz_requested == hz)
++ return 0;
++
++ /* The CCU section in the manual recommends to have the module
++ reset deasserted before the module clock gate is opened. */
++ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_SPI0);
++
++
++ /* Enable and set the module clock.
++ *
++ * At least for the A31, there's a requirements to provide at
++ * least 2x the sample clock, so we should never go below that
++ * ratio between the AHB clock and the (ampling) SCLK. On the
++ * low end of the clock, we use the provide two step-downs for
++ * clocks on the low end (below 375kHz).
++ *
++ * However, testing shows that for high-speed modes (on the
++ * A64), we may not divide SCLK from the AHB clock.
++ */
++#ifndef CONFIG_MACH_SUNIV
++ if (hz < 100000)
++ sclk_shift = 8;
++ else if (hz < 50000000)
++ sclk_shift = 2;
++ else
++ sclk_shift = 0;
++
++ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_SPI0);
++
++ /* Program the SPI clock control */
++ writel(CCTL_SEL_CDR1 | CDR1(sclk_shift), &spi->CCR);
++
++ target_freq = hz * (1 << sclk_shift);
++
++ if (target_freq < 24000000) {
++ writel(BIT(31) | max(24000000 / target_freq - 1, 0xf),
++ &ccm->spi0_clk_cfg);
++ hz_ahb = 24000000 / ((readl(&ccm->spi0_clk_cfg) & 0xf) + 1);
++ } else {
++ writel(BIT(31) | (0x01 << 24) | max(600000000 / target_freq - 1, 0xf),
++ &ccm->spi0_clk_cfg);
++ hz_ahb = 600000000 / ((readl(&ccm->spi0_clk_cfg) & 0xf) + 1);
++ }
++#else
++ hz_ahb = target_freq = 200000000; /* AHB clock on suniv */
++ sclk_shift = 0;
++ while(target_freq > hz && sclk_shift < 0xf) {
++ target_freq >>= 1;
++ sclk_shift += 1;
++ };
++
++ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_SPI0);
++
++ writel(CCTL_SEL_CDR1 | CDR1(sclk_shift), &spi->CCR);
++#endif
++
++ hz_sclk = hz_ahb >> sclk_shift;
++ priv->hz_actual = hz_sclk;
++ debug("%s: hz_ahb %d hz_sclk %d\n", bus->name, hz_ahb, hz_sclk);
++
++ /* If this is a high-speed mode (which we define---based upon
++ empirical testing---to be above 50 MHz), we need to move the
++ sampling point during data read. */
++ if (hz_sclk > 50000000)
++ setbits_le32(&spi->TCR, TCR_SDC);
++ else
++ clrbits_le32(&spi->TCR, TCR_SDC);
++
++ return 0;
++};
++
++static int sunxi_spi_set_mode(struct udevice *bus, unsigned int mode)
++{
++ return 0;
++};
++
++static const struct dm_spi_ops sunxi_spi_ops = {
++ .claim_bus = sunxi_spi_claim_bus,
++ .release_bus = sunxi_spi_release_bus,
++ .xfer = sunxi_spi_xfer,
++ .set_speed = sunxi_spi_set_speed,
++ .set_mode = sunxi_spi_set_mode,
++ /*
++ * cs_info is not needed, since we require all chip selects to be
++ * in the device tree explicitly
++ */
++};
++
++static struct sunxi_spi_driverdata sun6i_a31_data = {
++ .fifo_depth = 128,
++};
++
++static struct sunxi_spi_driverdata sun50i_a64_data = {
++ .fifo_depth = 64,
++};
++
++static const struct udevice_id sunxi_spi_ids[] = {
++ { .compatible = "allwinner,sun6i-a31-spi",
++ .data = (uintptr_t)&sun6i_a31_data },
++ { .compatible = "allwinner,sun8i-h3-spi",
++ .data = (uintptr_t)&sun50i_a64_data },
++ { }
++};
++
++U_BOOT_DRIVER(sunxi_spi) = {
++ .name = "sunxi_spi",
++ .id = UCLASS_SPI,
++ .of_match = sunxi_spi_ids,
++ .ofdata_to_platdata = sunxi_spi_ofdata_to_platdata,
++ .platdata_auto_alloc_size = sizeof(struct sunxi_spi_platdata),
++ .priv_auto_alloc_size = sizeof(struct sunxi_spi_privdata),
++ .probe = sunxi_spi_probe,
++ .ops = &sunxi_spi_ops,
++};
+--
+2.20.1
+
--- /dev/null
+From c5a5bf586bbd0290837f7297f8181aa83b4e1f85 Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sat, 20 Jan 2018 11:57:56 +0800
+Subject: [PATCH 13/29] sunxi: add SPI0 node for suniv
+
+The suniv SoC has two SPI controllers, in which SPI0 is bootable.
+
+Add device tree node of the controller and its bootable pinmux node.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/dts/suniv.dtsi | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/dts/suniv.dtsi b/arch/arm/dts/suniv.dtsi
+index 5bca082d2e..10da83b53a 100644
+--- a/arch/arm/dts/suniv.dtsi
++++ b/arch/arm/dts/suniv.dtsi
+@@ -76,6 +76,19 @@
+ };
+ };
+
++ spi0: spi@1c05000 {
++ compatible = "allwinner,suniv-spi",
++ "allwinner,sun8i-h3-spi";
++ reg = <0x01c05000 0x1000>;
++ interrupts = <10>;
++ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_BUS_SPI0>;
++ clock-names = "ahb", "mod";
++ resets = <&ccu RST_BUS_SPI0>;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ ccu: clock@1c20000 {
+ compatible = "allwinner,suniv-ccu";
+ reg = <0x01c20000 0x400>;
+@@ -103,6 +116,11 @@
+ #interrupt-cells = <3>;
+ #gpio-cells = <3>;
+
++ spi0_pins_a: spi0-pins-pc {
++ pins = "PC0", "PC1", "PC2", "PC3";
++ function = "spi0";
++ };
++
+ uart0_pins_a: uart-pins-pe {
+ pins = "PE0", "PE1";
+ function = "uart0";
+--
+2.20.1
+
--- /dev/null
+From f08fe4e963b095d9aa015749f87a262c29b6eab0 Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sat, 20 Jan 2018 12:02:25 +0800
+Subject: [PATCH 14/29] sunxi: enable SPI NOR on Lichee Pi Nano
+
+The Lichee Pi Nano board has a Winbond W25Q128 SPI flash on it.
+
+Enable it.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/dts/suniv-f1c100s-licheepi-nano.dts | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+index d54cded8e3..9c111e6228 100644
+--- a/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
++++ b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+@@ -15,6 +15,7 @@
+
+ aliases {
+ serial0 = &uart0;
++ spi0 = &spi0;
+ };
+
+ chosen {
+@@ -26,6 +27,20 @@
+ status = "okay";
+ };
+
++&spi0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi0_pins_a>;
++ status = "okay";
++
++ flash@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "winbond,w25q128", "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <40000000>;
++ };
++};
++
+ &uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+--
+2.20.1
+
--- /dev/null
+From af302872077323de681f7be76cf35becc6153f38 Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sat, 20 Jan 2018 21:00:50 +0800
+Subject: [PATCH 15/29] sunxi: add defconfig for Lichee Pi Nano with SPI Flash
+ support
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ configs/licheepi_nano_spiflash_defconfig | 25 ++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+ create mode 100644 configs/licheepi_nano_spiflash_defconfig
+
+diff --git a/configs/licheepi_nano_spiflash_defconfig b/configs/licheepi_nano_spiflash_defconfig
+new file mode 100644
+index 0000000000..07b6a27dbe
+--- /dev/null
++++ b/configs/licheepi_nano_spiflash_defconfig
+@@ -0,0 +1,25 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_ENV_SIZE=0x8000
++CONFIG_ENV_OFFSET=0xf8000
++CONFIG_MACH_SUNIV=y
++CONFIG_DRAM_CLK=156
++CONFIG_DRAM_ZQ=0
++# CONFIG_VIDEO_SUNXI is not set
++CONFIG_DEFAULT_DEVICE_TREE="suniv-f1c100s-licheepi-nano"
++CONFIG_SPL=y
++# CONFIG_CMD_FLASH is not set
++# CONFIG_CMD_FPGA is not set
++CONFIG_CMD_SF=y
++CONFIG_CMD_SPI=y
++CONFIG_ENV_IS_IN_SPI_FLASH=y
++CONFIG_DM_SPI_FLASH=y
++CONFIG_SPI_FLASH=y
++CONFIG_SPI_FLASH_BAR=y
++CONFIG_SPI_FLASH_GIGADEVICE=y
++CONFIG_SPI_FLASH_MACRONIX=y
++CONFIG_SPI_FLASH_WINBOND=y
++CONFIG_SPL_SPI_SUNXI=y
++# CONFIG_SPL_DM_SERIAL is not set
++CONFIG_DM_SPI=y
++CONFIG_SUN6I_SPI=y
+--
+2.20.1
+
--- /dev/null
+From 5feb0865dab1d81f0dee6cabf9038c12f8139e2f Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sun, 21 Jan 2018 00:39:27 +0800
+Subject: [PATCH 16/29] sunxi: add support for UART at PF for suniv
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ arch/arm/mach-sunxi/board.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index d20cf2dc38..cedab41f8f 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -75,7 +75,8 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUNXI_GPIO_INPUT);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUNXI_GPIO_INPUT);
+ #endif
+-#if defined(CONFIG_MACH_SUN8I) && !defined(CONFIG_MACH_SUN8I_R40)
++#if (defined(CONFIG_MACH_SUN8I) && !defined(CONFIG_MACH_SUN8I_R40)) || \
++ defined(CONFIG_MACH_SUNIV)
+ sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUN8I_GPF_UART0);
+ sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUN8I_GPF_UART0);
+ #else
+--
+2.20.1
+
--- /dev/null
+From 4bd08d34c87d85904f5205241909a3a4d908487f Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sun, 21 Jan 2018 00:40:14 +0800
+Subject: [PATCH 17/29] sunxi: do not set PF MMC0 pinmux when PF uart is used
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ board/sunxi/board.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/board/sunxi/board.c b/board/sunxi/board.c
+index 48ef12e514..0380d9b77b 100644
+--- a/board/sunxi/board.c
++++ b/board/sunxi/board.c
+@@ -375,17 +375,19 @@ void board_nand_init(void)
+ #ifdef CONFIG_MMC
+ static void mmc_pinmux_setup(int sdc)
+ {
+- unsigned int pin;
++ __maybe_unused unsigned int pin;
+ __maybe_unused int pins;
+
+ switch (sdc) {
+ case 0:
+ /* SDC0: PF0-PF5 */
++#ifndef CONFIG_UART0_PORT_F
+ for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPF_SDC0);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
++#endif
+ break;
+
+ case 1:
+--
+2.20.1
+
--- /dev/null
+From 42e14729ccd2aefc6726801554422497016b82bc Mon Sep 17 00:00:00 2001
+From: Icenowy Zheng <icenowy@aosc.io>
+Date: Sun, 21 Jan 2018 00:43:43 +0800
+Subject: [PATCH 18/29] sunxi: allow to enable MMC driver when using PF UART0
+
+As the pinmux setup of MMC0 at PF is masked, the sunxi MMC driver is now
+harmless for PF uart setup, and it may be used for the extra MMC port.
+
+Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
+---
+ drivers/mmc/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
+index 85fd1906bd..93281d8e30 100644
+--- a/drivers/mmc/Kconfig
++++ b/drivers/mmc/Kconfig
+@@ -653,7 +653,7 @@ config ZYNQ_HISPD_BROKEN
+
+ config MMC_SUNXI
+ bool "Allwinner sunxi SD/MMC Host Controller support"
+- depends on ARCH_SUNXI && !UART0_PORT_F
++ depends on ARCH_SUNXI
+ default y
+ help
+ This selects support for the SD/MMC Host Controller on
+--
+2.20.1
+
--- /dev/null
+From b35aa33d8f831dada5990cb07ac3b696cd9d6a78 Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 13:39:00 +0300
+Subject: [PATCH 19/29] sunxi timer forward declare function
+
+---
+ arch/arm/cpu/arm926ejs/sunxi/timer.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm/cpu/arm926ejs/sunxi/timer.c b/arch/arm/cpu/arm926ejs/sunxi/timer.c
+index 36263896d8..7baae749c9 100644
+--- a/arch/arm/cpu/arm926ejs/sunxi/timer.c
++++ b/arch/arm/cpu/arm926ejs/sunxi/timer.c
+@@ -28,6 +28,9 @@ DECLARE_GLOBAL_DATA_PTR;
+
+ #define TIMER_NUM 0 /* we use timer 0 */
+
++/* forward declaration */
++ulong get_timer_masked(void);
++
+ /* read the 32-bit timer */
+ static ulong read_timer(void)
+ {
+--
+2.20.1
+
--- /dev/null
+--- /dev/null
++++ b/configs/OLIMEX_A13_SOM_defconfig
+@@ -0,0 +1,17 @@
++CONFIG_SPL=y
++CONFIG_DEFAULT_DEVICE_TREE="sun5i-a13-olinuxino"
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_MACH_SUN5I=y
++CONFIG_DRAM_CLK=408
++CONFIG_DRAM_ZQ=123
++CONFIG_DRAM_EMR1=0
++# CONFIG_CMD_IMLS is not set
++# CONFIG_CMD_FLASH is not set
++# CONFIG_CMD_FPGA is not set
++CONFIG_DM_SERIAL=y
++CONFIG_USB=y
++CONFIG_DM_USB=y
++CONFIG_SYS_NS16550=y
++CONFIG_SUNXI_NO_PMIC=y
++CONFIG_USB_EHCI_HCD=y
--- /dev/null
+From 1f42a5fe1414e505cbf0d558de837dcc91f8d7ba Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 13:39:57 +0300
+Subject: [PATCH 20/29] disable sunxi enable_caches function for arm926ejs
+
+---
+ arch/arm/mach-sunxi/board.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
+index cedab41f8f..7e088c7e8a 100644
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -343,7 +343,7 @@ void reset_cpu(ulong addr)
+ #endif
+ }
+
+-#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_ARM64)
++#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_ARM64) && !defined(CONFIG_CPU_ARM926EJS)
+ void enable_caches(void)
+ {
+ /* Enable D-cache. I-cache is already enabled in start.S */
+--
+2.20.1
+
--- /dev/null
+From 9fcee618a2099677e015f3a1bd8fa1d66f7ac9f3 Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 13:57:19 +0300
+Subject: [PATCH 22/29] remove suniv config ubs phys define
+
+it isn't used by the driver anymore and triggers kconfig errors
+---
+ include/configs/suniv.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/include/configs/suniv.h b/include/configs/suniv.h
+index e6aca3ec4b..483c20edc1 100644
+--- a/include/configs/suniv.h
++++ b/include/configs/suniv.h
+@@ -7,8 +7,6 @@
+ #ifndef __CONFIG_H
+ #define __CONFIG_H
+
+-#define CONFIG_SUNXI_USB_PHYS 1
+-
+ /*
+ * Include common sunxi configuration where most the settings are
+ */
+--
+2.20.1
+
--- /dev/null
+From 92cd8a878ddd2948447b447305183e3df896f58d Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 13:57:56 +0300
+Subject: [PATCH 23/29] fix sun6i spi driver wait_for_bit
+
+---
+ drivers/spi/sun6i_spi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/spi/sun6i_spi.c b/drivers/spi/sun6i_spi.c
+index 750c4d8819..74146f8f2f 100644
+--- a/drivers/spi/sun6i_spi.c
++++ b/drivers/spi/sun6i_spi.c
+@@ -246,7 +246,7 @@ static int sunxi_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ /* Reset FIFO */
+ writel(FCR_RX_FIFO_RST | FCR_TX_FIFO_RST, &spi->FCR);
+ /* Wait until the FIFO reset autoclears */
+- ret = wait_for_bit(dev->name, &spi->FCR,
++ ret = wait_for_bit_32(&spi->FCR,
+ FCR_RX_FIFO_RST | FCR_TX_FIFO_RST,
+ false, 10, true);
+ if (ret < 0) {
+@@ -282,7 +282,7 @@ static int sunxi_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ /* Start transfer ... */
+ setbits_le32(&spi->TCR, TCR_XCH);
+ /* ... and wait until it finshes. */
+- ret = wait_for_bit(dev->name, &spi->TCR, TCR_XCH,
++ ret = wait_for_bit_32(&spi->TCR, TCR_XCH,
+ false, timeout_ms, true);
+ if (ret < 0) {
+ printf("%s: stuck in XCH for %ld ms\n",
+--
+2.20.1
+
--- /dev/null
+From 182334907bbf9fc3f14ea8c13f59171bdddecac4 Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 14:01:05 +0300
+Subject: [PATCH 24/29] ensure correct spi driver is loaded
+
+---
+ drivers/spi/spi-sunxi.c | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
+index dbfeac77ee..6e32d034b2 100644
+--- a/drivers/spi/spi-sunxi.c
++++ b/drivers/spi/spi-sunxi.c
+@@ -598,14 +598,6 @@ static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
+ .has_burst_ctl = true,
+ };
+
+-static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
+- .regs = sun6i_spi_regs,
+- .bits = sun6i_spi_bits,
+- .fifo_depth = 64,
+- .has_soft_reset = true,
+- .has_burst_ctl = true,
+-};
+-
+ static const struct udevice_id sun4i_spi_ids[] = {
+ {
+ .compatible = "allwinner,sun4i-a10-spi",
+@@ -615,10 +607,6 @@ static const struct udevice_id sun4i_spi_ids[] = {
+ .compatible = "allwinner,sun6i-a31-spi",
+ .data = (ulong)&sun6i_a31_spi_variant,
+ },
+- {
+- .compatible = "allwinner,sun8i-h3-spi",
+- .data = (ulong)&sun8i_h3_spi_variant,
+- },
+ { /* sentinel */ }
+ };
+
+--
+2.20.1
+
--- /dev/null
+From d3e6ffc3500df261617bf52676dfb548edc5fa68 Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 14:02:04 +0300
+Subject: [PATCH 25/29] add suniv-pinctrl compatibility to sunxi gpio driver
+
+---
+ drivers/gpio/sunxi_gpio.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+index 719efc2cef..be816c688c 100644
+--- a/drivers/gpio/sunxi_gpio.c
++++ b/drivers/gpio/sunxi_gpio.c
+@@ -355,6 +355,7 @@ static const struct udevice_id sunxi_gpio_ids[] = {
+ ID("allwinner,sun9i-a80-pinctrl", a_all),
+ ID("allwinner,sun50i-a64-pinctrl", a_all),
+ ID("allwinner,sun50i-h6-pinctrl", a_all),
++ ID("allwinner,suniv-pinctrl", a_all),
+ ID("allwinner,sun6i-a31-r-pinctrl", l_2),
+ ID("allwinner,sun8i-a23-r-pinctrl", l_1),
+ ID("allwinner,sun8i-a83t-r-pinctrl", l_1),
+--
+2.20.1
+
--- /dev/null
+From 42966ff87a183f6299ebc6d3f5db2b1f2bb02a1e Mon Sep 17 00:00:00 2001
+From: George Hilliard <thirtythreeforty@gmail.com>
+Date: Sun, 21 Jul 2019 15:21:18 -0500
+Subject: [PATCH 28/29] sunxi: suniv: add device tree nodes for f1c100s MMC
+ controllers
+
+The f1c100s has two MMC controllers. Add device tree nodes for them.
+
+Signed-off-by: George Hilliard <thirtythreeforty@gmail.com>
+---
+ arch/arm/dts/suniv.dtsi | 47 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+diff --git a/arch/arm/dts/suniv.dtsi b/arch/arm/dts/suniv.dtsi
+index 10da83b53a..660eb3d49c 100644
+--- a/arch/arm/dts/suniv.dtsi
++++ b/arch/arm/dts/suniv.dtsi
+@@ -125,6 +125,11 @@
+ pins = "PE0", "PE1";
+ function = "uart0";
+ };
++
++ mmc0_pins: mmc0-pins {
++ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
++ function = "mmc0";
++ };
+ };
+
+ timer@1c20c00 {
+@@ -197,5 +202,47 @@
+ #phy-cells = <1>;
+ status = "disabled";
+ };
++
++ mmc0: mmc@1c0f000 {
++ compatible = "allwinner,suniv-f1c100s-mmc",
++ "allwinner,sun7i-a20-mmc";
++ reg = <0x01c0f000 0x1000>;
++ clocks = <&ccu CLK_BUS_MMC0>,
++ <&ccu CLK_MMC0>,
++ <&ccu CLK_MMC0_OUTPUT>,
++ <&ccu CLK_MMC0_SAMPLE>;
++ clock-names = "ahb",
++ "mmc",
++ "output",
++ "sample";
++ resets = <&ccu RST_BUS_MMC0>;
++ reset-names = "ahb";
++ interrupts = <23>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&mmc0_pins>;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ mmc2: mmc@1c10000 {
++ compatible = "allwinner,suniv-f1c100s-mmc",
++ "allwinner,sun7i-a20-mmc";
++ reg = <0x01c10000 0x1000>;
++ clocks = <&ccu CLK_BUS_MMC1>,
++ <&ccu CLK_MMC1>,
++ <&ccu CLK_MMC1_OUTPUT>,
++ <&ccu CLK_MMC1_SAMPLE>;
++ clock-names = "ahb",
++ "mmc",
++ "output",
++ "sample";
++ resets = <&ccu RST_BUS_MMC1>;
++ reset-names = "ahb";
++ interrupts = <24>;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
+ };
+ };
+--
+2.20.1
+
--- /dev/null
+From 9f068e10bb9ddb4c9610427662be9048e75bcd6a Mon Sep 17 00:00:00 2001
+From: florpor <florist.powers@gmail.com>
+Date: Wed, 29 Apr 2020 14:07:19 +0300
+Subject: [PATCH 29/29] licheepi nano dts - enable mmc0
+
+---
+ arch/arm/dts/suniv-f1c100s-licheepi-nano.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+index 9c111e6228..0145fa027a 100644
+--- a/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
++++ b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
+@@ -5,6 +5,7 @@
+
+ /dts-v1/;
+ #include "suniv-f1c100s.dtsi"
++#include "sunxi-common-regulators.dtsi"
+
+ #include <dt-bindings/gpio/gpio.h>
+
+@@ -41,6 +42,13 @@
+ };
+ };
+
++&mmc0 {
++ vmmc-supply = <®_vcc3v3>;
++ bus-width = <4>;
++ broken-cd;
++ status = "okay";
++};
++
+ &uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+--
+2.20.1
+
--- /dev/null
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -455,6 +455,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
+ sun6i-a31-m9.dtb \
+ sun6i-a31-mele-a1000g-quad.dtb \
+ sun6i-a31-mixtile-loftq.dtb \
++ sun6i-a31-pangolin.dtb \
+ sun6i-a31s-colorfly-e708-q1.dtb \
+ sun6i-a31s-cs908.dtb \
+ sun6i-a31s-inet-q972.dtb \
+--- a/arch/arm/dts/sun6i-a31.dtsi
++++ b/arch/arm/dts/sun6i-a31.dtsi
+@@ -641,6 +641,11 @@
+ function = "lcd0";
+ };
+
++ i2c3_pins_a: i2c3@0 {
++ allwinner,pins = "PB5", "PB6";
++ allwinner,function = "i2c3";
++ };
++
+ mmc0_pins_a: mmc0@0 {
+ pins = "PF0", "PF1", "PF2",
+ "PF3", "PF4", "PF5";
+--- /dev/null
++++ b/arch/arm/dts/sun6i-a31-pangolin.dts
+@@ -0,0 +1,292 @@
++/*
++ * Copyright 2015, Theobroma Systems Design und Consulting GmbH
++ *
++ * This file is dual-licensed: you can use it either under the terms
++ * of the GPL or the X11 license, at your option. Note that this dual
++ * licensing only applies to this file, and not this project as a
++ * whole.
++ *
++ * a) This file is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Or, alternatively,
++ *
++ * b) Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation
++ * files (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use,
++ * copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following
++ * conditions:
++ *
++ * The above copyright notice and this permission notice shall be
++ * included in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++/dts-v1/;
++#include "sun6i-a31.dtsi"
++#include "sunxi-common-regulators.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/pinctrl/sun4i-a10.h>
++
++/ {
++ model = "Theobroma Systems A31 Pangolin";
++ compatible = "tsd,a31-pangolin", "allwinner,sun6i-a31";
++
++ aliases {
++ serial0 = &uart0;
++ serial2 = &uart2;
++ spi0 = &spi0;
++ spi1 = &spi1;
++ spi2 = &spi2;
++ spi3 = &spi3;
++ };
++
++ chosen {
++ stdout-path = "serial2:115200n8";
++ };
++};
++
++&ehci0 {
++ status = "okay";
++};
++
++&ohci0 {
++ status = "okay";
++};
++
++&ehci1 {
++ status = "okay";
++};
++
++&ohci1 {
++ status = "okay";
++};
++
++&ohci2 {
++ status = "okay";
++};
++
++&gmac {
++ pinctrl-names = "default";
++ pinctrl-0 = <&gmac_pins_rgmii_a>;
++ phy = <&phy1>;
++ phy-mode = "rgmii";
++ snps,reset-gpio = <&pio 0 7 GPIO_ACTIVE_LOW>;
++ snps,reset-active-low;
++ snps,reset-delays-us = <0 10000 30000>;
++ status = "okay";
++
++ phy1: ethernet-phy@4 {
++ reg = <4>;
++ };
++};
++
++&i2c0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c0_pins_a>;
++ status = "okay";
++};
++
++&i2c1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c1_pins_a>;
++ status = "okay";
++};
++
++&i2c2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c2_pins_a>;
++ status = "okay";
++};
++
++&i2c3 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c3_pins_a>;
++ status = "okay";
++
++ rtc_twi: rtc@6f {
++ compatible = "isil,isl1208";
++ reg = <0x6f>;
++ };
++ fan: fan@18 {
++ compatible = "ti,amc6821";
++ reg = <0x18>;
++ cooling-min-state = <0>;
++ cooling-max-state = <9>;
++ #cooling-cells = <2>;
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash: flash@0 {
++ compatible = "spansion,m25p40";
++ spi-max-frequency = <16000000>;
++ spi-cpol;
++ spi-cpha;
++ };
++};
++
++&spi1 {
++ status = "okay";
++};
++
++&ir {
++ pinctrl-names = "default";
++ pinctrl-0 = <&ir_pins_a>;
++ status = "okay";
++};
++
++&mmc0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_pangolin>;
++ vmmc-supply = <®_vcc3v0>;
++ bus-width = <4>;
++ cd-gpios = <&pio 2 19 GPIO_ACTIVE_LOW>; /* PC19 */
++ status = "okay";
++};
++
++&mmc0_pins_a {
++ /* external pull-ups missing for some pins */
++ allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
++};
++
++&mmc2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&mmc2_pins_a>;
++ vmmc-supply = <®_vcc3v0>;
++ bus-width = <8>;
++ non-removable;
++ status = "okay";
++};
++
++&pio {
++ mmc0_cd_pin_pangolin: mmc0_cd_pin@0 {
++ allwinner,pins = "PC19";
++ allwinner,function = "gpio_in";
++ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
++ allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
++ };
++
++ leds_pins_pangolin: led_pins@0 {
++ allwinner,pins = "PH7", "PC16";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <SUN4I_PINCTRL_20_MA>;
++ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
++ };
++
++ mmc2_pins_a: mmc2@0 {
++ allwinner,pins = "PC6","PC7","PC8","PC9","PC10","PC11",
++ "PC12","PC13","PC14","PC15";
++ allwinner,function = "mmc2";
++ allwinner,drive = <SUN4I_PINCTRL_30_MA>;
++ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
++ };
++};
++
++&p2wi {
++ status = "okay";
++
++ axp221: pmic@68 {
++ compatible = "x-powers,axp221";
++ reg = <0x68>;
++ interrupt-parent = <&nmi_intc>;
++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-controller;
++ #interrupt-cells = <1>;
++ dcdc1-supply = <&vcc_3v0>;
++ dcdc5-supply = <&vcc_dram>;
++
++ regulators {
++ x-powers,dcdc-freq = <3000>;
++
++ vcc_3v0: dcdc1 {
++ regulator-always-on;
++ regulator-min-microvolt = <3000000>;
++ regulator-max-microvolt = <3000000>;
++ regulator-name = "vcc-3v0";
++ };
++
++ vdd_cpu: dcdc2 {
++ regulator-always-on;
++ regulator-min-microvolt = <700000>;
++ regulator-max-microvolt = <1320000>;
++ regulator-name = "vdd-cpu";
++ };
++
++ vdd_gpu: dcdc3 {
++ regulator-always-on;
++ regulator-min-microvolt = <700000>;
++ regulator-max-microvolt = <1320000>;
++ regulator-name = "vdd-gpu";
++ };
++
++ vdd_sys_dll: dcdc4 {
++ regulator-always-on;
++ regulator-min-microvolt = <1100000>;
++ regulator-max-microvolt = <1100000>;
++ regulator-name = "vdd-sys-dll";
++ };
++
++ vcc_dram: dcdc5 {
++ regulator-always-on;
++ regulator-min-microvolt = <1500000>;
++ regulator-max-microvolt = <1500000>;
++ regulator-name = "vcc-dram";
++ };
++
++ vcc_wifi: aldo1 {
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-name = "vcc_wifi";
++ };
++
++ avcc: aldo3 {
++ regulator-always-on;
++ regulator-min-microvolt = <3000000>;
++ regulator-max-microvolt = <3000000>;
++ regulator-name = "avcc";
++ };
++ };
++ };
++};
++
++&uart0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins_a>;
++ status = "okay";
++};
++
++&usb1_vbus_pin_a {
++ allwinner,pins = "PD23";
++};
++
++®_usb1_vbus {
++ gpio = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD 23 */
++ status = "okay";
++};
++
++&usbphy {
++ status = "okay";
++ usb1_vbus-supply = <®_usb1_vbus>;
++};
+--- /dev/null
++++ b/configs/pangolin_defconfig
+@@ -0,0 +1,36 @@
++CONFIG_SUNXI_PANGOLIN=y
++CONFIG_SPL=y
++CONFIG_SYS_EXTRA_OPTIONS="USB_EHCI,SUNXI_GMAC,RGMII"
++CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-pangolin"
++CONFIG_VIDEO_VGA_VIA_LCD=y
++CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN="PH25"
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_MACH_SUN6I=y
++CONFIG_DRAM_CHANNELS=1
++CONFIG_DRAM_CLK=360
++CONFIG_DRAM_ZQ=70
++CONFIG_AXP_DCDC1_VOLT=3300
++CONFIG_AXP_ALDO1_VOLT=0
++CONFIG_AXP_ALDO2_VOLT=1800
++CONFIG_AXP_ALDO3_VOLT=3000
++CONFIG_AXP_DLDO4_VOLT=3300
++CONFIG_AXP_ELDO1_VOLT=1200
++CONFIG_AXP_ELDO2_VOLT=2500
++CONFIG_AXP_ELDO3_VOLT=3300
++CONFIG_MMC_SUNXI_SLOT_EXTRA=2
++CONFIG_CONS_INDEX=3
++# Vbus gpio for usb1
++CONFIG_USB1_VBUS_PIN=""
++# No Vbus gpio for usb2
++CONFIG_USB2_VBUS_PIN=""
++CONFIG_USB=y
++CONFIG_DM_USB=y
++CONFIG_USB_EHCI=y
++CONFIG_USB_KEYBOARD=y
++CONFIG_DM_ETH=y
++CONFIG_CMD_IMLS=n
++CONFIG_ETH_DESIGNWARE=y
++CONFIG_DM_SPI=y
++CONFIG_DM_SPI_FLASH=y
++CONFIG_SUNXI_SPI=y
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -896,6 +896,14 @@ config VIDEO_LCD_PANEL_I2C_SCL
+ Set the SCL pin for the LCD i2c interface. This takes a string in the
+ format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
+
++choice
++ prompt "Sunxi Board Variant"
++ optional
++
++config SUNXI_PANGOLIN
++ bool "Theobroma A31 uQ7 Board"
++
++endchoice
+
+ # Note only one of these may be selected at a time! But hidden choices are
+ # not supported by Kconfig
--- /dev/null
+ GNU nano 2.7.4 File: 062-A20-improve-gmac-upload.patch
+
+--- a/configs/A20-OLinuXino-Lime2_defconfig
++++ b/configs/A20-OLinuXino-Lime2_defconfig
+@@ -22,6 +22,7 @@ CONFIG_ETH_DESIGNWARE=y
+ CONFIG_RGMII=y
+ CONFIG_MII=y
+ CONFIG_SUN7I_GMAC=y
++CONFIG_GMAC_TX_DELAY=1
+ CONFIG_AXP_ALDO3_VOLT=2800
+ CONFIG_AXP_ALDO3_VOLT_SLOPE_08=y
+ CONFIG_AXP_ALDO3_INRUSH_QUIRK=y
--- /dev/null
+--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
++++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+@@ -8,6 +8,8 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+ CONFIG_USB0_VBUS_PIN="PC17"
+ CONFIG_USB0_VBUS_DET="PH5"
+ CONFIG_I2C1_ENABLE=y
++CONFIG_PHY_MICREL=y
++CONFIG_PHY_MICREL_KSZ90X1=y
+ CONFIG_SATAPWR="PC3"
+ CONFIG_SPL_SPI_SUNXI=y
+ CONFIG_AHCI=y
+--- a/configs/A20-OLinuXino-Lime2_defconfig
++++ b/configs/A20-OLinuXino-Lime2_defconfig
+@@ -7,6 +7,8 @@ CONFIG_MMC0_CD_PIN="PH1"
+ CONFIG_USB0_VBUS_PIN="PC17"
+ CONFIG_USB0_VBUS_DET="PH5"
+ CONFIG_I2C1_ENABLE=y
++CONFIG_PHY_MICREL=y
++CONFIG_PHY_MICREL_KSZ90X1=y
+ CONFIG_SATAPWR="PC3"
+ CONFIG_AHCI=y
+ # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+--- a/drivers/net/phy/micrel_ksz90x1.c
++++ b/drivers/net/phy/micrel_ksz90x1.c
+@@ -14,6 +14,8 @@
+ #include <errno.h>
+ #include <micrel.h>
+ #include <phy.h>
++#include <asm/io.h>
++#include <asm/arch/clock.h>
+
+ /*
+ * KSZ9021 - KSZ9031 common
+@@ -344,6 +346,10 @@ static int ksz9031_phy_extwrite(struct p
+ static int ksz9031_config(struct phy_device *phydev)
+ {
+ int ret;
++ struct sunxi_ccm_reg *const ccm =
++ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
++
++ setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_DELAY(4));
+
+ ret = ksz9031_of_config(phydev);
+ if (ret)
--- /dev/null
+From a58eb20fb80f478038243e9e0f30f6984725e265 Mon Sep 17 00:00:00 2001
+From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Date: Tue, 6 Jan 2015 15:47:18 +0100
+Subject: sun6i: Sync PLL1 multipliers/dividers with Boot1
+
+This change syncs up the multipliers and dividers used to initialize
+PLL1 (i.e. the fast clock driving the ARM cores) with the values used
+in Allwinner's Boot1 on sun6i.
+
+More specifically, the following settings are now used:
+ * up to 768MHz: mul=2, div=2 (was: mul=1, div=1)
+ * up to 1152MHz: mul=3, div=2 (unchanged)
+ * above 1152MHz: mul=4, div=2 (was: mul=2, div=1)
+
+--- a/arch/arm/mach-sunxi/clock_sun6i.c
++++ b/arch/arm/mach-sunxi/clock_sun6i.c
+@@ -112,11 +112,12 @@ void clock_set_pll1(unsigned int clk)
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ const int p = 0;
+- int k = 1;
+- int m = 1;
++ int k = 2;
++ int m = 2;
+
+ if (clk > 1152000000) {
+- k = 2;
++ k = 4;
++ m = 2;
+ } else if (clk > 768000000) {
+ k = 4;
+ m = 2;
--- /dev/null
+From b2b385df5095fff80b4655142f58a2a6801e6c80 Mon Sep 17 00:00:00 2001
+From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Date: Tue, 6 Jan 2015 21:26:44 +0100
+Subject: sun6i: Fix and document PLL LDO voltage selection
+
+The PRCM_PLL_CTRL_LDO_OUT_L and PRCM_PLL_CTRL_LDO_OUT_H macros had
+their meaning reversed. This is fixed by this change-set. With this
+changed, the PRCM_PLL_CTRL_LDO_OUT_L(1370) now becomes self-evident
+as setting the voltage to 1.37v (which it had done all along, even
+though stating a different target voltage).
+
+After changing the PLL LDO setting, it will take a little while for
+the voltage output to settle. A sdelay()-based loop waits the same
+order of magnitude as Boot1.
+
+Furthermore, a bit of documentation is added to clarify that the
+required setting for the PLL LDO is 1.37v as per the A31 manual.
+
+--- a/arch/arm/mach-sunxi/clock_sun6i.c
++++ b/arch/arm/mach-sunxi/clock_sun6i.c
+@@ -25,13 +25,26 @@ void clock_init_safe(void)
+ struct sunxi_prcm_reg * const prcm =
+ (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
+- /* Set PLL ldo voltage without this PLL6 does not work properly */
++ /* Set PLL ldo voltage without this PLL6 does not work properly.
++ *
++ * As the A31 manual states, that "before enable PLL, PLLVDD
++ * LDO should be set to 1.37v", we need to configure this to 2.5v
++ * in the "PLL Input Power Select" (0 << 15) and (7 << 16).
++ */
+ clrsetbits_le32(&prcm->pll_ctrl1, PRCM_PLL_CTRL_LDO_KEY_MASK,
+ PRCM_PLL_CTRL_LDO_KEY);
+ clrsetbits_le32(&prcm->pll_ctrl1, ~PRCM_PLL_CTRL_LDO_KEY_MASK,
+ PRCM_PLL_CTRL_LDO_DIGITAL_EN | PRCM_PLL_CTRL_LDO_ANALOG_EN |
+- PRCM_PLL_CTRL_EXT_OSC_EN | PRCM_PLL_CTRL_LDO_OUT_L(1140));
++ PRCM_PLL_CTRL_EXT_OSC_EN | PRCM_PLL_CTRL_LDO_OUT_L(1370));
+ clrbits_le32(&prcm->pll_ctrl1, PRCM_PLL_CTRL_LDO_KEY_MASK);
++
++ /* Give the PLL LDO voltage setting some time to take hold.
++ * Notes:
++ * 1) We need to use sdelay() as the timers aren't set up yet.
++ * 2) The 100k iterations come from Boot1, which spin's for 100k
++ * iterations through a loop.
++ */
++ sdelay(100000);
+ #endif
+
+ #if defined(CONFIG_MACH_SUN8I_R40) || defined(CONFIG_MACH_SUN50I)
+--- a/arch/arm/include/asm/arch-sunxi/prcm.h
++++ b/arch/arm/include/asm/arch-sunxi/prcm.h
+@@ -110,13 +110,13 @@
+ #define PRCM_PLL_CTRL_LDO_OUT_MASK \
+ __PRCM_PLL_CTRL_LDO_OUT(0x7)
+ /* When using the low voltage 20 mV steps, and high voltage 30 mV steps */
+-#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
+- __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
+ #define PRCM_PLL_CTRL_LDO_OUT_H(n) \
++ __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
++#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
+ __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
+-#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
+- __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
+ #define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
++ __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
++#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
+ __PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
+ #define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
+ #define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
--- /dev/null
+From d7311b6e7cdd1fc0e92665188e650934718cb2b1 Mon Sep 17 00:00:00 2001
+From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Date: Tue, 16 Jun 2015 10:52:01 +0200
+Subject: sun6i: define alternate-function for UART2 on GPG
+
+
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -190,6 +190,7 @@ enum sunxi_gpio_number {
+ #define SUN6I_GPG_SDC1 2
+ #define SUN8I_GPG_SDC1 2
+ #define SUN6I_GPG_TWI3 2
++#define SUN6I_GPG_UART2 2
+ #define SUN5I_GPG_UART1 4
+
+ #define SUN6I_GPH_PWM 2
--- /dev/null
+From c058dfb69136d62f88ae8b121104bdb7ce2df03f Mon Sep 17 00:00:00 2001
+From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Date: Tue, 16 Jun 2015 10:53:11 +0200
+Subject: ARM: sun6i: Support console on UART2 (GPG6/GPG7)
+
+
+--- a/arch/arm/mach-sunxi/board.c
++++ b/arch/arm/mach-sunxi/board.c
+@@ -129,6 +129,10 @@ static int gpio_init(void)
+ sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG_UART1);
+ sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG_UART1);
+ sunxi_gpio_set_pull(SUNXI_GPG(4), SUNXI_GPIO_PULL_UP);
++#elif CONFIG_CONS_INDEX == 3 && defined(CONFIG_MACH_SUN6I)
++ sunxi_gpio_set_cfgpin(SUNXI_GPG(6), SUN6I_GPG_UART2);
++ sunxi_gpio_set_cfgpin(SUNXI_GPG(7), SUN6I_GPG_UART2);
++ sunxi_gpio_set_pull(SUNXI_GPG(7), SUNXI_GPIO_PULL_UP);
+ #elif CONFIG_CONS_INDEX == 3 && defined(CONFIG_MACH_SUN8I)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
+--- a/include/configs/sunxi-common.h
++++ b/include/configs/sunxi-common.h
+@@ -244,6 +244,8 @@ extern int soft_i2c_gpio_scl;
+ #endif
+ #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN5I)
+ #define OF_STDOUT_PATH "/soc@01c00000/serial@01c28400:115200"
++#elif CONFIG_CONS_INDEX == 3 && defined(CONFIG_MACH_SUN6I)
++#define OF_STDOUT_PATH "/soc@01c00000/serial@01c28800:115200"
+ #elif CONFIG_CONS_INDEX == 3 && defined(CONFIG_MACH_SUN8I)
+ #define OF_STDOUT_PATH "/soc@01c00000/serial@01c28800:115200"
+ #elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
--- /dev/null
+From 78d5fab8e345b1273ec8c22d06f1a1d27670b518 Mon Sep 17 00:00:00 2001
+From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+Date: Tue, 16 Jun 2015 10:59:38 +0200
+Subject: ARM: sunxi: Make CONS_INDEX configurable
+
+
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -559,6 +559,14 @@ config SYS_BOARD
+ config SYS_SOC
+ default "sunxi"
+
++config CONS_INDEX
++ int "UART used for console"
++ range 1 5
++ default 1
++ ---help---
++ Defines the UART port used for serial output. It starts at 1 so UART0 is 1,
++ UART1 is 2 and so on.
++
+ config UART0_PORT_F
+ bool "UART0 on MicroSD breakout board"
+ default n
--- /dev/null
+From 637800493945ffed2f454756300437a4ec86e3b1 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Wed, 19 Jul 2017 22:23:15 +0200
+Subject: mkimage: check environment for dtc binary location
+
+Currently mkimage assumes the dtc binary is in the path and fails
+otherwise. This patch makes it check the DTC environment variable first
+for the dtc binary and then fall back to the default path. This makes
+it possible to call the u-boot build with make DTC=... and build a fit
+image with the dtc binary not being the the default path.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Cc: Simon Glass <sjg@chromium.org>
+---
+ tools/fit_image.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/tools/fit_image.c
++++ b/tools/fit_image.c
+@@ -726,9 +726,14 @@ static int fit_handle_file(struct image_
+ }
+ *cmd = '\0';
+ } else if (params->datafile) {
++ const char* dtc = getenv("DTC");
++
++ if (!dtc)
++ dtc = MKIMAGE_DTC;
++
+ /* dtc -I dts -O dtb -p 500 -o tmpfile datafile */
+ snprintf(cmd, sizeof(cmd), "%s %s -o \"%s\" \"%s\"",
+- MKIMAGE_DTC, params->dtc, tmpfile, params->datafile);
++ dtc, params->dtc, tmpfile, params->datafile);
+ debug("Trying to execute \"%s\"\n", cmd);
+ } else {
+ snprintf(cmd, sizeof(cmd), "cp \"%s\" \"%s\"",
--- /dev/null
+From def280c4792262a368c8861312dc6b376181021f Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Mon, 1 Jan 2018 23:10:56 +0100
+Subject: sunxi: deactivate binman
+
+Use the old way to generate the images instead of binman.
+binman needs python with swig to avoid this host tool dependency use the
+old way of generating images.
+---
+ Makefile | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -1555,8 +1555,10 @@ endif
+
+ ifneq ($(CONFIG_ARCH_SUNXI),)
+ ifeq ($(CONFIG_ARM64),)
+-u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb FORCE
+- $(call if_changed,binman)
++OBJCOPYFLAGS_u-boot-sunxi-with-spl.bin = -I binary -O binary \
++ --pad-to=$(CONFIG_SPL_PAD_TO) --gap-fill=0xff
++u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img FORCE
++ $(call if_changed,pad_cat)
+ else
+ u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.itb FORCE
+ $(call if_changed,cat)
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -962,7 +962,6 @@ config ARCH_SOCFPGA
+
+ config ARCH_SUNXI
+ bool "Support sunxi (Allwinner) SoCs"
+- select BINMAN
+ select CMD_GPIO
+ select CMD_MMC if MMC
+ select CMD_USB if DISTRO_DEFAULTS
--- /dev/null
+--- a/configs/A13-OLinuXino_defconfig
++++ b/configs/A13-OLinuXino_defconfig
+@@ -7,7 +7,6 @@ CONFIG_DRAM_EMR1=0
+ CONFIG_MMC0_CD_PIN="PG0"
+ CONFIG_USB0_VBUS_DET="PG1"
+ CONFIG_USB1_VBUS_PIN="PG11"
+-CONFIG_AXP_GPIO=y
+ # CONFIG_VIDEO_HDMI is not set
+ CONFIG_VIDEO_VGA_VIA_LCD=y
+ CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH=y
+@@ -21,7 +20,7 @@ CONFIG_CMD_USB_MASS_STORAGE=y
+ CONFIG_DEFAULT_DEVICE_TREE="sun5i-a13-olinuxino"
+ CONFIG_DFU_RAM=y
+ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+-CONFIG_AXP_ALDO3_VOLT=3300
++CONFIG_SUNXI_NO_PMIC=y
+ CONFIG_CONS_INDEX=2
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_OHCI_HCD=y
--- /dev/null
+diff -ruN u-boot-2020.04.old/arch/arm/dts/sun7i-a20-rgl-c64mini.dts u-boot-2020.04/arch/arm/dts/sun7i-a20-rgl-c64mini.dts
+--- u-boot-2020.04.old/arch/arm/dts/sun7i-a20-rgl-c64mini.dts 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2020.04/arch/arm/dts/sun7i-a20-rgl-c64mini.dts 2020-07-07 11:32:47.000000000 +0200
+@@ -0,0 +1,254 @@
++/*
++ * This is based on sun4i-a10-olinuxino-lime.dts
++ *
++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
++ * Copyright (c) 2014 FUKAUMI Naoki <naobsd@gmail.com>
++ *
++ * This file is dual-licensed: you can use it either under the terms
++ * of the GPL or the X11 license, at your option. Note that this dual
++ * licensing only applies to this file, and not this project as a
++ * whole.
++ *
++ * a) This file is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Or, alternatively,
++ *
++ * b) Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation
++ * files (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use,
++ * copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following
++ * conditions:
++ *
++ * The above copyright notice and this permission notice shall be
++ * included in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++/dts-v1/;
++#include "sun7i-a20.dtsi"
++#include "sunxi-common-regulators.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/ {
++ model = "Retro Games C=64 Mini";
++ compatible = "rgl,c64-mini", "allwinner,sun7i-a20";
++
++ aliases {
++ serial0 = &uart0;
++ };
++
++ chosen {
++ stdout-path = "serial0:115200n8";
++ };
++
++ hdmi-connector {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi_con_in: endpoint {
++ remote-endpoint = <&hdmi_out_con>;
++ };
++ };
++ };
++
++ leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&led_pins_olinuxinolime>;
++
++ green {
++ label = "a20-olinuxino-lime:green:usr";
++ gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>;
++ default-state = "on";
++ };
++ };
++};
++
++&de {
++ status = "okay";
++};
++
++&ehci0 {
++ status = "okay";
++};
++
++&ehci1 {
++ status = "okay";
++};
++
++&hdmi {
++ status = "okay";
++};
++
++&hdmi_out {
++ hdmi_out_con: endpoint {
++ remote-endpoint = <&hdmi_con_in>;
++ };
++};
++
++&i2c0 {
++ status = "okay";
++
++ axp209: pmic@34 {
++ compatible = "x-powers,axp209";
++ reg = <0x34>;
++ interrupt-parent = <&nmi_intc>;
++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++
++ interrupt-controller;
++ #interrupt-cells = <1>;
++ };
++};
++
++&i2c1 {
++ status = "okay";
++
++ eeprom: eeprom@50 {
++ compatible = "atmel,24c16";
++ reg = <0x50>;
++ pagesize = <16>;
++ };
++};
++
++&mmc0 {
++ vmmc-supply = <®_vcc3v3>;
++ bus-width = <4>;
++ cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; /* PH1 */
++ status = "okay";
++};
++
++&ohci0 {
++ status = "okay";
++};
++
++&ohci1 {
++ status = "okay";
++};
++
++&otg_sram {
++ status = "okay";
++};
++
++&pio {
++ led_pins_olinuxinolime: led_pins@0 {
++ pins = "PH2";
++ function = "gpio_out";
++ drive-strength = <20>;
++ };
++
++ usb0_id_detect_pin: usb0_id_detect_pin@0 {
++ pins = "PH4";
++ function = "gpio_in";
++ bias-pull-up;
++ };
++
++ usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
++ pins = "PH5";
++ function = "gpio_in";
++ bias-pull-down;
++ };
++
++ nand_pins: nand-pins {
++ pins = "PC0", "PC1", "PC2", "PC5",
++ "PC8", "PC9", "PC10", "PC11",
++ "PC12", "PC13", "PC14", "PC15";
++ function = "nand0";
++ };
++
++ nand_pins_cs0: nand-pins-cs0 {
++ pins = "PC4";
++ function = "nand0";
++ bias-pull-up;
++ };
++
++ nand_pins_cs1: nand-pins-cs1 {
++ pins = "PC3";
++ function = "nand0";
++ bias-pull-up;
++ };
++
++ nand_pins_rb0: nand-pins-rb0 {
++ pins = "PC6";
++ function = "nand0";
++ bias-pull-up;
++ };
++
++ nand_pins_rb1: nand-pins-rb1 {
++ pins = "PC7";
++ function = "nand0";
++ bias-pull-up;
++ };
++};
++
++®_usb0_vbus {
++ status = "okay";
++};
++
++®_usb1_vbus {
++ status = "okay";
++};
++
++®_usb2_vbus {
++ status = "okay";
++};
++
++&uart0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pb_pins>;
++ status = "okay";
++};
++
++&usb_otg {
++ dr_mode = "otg";
++ status = "okay";
++};
++
++&usbphy {
++ pinctrl-names = "default";
++ pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
++ usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
++ usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
++ usb0_vbus-supply = <®_usb0_vbus>;
++ usb1_vbus-supply = <®_usb1_vbus>;
++ usb2_vbus-supply = <®_usb2_vbus>;
++ status = "okay";
++};
++
++&nfc {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&nand_pins>, <&nand_pins_cs0>, <&nand_pins_rb0>;
++
++ /* ESMT NAND 128MiB 3,3V 8-bit */
++ nand@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ reg = <0>;
++ allwinner,rb = <0>;
++ nand-ecc-mode = "hw";
++ nand-ecc-strength = <16>;
++ nand-ecc-step-size = <1024>;
++ };
++};
+diff -ruN u-boot-2020.04.old/configs/rgl_c64mini_defconfig u-boot-2020.04/configs/rgl_c64mini_defconfig
+--- u-boot-2020.04.old/configs/rgl_c64mini_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2020.04/configs/rgl_c64mini_defconfig 2020-07-07 23:52:25.574583780 +0200
+@@ -0,0 +1,14 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_SPL=y
++CONFIG_MACH_SUN7I=y
++CONFIG_DRAM_CLK=384
++CONFIG_MMC0_CD_PIN="PH1"
++CONFIG_I2C1_ENABLE=y
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_SPL_I2C_SUPPORT=y
++CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-rgl-c64mini"
++CONFIG_AXP_ALDO3_VOLT=2800
++CONFIG_AXP_ALDO4_VOLT=2800
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_OHCI_HCD=y
+diff -ruN a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+--- a/arch/arm/dts/Makefile 2021-01-18 10:07:44.318693224 +0100
++++ b/arch/arm/dts/Makefile 2021-01-18 10:35:00.953333457 +0100
+@@ -491,6 +491,7 @@
+ sun7i-a20-pcduino3.dtb \
+ sun7i-a20-pcduino3-nano.dtb \
+ sun7i-a20-primo73.dtb \
++ sun7i-a20-rgl-c64mini.dtb \
+ sun7i-a20-wexler-tab7200.dtb \
+ sun7i-a20-wits-pro-a20-dkt.dtb \
+ sun7i-a20-yones-toptech-bd1078.dtb
--- /dev/null
+diff -ruN a/arch/arm/dts/sun5i-r8-chip.dts b/arch/arm/dts/sun5i-r8-chip.dts
+--- a/arch/arm/dts/sun5i-r8-chip.dts 2019-08-20 00:53:42.243401559 +0200
++++ b/arch/arm/dts/sun5i-r8-chip.dts 2019-08-20 00:34:38.000000000 +0200
+@@ -175,6 +175,16 @@
+ status = "okay";
+ };
+
++&mmc2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&chip_sdio_pin>;
++ vmmc-supply = <®_vcc3v3>;
++/* mmc-pwrseq = <&mmc2_pwrseq>;*/
++ bus-width = <4>;
++ broken-cd;
++ status = "okay";
++};
++
+ &ohci0 {
+ status = "okay";
+ };
+@@ -204,6 +214,11 @@
+ function = "gpio_in";
+ bias-pull-up;
+ };
++
++ chip_sdio_pin: chip_sdio_pin@0 {
++ pins = "PE4", "PE5", "PE6", "PE7", "PE8", "PE9";
++ function = "mmc2";
++ };
+ };
+
+ ®_dcdc2 {
+diff -ruN configs.old/CHIP_defconfig configs/CHIP_defconfig
+--- a/configs/CHIP_defconfig 2019-01-14 23:02:36.000000000 +0100
++++ b/configs/CHIP_defconfig 2019-08-20 01:14:47.076936367 +0200
+@@ -13,7 +13,6 @@
+ # CONFIG_SPL_EFI_PARTITION is not set
+ CONFIG_DEFAULT_DEVICE_TREE="sun5i-r8-chip"
+ CONFIG_DFU_RAM=y
+-# CONFIG_MMC is not set
+ CONFIG_AXP_ALDO3_VOLT=3300
+ CONFIG_AXP_ALDO4_VOLT=3300
+ CONFIG_CONS_INDEX=2
--- /dev/null
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -539,7 +539,8 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
+ sun8i-h3-orangepi-plus.dtb \
+ sun8i-h3-orangepi-plus2e.dtb \
+ sun8i-h3-orangepi-zero-plus2.dtb \
+- sun8i-h3-rervision-dvk.dtb
++ sun8i-h3-rervision-dvk.dtb \
++ sun8i-h3-zeropi.dtb
+ dtb-$(CONFIG_MACH_SUN8I_R40) += \
+ sun8i-r40-bananapi-m2-ultra.dtb \
+ sun8i-v40-bananapi-m2-berry.dtb
+--- /dev/null
++++ b/arch/arm/dts/sun8i-h3-zeropi.dts
+@@ -0,0 +1,66 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "sun8i-h3-nanopi.dtsi"
++
++/ {
++ model = "FriendlyElec ZeroPi";
++ compatible = "friendlyarm,zeropi", "allwinner,sun8i-h3";
++
++ aliases {
++ ethernet0 = &emac;
++ };
++
++ reg_gmac_3v3: gmac-3v3 {
++ compatible = "regulator-fixed";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gmac_power_pin_nanopi>;
++ regulator-name = "gmac-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ startup-delay-us = <100000>;
++ enable-active-high;
++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
++ };
++};
++
++&ehci0 {
++ status = "okay";
++};
++
++&ohci0 {
++ status = "okay";
++};
++
++&pio {
++ gmac_power_pin_nanopi: gmac_power_pin@0 {
++ pins = "PD6";
++ function = "gpio_out";
++ };
++};
++
++&external_mdio {
++ ext_rgmii_phy: ethernet-phy@1 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <7>;
++ };
++};
++
++&emac {
++ pinctrl-names = "default";
++ pinctrl-0 = <&emac_rgmii_pins>;
++ phy-supply = <®_gmac_3v3>;
++ phy-handle = <&ext_rgmii_phy>;
++ phy-mode = "rgmii";
++
++ allwinner,leds-active-low;
++ status = "okay";
++};
++
++&usb_otg {
++ status = "okay";
++ dr_mode = "peripheral";
++};
++
++&usbphy {
++ usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
++};
--- /dev/null
+--- /dev/null
++++ b/configs/zeropi_defconfig
+@@ -0,0 +1,21 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_MACH_SUN8I_H3=y
++CONFIG_DRAM_CLK=408
++CONFIG_DRAM_ZQ=3881979
++CONFIG_DRAM_ODT_EN=y
++CONFIG_MACPWR="PD6"
++# CONFIG_VIDEO_DE2 is not set
++CONFIG_NR_DRAM_BANKS=1
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-zeropi"
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_CONSOLE_MUX=y
++CONFIG_SPL=y
++CONFIG_SYS_CLK_FREQ=480000000
++# CONFIG_CMD_IMLS is not set
++# CONFIG_CMD_FLASH is not set
++# CONFIG_CMD_FPGA is not set
++CONFIG_SUN8I_EMAC=y
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_HCD=y
++CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
--- /dev/null
+From 0e8043aff1aae95d1f7b7422b91b57d9569860d3 Mon Sep 17 00:00:00 2001
+From: Jayantajit Gogoi <jayanta.gogoi525@gmail.com>
+Date: Mon, 12 Oct 2020 18:39:53 +0000
+Subject: [PATCH] sunxi: add support for FriendlyARM NanoPi R1
+
+Signed-off-by: Jayantajit Gogoi <jayanta.gogoi525@gmail.com>
+---
+ arch/arm/dts/Makefile | 1 +
+ arch/arm/dts/sun8i-h3-nanopi-r1.dts | 146 ++++++++++++++++++++++++++++
+ configs/nanopi_r1_defconfig | 22 +++++
+ 3 files changed, 169 insertions(+)
+ create mode 100644 arch/arm/dts/sun8i-h3-nanopi-r1.dts
+ create mode 100644 configs/nanopi_r1_defconfig
+
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -531,6 +531,7 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
+ sun8i-h3-nanopi-m1-plus.dtb \
+ sun8i-h3-nanopi-neo.dtb \
+ sun8i-h3-nanopi-neo-air.dtb \
++ sun8i-h3-nanopi-r1.dtb \
+ sun8i-h3-orangepi-2.dtb \
+ sun8i-h3-orangepi-lite.dtb \
+ sun8i-h3-orangepi-one.dtb \
+--- /dev/null
++++ b/arch/arm/dts/sun8i-h3-nanopi-r1.dts
+@@ -0,0 +1,146 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (C) 2019 Igor Pecovnik <igor@armbian.com>
++ * Copyright (C) 2020 Jayantajit Gogoi <jayanta.gogoi525@gmail.com>
++ */
++
++/* NanoPi R1 is based on the NanoPi-H3 design from FriendlyARM */
++#include "sun8i-h3-nanopi.dtsi"
++
++/ {
++ model = "FriendlyARM NanoPi R1";
++ compatible = "friendlyarm,nanopi-r1", "allwinner,sun8i-h3";
++
++ reg_gmac_3v3: gmac-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "gmac-3v3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ startup-delay-us = <100000>;
++ enable-active-high;
++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
++ };
++
++ vdd_cpux: gpio-regulator {
++ compatible = "regulator-gpio";
++ pinctrl-names = "default";
++ regulator-name = "vdd-cpux";
++ regulator-type = "voltage";
++ regulator-boot-on;
++ regulator-always-on;
++ regulator-min-microvolt = <1100000>;
++ regulator-max-microvolt = <1300000>;
++ regulator-ramp-delay = <50>;
++ gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>;
++ gpios-states = <0x1>;
++ states = <1100000 0x0
++ 1300000 0x1>;
++ };
++
++ wifi_pwrseq: wifi_pwrseq {
++ compatible = "mmc-pwrseq-simple";
++ pinctrl-names = "default";
++ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>;
++ };
++
++ leds {
++ /delete-node/ pwr;
++ status {
++ label = "nanopi:red:status";
++ gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>;
++ linux,default-trigger = "heartbeat";
++ };
++
++ wan {
++ label = "nanopi:green:wan";
++ gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>;
++ };
++
++ lan {
++ label = "nanopi:green:lan";
++ gpios = <&pio 0 9 GPIO_ACTIVE_HIGH>;
++ };
++ };
++
++ r_gpio_keys {
++ pinctrl-names = "default";
++ pinctrl-0 = <&sw_r_npi>;
++
++ /delete-node/ k1;
++ reset {
++ label = "reset";
++ linux,code = <KEY_RESTART>;
++ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
++ };
++ };
++};
++
++&cpu0 {
++ cpu-supply = <&vdd_cpux>;
++};
++
++&ehci1 {
++ status = "okay";
++};
++
++&ehci2 {
++ status = "okay";
++};
++
++&emac {
++ pinctrl-names = "default";
++ pinctrl-0 = <&emac_rgmii_pins>;
++ phy-supply = <®_gmac_3v3>;
++ phy-handle = <&ext_rgmii_phy>;
++ phy-mode = "rgmii";
++ status = "okay";
++};
++
++&external_mdio {
++ ext_rgmii_phy: ethernet-phy@1 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <7>;
++ };
++};
++
++&mmc1 {
++ vmmc-supply = <®_vcc3v3>;
++ vqmmc-supply = <®_vcc3v3>;
++ mmc-pwrseq = <&wifi_pwrseq>;
++ bus-width = <4>;
++ non-removable;
++ status = "okay";
++
++ sdio_wifi: sdio_wifi@1 {
++ reg = <1>;
++ compatible = "brcm,bcm4329-fmac";
++ interrupt-parent = <&pio>;
++ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "host-wake";
++ };
++};
++
++&mmc2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&mmc2_8bit_pins>;
++ vmmc-supply = <®_vcc3v3>;
++ vqmmc-supply = <®_vcc3v3>;
++ bus-width = <8>;
++ non-removable;
++ status = "okay";
++};
++
++&ohci1 {
++ status = "okay";
++};
++
++&ohci2 {
++ status = "okay";
++};
++
++&r_pio {
++ sw_r_npi: key_pins {
++ pins = "PL3";
++ function = "gpio_in";
++ };
++};
+--- /dev/null
++++ b/configs/nanopi_r1_defconfig
+@@ -0,0 +1,22 @@
++CONFIG_ARM=y
++CONFIG_ARCH_SUNXI=y
++CONFIG_SPL=y
++CONFIG_MACH_SUN8I_H3=y
++CONFIG_DRAM_CLK=408
++CONFIG_DRAM_ZQ=3881979
++CONFIG_DRAM_ODT_EN=y
++CONFIG_MACPWR="PD6"
++# CONFIG_VIDEO_DE2 is not set
++CONFIG_NR_DRAM_BANKS=1
++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
++CONFIG_CONSOLE_MUX=y
++CONFIG_SYS_CLK_FREQ=480000000
++# CONFIG_CMD_FLASH is not set
++# CONFIG_SPL_DOS_PARTITION is not set
++# CONFIG_SPL_EFI_PARTITION is not set
++CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-r1"
++CONFIG_SUN8I_EMAC=y
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_OHCI_HCD=y
++CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
++CONFIG_MMC_SUNXI_SLOT_EXTRA=2
--- /dev/null
+setenv fdt_high ffffffff
+setenv loadkernel fatload mmc 0 \$kernel_addr_r uImage
+setenv loaddtb fatload mmc 0 \$fdt_addr_r dtb
+setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
+setenv uenvcmd run loadkernel \&\& run loaddtb \&\& bootm \$kernel_addr_r - \$fdt_addr_r
+run uenvcmd
--- /dev/null
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+ARCH:=arm
+BOARD:=suniv
+BOARDNAME:=Allwinner F1C-series
+FEATURES:=gpio ramdisk rtc squashfs
+DEVICE_TYPE:=developerboard
+SUBTARGETS:=arm926ej-s
+
+MAINTAINER:=Zoltan HERPAI <wigyori@uid0.hu>
+
+KERNEL_PATCHVER:=5.10
+
+include $(INCLUDE_DIR)/target.mk
+
+DEFAULT_PACKAGES += \
+ kmod-button-hotplug kmod-input-gpio-keys-polled \
+ kmod-ledtrig-timer kmod-leds-gpio uboot-envtools
+
+KERNELNAME:=zImage dtbs
+
+$(eval $(call BuildTarget))
--- /dev/null
+CONFIG_ARCH_32BIT_OFF_T=y
+CONFIG_ARCH_HAS_BINFMT_FLAT=y
+CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y
+CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_DWMAC_SUN8I=y
+# CONFIG_MACH_SUN4I is not set
+# CONFIG_MACH_SUN5I is not set
+CONFIG_MDIO_BUS_MUX=y
+# CONFIG_PINCTRL_SUN50I_A64 is not set
+# CONFIG_PINCTRL_SUN50I_A64_R is not set
+# CONFIG_PINCTRL_SUN50I_H5 is not set
+# CONFIG_PINCTRL_SUN50I_H6 is not set
+# CONFIG_PINCTRL_SUN50I_H6_R is not set
+CONFIG_UNWINDER_ARM=y
--- /dev/null
+#
+# Copyright (C) 2017 Hauke Mehrtens
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+BOARDNAME:=Allwinner F1C100s
+CPU_TYPE:=arm926ej-s
--- /dev/null
+#!/bin/sh
+# Copyright (C) 2013-2019 OpenWrt.org
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+board=$(board_name)
+
+case "$board" in
+*)
+ ucidef_set_interface_lan 'eth0'
+ ;;
+esac
+
+board_config_flush
+
+exit 0
--- /dev/null
+REQUIRE_IMAGE_METADATA=1
+
+platform_check_image() {
+ return 0
+}
+
+platform_do_upgrade() {
+ return 0
+}
--- /dev/null
+CONFIG_AHCI_SUNXI=m
+# CONFIG_AIO is not set
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_ARCH_32BIT_OFF_T=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_KEEP_MEMBLOCK=y
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_ARCH_MULTIPLATFORM=y
+CONFIG_ARCH_MULTI_CPU_AUTO=y
+# CONFIG_ARCH_MULTI_V4 is not set
+# CONFIG_ARCH_MULTI_V4T is not set
+CONFIG_ARCH_MULTI_V4_V5=y
+CONFIG_ARCH_MULTI_V5=y
+CONFIG_ARCH_NR_GPIO=416
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM=y
+# CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM is not set
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_UNWIND=y
+CONFIG_ATA=y
+CONFIG_ATAGS=y
+# CONFIG_ATA_SFF is not set
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_AXP20X_POWER=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
+CONFIG_BINFMT_MISC=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_PM=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BOUNCE=y
+CONFIG_CAN=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLK_SUNXI=y
+CONFIG_CLK_SUNXI_CLOCKS=y
+CONFIG_CLK_SUNXI_PRCM_SUN6I=y
+CONFIG_CLK_SUNXI_PRCM_SUN8I=y
+CONFIG_CLK_SUNXI_PRCM_SUN9I=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONNECTOR=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_COREDUMP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_ARM926T=y
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_THERMAL=y
+CONFIG_CPU_THUMB_CAPABLE=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_USE_DOMAINS=y
+CONFIG_CRASH_CORE=y
+CONFIG_CRASH_DUMP=y
+CONFIG_CRC16=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_DEV_SUN4I_SS=y
+CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_LIB_DES=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_REMAP=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DWMAC_GENERIC=y
+# CONFIG_DWMAC_SUN8I is not set
+CONFIG_DWMAC_SUNXI=y
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_ELF_CORE=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_EXT4_FS=y
+CONFIG_EXTCON=y
+CONFIG_F2FS_FS=y
+CONFIG_FAT_FS=y
+CONFIG_FB=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_LITTLE_ENDIAN=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_SIMPLE=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FRAME_WARN=2048
+CONFIG_FREEZER=y
+CONFIG_FS_IOMAP=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GLOB=y
+CONFIG_GPIOLIB=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+CONFIG_HWMON=y
+CONFIG_HW_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=y
+CONFIG_HZ=100
+CONFIG_HZ_100=y
+CONFIG_HZ_FIXED=0
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_IIO=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INPUT=y
+CONFIG_INPUT_AXP20X_PEK=y
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IPV6=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_IPV6_SEG6_LWTUNNEL is not set
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_COMMON=y
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_UNCOMPRESSED=y
+CONFIG_KEXEC=y
+CONFIG_KEXEC_CORE=y
+CONFIG_KEYBOARD_SUN4I_LRADC=y
+CONFIG_KSM=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_MACH_SUNIV=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_SUN4I=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MFD_AXP20X=y
+CONFIG_MFD_AXP20X_I2C=y
+CONFIG_MFD_AXP20X_RSB=y
+CONFIG_MFD_CORE=y
+CONFIG_MFD_SUN6I_PRCM=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_SUNXI=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_FIT_FW=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_KUSER_HELPERS=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_NETFILTER_INGRESS=y
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_NAT=m
+CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NET_INGRESS=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NET_VENDOR_ALLWINNER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_RTCACHE=m
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_FLOW_TABLE=m
+CONFIG_NF_FLOW_TABLE_HW=m
+CONFIG_NF_LOG_COMMON=m
+CONFIG_NF_LOG_IPV4=m
+CONFIG_NF_LOG_IPV6=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_MASQUERADE=y
+CONFIG_NF_NAT_REDIRECT=y
+CONFIG_NF_REJECT_IPV4=m
+CONFIG_NF_REJECT_IPV6=m
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SUNXI_SID=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PAGE_POOL=y
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+CONFIG_PHYLINK=y
+CONFIG_PHY_SUN4I_USB=y
+# CONFIG_PHY_SUN6I_MIPI_DPHY is not set
+# CONFIG_PHY_SUN9I_USB is not set
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AXP209=y
+# CONFIG_PINCTRL_SINGLE is not set
+# CONFIG_PINCTRL_SUN4I_A10 is not set
+# CONFIG_PINCTRL_SUN50I_A64 is not set
+# CONFIG_PINCTRL_SUN50I_A64_R is not set
+# CONFIG_PINCTRL_SUN50I_H5 is not set
+# CONFIG_PINCTRL_SUN50I_H6 is not set
+# CONFIG_PINCTRL_SUN50I_H6_R is not set
+# CONFIG_PINCTRL_SUN5I is not set
+# CONFIG_PINCTRL_SUN6I_A31 is not set
+# CONFIG_PINCTRL_SUN6I_A31_R is not set
+# CONFIG_PINCTRL_SUN8I_A23 is not set
+# CONFIG_PINCTRL_SUN8I_A23_R is not set
+# CONFIG_PINCTRL_SUN8I_A33 is not set
+# CONFIG_PINCTRL_SUN8I_A83T is not set
+# CONFIG_PINCTRL_SUN8I_A83T_R is not set
+# CONFIG_PINCTRL_SUN8I_H3 is not set
+# CONFIG_PINCTRL_SUN8I_H3_R is not set
+# CONFIG_PINCTRL_SUN8I_V3S is not set
+# CONFIG_PINCTRL_SUN9I_A80 is not set
+# CONFIG_PINCTRL_SUN9I_A80_R is not set
+CONFIG_PINCTRL_SUNIV_F1C100S=y
+CONFIG_PINCTRL_SUNXI=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+CONFIG_PM_OPP=y
+CONFIG_PM_SLEEP=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PPP=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPS=y
+CONFIG_PREEMPT=y
+CONFIG_PREEMPTION=y
+CONFIG_PREEMPT_COUNT=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PROC_EVENTS=y
+CONFIG_PROC_VMCORE=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PWM=y
+CONFIG_PWM_SUN4I=y
+CONFIG_PWM_SYSFS=y
+CONFIG_RATIONAL=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_IRQ=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_AXP20X=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_SY8106A=y
+CONFIG_RELAY=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
+CONFIG_RESET_SUNXI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_I2C_AND_SPI=y
+CONFIG_RTC_MC146818_LIB=y
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_PMP=y
+CONFIG_SCSI=y
+CONFIG_SDIO_UART=y
+CONFIG_SECURITYFS=y
+# CONFIG_SENSORS_DRIVETEMP is not set
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_DWLIB=y
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=8
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SG_POOL=y
+CONFIG_SLHC=m
+CONFIG_SND=y
+CONFIG_SND_COMPRESS_OFFLOAD=y
+CONFIG_SND_JACK=y
+CONFIG_SND_JACK_INPUT_DEV=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SUN4I_I2S is not set
+# CONFIG_SND_SUN4I_SPDIF is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_SUN4I=y
+# CONFIG_SPI_SUN6I is not set
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+CONFIG_SRCU=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_PLATFORM=y
+# CONFIG_STMMAC_SELFTESTS is not set
+CONFIG_SUN4I_EMAC=m
+CONFIG_SUN4I_TIMER=y
+# CONFIG_SUN8I_A83T_CCU is not set
+CONFIG_SUN8I_DE2_CCU=y
+CONFIG_SUN8I_R_CCU=y
+CONFIG_SUNIV_F1C100S_CCU=y
+CONFIG_SUNXI_CCU=y
+CONFIG_SUNXI_RSB=y
+CONFIG_SUNXI_SRAM=y
+CONFIG_SUNXI_WATCHDOG=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SWCONFIG=y
+CONFIG_SWCONFIG_B53=y
+CONFIG_SWCONFIG_B53_PHY_DRIVER=y
+CONFIG_SWCONFIG_B53_PHY_FIXUP=y
+CONFIG_SWPHY=y
+CONFIG_SYSFS_SYSCALL=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_OF=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+CONFIG_TOUCHSCREEN_SUN4I=y
+CONFIG_TREE_SRCU=y
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_UNWINDER_ARM=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_NET_DRIVERS=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USERIO=y
+CONFIG_USE_OF=y
+CONFIG_VFAT_FS=y
+CONFIG_VFP=y
+CONFIG_VHOST=y
+CONFIG_VHOST_NET=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_XXHASH=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ZBOOT_ROM_TEXT=0
--- /dev/null
+config SUNXI_SD_BOOT_PARTSIZE
+ int "Boot (SD Card) filesystem partition size (in MB)"
+ depends on TARGET_suniv
+ default 20
+
--- /dev/null
+#
+# Copyright (C) 2013-2016 OpenWrt.org
+# Copyright (C) 2016 Yousong Zhou
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+FAT32_BLOCK_SIZE=1024
+FAT32_BLOCKS=$(shell echo $$(($(CONFIG_SUNXI_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
+
+DEVICE_VARS := SUNXI_DTS SUNXI_DTS_DIR
+KERNEL_LOADADDR:=0x40008000
+
+define Build/sunxi-sdcard
+ rm -f $@.boot
+ mkfs.fat $@.boot -C $(FAT32_BLOCKS)
+
+ mcopy -i $@.boot $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-boot.scr ::boot.scr
+ mcopy -i $@.boot $(DTS_DIR)/$(SUNXI_DTS).dtb ::dtb
+ mcopy -i $@.boot $(IMAGE_KERNEL) ::uImage
+ ./gen_sunxi_sdcard_img.sh $@ \
+ $@.boot \
+ $(IMAGE_ROOTFS) \
+ $(CONFIG_SUNXI_SD_BOOT_PARTSIZE) \
+ $(CONFIG_TARGET_ROOTFS_PARTSIZE) \
+ $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-u-boot-with-spl.bin
+ rm -f $@.boot
+endef
+
+# why \x00\x00\x00\x00 for zImage-initramfs
+define Device/Default
+ PROFILES := Default
+ KERNEL_NAME := zImage
+ KERNEL := kernel-bin | uImage none
+ IMAGES := sdcard.img.gz
+ IMAGE/sdcard.img.gz := sunxi-sdcard | append-metadata | gzip
+ SUPPORTED_DEVICES := $(subst _,$(comma),$(1))
+ SUNXI_DTS_DIR :=
+ SUNXI_DTS = $$(SUNXI_DTS_DIR)$$(SOC)-$(lastword $(subst _, ,$(1)))
+endef
+
+include $(SUBTARGET).mk
+
+$(eval $(call BuildImage))
--- /dev/null
+#
+# Copyright (C) 2013-2021 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Device/licheepi-nano
+ DEVICE_VENDOR := LicheePi
+ DEVICE_MODEL := Nano
+ DEVICE_PACKAGES:=kmod-rtc-sunxi kmod-rtl8192cu
+ SOC := suniv-f1c100s
+endef
+TARGET_DEVICES += licheepi-nano
+
+#define Device/cubietech_a10-cubieboard
+# DEVICE_VENDOR := Cubietech
+# DEVICE_MODEL := Cubieboard
+# DEVICE_PACKAGES:=kmod-ata-sunxi kmod-sun4i-emac kmod-rtc-sunxi
+# SOC := sun4i
+#endef
+#TARGET_DEVICES += cubietech_a10-cubieboard
+
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+set -ex
+[ $# -eq 6 ] || {
+ echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size> <u-boot image>"
+ exit 1
+}
+
+OUTPUT="$1"
+BOOTFS="$2"
+ROOTFS="$3"
+BOOTFSSIZE="$4"
+ROOTFSSIZE="$5"
+UBOOT="$6"
+
+head=4
+sect=63
+
+set $(ptgen -o $OUTPUT -h $head -s $sect -l 1024 -t c -p ${BOOTFSSIZE}M -t 83 -p ${ROOTFSSIZE}M)
+
+BOOTOFFSET="$(($1 / 512))"
+BOOTSIZE="$(($2 / 512))"
+ROOTFSOFFSET="$(($3 / 512))"
+ROOTFSSIZE="$(($4 / 512))"
+
+dd bs=1024 if="$UBOOT" of="$OUTPUT" seek=8 conv=notrunc
+dd bs=512 if="$BOOTFS" of="$OUTPUT" seek="$BOOTOFFSET" conv=notrunc
+dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc
--- /dev/null
+Allwinner ARMv5 F1C100s has similar sram controller to sun4i A10
+Add compatible strings for it.
+
+Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
+Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
+---
+ drivers/soc/sunxi/sunxi_sram.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
+index b4b0f34..27f0607 100644
+--- a/drivers/soc/sunxi/sunxi_sram.c
++++ b/drivers/soc/sunxi/sunxi_sram.c
+@@ -99,6 +99,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
+ .compatible = "allwinner,sun50i-a64-sram-c",
+ .data = &sun50i_a64_sram_c.data,
+ },
++ {
++ .compatible = "allwinner,suniv-f1c100s-sram-d",
++ .data = &sun4i_a10_sram_d.data,
++ },
+ {}
+ };
+
+@@ -389,6 +393,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
+ .compatible = "allwinner,sun50i-a64-system-control",
+ .data = &sun50i_a64_sramc_variant,
+ },
++ {
++ .compatible = "allwinner,suniv-f1c100s-system-control",
++ .data = &sun4i_a10_sramc_variant,
++ },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
+
+Allwinner ARMv5 F1C100s has similar watchdog timer to sun6i A31.
+Add compatible string for it.
+
+Signed-off-by: Mesih Kilinc <mesihkilinc@gmail.com>
+---
+ drivers/watchdog/sunxi_wdt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c
+index c6c7365..bc70742 100644
+--- a/drivers/watchdog/sunxi_wdt.c
++++ b/drivers/watchdog/sunxi_wdt.c
+@@ -227,6 +227,7 @@ static const struct sunxi_wdt_reg sun6i_wdt_reg = {
+ static const struct of_device_id sunxi_wdt_dt_ids[] = {
+ { .compatible = "allwinner,sun4i-a10-wdt", .data = &sun4i_wdt_reg },
+ { .compatible = "allwinner,sun6i-a31-wdt", .data = &sun6i_wdt_reg },
++ { .compatible = "allwinner,suniv-f1c100s-wdt", .data = &sun6i_wdt_reg },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
+