summaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2022-02-03 23:20:20 -0500
committerTom Rini <[email protected]>2022-02-03 23:24:31 -0500
commit3aaabfe9ff4bbcd11096513b1b28d1fb0a40800f (patch)
treecf8ffc29edb6bd06cd7ba02f1eb246798289539e /arch/arm/cpu
parent3e5f4b337d89e95af9d3700a4b055b552bf22ac4 (diff)
parentb6ffd58e45043b822844345d4ca9b2cb1e2917b7 (diff)
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.
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/arm926ejs/Makefile1
-rw-r--r--arch/arm/cpu/arm926ejs/cpu.c13
-rw-r--r--arch/arm/cpu/arm926ejs/start.S19
-rw-r--r--arch/arm/cpu/arm926ejs/sunxi/Makefile5
-rw-r--r--arch/arm/cpu/arm926ejs/sunxi/config.mk6
-rw-r--r--arch/arm/cpu/arm926ejs/sunxi/fel_utils.S33
-rw-r--r--arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds48
-rw-r--r--arch/arm/cpu/armv7/Kconfig5
-rw-r--r--arch/arm/cpu/armv7/start.S11
-rw-r--r--arch/arm/cpu/armv7/sunxi/Makefile4
-rw-r--r--arch/arm/cpu/armv7/sunxi/sram.c40
-rw-r--r--arch/arm/cpu/armv7/sunxi/timer.c116
-rw-r--r--arch/arm/cpu/armv8/Makefile1
-rw-r--r--arch/arm/cpu/armv8/lowlevel_init.S43
14 files changed, 184 insertions, 161 deletions
diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile
index b901b7c5c90..7f1436d76e1 100644
--- a/arch/arm/cpu/arm926ejs/Makefile
+++ b/arch/arm/cpu/arm926ejs/Makefile
@@ -15,6 +15,7 @@ endif
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 93d7a02ed4c..2ce413a7f86 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 0afcc47aad7..aca7793c579 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_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 00000000000..7d8b959dcd1
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/sunxi/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+# (C) Copyright 2012 Henrik Nordstrom <[email protected]>
+
+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 00000000000..76ffec9df6a
--- /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 00000000000..08be7ed11aa
--- /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 00000000000..9a000ac5d38
--- /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 <[email protected]>
+ *
+ * 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 60bb0a9e1ec..2eeef3cba96 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -76,4 +76,9 @@ config ARMV7_LPAE
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 698e15b8e18..af87a5432ae 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -173,6 +173,17 @@ ENDPROC(switch_to_hypervisor)
*
*************************************************************************/
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 1d40d6a18dc..3e975b366c4 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, [email protected].
-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 00000000000..28564c2846a
--- /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 <[email protected]>
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <[email protected]>
+ *
+ * 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/armv7/sunxi/timer.c b/arch/arm/cpu/armv7/sunxi/timer.c
deleted file mode 100644
index b7585996369..00000000000
--- a/arch/arm/cpu/armv7/sunxi/timer.c
+++ /dev/null
@@ -1,116 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2007-2011
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Tom Cubie <[email protected]>
- */
-
-#include <common.h>
-#include <init.h>
-#include <time.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
-#include <asm/arch/timer.h>
-#include <linux/delay.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define TIMER_MODE (0x0 << 7) /* continuous mode */
-#define TIMER_DIV (0x0 << 4) /* pre scale 1 */
-#define TIMER_SRC (0x1 << 2) /* osc24m */
-#define TIMER_RELOAD (0x1 << 1) /* reload internal value */
-#define TIMER_EN (0x1 << 0) /* enable timer */
-
-#define TIMER_CLOCK (24 * 1000 * 1000)
-#define COUNT_TO_USEC(x) ((x) / 24)
-#define USEC_TO_COUNT(x) ((x) * 24)
-#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ)
-#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ)
-
-#define TIMER_LOAD_VAL 0xffffffff
-
-#define TIMER_NUM 0 /* we use timer 0 */
-
-/* read the 32-bit timer */
-static ulong read_timer(void)
-{
- struct sunxi_timer_reg *timers =
- (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
- struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
-
- /*
- * The hardware timer counts down, therefore we invert to
- * produce an incrementing timer.
- */
- return ~readl(&timer->val);
-}
-
-/* init timer register */
-int timer_init(void)
-{
- struct sunxi_timer_reg *timers =
- (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
- struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
- writel(TIMER_LOAD_VAL, &timer->inter);
- writel(TIMER_MODE | TIMER_DIV | TIMER_SRC | TIMER_RELOAD | TIMER_EN,
- &timer->ctl);
-
- return 0;
-}
-
-/* timer without interrupts */
-static 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;
-}
-
-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/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index d85ddde430a..85fe0475c86 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -42,6 +42,5 @@ obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/
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 f4f0cdce9b3..00000000000
--- 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)