Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sunxi
This is the promised second part of the sunxi PR for 2022.04, albeit
technially outside of the merge window. We were working on this full
steam since the beginning of the year, and it deserves to be merged,
I think.
The main attraction is support for the F1C100s SoC, which sports a
venerable ARM926 core. Support for this SoC and the LicheePi Nano board
has been in Linux for years, and U-Boot patches were posted mid last
year already.
The new SoC using ARMv5 also means that the bulk of the new code should
not touch any existing boards, although we did some refactorings first,
of course, which actually cleans up some existing sunxi code.
Compile tested for all 160 sunxi boards, and briefly tested on BananaPi M1,
OrangePi Zero, Pine64 and Pine-H64. Tested by others on their boards,
including F1C100s and F1C200s devices.
diff --git a/Kconfig b/Kconfig
index b0e45cd..acf146c 100644
--- a/Kconfig
+++ b/Kconfig
@@ -246,9 +246,10 @@
config SYS_MALLOC_LEN
hex "Define memory for Dynamic allocation"
default 0x2000000 if ARCH_ROCKCHIP || ARCH_OMAP2PLUS || ARCH_MESON
- default 0x4020000 if ARCH_SUNXI && !MACH_SUN8I_V3S
default 0x200000 if ARCH_BMIPS || X86
- default 0x220000 if ARCH_SUNXI && MACH_SUN8I_V3S
+ default 0x120000 if MACH_SUNIV
+ default 0x220000 if MACH_SUN8I_V3S
+ default 0x4020000 if ARCH_SUNXI
default 0x400000
help
This defines memory to be allocated for Dynamic allocation
@@ -391,8 +392,9 @@
hex "Address in memory to use by default"
default 0x01000000 if ARCH_SOCFPGA
default 0x02000000 if PPC || X86
+ default 0x81000000 if MACH_SUNIV
default 0x22000000 if MACH_SUN9I
- default 0x42000000 if ARCH_SUNXI && !MACH_SUN9I
+ default 0x42000000 if ARCH_SUNXI
default 0x82000000 if ARCH_KEYSTONE || ARCH_OMAP2PLUS || ARCH_K3
default 0x82000000 if ARCH_MX6 && (MX6SL || MX6SLL || MX6SX || MX6UL || MX6ULL)
default 0x12000000 if ARCH_MX6 && !(MX6SL || MX6SLL || MX6SX || MX6UL || MX6ULL)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index eb0f5bc..9a62b55 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -452,9 +452,6 @@
values, then choose this option, and create a file included as
<asm/arch/boot0.h> which contains the required assembler code.
-config ARM_CORTEX_CPU_IS_UP
- bool
-
config USE_ARCH_MEMCPY
bool "Use an assembly optimized implementation of memcpy"
default y if !ARM64
diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
index b901b7c..7f1436d 100644
--- a/arch/arm/cpu/arm926ejs/Makefile
+++ b/arch/arm/cpu/arm926ejs/Makefile
@@ -15,6 +15,7 @@
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/cpu.c b/arch/arm/cpu/arm926ejs/cpu.c
index 93d7a02..2ce413a 100644
--- a/arch/arm/cpu/arm926ejs/cpu.c
+++ b/arch/arm/cpu/arm926ejs/cpu.c
@@ -21,6 +21,19 @@
static void cache_flush(void);
+/************************************************************
+ * sdelay() - simple spin loop. Will be constant time as
+ * its generally used in bypass conditions only. This
+ * is necessary until timers are accessible.
+ *
+ * not inline to increase chances its in cache when called
+ *************************************************************/
+void sdelay(unsigned long loops)
+{
+ __asm__ volatile ("1:\n" "subs %0, %1, #1\n"
+ "bne 1b":"=r" (loops):"0"(loops));
+}
+
int cleanup_before_linux (void)
{
/*
diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S
index 0afcc47..aca7793 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 @@
#endif
mov pc, lr /* back to my caller */
#endif /* CONFIG_IS_ENABLED(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)
diff --git a/arch/arm/cpu/arm926ejs/sunxi/Makefile b/arch/arm/cpu/arm926ejs/sunxi/Makefile
new file mode 100644
index 0000000..7d8b959
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/sunxi/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+# (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+
+obj-y += fel_utils.o
+CFLAGS_fel_utils.o := -marm
diff --git a/arch/arm/cpu/arm926ejs/sunxi/config.mk b/arch/arm/cpu/arm926ejs/sunxi/config.mk
new file mode 100644
index 0000000..76ffec9
--- /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 0000000..08be7ed
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Utility functions for FEL mode.
+ *
+ * Copyright (c) 2015 Google, Inc
+ */
+
+#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]
+ 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]
+ msr cpsr, r1 @ Write CPSR
+ bx lr
+ENDPROC(return_to_fel)
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 0000000..9a000ac
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018
+ * Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on arch/arm/cpu/armv7/sunxi/u-boot-spl.lds:
+ */
+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)
+ *(.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
+}
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index 60bb0a9..2eeef3c 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -76,4 +76,9 @@
Say Y here to use the long descriptor page table format. This is
required if U-Boot runs in HYP mode.
+config SPL_ARMV7_SET_CORTEX_SMPEN
+ bool
+ help
+ Enable the ARM Cortex ACTLR.SMP enable bit on SPL startup.
+
endif
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index 698e15b..af87a54 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -173,6 +173,17 @@
*
*************************************************************************/
ENTRY(cpu_init_cp15)
+
+#if CONFIG_IS_ENABLED(ARMV7_SET_CORTEX_SMPEN)
+ /*
+ * The Arm Cortex-A7 TRM says this bit must be enabled before
+ * "any cache or TLB maintenance operations are performed".
+ */
+ mrc p15, 0, r0, c1, c0, 1 @ read auxilary control register
+ orr r0, r0, #1 << 6 @ set SMP bit to enable coherency
+ mcr p15, 0, r0, c1, c0, 1 @ write auxilary control register
+#endif
+
/*
* Invalidate L1 I/D
*/
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 1d40d6a..3e975b3 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -5,11 +5,13 @@
# Based on some other Makefile
# (C) Copyright 2000-2003
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-obj-y += timer.o
obj-$(CONFIG_MACH_SUN6I) += tzpc.o
obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o
+obj-$(CONFIG_MACH_SUN6I) += sram.o
+obj-$(CONFIG_MACH_SUN8I) += sram.o
+
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ARMV7_PSCI) += psci.o
endif
diff --git a/arch/arm/cpu/armv7/sunxi/sram.c b/arch/arm/cpu/armv7/sunxi/sram.c
new file mode 100644
index 0000000..28564c2
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/sram.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SRAM init for older sunxi SoCs.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/io.h>
+
+void sunxi_sram_init(void)
+{
+ /*
+ * Undocumented magic taken from boot0, without this DRAM
+ * access gets messed up (seems cache related).
+ * The boot0 sources describe this as: "config ema for cache sram"
+ * Newer SoCs (A83T, H3 and anything beyond) don't need this anymore.
+ */
+ if (IS_ENABLED(CONFIG_MACH_SUN6I))
+ setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
+
+ if (IS_ENABLED(CONFIG_MACH_SUN8I)) {
+ uint version = sunxi_get_sram_id();
+
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_A23)) {
+ if (version == 0x1650)
+ setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
+ else /* 0x1661 ? */
+ setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0);
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_A33)) {
+ if (version != 0x1667)
+ setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0);
+ }
+ }
+}
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index d85ddde..85fe047 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -42,6 +42,5 @@
obj-$(CONFIG_S32V234) += s32v234/
obj-$(CONFIG_TARGET_HIKEY) += hisilicon/
obj-$(CONFIG_ARMV8_PSCI) += psci.o
-obj-$(CONFIG_ARCH_SUNXI) += lowlevel_init.o
obj-$(CONFIG_TARGET_BCMNS3) += bcmns3/
obj-$(CONFIG_XEN) += xen/
diff --git a/arch/arm/cpu/armv8/lowlevel_init.S b/arch/arm/cpu/armv8/lowlevel_init.S
deleted file mode 100644
index f4f0cdc..0000000
--- a/arch/arm/cpu/armv8/lowlevel_init.S
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * A lowlevel_init function that sets up the stack to call a C function to
- * perform further init.
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <linux/linkage.h>
-
-ENTRY(lowlevel_init)
- /*
- * Setup a temporary stack. Global data is not available yet.
- */
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
- ldr w0, =CONFIG_SPL_STACK
-#else
- ldr w0, =CONFIG_SYS_INIT_SP_ADDR
-#endif
- bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
-
- /*
- * Save the old LR(passed in x29) and the current LR to stack
- */
- stp x29, x30, [sp, #-16]!
-
- /*
- * 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
- ldp x29, x30, [sp]
- ret
-ENDPROC(lowlevel_init)
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0ed8de2..75ea7e8 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -504,6 +504,8 @@
stm32h743i-eval.dtb \
stm32h750i-art-pi.dtb
+dtb-$(CONFIG_MACH_SUNIV) += \
+ suniv-f1c100s-licheepi-nano.dtb
dtb-$(CONFIG_MACH_SUN4I) += \
sun4i-a10-a1000.dtb \
sun4i-a10-ba10-tvbox.dtb \
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 0000000..a1154e6
--- /dev/null
+++ b/arch/arm/dts/suniv-f1c100s-licheepi-nano.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR X11)
+/*
+ * Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+/dts-v1/;
+#include "suniv-f1c100s.dtsi"
+
+/ {
+ model = "Lichee Pi Nano";
+ compatible = "licheepi,licheepi-nano", "allwinner,suniv-f1c100s";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pe_pins>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/suniv-f1c100s.dtsi b/arch/arm/dts/suniv-f1c100s.dtsi
new file mode 100644
index 0000000..6100d3b
--- /dev/null
+++ b/arch/arm/dts/suniv-f1c100s.dtsi
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR X11)
+/*
+ * Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
+ * Copyright 2018 Mesih Kilinc <mesihkilinc@gmail.com>
+ */
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ clocks {
+ 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";
+ };
+ };
+
+ cpus {
+ cpu {
+ compatible = "arm,arm926ej-s";
+ device_type = "cpu";
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ sram-controller@1c00000 {
+ compatible = "allwinner,suniv-f1c100s-system-control",
+ "allwinner,sun4i-a10-system-control";
+ 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,suniv-f1c100s-sram-d",
+ "allwinner,sun4i-a10-sram-d";
+ reg = <0x0000 0x1000>;
+ status = "disabled";
+ };
+ };
+ };
+
+ ccu: clock@1c20000 {
+ compatible = "allwinner,suniv-f1c100s-ccu";
+ reg = <0x01c20000 0x400>;
+ clocks = <&osc24M>, <&osc32k>;
+ clock-names = "hosc", "losc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ intc: interrupt-controller@1c20400 {
+ compatible = "allwinner,suniv-f1c100s-ic";
+ reg = <0x01c20400 0x400>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ pio: pinctrl@1c20800 {
+ compatible = "allwinner,suniv-f1c100s-pinctrl";
+ reg = <0x01c20800 0x400>;
+ interrupts = <38>, <39>, <40>;
+ clocks = <&ccu 37>, <&osc24M>, <&osc32k>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #gpio-cells = <3>;
+
+ uart0_pe_pins: uart0-pe-pins {
+ pins = "PE0", "PE1";
+ function = "uart0";
+ };
+ };
+
+ timer@1c20c00 {
+ compatible = "allwinner,suniv-f1c100s-timer";
+ reg = <0x01c20c00 0x90>;
+ interrupts = <13>;
+ clocks = <&osc24M>;
+ };
+
+ wdt: watchdog@1c20ca0 {
+ compatible = "allwinner,suniv-f1c100s-wdt",
+ "allwinner,sun4i-a10-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 38>;
+ resets = <&ccu 24>;
+ status = "disabled";
+ };
+
+ uart1: serial@1c25400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c25400 0x400>;
+ interrupts = <2>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu 39>;
+ resets = <&ccu 25>;
+ status = "disabled";
+ };
+
+ uart2: serial@1c25800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c25800 0x400>;
+ interrupts = <3>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu 40>;
+ resets = <&ccu 26>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index f2d7361..0f573e6 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -12,7 +12,9 @@
/ {
aliases {
+#ifndef CONFIG_MACH_SUNIV
mmc0 = &mmc0;
+#endif
#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 2
mmc1 = &mmc2;
#endif
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index cbbe5c7..2cfd540 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_SUN50I_GEN_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 ee38712..7fcf340 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -226,7 +226,12 @@
#define CCM_PLL5_CTRL_SIGMA_DELTA_EN (0x1 << 24)
#define CCM_PLL5_CTRL_EN (0x1 << 31)
+#ifdef CONFIG_MACH_SUNIV
+/* suniv pll6 doesn't have postdiv 2, so k is set to 0 */
+#define PLL6_CFG_DEFAULT 0x90041801
+#else
#define PLL6_CFG_DEFAULT 0x90041811 /* 600 MHz */
+#endif
#define CCM_PLL6_CTRL_N_SHIFT 8
#define CCM_PLL6_CTRL_N_MASK (0x1f << CCM_PLL6_CTRL_N_SHIFT)
@@ -488,6 +493,14 @@
#define AHB_RESET_OFFSET_EPHY 2
#define AHB_RESET_OFFSET_LVDS 0
+/* apb1 reset */
+#ifdef CONFIG_MACH_SUNIV
+#define APB1_GATE_UART_SHIFT (20)
+#define APB1_GATE_TWI_SHIFT (16)
+#define APB1_RESET_UART_SHIFT (20)
+#define APB1_RESET_TWI_SHIFT (16)
+#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 d4c795d..f7ecc79 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -129,9 +129,15 @@
#define SUNXI_CPUCFG_BASE 0x01c25c00
#endif
+#ifdef CONFIG_MACH_SUNIV
+#define SUNXI_UART0_BASE 0x01c25000
+#define SUNXI_UART1_BASE 0x01c25400
+#define SUNXI_UART2_BASE 0x01c25800
+#else
#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
@@ -226,6 +232,7 @@
void sunxi_reset(void);
int sunxi_get_ss_bonding_id(void);
int sunxi_get_sid(unsigned int *sid);
+unsigned int sunxi_get_sram_id(void);
#endif /* __ASSEMBLY__ */
#endif /* _SUNXI_CPU_SUN4I_H */
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index c3b3e1f..682daae 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -31,6 +31,8 @@
#include <asm/arch/dram_sun50i_h6.h>
#elif defined(CONFIG_MACH_SUN50I_H616)
#include <asm/arch/dram_sun50i_h616.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 0000000..6f4c051
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram_suniv.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 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>
+ */
+
+#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 106605a..7f7eb05 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -165,6 +165,7 @@
#define SUNXI_GPD_LVDS0 3
#define SUNXI_GPD_PWM 2
+#define SUNIV_GPE_UART0 5
#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 d7f9a03..205fe3c 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1,6 +1,7 @@
if ARCH_SUNXI
config SPL_LDSCRIPT
+ 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
config IDENT_STRING
@@ -183,10 +184,15 @@
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
- select ARM_CORTEX_CPU_IS_UP
select PHY_SUN4I_USB
select DRAM_SUN4I
select SUNXI_GEN_SUN4I
@@ -197,7 +203,6 @@
config MACH_SUN5I
bool "sun5i (Allwinner A13)"
select CPU_V7A
- select ARM_CORTEX_CPU_IS_UP
select DRAM_SUN4I
select PHY_SUN4I_USB
select SUNXI_GEN_SUN4I
@@ -212,6 +217,7 @@
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select ARCH_SUPPORT_PSCI
+ select SPL_ARMV7_SET_CORTEX_SMPEN
select DRAM_SUN6I
select PHY_SUN4I_USB
select SPL_I2C
@@ -227,6 +233,7 @@
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select ARCH_SUPPORT_PSCI
+ select SPL_ARMV7_SET_CORTEX_SMPEN
select DRAM_SUN4I
select PHY_SUN4I_USB
select SUNXI_GEN_SUN4I
@@ -315,6 +322,7 @@
config MACH_SUN9I
bool "sun9i (Allwinner A80)"
select CPU_V7A
+ select SPL_ARMV7_SET_CORTEX_SMPEN
select DRAM_SUN9I
select SPL_I2C
select SUN6I_PRCM
@@ -365,6 +373,7 @@
# The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
config MACH_SUN8I
bool
+ select SPL_ARMV7_SET_CORTEX_SMPEN if !ARM64
select SUN6I_PRCM
default y if MACH_SUN8I_A23
default y if MACH_SUN8I_A33
@@ -587,6 +596,7 @@
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
@@ -598,6 +608,7 @@
default 1008000000 if MACH_SUN50I_H616
config SYS_CONFIG_NAME
+ default "suniv" if MACH_SUNIV
default "sun4i" if MACH_SUN4I
default "sun5i" if MACH_SUN5I
default "sun6i" if MACH_SUN6I
@@ -815,7 +826,7 @@
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.
@@ -1015,6 +1026,7 @@
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 5d3fd70..58f807c 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -13,6 +13,7 @@
obj-y += pinmux.o
obj-$(CONFIG_SUN6I_PRCM) += prcm.o
obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.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
@@ -25,8 +26,12 @@
endif
obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
obj-$(CONFIG_SUN50I_GEN_H6) += clock_sun50i_h6.o
+ifndef CONFIG_ARM64
+obj-y += timer.o
+endif
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 3ef1797..57078f7 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -75,6 +75,7 @@
}
#endif
+#ifdef CONFIG_SPL_BUILD
static int gpio_init(void)
{
__maybe_unused uint val;
@@ -86,7 +87,8 @@
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
@@ -94,6 +96,10 @@
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))
@@ -172,7 +178,6 @@
return 0;
}
-#if defined(CONFIG_SPL_BOARD_LOAD_IMAGE) && defined(CONFIG_SPL_BUILD)
static int spl_board_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
@@ -183,63 +188,6 @@
}
SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
#endif
-
-void s_init(void)
-{
- /*
- * Undocumented magic taken from boot0, without this DRAM
- * access gets messed up (seems cache related).
- * The boot0 sources describe this as: "config ema for cache sram"
- */
-#if defined CONFIG_MACH_SUN6I
- setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
-#elif defined CONFIG_MACH_SUN8I
- __maybe_unused uint version;
-
- /* Unlock sram version info reg, read it, relock */
- setbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15));
- version = readl(SUNXI_SRAMC_BASE + 0x24) >> 16;
- clrbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15));
-
- /*
- * Ideally this would be a switch case, but we do not know exactly
- * which versions there are and which version needs which settings,
- * so reproduce the per SoC code from the BSP.
- */
-#if defined CONFIG_MACH_SUN8I_A23
- if (version == 0x1650)
- setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
- else /* 0x1661 ? */
- setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0);
-#elif defined CONFIG_MACH_SUN8I_A33
- if (version != 0x1667)
- setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0);
-#endif
- /* A83T BSP never modifies SUNXI_SRAMC_BASE + 0x44 */
- /* No H3 BSP, boot0 seems to not modify SUNXI_SRAMC_BASE + 0x44 */
-#endif
-
-#if !defined(CONFIG_ARM_CORTEX_CPU_IS_UP) && !defined(CONFIG_ARM64)
- /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
- asm volatile(
- "mrc p15, 0, r0, c1, c0, 1\n"
- "orr r0, r0, #1 << 6\n"
- "mcr p15, 0, r0, c1, c0, 1\n"
- ::: "r0");
-#endif
-#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_H3
- /* Enable non-secure access to some peripherals */
- tzpc_init();
-#endif
-
- clock_init();
- timer_init();
- gpio_init();
-#if !CONFIG_IS_ENABLED(DM_I2C)
- i2c_init_board();
-#endif
- eth_init_board();
-}
#define SUNXI_INVALID_BOOT_SOURCE -1
@@ -328,18 +276,61 @@
return sector;
}
+#ifdef CONFIG_MACH_SUNIV
+/*
+ * The suniv BROM does not pass the boot media type to SPL, so we try with the
+ * boot sequence in BROM: mmc0->spinor->fail.
+ * TODO: This has the slight chance of being wrong (invalid SPL signature,
+ * but valid U-Boot legacy image on the SD card), but this should be rare.
+ * It looks like we can deduce from some BROM state upon entering the SPL
+ * (registers, SP, or stack itself) where the BROM was coming from and use
+ * that here.
+ */
+void board_boot_order(u32 *spl_boot_list)
+{
+ /*
+ * See the comments above in sunxi_get_boot_device() for information
+ * 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;
+}
+#else
u32 spl_boot_device(void)
{
return sunxi_get_boot_device();
}
+#endif
+
+__weak void sunxi_sram_init(void)
+{
+}
void board_init_f(ulong dummy)
{
+ sunxi_sram_init();
+
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_H3
+ /* Enable non-secure access to some peripherals */
+ tzpc_init();
+#endif
+
+ clock_init();
+ timer_init();
+ gpio_init();
+ eth_init_board();
+
spl_init();
preloader_console_init();
#if CONFIG_IS_ENABLED(I2C) && CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
/* Needed early by sunxi_board_init if PMU is enabled */
+ i2c_init_board();
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
#endif
sunxi_board_init();
diff --git a/arch/arm/mach-sunxi/clock.c b/arch/arm/mach-sunxi/clock.c
index de7e875..da3a0eb 100644
--- a/arch/arm/mach-sunxi/clock.c
+++ b/arch/arm/mach-sunxi/clock.c
@@ -35,7 +35,8 @@
}
/* 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 8e84062..cda6949 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -23,7 +23,8 @@
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;
@@ -49,9 +50,11 @@
writel(AHB1_ABP1_DIV_DEFAULT, &ccm->ahb1_apb1_div);
- writel(MBUS_CLK_DEFAULT, &ccm->mbus0_clk_cfg);
- if (IS_ENABLED(CONFIG_MACH_SUN6I))
- writel(MBUS_CLK_DEFAULT, &ccm->mbus1_clk_cfg);
+ if (!IS_ENABLED(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);
+ }
#if defined(CONFIG_MACH_SUN8I_R40) && defined(CONFIG_SUNXI_AHCI)
setbits_le32(&ccm->sata_pll_cfg, CCM_SATA_PLL_DEFAULT);
@@ -87,22 +90,36 @@
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- /* uart clock source is apb2 */
- writel(APB2_CLK_SRC_OSC24M|
- APB2_CLK_RATE_N_1|
- APB2_CLK_RATE_M(1),
- &ccm->apb2_div);
+#ifdef CONFIG_MACH_SUNIV
+ /* suniv doesn't have apb2, UART clock source is always apb1 */
- /* open the clock for uart */
- setbits_le32(&ccm->apb2_gate,
- CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT +
- CONFIG_CONS_INDEX - 1));
+ /* 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->apb2_reset_cfg,
- 1 << (APB2_RESET_UART_SHIFT +
- CONFIG_CONS_INDEX - 1));
+ /* deassert uart reset */
+ setbits_le32(&ccm->apb1_reset_cfg,
+ 1 << (APB1_RESET_UART_SHIFT +
+ CONFIG_CONS_INDEX - 1));
#else
+ /* uart clock source is apb2 */
+ writel(APB2_CLK_SRC_OSC24M|
+ APB2_CLK_RATE_N_1|
+ APB2_CLK_RATE_M(1),
+ &ccm->apb2_div);
+
+ /* open the clock for uart */
+ setbits_le32(&ccm->apb2_gate,
+ CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT +
+ CONFIG_CONS_INDEX - 1));
+
+ /* deassert uart reset */
+ setbits_le32(&ccm->apb2_reset_cfg,
+ 1 << (APB2_RESET_UART_SHIFT +
+ CONFIG_CONS_INDEX - 1));
+#endif /* !CONFIG_MACH_SUNIV */
+#else /* CONFIG_CONS_INDEX >= 5 */
/* enable R_PIO and R_UART clocks, and de-assert resets */
prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_UART);
#endif
@@ -125,10 +142,15 @@
}
/* Switch to 24MHz clock while changing PLL1 */
- 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);
+ if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
+ writel(CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_axi_cfg);
+ } else {
+ 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);
+ }
/*
* sun6i: PLL1 rate = ((24000000 * n * k) >> 0) / m (p is ignored)
@@ -140,10 +162,15 @@
sdelay(200);
/* Switch CPU to PLL1 */
- 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);
+ if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
+ writel(CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_axi_cfg);
+ } else {
+ 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);
+ }
}
#endif
@@ -317,7 +344,10 @@
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;
- return 24000000 * n * k / 2;
+ if (IS_ENABLED(CONFIG_MACH_SUNIV))
+ return 24000000 * n * k;
+ else
+ return 24000000 * n * k / 2;
}
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 ba33ef2..7eef178 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -57,6 +57,8 @@
{
#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 520b597..2c87319 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -26,7 +26,10 @@
/*
* 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 @@
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 0000000..56c2d55
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_suniv.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: (GPL-2.0+)
+/*
+ * 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>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/gpio.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <hang.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;
+ }
+ 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]);
+ hang();
+ }
+ }
+
+ 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]);
+ hang();
+ }
+ }
+}
+
+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);
+ mdelay(5);
+ /* 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));
+ mdelay(5);
+
+ 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/arch/arm/cpu/armv7/sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
similarity index 97%
rename from arch/arm/cpu/armv7/sunxi/timer.c
rename to arch/arm/mach-sunxi/timer.c
index b758599..fc9d419 100644
--- a/arch/arm/cpu/armv7/sunxi/timer.c
+++ b/arch/arm/mach-sunxi/timer.c
@@ -51,6 +51,7 @@
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);
@@ -58,15 +59,14 @@
return 0;
}
-/* timer without interrupts */
static ulong get_timer_masked(void)
{
/* current tick value */
ulong now = TICKS_TO_HZ(read_timer());
- if (now >= gd->arch.lastinc) /* normal (non rollover) */
+ if (now >= gd->arch.lastinc) { /* normal (non rollover) */
gd->arch.tbl += (now - gd->arch.lastinc);
- else {
+ } else {
/* rollover */
gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL)
- gd->arch.lastinc) + now;
@@ -76,6 +76,7 @@
return gd->arch.tbl;
}
+/* timer without interrupts */
ulong get_timer(ulong base)
{
return get_timer_masked() - base;
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 56a0ee3..5a0b598 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -266,6 +266,11 @@
S: Maintained
F: configs/LicheePi_Zero_defconfig
+LICHEEPI NANO BOARD
+M: Icenowy Zheng <icenowy@aosc.xyz>
+S: Maintained
+F: configs/licheepi_nano_defconfig
+
LINKSPRITE-PCDUINO BOARD
M: Zoltan Herpai <wigyori@uid0.hu>
S: Maintained
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 9146300..82c52b2 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -198,7 +198,7 @@
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? */
@@ -225,7 +225,7 @@
#endif
}
}
-#endif /* !CONFIG_ARM64 */
+#endif /* !CONFIG_ARM64 && !CONFIG_MACH_SUNIV */
ret = axp_gpio_init();
if (ret)
diff --git a/boot/Kconfig b/boot/Kconfig
index c8d5906..b83a4e8 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -362,9 +362,10 @@
depends on HAVE_SYS_TEXT_BASE
default 0x0 if POSITION_INDEPENDENT
default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3
- default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S
- default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I
- default 0x42e00000 if ARCH_SUNXI && MACH_SUN8I_V3S
+ default 0x81700000 if MACH_SUNIV
+ default 0x2a000000 if MACH_SUN9I
+ default 0x42e00000 if MACH_SUN8I_V3S
+ default 0x4a000000 if ARCH_SUNXI
hex "Text Base"
help
The address in memory that U-Boot will be running from, initially.
diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig
new file mode 100644
index 0000000..ecec869
--- /dev/null
+++ b/configs/licheepi_nano_defconfig
@@ -0,0 +1,11 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUNIV=y
+CONFIG_SKIP_LOWLEVEL_INIT_ONLY=y
+CONFIG_SPL_SKIP_LOWLEVEL_INIT_ONLY=y
+CONFIG_DRAM_CLK=156
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_DRAM_ZQ=0
+# CONFIG_VIDEO_SUNXI is not set
+CONFIG_DEFAULT_DEVICE_TREE="suniv-f1c100s-licheepi-nano"
+CONFIG_SPL=y
diff --git a/include/configs/suniv.h b/include/configs/suniv.h
new file mode 100644
index 0000000..6118cd5
--- /dev/null
+++ b/include/configs/suniv.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration settings for new Allwinner F-series (suniv) CPU
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * 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 7260eb7..4bab917 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -22,7 +22,12 @@
/* Serial & console */
#define CONFIG_SYS_NS16550_SERIAL
/* ns16550 reg in the low bits of cpu reg */
+#ifdef CONFIG_MACH_SUNIV
+/* suniv doesn't have apb2 and uart is connected to apb1 */
+#define CONFIG_SYS_NS16550_CLK 100000000
+#else
#define CONFIG_SYS_NS16550_CLK 24000000
+#endif
#ifndef CONFIG_DM_SERIAL
# define CONFIG_SYS_NS16550_REG_SIZE -4
# define CONFIG_SYS_NS16550_COM1 SUNXI_UART0_BASE
@@ -49,6 +54,15 @@
* 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_BSS_START_ADDR 0x2ff80000
+#elif defined(CONFIG_MACH_SUNIV)
+#define SDRAM_OFFSET(x) 0x8##x
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+/* 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
@@ -93,13 +107,9 @@
#endif
/* mmc config */
-#ifdef CONFIG_MMC
#define CONFIG_MMC_SUNXI_SLOT 0
-#endif
#if defined(CONFIG_ENV_IS_IN_MMC)
-
-#ifdef CONFIG_ARM64
/*
* This is actually (CONFIG_ENV_OFFSET -
* (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512)), but the value will be used
@@ -109,7 +119,6 @@
#endif
#define CONFIG_SYS_MMC_MAX_DEVICE 4
-#endif
/*
* Miscellaneous configurable options
@@ -124,8 +133,6 @@
#define CONFIG_SYS_MONITOR_LEN (768 << 10) /* 768 KiB */
-#define CONFIG_SPL_BOARD_LOAD_IMAGE
-
/*
* We cannot use expressions here, because expressions won't be evaluated in
* autoconf.mk.
@@ -186,13 +193,40 @@
#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(FE00000))
#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(FF00000))
+#elif 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,
+ * 1M script, 1M pxe, 1M dt overlay and the ramdisk at the end.
+ */
+#define BOOTM_SIZE __stringify(0x2e00000)
+#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(1000000))
+#define FDT_ADDR_R __stringify(SDRAM_OFFSET(1800000))
+#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(1900000))
+#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(1A00000))
+#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(1B00000))
+#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(1C00000))
+
+#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 FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(0D50000))
+#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(0D60000))
+
#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, 1M dt overlay 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))
@@ -200,20 +234,6 @@
#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(3200000))
#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(3300000))
#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(3400000))
-#else
-/*
- * 64M RAM minus 2MB heap + 16MB for u-boot, stack, fb, etc.
- * 16M uncompressed kernel, 8M compressed kernel, 1M fdt,
- * 1M script, 1M pxe, 1M dt overlay and the ramdisk at the end.
- */
-#define BOOTM_SIZE __stringify(0x2e00000)
-#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(1000000))
-#define FDT_ADDR_R __stringify(SDRAM_OFFSET(1800000))
-#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(1900000))
-#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(1A00000))
-#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(1B00000))
-#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(1C00000))
-#endif
#endif
#define MEM_LAYOUT_ENV_SETTINGS \
diff --git a/include/dt-bindings/clock/suniv-ccu-f1c100s.h b/include/dt-bindings/clock/suniv-ccu-f1c100s.h
new file mode 100644
index 0000000..f5ac155
--- /dev/null
+++ b/include/dt-bindings/clock/suniv-ccu-f1c100s.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ *
+ * Copyright (c) 2018 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUNIV_F1C100S_H_
+#define _DT_BINDINGS_CLK_SUNIV_F1C100S_H_
+
+#define CLK_CPU 11
+
+#define CLK_BUS_DMA 14
+#define CLK_BUS_MMC0 15
+#define CLK_BUS_MMC1 16
+#define CLK_BUS_DRAM 17
+#define CLK_BUS_SPI0 18
+#define CLK_BUS_SPI1 19
+#define CLK_BUS_OTG 20
+#define CLK_BUS_VE 21
+#define CLK_BUS_LCD 22
+#define CLK_BUS_DEINTERLACE 23
+#define CLK_BUS_CSI 24
+#define CLK_BUS_TVD 25
+#define CLK_BUS_TVE 26
+#define CLK_BUS_DE_BE 27
+#define CLK_BUS_DE_FE 28
+#define CLK_BUS_CODEC 29
+#define CLK_BUS_SPDIF 30
+#define CLK_BUS_IR 31
+#define CLK_BUS_RSB 32
+#define CLK_BUS_I2S0 33
+#define CLK_BUS_I2C0 34
+#define CLK_BUS_I2C1 35
+#define CLK_BUS_I2C2 36
+#define CLK_BUS_PIO 37
+#define CLK_BUS_UART0 38
+#define CLK_BUS_UART1 39
+#define CLK_BUS_UART2 40
+
+#define CLK_MMC0 41
+#define CLK_MMC0_SAMPLE 42
+#define CLK_MMC0_OUTPUT 43
+#define CLK_MMC1 44
+#define CLK_MMC1_SAMPLE 45
+#define CLK_MMC1_OUTPUT 46
+#define CLK_I2S 47
+#define CLK_SPDIF 48
+
+#define CLK_USB_PHY0 49
+
+#define CLK_DRAM_VE 50
+#define CLK_DRAM_CSI 51
+#define CLK_DRAM_DEINTERLACE 52
+#define CLK_DRAM_TVD 53
+#define CLK_DRAM_DE_FE 54
+#define CLK_DRAM_DE_BE 55
+
+#define CLK_DE_BE 56
+#define CLK_DE_FE 57
+#define CLK_TCON 58
+#define CLK_DEINTERLACE 59
+#define CLK_TVE2_CLK 60
+#define CLK_TVE1_CLK 61
+#define CLK_TVD 62
+#define CLK_CSI 63
+#define CLK_VE 64
+#define CLK_CODEC 65
+#define CLK_AVS 66
+
+#endif
diff --git a/include/dt-bindings/reset/suniv-ccu-f1c100s.h b/include/dt-bindings/reset/suniv-ccu-f1c100s.h
new file mode 100644
index 0000000..6a4b438
--- /dev/null
+++ b/include/dt-bindings/reset/suniv-ccu-f1c100s.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ */
+
+#ifndef _DT_BINDINGS_RST_SUNIV_F1C100S_H_
+#define _DT_BINDINGS_RST_SUNIV_F1C100S_H_
+
+#define RST_USB_PHY0 0
+#define RST_BUS_DMA 1
+#define RST_BUS_MMC0 2
+#define RST_BUS_MMC1 3
+#define RST_BUS_DRAM 4
+#define RST_BUS_SPI0 5
+#define RST_BUS_SPI1 6
+#define RST_BUS_OTG 7
+#define RST_BUS_VE 8
+#define RST_BUS_LCD 9
+#define RST_BUS_DEINTERLACE 10
+#define RST_BUS_CSI 11
+#define RST_BUS_TVD 12
+#define RST_BUS_TVE 13
+#define RST_BUS_DE_BE 14
+#define RST_BUS_DE_FE 15
+#define RST_BUS_CODEC 16
+#define RST_BUS_SPDIF 17
+#define RST_BUS_IR 18
+#define RST_BUS_RSB 19
+#define RST_BUS_I2S0 20
+#define RST_BUS_I2C0 21
+#define RST_BUS_I2C1 22
+#define RST_BUS_I2C2 23
+#define RST_BUS_UART0 24
+#define RST_BUS_UART1 25
+#define RST_BUS_UART2 26
+
+#endif /* _DT_BINDINGS_RST_SUNIV_F1C100S_H_ */