[PATCH 00/27] Add F1C100s based PocketGo handheld support

This series add support for the PocketGo handheld, a low cost portable gaming console that is based on the Allwinner F1C100s chip.
A significant portion of this patchset is authored by: - Icenowy Zheng icenowy@aosc.io - George Hilliard thirtythreeforty@gmail.com
This patchset includes 4 parts necessary to make PocketGo work:
- suniv + f1c100s support by Icenowy Zheng icenowy@aosc.io, rebased by George Hilliard thirtythreeforty@gmail.com and then by me. See: https://github.com/Icenowy/u-boot/commits/f1c100s-spiflash
- additional support for suniv clock and MMC controller by George Hilliard, rebased. See: https://github.com/thirtythreeforty/u-boot/tree/f1c100s-v2019.04
- additional support for serial uart1, and misc fixes for compilation, SPL -> U-Boot proper load on F1C100s.
- DTS and defconfig for PocketGo
I have accidentally CC'ed a few people while testing git send-email, I am awfully sorry for my lack of experience in email-patch based workflows. This is my first time attempting to contribute to U-Boot.
Cc: Jagan Teki jagan@amarulasolutions.com Cc: Andre Przywara andre.przywara@arm.com Cc: Icenowy Zheng icenowy@aosc.io Cc: George Hilliard thirtythreeforty@gmail.com
George Hilliard (6): sunxi: Don't provide enable_cache() on suniv sunxi: implement clock driver for suniv f1c100s sunxi: gpio: Add support for suniv-f1c100s sunxi: spi: restore bus speed and mode after reset sunxi: spi: Add suniv pin controller support sunxi: suniv: add device tree nodes for f1c100s MMC controllers
Icenowy Zheng (12): arm: arm926ejs: start.S: port save_boot_params support from armv7 code arm: arm926ej-s: add sunxi code sunxi: add support for suniv architecture sunxi: suniv: add support for Lichee Pi Nano sunxi: suniv: add boot sequence for SPL to try sunxi: spi-spl: add support for SUNIV sunxi: add SPI0 node for suniv sunxi: enable SPI NOR on Lichee Pi Nano sunxi: add defconfig for Lichee Pi Nano with SPI Flash support sunxi: add support for UART at PF for suniv sunxi: do not set PF MMC0 pinmux when PF uart is used sunxi: allow to enable MMC driver when using PF UART0
Yifan Gu (9): arm: dts: sunxi: do not renumber if mmc2 does not exist board: licheepi_nano: set CONFIG_MMC_SUNXI_SLOT_EXTRA sunxi: suniv: add missing header include for udelay sunxi: suniv: allow serial connection on uart1 sunxi: suniv: do not detect boot sector on suniv sunxi: suniv: set SYS_TEXT_BASE default sunxi: suniv: disable mmc optimization for suniv arm: dts: suniv: define uart1 pins arm: dts: add pocketgo handheld support
arch/arm/cpu/arm926ejs/Makefile | 1 + arch/arm/cpu/arm926ejs/start.S | 19 + 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 | 114 ++++ arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds | 63 +++ arch/arm/dts/Makefile | 3 + arch/arm/dts/suniv-f1c100s-licheepi-nano.dts | 58 ++ arch/arm/dts/suniv-f1c100s-pocketgo.dts | 48 ++ arch/arm/dts/suniv-f1c100s.dtsi | 6 + arch/arm/dts/suniv.dtsi | 253 +++++++++ arch/arm/dts/sunxi-u-boot.dtsi | 2 + 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 | 3 + arch/arm/mach-sunxi/Kconfig | 16 +- arch/arm/mach-sunxi/Makefile | 2 + arch/arm/mach-sunxi/board.c | 37 +- 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 | 497 ++++++++++++++++++ arch/arm/mach-sunxi/spl_spi_sunxi.c | 13 + board/sunxi/board.c | 8 +- common/Kconfig.boot | 3 +- configs/licheepi_nano_defconfig | 10 + configs/licheepi_nano_spiflash_defconfig | 26 + configs/pocketgo_defconfig | 12 + drivers/clk/sunxi/Kconfig | 7 + drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_f1c100s.c | 66 +++ drivers/gpio/sunxi_gpio.c | 6 + drivers/mmc/Kconfig | 2 +- drivers/mmc/sunxi_mmc.c | 6 +- drivers/spi/spi-sunxi.c | 12 +- include/configs/suniv.h | 15 + include/configs/sunxi-common.h | 69 ++- include/dt-bindings/clock/suniv-ccu.h | 69 +++ include/dt-bindings/reset/suniv-ccu.h | 37 ++ 46 files changed, 1715 insertions(+), 34 deletions(-) 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 create mode 100644 arch/arm/dts/suniv-f1c100s-licheepi-nano.dts create mode 100644 arch/arm/dts/suniv-f1c100s-pocketgo.dts 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 configs/licheepi_nano_defconfig create mode 100644 configs/licheepi_nano_spiflash_defconfig create mode 100644 configs/pocketgo_defconfig create mode 100644 drivers/clk/sunxi/clk_f1c100s.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

From: Icenowy Zheng icenowy@aosc.io
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 Signed-off-by: Yifan Gu me@yifangu.com --- 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)

From: Icenowy Zheng icenowy@aosc.io
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 Signed-off-by: Yifan Gu me@yifangu.com --- 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 | 114 +++++++++++++++++++ arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds | 63 ++++++++++ 8 files changed, 307 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 98aafe805a..5cf089d8e5 100644 --- a/arch/arm/cpu/arm926ejs/Makefile +++ b/arch/arm/cpu/arm926ejs/Makefile @@ -17,6 +17,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..da2c50af15 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/sunxi/timer.c @@ -0,0 +1,114 @@ +/* + * (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> +#include <asm/global_data.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; +} + +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; +} + +/* timer without interrupts */ +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* 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 +}

From: Icenowy Zheng icenowy@aosc.io
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 Rebased-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com --- 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 | 15 + include/configs/sunxi-common.h | 69 ++- include/dt-bindings/clock/suniv-ccu.h | 69 +++ include/dt-bindings/reset/suniv-ccu.h | 37 ++ 21 files changed, 1013 insertions(+), 26 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..a5673f5006 --- /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-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-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_pe_pins: 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 cbbe5c7a1e..2cfd540742 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 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 c3b3e1f512..682daae6b1 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 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 2969a530ae..b0b86b812a 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -178,6 +178,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 49f94f095c..f15b4e8bda 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" @@ -201,6 +202,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 @@ -593,6 +600,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 @@ -604,6 +612,7 @@ config SYS_CLK_FREQ 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 @@ -830,7 +839,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. @@ -1046,6 +1055,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 3f081d92f3..367690c357 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_SUN50I_GEN_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 e979e426dd..3b1a79eb5e 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -95,6 +95,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)) @@ -220,7 +224,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 8e84062bd7..6bd94f0a41 100644 --- a/arch/arm/mach-sunxi/clock_sun6i.c +++ b/arch/arm/mach-sunxi/clock_sun6i.c @@ -23,7 +23,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;
@@ -49,9 +50,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); @@ -87,6 +90,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| @@ -102,6 +106,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); @@ -125,10 +147,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) @@ -137,13 +164,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
@@ -317,7 +358,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 ba33ef2430..7eef178859 100644 --- a/arch/arm/mach-sunxi/cpu_info.c +++ b/arch/arm/mach-sunxi/cpu_info.c @@ -57,6 +57,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 67acc01d83..27ab44b67c 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -237,7 +237,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? */ @@ -264,7 +264,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..483c20edc1 --- /dev/null +++ b/include/configs/suniv.h @@ -0,0 +1,15 @@ +/* + * Configuration settings for new Allwinner F-series (suniv) CPU + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 9e37e99684..c3de1712e8 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,15 @@ * 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 */ +/* 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 @@ -137,12 +151,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
/* @@ -252,20 +269,8 @@ extern int soft_i2c_gpio_scl; #define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(FF00000))
#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)) -#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(3100000)) -#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 + +#ifdef CONFIG_MACH_SUN8I_V3S /* * 64M RAM minus 2MB heap + 16MB for u-boot, stack, fb, etc. * 16M uncompressed kernel, 8M compressed kernel, 1M fdt, @@ -278,6 +283,34 @@ extern int soft_i2c_gpio_scl; #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, 512K dt overlay 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(0E00000)) + +#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. + */ +#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 FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(3300000)) +#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(3400000)) #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_ */

From: Icenowy Zheng icenowy@aosc.io
Lichee Pi Nano is a board based on F1C100s.
Add support for it.
Signed-off-by: Icenowy Zheng icenowy@aosc.io Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/dts/Makefile | 2 + arch/arm/dts/suniv-f1c100s-licheepi-nano.dts | 43 ++++++++++++++++++++ configs/licheepi_nano_defconfig | 9 ++++ 3 files changed, 54 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/Makefile b/arch/arm/dts/Makefile index 3941a08cf4..a1207a33f5 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -665,6 +665,8 @@ dtb-$(CONFIG_MACH_SUN9I) += \ 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 \ 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..2820f8238d --- /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_pe_pins>; + 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

From: Icenowy Zheng icenowy@aosc.io
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 Signed-off-by: Yifan Gu me@yifangu.com --- 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 3b1a79eb5e..e84687973a 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -334,10 +334,32 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, 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) {

From: Icenowy Zheng icenowy@aosc.io
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 Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/include/asm/arch-sunxi/gpio.h | 1 + arch/arm/mach-sunxi/Kconfig | 2 +- arch/arm/mach-sunxi/spl_spi_sunxi.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index b0b86b812a..26c900fb11 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -170,6 +170,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
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index f15b4e8bda..4fde7e1da1 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1067,7 +1067,7 @@ config SPL_STACK_R_ADDR
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_SUNIV || MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 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/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c index 15e86cbac8..f6f65a0e3d 100644 --- a/arch/arm/mach-sunxi/spl_spi_sunxi.c +++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c @@ -89,6 +89,7 @@
#define SPI0_CLK_DIV_BY_2 0x1000 #define SPI0_CLK_DIV_BY_4 0x1001 +#define SPI0_CLK_DIV_BY_32 0x100f
/*****************************************************************************/
@@ -120,6 +121,7 @@ static void spi0_pinmux_setup(unsigned int pin_function) static bool is_sun6i_gen_spi(void) { return IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) || + IS_ENABLED(CONFIG_MACH_SUNIV) || IS_ENABLED(CONFIG_MACH_SUN50I_H6); }
@@ -155,11 +157,17 @@ static void spi0_enable_clock(void) if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6)) setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
+#ifdef CONFIG_MACH_SUNIV + /* Divide by 32, clock source is AHB clock 200MHz */ + writel(SPI0_CLK_DIV_BY_32, base + (is_sun6i_gen_spi() ? + SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL)); +#else /* 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); +#endif
if (is_sun6i_gen_spi()) { /* Enable SPI in the master mode and do a soft reset */ @@ -189,8 +197,10 @@ static void spi0_disable_clock(void) 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)) @@ -212,6 +222,9 @@ static void spi0_init(void) IS_ENABLED(CONFIG_MACH_SUN50I_H6)) pin_function = SUN50I_GPC_SPI0;
+ if (IS_ENABLED(CONFIG_MACH_SUNIV)) + pin_function = SUNIV_GPC_SPI0; + spi0_pinmux_setup(pin_function); spi0_enable_clock(); }

From: Icenowy Zheng icenowy@aosc.io
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 Signed-off-by: Yifan Gu me@yifangu.com --- 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 a5673f5006..b11d9eb57a 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-f1c100s-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_pe_pins: uart-pins-pe { pins = "PE0", "PE1"; function = "uart0";

From: Icenowy Zheng icenowy@aosc.io
The Lichee Pi Nano board has a Winbond W25Q128 SPI flash on it.
Enable it.
Signed-off-by: Icenowy Zheng icenowy@aosc.io Signed-off-by: Yifan Gu me@yifangu.com --- 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 2820f8238d..f2794e46f2 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_pe_pins>;

From: Icenowy Zheng icenowy@aosc.io
Signed-off-by: Icenowy Zheng icenowy@aosc.io Signed-off-by: Yifan Gu me@yifangu.com --- 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

From: Icenowy Zheng icenowy@aosc.io
Signed-off-by: Icenowy Zheng icenowy@aosc.io Signed-off-by: Yifan Gu me@yifangu.com --- 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 e84687973a..b471933ec8 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -87,7 +87,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

From: Icenowy Zheng icenowy@aosc.io
Signed-off-by: Icenowy Zheng icenowy@aosc.io Signed-off-by: Yifan Gu me@yifangu.com --- 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 27ab44b67c..748c1a8673 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -412,17 +412,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:

From: Icenowy Zheng icenowy@aosc.io
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 Signed-off-by: Yifan Gu me@yifangu.com --- drivers/mmc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 717ce5a62f..5c363972ec 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -723,7 +723,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

From: George Hilliard thirtythreeforty@gmail.com
The arm926 code provides this function. Disable it here.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com --- 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 b471933ec8..6dd2c6a4d8 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -406,7 +406,7 @@ void reset_cpu(void) #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 */

From: George Hilliard thirtythreeforty@gmail.com
The f1c100s has a simple clock tree similar to those of other sunxi parts. Add support for it.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com --- drivers/clk/sunxi/Kconfig | 7 ++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_f1c100s.c | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 drivers/clk/sunxi/clk_f1c100s.c
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index bf084fa7a8..28928fef1f 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -9,6 +9,13 @@ config CLK_SUNXI
if CLK_SUNXI
+config CLK_SUNIV_F1C100S + bool "Clock driver for Allwinner F1C100s" + default MACH_SUNIV + help + This enables common clock driver support for platforms based + on Allwinner F1C100s SoC. + config CLK_SUN4I_A10 bool "Clock driver for Allwinner A10/A20" default MACH_SUN4I || MACH_SUN7I diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 4f9282a8b9..da43f8a0ed 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
obj-$(CONFIG_CLK_SUNXI) += clk_sun6i_rtc.o
+obj-$(CONFIG_CLK_SUNIV_F1C100S) += clk_f1c100s.o obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c new file mode 100644 index 0000000000..3b64445d89 --- /dev/null +++ b/drivers/clk/sunxi/clk_f1c100s.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: (GPL-2.0+) +/* + * Copyright (C) 2019 George Hilliard thirtythreeforty@gmail.com. + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <errno.h> +#include <asm/arch/ccu.h> +#include <dt-bindings/clock/suniv-ccu.h> +#include <dt-bindings/reset/suniv-ccu.h> + +static struct ccu_clk_gate f1c100s_gates[] = { + [CLK_BUS_MMC0] = GATE(0x060, BIT(8)), + [CLK_BUS_MMC1] = GATE(0x060, BIT(9)), + [CLK_BUS_SPI0] = GATE(0x060, BIT(20)), + [CLK_BUS_SPI1] = GATE(0x060, BIT(21)), + [CLK_BUS_OTG] = GATE(0x060, BIT(24)), + + [CLK_BUS_UART0] = GATE(0x06c, BIT(20)), + [CLK_BUS_UART1] = GATE(0x06c, BIT(21)), + [CLK_BUS_UART2] = GATE(0x06c, BIT(22)), + + [CLK_USB_PHY0] = GATE(0x0cc, BIT(1)), +}; + +static struct ccu_reset f1c100s_resets[] = { + [RST_USB_PHY0] = RESET(0x0cc, BIT(0)), + + [RST_BUS_MMC0] = RESET(0x2c0, BIT(8)), + [RST_BUS_MMC1] = RESET(0x2c0, BIT(9)), + [RST_BUS_SPI0] = RESET(0x2c0, BIT(20)), + [RST_BUS_SPI1] = RESET(0x2c0, BIT(21)), + [RST_BUS_OTG] = RESET(0x2c0, BIT(24)), + + [RST_BUS_UART0] = RESET(0x2d0, BIT(20)), + [RST_BUS_UART1] = RESET(0x2d0, BIT(21)), + [RST_BUS_UART2] = RESET(0x2d0, BIT(22)), +}; + +static const struct ccu_desc f1c100s_ccu_desc = { + .gates = f1c100s_gates, + .resets = f1c100s_resets, +}; + +static int f1c100s_clk_bind(struct udevice *dev) +{ + return sunxi_reset_bind(dev, ARRAY_SIZE(f1c100s_resets)); +} + +static const struct udevice_id f1c100s_clk_ids[] = { + { .compatible = "allwinner,suniv-f1c100s-ccu", + .data = (ulong)&f1c100s_ccu_desc }, + { } +}; + +U_BOOT_DRIVER(clk_suniv_f1c100s) = { + .name = "suniv_f1c100s_ccu", + .id = UCLASS_CLK, + .of_match = f1c100s_clk_ids, + .priv_auto = sizeof(struct ccu_priv), + .ops = &sunxi_clk_ops, + .probe = sunxi_clk_probe, + .bind = f1c100s_clk_bind, +};

On 7/25/21 7:16 PM, Yifan Gu wrote:
From: George Hilliard thirtythreeforty@gmail.com
The f1c100s has a simple clock tree similar to those of other sunxi parts. Add support for it.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com
drivers/clk/sunxi/Kconfig | 7 ++++ drivers/clk/sunxi/Makefile | 1 + drivers/clk/sunxi/clk_f1c100s.c | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 drivers/clk/sunxi/clk_f1c100s.c
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index bf084fa7a8..28928fef1f 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -9,6 +9,13 @@ config CLK_SUNXI
if CLK_SUNXI
+config CLK_SUNIV_F1C100S
- bool "Clock driver for Allwinner F1C100s"
- default MACH_SUNIV
- help
This enables common clock driver support for platforms based
on Allwinner F1C100s SoC.
- config CLK_SUN4I_A10 bool "Clock driver for Allwinner A10/A20" default MACH_SUN4I || MACH_SUN7I
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 4f9282a8b9..da43f8a0ed 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
obj-$(CONFIG_CLK_SUNXI) += clk_sun6i_rtc.o
+obj-$(CONFIG_CLK_SUNIV_F1C100S) += clk_f1c100s.o obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c new file mode 100644 index 0000000000..3b64445d89 --- /dev/null +++ b/drivers/clk/sunxi/clk_f1c100s.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: (GPL-2.0+) +/*
- Copyright (C) 2019 George Hilliard thirtythreeforty@gmail.com.
- */
+#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <errno.h> +#include <asm/arch/ccu.h> +#include <dt-bindings/clock/suniv-ccu.h> +#include <dt-bindings/reset/suniv-ccu.h>
+static struct ccu_clk_gate f1c100s_gates[] = {
- [CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
- [CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
- [CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
- [CLK_BUS_SPI1] = GATE(0x060, BIT(21)),
- [CLK_BUS_OTG] = GATE(0x060, BIT(24)),
- [CLK_BUS_UART0] = GATE(0x06c, BIT(20)),
- [CLK_BUS_UART1] = GATE(0x06c, BIT(21)),
- [CLK_BUS_UART2] = GATE(0x06c, BIT(22)),
- [CLK_USB_PHY0] = GATE(0x0cc, BIT(1)),
+};
+static struct ccu_reset f1c100s_resets[] = {
- [RST_USB_PHY0] = RESET(0x0cc, BIT(0)),
- [RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
- [RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
- [RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
- [RST_BUS_SPI1] = RESET(0x2c0, BIT(21)),
- [RST_BUS_OTG] = RESET(0x2c0, BIT(24)),
- [RST_BUS_UART0] = RESET(0x2d0, BIT(20)),
- [RST_BUS_UART1] = RESET(0x2d0, BIT(21)),
- [RST_BUS_UART2] = RESET(0x2d0, BIT(22)),
+};
+static const struct ccu_desc f1c100s_ccu_desc = {
- .gates = f1c100s_gates,
- .resets = f1c100s_resets,
+};
+static int f1c100s_clk_bind(struct udevice *dev) +{
- return sunxi_reset_bind(dev, ARRAY_SIZE(f1c100s_resets));
+}
+static const struct udevice_id f1c100s_clk_ids[] = {
- { .compatible = "allwinner,suniv-f1c100s-ccu",
.data = (ulong)&f1c100s_ccu_desc },
- { }
+};
+U_BOOT_DRIVER(clk_suniv_f1c100s) = {
- .name = "suniv_f1c100s_ccu",
- .id = UCLASS_CLK,
- .of_match = f1c100s_clk_ids,
- .priv_auto = sizeof(struct ccu_priv),
- .ops = &sunxi_clk_ops,
- .probe = sunxi_clk_probe,
- .bind = f1c100s_clk_bind,
+};
Acked-by: Sean Anderson seanga2@gmail.com

From: George Hilliard thirtythreeforty@gmail.com
The f1c100s has a controller pretty similar to that of most sunxi parts, but there are only 6 banks. Add a new compatible entry for this peripheral.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com --- drivers/gpio/sunxi_gpio.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 24cb604e3e..c7bdb3d3f3 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -319,6 +319,11 @@ static const struct sunxi_gpio_soc_data soc_data_a_all = { .no_banks = SUNXI_GPIO_BANKS, };
+static const struct sunxi_gpio_soc_data soc_data_a_6 = { + .start = 0, + .no_banks = 6, +}; + static const struct sunxi_gpio_soc_data soc_data_l_1 = { .start = 'L' - 'A', .no_banks = 1, @@ -364,6 +369,7 @@ static const struct udevice_id sunxi_gpio_ids[] = { ID("allwinner,sun50i-a64-r-pinctrl", l_1), ID("allwinner,sun50i-h6-r-pinctrl", l_2), ID("allwinner,sun50i-h616-r-pinctrl", l_1), + ID("allwinner,suniv-pinctrl", a_6), { } };

From: George Hilliard thirtythreeforty@gmail.com
The sunxi SPI peripheral driver resets the device completely (disabling clocks and power) when the bus is released and turns it back on when claiming. On the F1C100s (and maybe others), the peripheral resets back to default register settings, losing speed and mode settings.
Restore these settings when resetting the peripheral.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com --- drivers/spi/spi-sunxi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index 4ca5d3a93a..aa392502b7 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -39,6 +39,10 @@
DECLARE_GLOBAL_DATA_PTR;
+/* Forward declarations of some reused functions */ +static int sun4i_spi_set_speed(struct udevice *dev, uint speed); +static int sun4i_spi_set_mode(struct udevice *dev, uint mode); + /* sun4i spi registers */ #define SUN4I_RXDATA_REG 0x00 #define SUN4I_TXDATA_REG 0x04 @@ -304,7 +308,8 @@ err_ahb:
static int sun4i_spi_claim_bus(struct udevice *dev) { - struct sun4i_spi_priv *priv = dev_get_priv(dev->parent); + struct udevice *bus = dev->parent; + struct sun4i_spi_priv *priv = dev_get_priv(bus); int ret;
ret = sun4i_spi_set_clock(dev->parent, true); @@ -321,6 +326,9 @@ static int sun4i_spi_claim_bus(struct udevice *dev) setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) | SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
+ sun4i_spi_set_speed(bus, priv->freq); + sun4i_spi_set_mode(bus, priv->mode); + return 0; }

From: George Hilliard thirtythreeforty@gmail.com
suniv needs slightly different register settings to enable the SPI peripheral. The magic numbers are already provided by the architecture support; we just have to check for them here.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.com --- drivers/spi/spi-sunxi.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index aa392502b7..320bd61d13 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -255,6 +255,8 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
if (IS_ENABLED(CONFIG_MACH_SUN50I)) sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0); + else if (IS_ENABLED(CONFIG_MACH_SUNIV)) + sunxi_gpio_set_cfgpin(pin, SUNIV_GPC_SPI0); else sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0); sunxi_gpio_set_drv(pin, drive);

From: George Hilliard thirtythreeforty@gmail.com
The f1c100s has two MMC controllers. Add device tree nodes for them.
Signed-off-by: George Hilliard thirtythreeforty@gmail.com Signed-off-by: Yifan Gu me@yifangu.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 b11d9eb57a..bea7c08e7d 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>; + }; + + mmc1: 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>; + }; }; };

We renumber mmc2 to mmc1 for sunxi devices, but if mmc2 does not exist dts will not build.
This patch prevents that by checking CONFIG_MMC_SUNXI_SLOT_EXTRA. --- arch/arm/dts/sunxi-u-boot.dtsi | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi index 06da009fa2..53db622144 100644 --- a/arch/arm/dts/sunxi-u-boot.dtsi +++ b/arch/arm/dts/sunxi-u-boot.dtsi @@ -13,7 +13,9 @@ / { aliases { mmc0 = &mmc0; +#if CONFIG_MMC_SUNXI_SLOT_EXTRA > 1 mmc1 = &mmc2; +#endif };
binman: binman {

在 2021-07-25星期日的 19:16 -0400,Yifan Gu写道:
We renumber mmc2 to mmc1 for sunxi devices, but if mmc2 does not exist dts will not build.
This patch prevents that by checking CONFIG_MMC_SUNXI_SLOT_EXTRA.
I have a similar patch at https://patchwork.ozlabs.org/project/uboot/patch/20210722063015.421923-3-ice...
arch/arm/dts/sunxi-u-boot.dtsi | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u- boot.dtsi index 06da009fa2..53db622144 100644 --- a/arch/arm/dts/sunxi-u-boot.dtsi +++ b/arch/arm/dts/sunxi-u-boot.dtsi @@ -13,7 +13,9 @@ / { aliases { mmc0 = &mmc0; +#if CONFIG_MMC_SUNXI_SLOT_EXTRA > 1 mmc1 = &mmc2; +#endif }; binman: binman {

--- configs/licheepi_nano_defconfig | 1 + configs/licheepi_nano_spiflash_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig index 6e455baadf..6ea73c6408 100644 --- a/configs/licheepi_nano_defconfig +++ b/configs/licheepi_nano_defconfig @@ -7,3 +7,4 @@ CONFIG_DRAM_ZQ=0 CONFIG_DEFAULT_DEVICE_TREE="suniv-f1c100s-licheepi-nano" CONFIG_SPL=y # CONFIG_SPL_DM_SERIAL is not set +CONFIG_MMC_SUNXI_SLOT_EXTRA=1 diff --git a/configs/licheepi_nano_spiflash_defconfig b/configs/licheepi_nano_spiflash_defconfig index 07b6a27dbe..c3b7fdd67d 100644 --- a/configs/licheepi_nano_spiflash_defconfig +++ b/configs/licheepi_nano_spiflash_defconfig @@ -23,3 +23,4 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SPL_DM_SERIAL is not set CONFIG_DM_SPI=y CONFIG_SUN6I_SPI=y +CONFIG_MMC_SUNXI_SLOT_EXTRA=1

Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/mach-sunxi/dram_suniv.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c index 40aebf6eba..e7460ec3c3 100644 --- a/arch/arm/mach-sunxi/dram_suniv.c +++ b/arch/arm/mach-sunxi/dram_suniv.c @@ -15,6 +15,7 @@ #include <asm/arch/clock.h> #include <asm/arch/dram.h> #include <asm/arch/gpio.h> +#include <linux/delay.h>
#define SDR_T_CAS (0x2) #define SDR_T_RAS (0x8)

Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/include/asm/arch-sunxi/gpio.h | 1 + arch/arm/mach-sunxi/board.c | 4 ++++ 2 files changed, 5 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 26c900fb11..2b03325adf 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -180,6 +180,7 @@ enum sunxi_gpio_number { #define SUNXI_GPD_PWM 2
#define SUNIV_GPE_UART0 5 +#define SUNIV_GPA_UART1 5 #define SUN5I_GPE_SDC2 3 #define SUN8I_GPE_TWI2 3 #define SUN50I_GPE_TWI2 3 diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 6dd2c6a4d8..7fa44b6f3a 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -100,6 +100,10 @@ static int gpio_init(void) 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 == 2 && defined(CONFIG_MACH_SUNIV) + sunxi_gpio_set_cfgpin(SUNXI_GPA(2), SUNIV_GPA_UART1); + sunxi_gpio_set_cfgpin(SUNXI_GPA(3), SUNIV_GPA_UART1); + sunxi_gpio_set_pull(SUNXI_GPA(2), SUNXI_GPIO_PULL_UP); #elif CONFIG_CONS_INDEX == 1 && (defined(CONFIG_MACH_SUN4I) || \ defined(CONFIG_MACH_SUN7I) || \ defined(CONFIG_MACH_SUN8I_R40))

The BROM of suniv does not pass info to SPL, and it should always boot from the 8KB offset.
Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/mach-sunxi/board.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 7fa44b6f3a..90c58ce86c 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -305,6 +305,7 @@ uint32_t sunxi_get_boot_device(void) }
#ifdef CONFIG_SPL_BUILD +#ifndef CONFIG_MACH_SUNIV static u32 sunxi_get_spl_size(void) { if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */ @@ -339,8 +340,6 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return sector; }
- -#ifndef CONFIG_MACH_SUNIV u32 spl_boot_device(void) { return sunxi_get_boot_device();

suniv ddr memory starts at 0x8000000. Set SYS_TEXT_BASE accordingly so SPL can copy U-Boot proper to DRAM.
Signed-off-by: Yifan Gu me@yifangu.com --- common/Kconfig.boot | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/common/Kconfig.boot b/common/Kconfig.boot index 642dd9bcfb..23c6db286a 100644 --- a/common/Kconfig.boot +++ b/common/Kconfig.boot @@ -360,9 +360,10 @@ config SYS_TEXT_BASE 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 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S && !MACH_SUNIV default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I default 0x42e00000 if ARCH_SUNXI && MACH_SUN8I_V3S + default 0x81c00000 if ARCH_SUNXI && MACH_SUNIV hex "Text Base" help The address in memory that U-Boot will be running from, initially.

suniv cannot boot with this mmc optimization, as suniv fifo level register is only 4 bits.
Disable this optimization for suniv for now.
Signed-off-by: Yifan Gu me@yifangu.com --- drivers/mmc/sunxi_mmc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 178b8cf106..779c10407a 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -324,7 +324,7 @@ static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, start = get_timer(0);
for (i = 0; i < word_cnt;) { - unsigned int in_fifo; + __maybe_unused unsigned int in_fifo;
while ((status = readl(&priv->reg->status)) & status_bit) { if (get_timer(start) > timeout_msecs) @@ -343,6 +343,9 @@ static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, continue; }
+#ifdef CONFIG_MACH_SUNIV + buff[i++] = readl(&priv->reg->fifo); +#else /* * The status register holds the current FIFO level, so we * can be sure to collect as many words from the FIFO @@ -355,6 +358,7 @@ static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, in_fifo--) buff[i++] = readl_relaxed(&priv->reg->fifo); dmb(); +#endif }
return 0;

Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/dts/suniv.dtsi | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/dts/suniv.dtsi b/arch/arm/dts/suniv.dtsi index bea7c08e7d..5d84f1e1af 100644 --- a/arch/arm/dts/suniv.dtsi +++ b/arch/arm/dts/suniv.dtsi @@ -126,6 +126,11 @@ function = "uart0"; };
+ uart1_pa_pins: uart-pins-pa { + pins = "PA2", "PA3"; + function = "uart1"; + }; + mmc0_pins: mmc0-pins { pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5"; function = "mmc0";

Signed-off-by: Yifan Gu me@yifangu.com --- arch/arm/dts/Makefile | 3 +- arch/arm/dts/suniv-f1c100s-pocketgo.dts | 48 +++++++++++++++++++++++++ configs/pocketgo_defconfig | 12 +++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 arch/arm/dts/suniv-f1c100s-pocketgo.dts create mode 100644 configs/pocketgo_defconfig
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index a1207a33f5..a2287f5b35 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -666,7 +666,8 @@ dtb-$(CONFIG_MACH_SUN9I) += \ sun9i-a80-cubieboard4.dtb \ sun9i-a80-cx-a99.dtb dtb-$(CONFIG_MACH_SUNIV) += \ - suniv-f1c100s-licheepi-nano.dtb + suniv-f1c100s-licheepi-nano.dtb \ + suniv-f1c100s-pocketgo.dtb
dtb-$(CONFIG_VF610) += vf500-colibri.dtb \ vf610-colibri.dtb \ diff --git a/arch/arm/dts/suniv-f1c100s-pocketgo.dts b/arch/arm/dts/suniv-f1c100s-pocketgo.dts new file mode 100644 index 0000000000..9fdb646ac8 --- /dev/null +++ b/arch/arm/dts/suniv-f1c100s-pocketgo.dts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR X11) +/* + * Copyright 2018 Icenowy Zheng icenowy@aosc.io + * Copyright 2021 Yifan Gu me@yifangu.com + */ + +/dts-v1/; +#include "suniv-f1c100s.dtsi" + +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "PocketGo Handheld"; + compatible = "miyoo,pocketgo", "allwinner,suniv-f1c100s", + "allwinner,suniv"; + + aliases { + serial1 = &uart1; + }; + + chosen { + stdout-path = "serial1:115200n8"; + }; +}; + +&otg_sram { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pa_pins>; + status = "okay"; +}; + +&mmc0 { + 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/pocketgo_defconfig b/configs/pocketgo_defconfig new file mode 100644 index 0000000000..1f9bf4001f --- /dev/null +++ b/configs/pocketgo_defconfig @@ -0,0 +1,12 @@ +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-pocketgo" +CONFIG_SPL=y +# CONFIG_SPL_DM_SERIAL is not set +CONFIG_MMC_SUNXI=y +CONFIG_CONS_INDEX=2 +CONFIG_NET=n
participants (3)
-
Icenowy Zheng
-
Sean Anderson
-
Yifan Gu