Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- Fix ARMv5/F1C100 FEL booting
- Fix F1C100 reset
- Introduce proper F1C100 boot method detection
- Enable SPI booting for F1C100

Boot tested from FEL, SPI, SD card and eMMC (where applicable) on
Pine64-LTS, Pine-H64, BananaPi M1, OrangePi Zero, LicheePi Nano(F1C100).
  • Loading branch information
trini committed Mar 6, 2022
2 parents 0444cbb + cfcf195 commit 6d3c46e
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 37 deletions.
4 changes: 2 additions & 2 deletions arch/arm/cpu/arm926ejs/sunxi/fel_utils.S
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ 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)
1 change: 1 addition & 0 deletions arch/arm/include/asm/arch-sunxi/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ enum sunxi_gpio_number {
#define SUNXI_GPC_SDC2 3
#define SUN6I_GPC_SDC3 4
#define SUN50I_GPC_SPI0 4
#define SUNIV_GPC_SPI0 2

#define SUNXI_GPD_LCD0 2
#define SUNXI_GPD_LVDS0 3
Expand Down
9 changes: 9 additions & 0 deletions arch/arm/include/asm/arch-sunxi/spl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
#define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10
#define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12

/*
* Values taken from the F1C200s BootROM stack
* to determine where we booted from.
*/
#define SUNIV_BOOTED_FROM_MMC0 0xffff40f8
#define SUNIV_BOOTED_FROM_NAND 0xffff4114
#define SUNIV_BOOTED_FROM_SPI 0xffff4130
#define SUNIV_BOOTED_FROM_MMC1 0xffff4150

#define is_boot0_magic(addr) (memcmp((void *)(addr), BOOT0_MAGIC, 8) == 0)

uint32_t sunxi_get_boot_device(void);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-sunxi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,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_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 || MACH_SUNIV
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
Expand Down
64 changes: 37 additions & 27 deletions arch/arm/mach-sunxi/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,48 @@ SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image);

#define SUNXI_INVALID_BOOT_SOURCE -1

static int suniv_get_boot_source(void)
{
/* Get the last function call from BootROM's stack. */
u32 brom_call = *(u32 *)(uintptr_t)(fel_stash.sp - 4);

/* translate SUNIV BootROM stack to standard SUNXI boot sources */
switch (brom_call) {
case SUNIV_BOOTED_FROM_MMC0:
return SUNXI_BOOTED_FROM_MMC0;
case SUNIV_BOOTED_FROM_SPI:
return SUNXI_BOOTED_FROM_SPI;
case SUNIV_BOOTED_FROM_MMC1:
return SUNXI_BOOTED_FROM_MMC2;
/* SPI NAND is not supported yet. */
case SUNIV_BOOTED_FROM_NAND:
return SUNXI_INVALID_BOOT_SOURCE;
}
/* If we get here something went wrong try to boot from FEL.*/
printf("Unknown boot source from BROM: 0x%x\n", brom_call);
return SUNXI_INVALID_BOOT_SOURCE;
}

static int sunxi_get_boot_source(void)
{
/*
* On the ARMv5 SoCs, the SPL header in SRAM is overwritten by the
* exception vectors in U-Boot proper, so we won't find any
* information there. Also the FEL stash is only valid in the SPL,
* so we can't use that either. So if this is called from U-Boot
* proper, just return MMC0 as a placeholder, for now.
*/
if (IS_ENABLED(CONFIG_MACH_SUNIV) &&
!IS_ENABLED(CONFIG_SPL_BUILD))
return SUNXI_BOOTED_FROM_MMC0;

if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
return SUNXI_INVALID_BOOT_SOURCE;

return readb(SPL_ADDR + 0x28);
if (IS_ENABLED(CONFIG_MACH_SUNIV))
return suniv_get_boot_source();
else
return readb(SPL_ADDR + 0x28);
}

/* The sunxi internal brom will try to loader external bootloader
Expand Down Expand Up @@ -276,36 +312,10 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
return sector;
}

#ifdef CONFIG_MACH_SUNIV
/*
* The suniv BROM does not pass the boot media type to SPL, so we try with the
* boot sequence in BROM: mmc0->spinor->fail.
* TODO: This has the slight chance of being wrong (invalid SPL signature,
* but valid U-Boot legacy image on the SD card), but this should be rare.
* It looks like we can deduce from some BROM state upon entering the SPL
* (registers, SP, or stack itself) where the BROM was coming from and use
* that here.
*/
void board_boot_order(u32 *spl_boot_list)
{
/*
* See the comments above in sunxi_get_boot_device() for information
* about FEL boot.
*/
if (!is_boot0_magic(SPL_ADDR + 4)) {
spl_boot_list[0] = BOOT_DEVICE_BOARD;
return;
}

spl_boot_list[0] = BOOT_DEVICE_MMC1;
spl_boot_list[1] = BOOT_DEVICE_SPI;
}
#else
u32 spl_boot_device(void)
{
return sunxi_get_boot_device();
}
#endif

__weak void sunxi_sram_init(void)
{
Expand Down
24 changes: 17 additions & 7 deletions arch/arm/mach-sunxi/spl_spi_sunxi.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@

#define SPI0_CLK_DIV_BY_2 0x1000
#define SPI0_CLK_DIV_BY_4 0x1001
#define SPI0_CLK_DIV_BY_32 0x100f

/*****************************************************************************/

Expand Down Expand Up @@ -132,7 +133,8 @@ static uintptr_t spi0_base_address(void)
if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
return 0x05010000;

if (!is_sun6i_gen_spi())
if (!is_sun6i_gen_spi() ||
IS_ENABLED(CONFIG_MACH_SUNIV))
return 0x01C05000;

return 0x01C68000;
Expand All @@ -156,11 +158,16 @@ static void spi0_enable_clock(void)
if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6))
setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));

/* 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);
if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
/* Divide by 32, clock source is AHB clock 200MHz */
writel(SPI0_CLK_DIV_BY_32, base + SUN6I_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);
}

if (is_sun6i_gen_spi()) {
/* Enable SPI in the master mode and do a soft reset */
Expand Down Expand Up @@ -191,7 +198,8 @@ static void spi0_disable_clock(void)
SUN4I_CTL_ENABLE);

/* Disable the SPI0 clock */
writel(0, CCM_SPI0_CLK);
if (!IS_ENABLED(CONFIG_MACH_SUNIV))
writel(0, CCM_SPI0_CLK);

/* Close the SPI0 gate */
if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6))
Expand All @@ -212,6 +220,8 @@ static void spi0_init(void)
if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
IS_ENABLED(CONFIG_MACH_SUN50I_H6))
pin_function = SUN50I_GPC_SPI0;
else if (IS_ENABLED(CONFIG_MACH_SUNIV))
pin_function = SUNIV_GPC_SPI0;

spi0_pinmux_setup(pin_function);
spi0_enable_clock();
Expand Down
2 changes: 2 additions & 0 deletions configs/licheepi_nano_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ CONFIG_MACH_SUNIV=y
CONFIG_DRAM_CLK=156
CONFIG_DRAM_ZQ=0
# CONFIG_VIDEO_SUNXI is not set
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYSRESET is not set

0 comments on commit 6d3c46e

Please sign in to comment.