diff options
| author | Tom Rini <[email protected]> | 2021-01-11 21:23:59 -0500 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2021-01-11 21:23:59 -0500 |
| commit | f71e574cf993bb89b07420ad90c209fd3f0a3f68 (patch) | |
| tree | f078d5c8a683b806508b606bcbe08603f1a97d8e /arch | |
| parent | d71be1990218957b9f05dbf13a72859a2abe06d7 (diff) | |
| parent | 9267ff89ee27a624ddb5d8eb7d90830ee0ff6f77 (diff) | |
Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-sunxi
- Pinecube board support
- 64-bit FEL support
- mkimage support for eGON images (superseding mksunxiboot)
- Bluetooth BD address generation
- some fixes
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/arm/Kconfig | 1 | ||||
| -rw-r--r-- | arch/arm/cpu/armv8/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/cpu/armv8/fel_utils.S | 78 | ||||
| -rw-r--r-- | arch/arm/dts/Makefile | 1 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-sunxi/boot0.h | 14 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-sunxi/spl.h | 68 | ||||
| -rw-r--r-- | arch/arm/mach-sunxi/Kconfig | 11 | ||||
| -rw-r--r-- | arch/arm/mach-sunxi/dram_sun50i_h6.c | 100 |
8 files changed, 165 insertions, 110 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fbe90875ae4..54762ce03a6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1045,6 +1045,7 @@ config ARCH_SUNXI select SPL_USE_TINY_PRINTF select USE_PREBOOT select SYS_RELOC_GD_ENV_ADDR + imply BOARD_LATE_INIT imply CMD_DM imply CMD_GPT imply CMD_UBI if MTD_RAW_NAND diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index 93d26f98568..f7b4a5ee46c 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -27,6 +27,8 @@ obj-$(CONFIG_ARM_SMCCC) += smccc-call.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o +else +obj-$(CONFIG_ARCH_SUNXI) += fel_utils.o endif obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S new file mode 100644 index 00000000000..9510dcd9e4c --- /dev/null +++ b/arch/arm/cpu/armv8/fel_utils.S @@ -0,0 +1,78 @@ +/* + * Utility functions for FEL mode, when running SPL in AArch64. + * + * Copyright (c) 2017 Arm Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/system.h> +#include <linux/linkage.h> + +/* + * We don't overwrite save_boot_params() here, to save the FEL state upon + * entry, since this would run *after* the RMR reset, which clobbers that + * state. + * Instead we store the state _very_ early in the boot0 hook, *before* + * resetting to AArch64. + */ + +/* + * The FEL routines in BROM run in AArch32. + * Reset back into 32-bit mode here and restore the saved FEL state + * afterwards. + * Resetting back into AArch32/EL3 using the RMR always enters the BROM, + * but we can use the CPU hotplug mechanism to branch back to our code + * immediately. + */ +ENTRY(return_to_fel) + /* + * the RMR reset will clear all registers, so save the arguments + * (LR and SP) in the fel_stash structure, which we read anyways later + */ + adr x2, fel_stash + str w0, [x2] + str w1, [x2, #4] + + adr x1, fel_stash_addr // to find the fel_stash address in AA32 + str w2, [x1] + + ldr x0, =0xfa50392f // CPU hotplug magic +#ifdef CONFIG_MACH_SUN50I_H6 + ldr x2, =(SUNXI_RTC_BASE + 0x1b8) // BOOT_CPU_HP_FLAG_REG + str w0, [x2], #0x4 +#else + ldr x2, =(SUNXI_CPUCFG_BASE + 0x1a4) // offset for CPU hotplug base + str w0, [x2, #0x8] +#endif + adr x0, back_in_32 + str w0, [x2] + + dsb sy + isb sy + mov x0, #2 // RMR reset into AArch32 + dsb sy + msr RMR_EL3, x0 + isb sy +1: wfi + b 1b + +/* AArch32 code to restore the state from fel_stash and return back to FEL. */ +back_in_32: + .word 0xe59f0028 // ldr r0, [pc, #40] ; load fel_stash address + .word 0xe5901008 // ldr r1, [r0, #8] + .word 0xe129f001 // msr CPSR_fc, r1 + .word 0xf57ff06f // isb + .word 0xe590d000 // ldr sp, [r0] + .word 0xe590e004 // ldr lr, [r0, #4] + .word 0xe5901010 // ldr r1, [r0, #16] + .word 0xee0c1f10 // mcr 15, 0, r1, cr12, cr0, {0} ; VBAR + .word 0xe590100c // ldr r1, [r0, #12] + .word 0xee011f10 // mcr 15, 0, r1, cr1, cr0, {0} ; SCTLR + .word 0xf57ff06f // isb + .word 0xe12fff1e // bx lr ; return to FEL +fel_stash_addr: + .word 0x00000000 // receives fel_stash addr, by AA64 code above +ENDPROC(return_to_fel) diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index fd47e408f82..1a62e4c0708 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -590,6 +590,7 @@ dtb-$(CONFIG_MACH_SUN8I_R40) += \ sun8i-r40-bananapi-m2-ultra.dtb \ sun8i-v40-bananapi-m2-berry.dtb dtb-$(CONFIG_MACH_SUN8I_V3S) += \ + sun8i-s3-pinecube.dtb \ sun8i-v3s-licheepi-zero.dtb dtb-$(CONFIG_MACH_SUN50I_H5) += \ sun50i-h5-bananapi-m2-plus.dtb \ diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h index 54c144afd8c..46d0f0666c2 100644 --- a/arch/arm/include/asm/arch-sunxi/boot0.h +++ b/arch/arm/include/asm/arch-sunxi/boot0.h @@ -15,6 +15,19 @@ tst x0, x0 // this is "b #0x84" in ARM b reset .space 0x7c + + .word 0xe28f0058 // add r0, pc, #88 + .word 0xe59f1054 // ldr r1, [pc, #84] + .word 0xe0800001 // add r0, r0, r1 + .word 0xe580d000 // str sp, [r0] + .word 0xe580e004 // str lr, [r0, #4] + .word 0xe10fe000 // mrs lr, CPSR + .word 0xe580e008 // str lr, [r0, #8] + .word 0xee11ef10 // mrc 15, 0, lr, cr1, cr0, {0} + .word 0xe580e00c // str lr, [r0, #12] + .word 0xee1cef10 // mrc 15, 0, lr, cr12, cr0, {0} + .word 0xe580e010 // str lr, [r0, #16] + .word 0xe59f1024 // ldr r1, [pc, #36] ; 0x170000a0 .word 0xe59f0024 // ldr r0, [pc, #36] ; CONFIG_*_TEXT_BASE .word 0xe5810000 // str r0, [r1] @@ -36,6 +49,7 @@ #else .word CONFIG_SYS_TEXT_BASE #endif + .word fel_stash - . #else /* normal execution */ b reset diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index 8c916e8c752..58cdf806d9a 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -7,19 +7,7 @@ #ifndef _ASM_ARCH_SPL_H_ #define _ASM_ARCH_SPL_H_ -#define BOOT0_MAGIC "eGON.BT0" -#define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */ -#define SPL_MAJOR_BITS 3 -#define SPL_MINOR_BITS 5 -#define SPL_VERSION(maj, min) \ - ((((maj) & ((1U << SPL_MAJOR_BITS) - 1)) << SPL_MINOR_BITS) | \ - ((min) & ((1U << SPL_MINOR_BITS) - 1))) - -#define SPL_HEADER_VERSION SPL_VERSION(0, 2) - -#define SPL_ENV_HEADER_VERSION SPL_VERSION(0, 1) -#define SPL_DT_HEADER_VERSION SPL_VERSION(0, 2) -#define SPL_DRAM_HEADER_VERSION SPL_VERSION(0, 3) +#include <sunxi_image.h> #define SPL_ADDR CONFIG_SUNXI_SRAM_ADDRESS @@ -31,59 +19,7 @@ #define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10 #define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12 -/* boot head definition from sun4i boot code */ -struct boot_file_head { - uint32_t b_instruction; /* one intruction jumping to real code */ - uint8_t magic[8]; /* ="eGON.BT0" or "eGON.BT1", not C-style str */ - uint32_t check_sum; /* generated by PC */ - uint32_t length; /* generated by PC */ - /* - * We use a simplified header, only filling in what is needed - * by the boot ROM. To be compatible with Allwinner tools we - * would need to implement the proper fields here instead of - * padding. - * - * Actually we want the ability to recognize our "sunxi" variant - * of the SPL. To do so, let's place a special signature into the - * "pub_head_size" field. We can reasonably expect Allwinner's - * boot0 to always have the upper 16 bits of this set to 0 (after - * all the value shouldn't be larger than the limit imposed by - * SRAM size). - * If the signature is present (at 0x14), then we know it's safe - * to use the remaining 8 bytes (at 0x18) for our own purposes. - * (E.g. sunxi-tools "fel" utility can pass information there.) - */ - union { - uint32_t pub_head_size; - uint8_t spl_signature[4]; - }; - uint32_t fel_script_address; /* since v0.1, set by sunxi-fel */ - /* - * If the fel_uEnv_length member below is set to a non-zero value, - * it specifies the size (byte count) of data at fel_script_address. - * At the same time this indicates that the data is in uEnv.txt - * compatible format, ready to be imported via "env import -t". - */ - uint32_t fel_uEnv_length; /* since v0.1, set by sunxi-fel */ - /* - * Offset of an ASCIIZ string (relative to the SPL header), which - * contains the default device tree name (CONFIG_DEFAULT_DEVICE_TREE). - * This is optional and may be set to NULL. Is intended to be used - * by flash programming tools for providing nice informative messages - * to the users. - */ - uint32_t dt_name_offset; /* since v0.2, set by mksunxiboot */ - uint32_t dram_size; /* in MiB, since v0.3, set by SPL */ - uint32_t boot_media; /* written here by the boot ROM */ - /* A padding area (may be used for storing text strings) */ - uint32_t string_pool[13]; /* since v0.2, filled by mksunxiboot */ - /* The header must be a multiple of 32 bytes (for VBAR alignment) */ -}; - -/* Compile time check to assure proper alignment of structure */ -typedef char boot_file_head_not_multiple_of_32[1 - 2*(sizeof(struct boot_file_head) % 32)]; - -#define is_boot0_magic(addr) (memcmp((void *)addr, BOOT0_MAGIC, 8) == 0) +#define is_boot0_magic(addr) (memcmp((void *)(addr), BOOT0_MAGIC, 8) == 0) uint32_t sunxi_get_boot_device(void); diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 49ef217f08c..11e64451927 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1016,4 +1016,15 @@ config PINEPHONE_DT_SELECTION Enable this option to automatically select the device tree for the correct PinePhone hardware revision during boot. +config BLUETOOTH_DT_DEVICE_FIXUP + string "Fixup the Bluetooth controller address" + default "" + help + This option specifies the DT compatible name of the Bluetooth + controller for which to set the "local-bd-address" property. + Set this option if your device ships with the Bluetooth controller + default address. + The used address is "bdaddr" if set, and "ethaddr" with the LSB + flipped elsewise. + endif diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c index 9e34da47479..32ec0bc4cd4 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h6.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c @@ -37,9 +37,9 @@ static void mctl_sys_init(struct dram_para *para); static void mctl_com_init(struct dram_para *para); -static void mctl_channel_init(struct dram_para *para); +static bool mctl_channel_init(struct dram_para *para); -static void mctl_core_init(struct dram_para *para) +static bool mctl_core_init(struct dram_para *para) { mctl_sys_init(para); mctl_com_init(para); @@ -51,7 +51,7 @@ static void mctl_core_init(struct dram_para *para) default: panic("Unsupported DRAM type!"); }; - mctl_channel_init(para); + return mctl_channel_init(para); } /* PHY initialisation */ @@ -411,7 +411,7 @@ static void mctl_bit_delay_set(struct dram_para *para) } } -static void mctl_channel_init(struct dram_para *para) +static bool mctl_channel_init(struct dram_para *para) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -528,46 +528,15 @@ static void mctl_channel_init(struct dram_para *para) clrbits_le32(&mctl_phy->dx[i].gcr[3], ~0x3ffff); udelay(10); - if (readl(&mctl_phy->pgsr[0]) & 0x400000) - { - /* Check for single rank and optionally half DQ. */ - if ((readl(&mctl_phy->dx[0].rsr[0]) & 0x3) == 2 && - (readl(&mctl_phy->dx[1].rsr[0]) & 0x3) == 2) { - para->ranks = 1; - - if ((readl(&mctl_phy->dx[2].rsr[0]) & 0x3) != 2 || - (readl(&mctl_phy->dx[3].rsr[0]) & 0x3) != 2) - para->bus_full_width = 0; - - /* Restart DRAM initialization from scratch. */ - mctl_core_init(para); - return; - } - - /* - * Check for dual rank and half DQ. NOTE: This combination - * is highly unlikely and was not tested. Condition is the - * same as in libdram, though. - */ - if ((readl(&mctl_phy->dx[0].rsr[0]) & 0x3) == 0 && - (readl(&mctl_phy->dx[1].rsr[0]) & 0x3) == 0) { - para->bus_full_width = 0; - - /* Restart DRAM initialization from scratch. */ - mctl_core_init(para); - return; - } - - panic("This DRAM setup is currently not supported.\n"); - } - if (readl(&mctl_phy->pgsr[0]) & 0xff00000) { /* Oops! There's something wrong! */ debug("PLL = %x\n", readl(0x3001010)); debug("DRAM PHY PGSR0 = %x\n", readl(&mctl_phy->pgsr[0])); for (i = 0; i < 4; i++) debug("DRAM PHY DX%dRSR0 = %x\n", i, readl(&mctl_phy->dx[i].rsr[0])); - panic("Error while initializing DRAM PHY!\n"); + debug("Error while initializing DRAM PHY!\n"); + + return false; } if (sunxi_dram_is_lpddr(para->type)) @@ -582,13 +551,59 @@ static void mctl_channel_init(struct dram_para *para) writel(0xffffffff, &mctl_com->maer0); writel(0x7ff, &mctl_com->maer1); writel(0xffff, &mctl_com->maer2); + + return true; +} + +static void mctl_auto_detect_rank_width(struct dram_para *para) +{ + /* this is minimum size that it's supported */ + para->cols = 8; + para->rows = 13; + + /* + * Previous versions of this driver tried to auto detect the rank + * and width by looking at controller registers. However this proved + * to be not reliable, so this approach here is the more robust + * solution. Check the git history for details. + * + * Strategy here is to test most demanding combination first and least + * demanding last, otherwise HW might not be fully utilized. For + * example, half bus width and rank = 1 combination would also work + * on HW with full bus width and rank = 2, but only 1/4 RAM would be + * visible. + */ + + debug("testing 32-bit width, rank = 2\n"); + para->bus_full_width = 1; + para->ranks = 2; + if (mctl_core_init(para)) + return; + + debug("testing 32-bit width, rank = 1\n"); + para->bus_full_width = 1; + para->ranks = 1; + if (mctl_core_init(para)) + return; + + debug("testing 16-bit width, rank = 2\n"); + para->bus_full_width = 0; + para->ranks = 2; + if (mctl_core_init(para)) + return; + + debug("testing 16-bit width, rank = 1\n"); + para->bus_full_width = 0; + para->ranks = 1; + if (mctl_core_init(para)) + return; + + panic("This DRAM setup is currently not supported.\n"); } static void mctl_auto_detect_dram_size(struct dram_para *para) { /* TODO: non-(LP)DDR3 */ - /* Detect rank number and half DQ by the code in mctl_channel_init. */ - mctl_core_init(para); /* detect row address bits */ para->cols = 8; @@ -652,10 +667,6 @@ unsigned long sunxi_dram_init(void) (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; struct dram_para para = { .clk = CONFIG_DRAM_CLK, - .ranks = 2, - .cols = 11, - .rows = 14, - .bus_full_width = 1, #ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3 .type = SUNXI_DRAM_TYPE_LPDDR3, .dx_read_delays = SUN50I_H6_LPDDR3_DX_READ_DELAYS, @@ -673,6 +684,7 @@ unsigned long sunxi_dram_init(void) setbits_le32(0x7010310, BIT(8)); clrbits_le32(0x7010318, 0x3f); + mctl_auto_detect_rank_width(¶); mctl_auto_detect_dram_size(¶); mctl_core_init(¶); |
