Skip to content

Instantly share code, notes, and snippets.

@apritzel
Created April 5, 2018 09:06
Show Gist options
  • Save apritzel/2d7668db6470a6d033b791a08029943a to your computer and use it in GitHub Desktop.
Save apritzel/2d7668db6470a6d033b791a08029943a to your computer and use it in GitHub Desktop.
check configurable GPIO button in SPL and go to FEL mode if low
From 48be8001e507a0bd431b4f8186a95d11ddc6ee36 Mon Sep 17 00:00:00 2001
From: Andre Przywara <[email protected]>
Date: Wed, 23 Nov 2016 00:35:01 +0000
Subject: [PATCH] sunxi: add SPL FEL button
Some of the newer Allwinner boards that come with SPI flash soldered
are missing an easy way to trigger the USB-OTG FEL boot mode.
On most boards without eMMC FEL mode is entered when there is no SD card
found, boards with eMMC typically feature a hardware FEL button.
Now some boards like newer boards from OrangePi have no eMMC, but have a SPI
flash chip soldered, which will be considered when booting the board.
If there is now some valid eGON boot code on that SPI chip, it will
never trigger FEL mode, unless one uses a magic uSD card which
deliberately branches into the BootROM FEL routine.
To avoid this rather involved way, we can emulate a FEL button in
software, using any GPIO. Very early in the boot process this GPIO pin
is configured as an input and sampled. If it is low, the code branches
to the FEL routine, if not, normal booting proceeds.
Add a simple routine which reads the configured GPIO and branches to FEL
if needed. The exact GPIO to be used can be specified via Kconfig.
Signed-off-by: Andre Przywara <[email protected]>
---
arch/arm/mach-sunxi/Kconfig | 12 ++++++++++++
arch/arm/mach-sunxi/board.c | 33 +++++++++++++++++++++++++++++++++
include/configs/sunxi-common.h | 2 ++
3 files changed, 47 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 45dac4d445..8c93f3bb48 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -436,6 +436,18 @@ config SYS_BOARD
config SYS_SOC
default "sunxi"
+config SUNXI_FEL_BUTTON_PIN
+ string "FEL button pin"
+ default ""
+ depends on SUPPORT_SPL
+ ---help---
+ Set a GPIO which acts as a FEL button. Very early in the SPL code
+ this pin is briefly configured as an input and sampled.
+ If it is pulled to GND, the code will jump to the BROM FEL routine.
+ If it is floating or high, the boot process will proceed as normal.
+ This takes a string in the format understood by sunxi_name_to_gpio,
+ e.g. PH1 for pin 1 of port H.
+
config UART0_PORT_F
bool "UART0 on MicroSD breakout board"
default n
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 65b1ebd837..2ce074bbc4 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -151,10 +151,43 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
return 0;
}
SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
+
+static void check_fel_button(void)
+{
+#if defined(CONFIG_SUNXI_FEL_BUTTON_PIN)
+ int mux, ret;
+ uint32_t clockreg;
+ int gpio = sunxi_name_to_gpio(CONFIG_SUNXI_FEL_BUTTON_PIN);
+
+ if (gpio < 0)
+ return;
+
+ if (gpio >= SUNXI_GPL(0)) {
+ clockreg = readl(SUNXI_PRCM_BASE + 0x28);
+ writel(clockreg | 0x01, SUNXI_PRCM_BASE + 0x28);
+ }
+
+ mux = sunxi_gpio_get_cfgpin(gpio);
+ sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
+ ret = gpio_get_value(gpio);
+ sunxi_gpio_set_cfgpin(gpio, mux);
+
+ if (gpio >= SUNXI_GPL(0))
+ writel(clockreg, SUNXI_PRCM_BASE + 0x28);
+
+ if (ret == 0)
+ return_to_fel(fel_stash.sp, FEL_ENTRY_POINT);
+#endif /* FEL_BUTTON_GPIO */
+}
+#else
+static void check_fel_button(void)
+{
+}
#endif
void s_init(void)
{
+ check_fel_button();
/*
* Undocumented magic taken from boot0, without this DRAM
* access gets messed up (seems cache related).
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 4552418243..67006ea4d7 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -98,9 +98,11 @@
*/
#define CONFIG_SYS_INIT_RAM_ADDR 0x10000
#define CONFIG_SYS_INIT_RAM_SIZE 0x08000 /* FIXME: 40 KiB ? */
+#define FEL_ENTRY_POINT 0x00000020
#else
#define CONFIG_SYS_INIT_RAM_ADDR 0x0
#define CONFIG_SYS_INIT_RAM_SIZE 0x8000 /* 32 KiB */
+#define FEL_ENTRY_POINT 0xffff0020
#endif
#define CONFIG_SYS_INIT_SP_OFFSET \
--
2.14.1
@nunojpg
Copy link

nunojpg commented Apr 5, 2018

@apritzel worked perfectly for me, thanks!

@nunojpg
Copy link

nunojpg commented Apr 5, 2018

@apritzel, do you know by chance how would I read a gpio status, also just after s_init, but in main u-boot and not SPL?

I guess the DM is giving me some difficulties, and just reading with readl the register (as in sunxi_gpio_input) is not the same as in SPL.

This is not related to FEL, I'm actually trying to get a GPIO state early in boot to blacklist/disable drivers that should not be loaded for a faster boot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment