Re: [PATCH 02/11] arm: arm926ej-s: add sunxi code

Jesse Taube
2022-01-21T03:16:54Z

On 1/20/22 21:25, Andre Przywara wrote:
> On Tue, 4 Jan 2022 19:34:59 -0500
> Jesse Taube <mr.bossman075@gmail.com> wrote:
>
> Hi,
>
>> 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: Jesse Taube <Mr.Bossman075@gmail.com>
>> ---
>> arch/arm/cpu/arm926ejs/Makefile | 1 +
>> arch/arm/cpu/arm926ejs/sunxi/Makefile | 15 +++
>> arch/arm/cpu/arm926ejs/sunxi/config.mk | 6 +
>> arch/arm/cpu/arm926ejs/sunxi/fel_utils.S | 37 ++++++
>> arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S | 67 +++++++++++
>> 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 | 62 ++++++++++
>> 8 files changed, 303 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 b901b7c5c9..7f1436d76e 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/sunxi/Makefile b/arch/arm/cpu/arm926ejs/sunxi/Makefile
>> new file mode 100644
>> index 0000000000..894c461c50
>> --- /dev/null
>> +++ b/arch/arm/cpu/arm926ejs/sunxi/Makefile
>> @@ -0,0 +1,15 @@
>> +# SPDX-License-Identifier: GPL-2.0+
>> +#
>> +# (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.
>
> Please remove this heritage. I appreciate the effort to give credit,
> but for a trivial Makefile stub (which even differs significantly) this
> is surely overkill.
> Just one line with some current copyright should be enough.
>
Fixed.
>> +
>> +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..0997a2dc65
>> --- /dev/null
>> +++ b/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S
>> @@ -0,0 +1,37 @@
>> +/* 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]
>> + mrc p15, 0, lr, c1, c0, 0 @ Read CP15 Control Register
>> + str lr, [r0, #16]
>
> This is the very same register twice, also written to the wrong offset.
> Please remove the last two lines.
> Yes, this is a bug in armv7/sunxi/fel_utils.S as well, I will send a
> fix.
Please CC me.
>
>> + 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
>
> Same here, those two lines can be removed.
>
>> + 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..db09bcc4d0
>> --- /dev/null
>> +++ b/arch/arm/cpu/arm926ejs/sunxi/lowlevel_init.S
>> @@ -0,0 +1,67 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * 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>
>> + */
>> +
>> +#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
>
> I would say we don't need this weak stub. In contrast to armv7, we are
> the only user of this file, and s_init should be provided by
> arch/arm/mach-sunxi/board.c.
>
> In general the toplevel README seems to deprecate lowlevel_init, but
> this probably needs some fixing in the other sunxi code first.
I removed it its defined in board like you said.
>> +
>> +.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
>
> We probably don't need this SPL_DM part?
Hmmmmm you are right im assuiming this got copied from somewhere. I
replaced the ifdef with `mov r9, #0`.
>
>> + /*
>> + * 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.
>> + */
>
> Yeah, this (copied) comments seems to suggest we are somewhat off here.
> But I think we rely on board.c:s_init() too much to easily remove this.
>
> So for the sake of not blocking this I am willing to keep this part for
> now.
Much apretiated!
>
>> + 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..e624174581
>> --- /dev/null
>> +++ b/arch/arm/cpu/arm926ejs/sunxi/timer.c
>
> I don't see immediately why the original file lives in
> arch/arm/cpu/armv7/sunxi/timer.c. Can we move that to
> arch/arm/mach-sunxi or board/sunxi, then just not compile it for arm64?
> Because otherwise this looks identical to its donor, minus some smaller
> (but good) cleanups.
> So I'm curious if we can move and then reuse the original file.
I will try thanks for the pointer.
>
>> @@ -0,0 +1,114 @@
>> +// SPDX-License-Identifier: (GPL-2.0+)
>> +/*
>> + * (C) Copyright 2007-2011
>> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
>> + * Tom Cubie <tangliang@allwinnertech.com>
>> + */
>> +
>> +#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)
>
> Any reason you lost the static here?
No, presumibly becuse it got changed sence 2018.
>
>> +{
>> + /* 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..048aab788a
>> --- /dev/null
>> +++ b/arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds
>> @@ -0,0 +1,62 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * (C) Copyright 2018
>> + * Icenowy Zheng <icenowy@aosc.io>
>> + *
>> + * Based on arch/arm/cpu/armv7/sunxi/u-boot-spl.lds:
>> + *
>> + * (C) Copyright 2012
>> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
>> + * Tom Cubie <tangliang@allwinnertech.com>
>> + *
>
> I think that's enough history at this point ...
LOL I'll fix this, I think Icenowy wanted to make licencing clear.
>
>> + * 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>
>> + */
>> +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)
>
> Do we actually need this, if it's empty? Isn't that file just to
> satisfy the needs of the generic linker scripts?
>
Nope I droped it and the file.

I'm impresesd with how fast you reviewd this one thanks for the
feedback. You don't have to review patch 6 unless its okay that dram
isnt using device tree, I think it should use it so thats on my todo list.

Thanks,
Jesse Taube
> Cheers,
> Andre.
>
>> + *(.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
>> +}
>