[PATCH 0/7] sunxi: Fix U-Boot proper SPI operation

Hi,
despite U-Boot supporting SPI on Allwinner chips and SPI flash in general for a while, it wasn't really working well for many sunxi boards. Booting from SPI is handled by separate SPL code, which works fine, but the "sf" command in U-Boot proper is often just not operational.
This series tries to improve the situation, by: - cleaning up the SPI Kconfig situation for sunxi (patch 2) - adding support for environment in SPI flash (patch 3-5) - trying to enable more boards for U-Boot-proper SPI flash (patch 6)
As an added bonus there is some whacky code to make the SPI flash usable in Linux on H6 boards. Marking this as RFC.
Actually even after this series many boards still miss out, because they are lacking the required "spi0" alias in the DT. We could go with *-u-boot.dtsi fixes for now (as the SoPine does), but even mainline DT support wouldn't help, as we are somewhat stuck with DT updates. But that's a story for another time, let's get this SPI support fixed first.
Cheers, Andre
Andre Przywara (6): sunxi: Kconfig: Fix up SPI configuration env: sunxi: Define location in SPI flash sunxi: use boot source for determining environment location env: sunxi: enable ENV_IS_IN_SPI_FLASH sunxi: boards: Enable SPI flash support in U-Boot proper sunxi: H6: Enable SPI0 in DT when no eMMC is used
Daniel Wagenknecht (1): sunxi: SPI: fix pinmuxing for Allwinner H6 SoCs
arch/arm/Kconfig | 2 + arch/arm/mach-sunxi/Kconfig | 13 ++- board/sunxi/board.c | 101 +++++++++++++++++++++-- configs/libretech_all_h3_it_h5_defconfig | 2 - configs/libretech_all_h5_cc_h5_defconfig | 2 - configs/oceanic_5205_5inmfd_defconfig | 1 + configs/orangepi_pc2_defconfig | 2 + configs/orangepi_r1_defconfig | 2 + configs/orangepi_win_defconfig | 2 + configs/orangepi_zero2_defconfig | 2 + configs/orangepi_zero_defconfig | 2 + configs/pine64-lts_defconfig | 2 + configs/pine_h64_defconfig | 3 + configs/pinecube_defconfig | 2 + configs/sopine_baseboard_defconfig | 1 + drivers/spi/spi-sunxi.c | 3 +- env/Kconfig | 7 +- 17 files changed, 131 insertions(+), 18 deletions(-)

From: Daniel Wagenknecht dwagenk@mailbox.org
The driver for SPI0 on Allwinner H6 SoCs did not use the correct define SUN50I_GPC_SPI0 for the pin function, but one for a different Allwinner SoC series.
Fix the conditionals to use the correct define for H6 SoCs. This matches the conditional logic in the SPL spi driver.
Tested by probing the spi-flash on a pine64_h64-model-b board with adapted device-tree (disable mmc2, enable spi0).
Signed-off-by: Daniel Wagenknecht dwagenk@mailbox.org Reviewed-by: Andre Przywara andre.przywara@arm.com Signed-off-by: Andre Przywara andre.przywara@arm.com --- drivers/spi/spi-sunxi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index bc2f544e86..d62355ec6f 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -249,7 +249,8 @@ static int sun4i_spi_parse_pins(struct udevice *dev) if (pin < 0) break;
- if (IS_ENABLED(CONFIG_MACH_SUN50I)) + if (IS_ENABLED(CONFIG_MACH_SUN50I) || + IS_ENABLED(CONFIG_SUN50I_GEN_H6)) sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0); else sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);

Commit 7945caf22c44 ("arm: sunxi: Enable SPI/SPI-FLASH support for A64") selected CONFIG_SPI by default on all Allwinner A64 boards, even though only 4 out of the 14 A64 boards have a SPI flash chip. All other SoCs had to manually select DM_SPI and friends, even though they are a platform property (the sunxi SPI driver is DM_SPI only).
Clean this up to allow easy selection of SPI flash support in U-Boot proper, by selecting DM_SPI and DM_SPI_FLASH *if* CONFIG_SPI is selected, for *all* Allwinner SoCs. This simplifies the defconfig for two Libretech boards already.
Also remove the forced CONFIG_SPI from the A64 Kconfig, instead let the four boards which allow SPI booting select this explicitly.
Any board wishing to support SPI flash in U-Boot proper now just defines CONFIG_SPI and CONFIG_SPI_FLASH_<vendor> in its defconfig, Kconfig takes care of the rest.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- arch/arm/Kconfig | 2 ++ arch/arm/mach-sunxi/Kconfig | 3 --- configs/libretech_all_h3_it_h5_defconfig | 2 -- configs/libretech_all_h5_cc_h5_defconfig | 2 -- configs/oceanic_5205_5inmfd_defconfig | 1 + configs/orangepi_win_defconfig | 1 + configs/pine64-lts_defconfig | 1 + configs/sopine_baseboard_defconfig | 1 + 8 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7264d72bde..0f63bfdded 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1055,6 +1055,8 @@ config ARCH_SUNXI select DM_ETH select DM_GPIO select DM_I2C if I2C + select DM_SPI if SPI + select DM_SPI_FLASH if SPI select DM_KEYBOARD select DM_MMC if MMC select DM_SCSI if SCSI diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 2c18cf02d1..56ff1e197c 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -324,9 +324,6 @@ config MACH_SUN9I config MACH_SUN50I bool "sun50i (Allwinner A64)" select ARM64 - select SPI - select DM_SPI if SPI - select DM_SPI_FLASH select PHY_SUN4I_USB select SUN6I_PRCM select SUNXI_DE2 diff --git a/configs/libretech_all_h3_it_h5_defconfig b/configs/libretech_all_h3_it_h5_defconfig index 7f0e0be50b..cb7ffb4d7d 100644 --- a/configs/libretech_all_h3_it_h5_defconfig +++ b/configs/libretech_all_h3_it_h5_defconfig @@ -7,9 +7,7 @@ CONFIG_DRAM_CLK=672 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_XMC=y CONFIG_SPI=y -CONFIG_DM_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/libretech_all_h5_cc_h5_defconfig b/configs/libretech_all_h5_cc_h5_defconfig index 25bfe52b32..c3aa4b1061 100644 --- a/configs/libretech_all_h5_cc_h5_defconfig +++ b/configs/libretech_all_h5_cc_h5_defconfig @@ -7,10 +7,8 @@ CONFIG_DRAM_CLK=672 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_XMC=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y -CONFIG_DM_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig index 9ba115c97d..7ce63ba665 100644 --- a/configs/oceanic_5205_5inmfd_defconfig +++ b/configs/oceanic_5205_5inmfd_defconfig @@ -11,5 +11,6 @@ CONFIG_MMC0_CD_PIN="" CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig index 8c2179ba8b..133755291a 100644 --- a/configs/orangepi_win_defconfig +++ b/configs/orangepi_win_defconfig @@ -9,5 +9,6 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig index 6209e68e2d..75a77acc44 100644 --- a/configs/pine64-lts_defconfig +++ b/configs/pine64-lts_defconfig @@ -11,5 +11,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig index 0093076dc5..982f7b0b67 100644 --- a/configs/sopine_baseboard_defconfig +++ b/configs/sopine_baseboard_defconfig @@ -13,5 +13,6 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y

On Tue, 11 Jan 2022 12:46:02 +0000 Andre Przywara andre.przywara@arm.com wrote:
Hi Jagan,
can you please have a look at this patch? It seems like a nice cleanup to me, but I would like to hear your opinion.
Cheers, Andre
Commit 7945caf22c44 ("arm: sunxi: Enable SPI/SPI-FLASH support for A64") selected CONFIG_SPI by default on all Allwinner A64 boards, even though only 4 out of the 14 A64 boards have a SPI flash chip. All other SoCs had to manually select DM_SPI and friends, even though they are a platform property (the sunxi SPI driver is DM_SPI only).
Clean this up to allow easy selection of SPI flash support in U-Boot proper, by selecting DM_SPI and DM_SPI_FLASH *if* CONFIG_SPI is selected, for *all* Allwinner SoCs. This simplifies the defconfig for two Libretech boards already.
Also remove the forced CONFIG_SPI from the A64 Kconfig, instead let the four boards which allow SPI booting select this explicitly.
Any board wishing to support SPI flash in U-Boot proper now just defines CONFIG_SPI and CONFIG_SPI_FLASH_<vendor> in its defconfig, Kconfig takes care of the rest.
Signed-off-by: Andre Przywara andre.przywara@arm.com
arch/arm/Kconfig | 2 ++ arch/arm/mach-sunxi/Kconfig | 3 --- configs/libretech_all_h3_it_h5_defconfig | 2 -- configs/libretech_all_h5_cc_h5_defconfig | 2 -- configs/oceanic_5205_5inmfd_defconfig | 1 + configs/orangepi_win_defconfig | 1 + configs/pine64-lts_defconfig | 1 + configs/sopine_baseboard_defconfig | 1 + 8 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7264d72bde..0f63bfdded 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1055,6 +1055,8 @@ config ARCH_SUNXI select DM_ETH select DM_GPIO select DM_I2C if I2C
- select DM_SPI if SPI
- select DM_SPI_FLASH if SPI select DM_KEYBOARD select DM_MMC if MMC select DM_SCSI if SCSI
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 2c18cf02d1..56ff1e197c 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -324,9 +324,6 @@ config MACH_SUN9I config MACH_SUN50I bool "sun50i (Allwinner A64)" select ARM64
- select SPI
- select DM_SPI if SPI
- select DM_SPI_FLASH select PHY_SUN4I_USB select SUN6I_PRCM select SUNXI_DE2
diff --git a/configs/libretech_all_h3_it_h5_defconfig b/configs/libretech_all_h3_it_h5_defconfig index 7f0e0be50b..cb7ffb4d7d 100644 --- a/configs/libretech_all_h3_it_h5_defconfig +++ b/configs/libretech_all_h3_it_h5_defconfig @@ -7,9 +7,7 @@ CONFIG_DRAM_CLK=672 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_XMC=y CONFIG_SPI=y -CONFIG_DM_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/libretech_all_h5_cc_h5_defconfig b/configs/libretech_all_h5_cc_h5_defconfig index 25bfe52b32..c3aa4b1061 100644 --- a/configs/libretech_all_h5_cc_h5_defconfig +++ b/configs/libretech_all_h5_cc_h5_defconfig @@ -7,10 +7,8 @@ CONFIG_DRAM_CLK=672 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_XMC=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y -CONFIG_DM_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig index 9ba115c97d..7ce63ba665 100644 --- a/configs/oceanic_5205_5inmfd_defconfig +++ b/configs/oceanic_5205_5inmfd_defconfig @@ -11,5 +11,6 @@ CONFIG_MMC0_CD_PIN="" CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig index 8c2179ba8b..133755291a 100644 --- a/configs/orangepi_win_defconfig +++ b/configs/orangepi_win_defconfig @@ -9,5 +9,6 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig index 6209e68e2d..75a77acc44 100644 --- a/configs/pine64-lts_defconfig +++ b/configs/pine64-lts_defconfig @@ -11,5 +11,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig index 0093076dc5..982f7b0b67 100644 --- a/configs/sopine_baseboard_defconfig +++ b/configs/sopine_baseboard_defconfig @@ -13,5 +13,6 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y

On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
Commit 7945caf22c44 ("arm: sunxi: Enable SPI/SPI-FLASH support for A64") selected CONFIG_SPI by default on all Allwinner A64 boards, even though only 4 out of the 14 A64 boards have a SPI flash chip. All other SoCs had to manually select DM_SPI and friends, even though they are a platform property (the sunxi SPI driver is DM_SPI only).
Clean this up to allow easy selection of SPI flash support in U-Boot proper, by selecting DM_SPI and DM_SPI_FLASH *if* CONFIG_SPI is selected, for *all* Allwinner SoCs. This simplifies the defconfig for two Libretech boards already.
Also remove the forced CONFIG_SPI from the A64 Kconfig, instead let the four boards which allow SPI booting select this explicitly.
Any board wishing to support SPI flash in U-Boot proper now just defines CONFIG_SPI and CONFIG_SPI_FLASH_<vendor> in its defconfig, Kconfig takes care of the rest.
Signed-off-by: Andre Przywara andre.przywara@arm.com

On Thu, Feb 24, 2022 at 12:56 PM Jagan Teki jagan@amarulasolutions.com wrote:
On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
Commit 7945caf22c44 ("arm: sunxi: Enable SPI/SPI-FLASH support for A64") selected CONFIG_SPI by default on all Allwinner A64 boards, even though only 4 out of the 14 A64 boards have a SPI flash chip. All other SoCs had to manually select DM_SPI and friends, even though they are a platform property (the sunxi SPI driver is DM_SPI only).
Clean this up to allow easy selection of SPI flash support in U-Boot proper, by selecting DM_SPI and DM_SPI_FLASH *if* CONFIG_SPI is selected, for *all* Allwinner SoCs. This simplifies the defconfig for two Libretech boards already.
Also remove the forced CONFIG_SPI from the A64 Kconfig, instead let the four boards which allow SPI booting select this explicitly.
Any board wishing to support SPI flash in U-Boot proper now just defines CONFIG_SPI and CONFIG_SPI_FLASH_<vendor> in its defconfig, Kconfig takes care of the rest.
Signed-off-by: Andre Przywara andre.przywara@arm.com
Reviewed-by: Jagan Teki jagan@amarulasolutions.com

To allow loading and storing the environment from SPI flash, adjust the raw offset variables for Allwinner boards to make sense there.
U-Boot (including SPL and other blobs) is loaded from the beginning of SPI flash, so move the environment location as far back as possible, to not create unnecessary limits. As those offsets are shared with (now mostly unused) raw MMC environment, we should respect the common one megabyte limit, which also makes sense on SPI flash.
So limit the environment for those raw locations to 64KB, and place it just below 1MB (@960KB).
Those values are currently unused, unless someone forcibly enables the raw MMC environment. In this case it would break as of now, as the current offset of 544KB is far too low for the current (arm64) U-Boot proper.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- env/Kconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/env/Kconfig b/env/Kconfig index 6dc8d8d860..45b7895047 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -536,7 +536,7 @@ config ENV_OFFSET ENV_IS_IN_SPI_FLASH default 0x3f8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC default 0x140000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH - default 0x88000 if ARCH_SUNXI + default 0xF0000 if ARCH_SUNXI default 0xE0000 if ARCH_ZYNQ default 0x1E00000 if ARCH_ZYNQMP default 0x7F40000 if ARCH_VERSAL @@ -559,7 +559,8 @@ config ENV_OFFSET_REDUND config ENV_SIZE hex "Environment Size" default 0x40000 if ENV_IS_IN_SPI_FLASH && ARCH_ZYNQMP - default 0x20000 if ARCH_SUNXI || ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91 + default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91 + default 0x10000 if ARCH_SUNXI default 0x8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC default 0x2000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH default 0x8000 if ARCH_ZYNQMP || ARCH_VERSAL @@ -575,6 +576,7 @@ config ENV_SECT_SIZE default 0x40000 if ARCH_ZYNQMP || ARCH_VERSAL default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91 default 0x20000 if MICROBLAZE && ENV_IS_IN_SPI_FLASH + default 0x10000 if ARCH_SUNXI && ENV_IS_IN_SPI_FLASH help Size of the sector containing the environment.

Currently we only support to load the environment from raw MMC or FAT locations on Allwinner boards. With the advent of SPI flash we probably also want to support using the environment there, so we need to become a bit more flexible.
Change the environment priority function to take the boot source into account. When booted from eMMC or SD card, we use FAT or MMC, if configured, as before. If we are booted from SPI flash, we try to use the environment from there, if possible. The same is true for NAND flash booting, although this is somewhat theoretical right now (as untested).
This way we can use the same image for SD and SPI flash booting, which allows us to simply copy a booted image from SD card to the SPI flash, for instance.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- board/sunxi/board.c | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2790a0f9e8..2472343d00 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -170,21 +170,56 @@ void i2c_init_board(void) #endif }
-#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT) +/* + * Try to use the environment from the boot source first. + * For MMC, this means a FAT partition on the boot device (SD or eMMC). + * If the raw MMC environment is also enabled, this is tried next. + * SPI flash falls back to FAT (on SD card). + */ enum env_location env_get_location(enum env_operation op, int prio) { - switch (prio) { - case 0: - return ENVL_FAT; + enum env_location boot_loc = ENVL_FAT;
- case 1: - return ENVL_MMC; + gd->env_load_prio = prio;
+ switch (sunxi_get_boot_device()) { + case BOOT_DEVICE_MMC1: + case BOOT_DEVICE_MMC2: + boot_loc = ENVL_FAT; + break; + case BOOT_DEVICE_NAND: + if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND)) + boot_loc = ENVL_NAND; + break; + case BOOT_DEVICE_SPI: + if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)) + boot_loc = ENVL_SPI_FLASH; + break; + case BOOT_DEVICE_BOARD: + break; default: - return ENVL_UNKNOWN; + break; + } + + /* Always try to access the environment on the boot device first. */ + if (prio == 0) + return boot_loc; + + if (prio == 1) { + switch (boot_loc) { + case ENVL_SPI_FLASH: + return ENVL_FAT; + case ENVL_FAT: + if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC)) + return ENVL_MMC; + break; + default: + break; + } } + + return ENVL_UNKNOWN; } -#endif
#ifdef CONFIG_DM_MMC static void mmc_pinmux_setup(int sdc);

On Tue, Jan 11, 2022 at 12:46:04PM +0000, Andre Przywara wrote:
Currently we only support to load the environment from raw MMC or FAT locations on Allwinner boards. With the advent of SPI flash we probably also want to support using the environment there, so we need to become a bit more flexible.
Change the environment priority function to take the boot source into account. When booted from eMMC or SD card, we use FAT or MMC, if configured, as before. If we are booted from SPI flash, we try to use the environment from there, if possible. The same is true for NAND flash booting, although this is somewhat theoretical right now (as untested).
This way we can use the same image for SD and SPI flash booting, which allows us to simply copy a booted image from SD card to the SPI flash, for instance.
Unfortunately after a git-bisect I can confirm this patch breaks booting in FEL mode whenever the environment is set to CONFIG_ENV_IS_NOWHERE. Tested and reproducible on an NTC CHIP or a Source Parts Popcorn (both Allwinner R8 chips).
The curious thing though is that I could never see env_get_location called, but whenever I either set the environment to something like FAT or comment out this change (which I believe causes the non-board specific version of env_get_location to be used) it would boot again. So while I can confirm this patch breaks booting FEL when the env is set to nowhere, I was not able to figure out why that is.
Thank you.
Signed-off-by: Andre Przywara andre.przywara@arm.com
board/sunxi/board.c | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2790a0f9e8..2472343d00 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -170,21 +170,56 @@ void i2c_init_board(void) #endif }
-#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT) +/*
- Try to use the environment from the boot source first.
- For MMC, this means a FAT partition on the boot device (SD or eMMC).
- If the raw MMC environment is also enabled, this is tried next.
- SPI flash falls back to FAT (on SD card).
- */
enum env_location env_get_location(enum env_operation op, int prio) {
- switch (prio) {
- case 0:
return ENVL_FAT;
- enum env_location boot_loc = ENVL_FAT;
- case 1:
return ENVL_MMC;
gd->env_load_prio = prio;
switch (sunxi_get_boot_device()) {
case BOOT_DEVICE_MMC1:
case BOOT_DEVICE_MMC2:
boot_loc = ENVL_FAT;
break;
case BOOT_DEVICE_NAND:
if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
boot_loc = ENVL_NAND;
break;
case BOOT_DEVICE_SPI:
if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
boot_loc = ENVL_SPI_FLASH;
break;
case BOOT_DEVICE_BOARD:
break;
default:
return ENVL_UNKNOWN;
break;
- }
- /* Always try to access the environment on the boot device first. */
- if (prio == 0)
return boot_loc;
- if (prio == 1) {
switch (boot_loc) {
case ENVL_SPI_FLASH:
return ENVL_FAT;
case ENVL_FAT:
if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
return ENVL_MMC;
break;
default:
break;
}}
- return ENVL_UNKNOWN;
} -#endif
#ifdef CONFIG_DM_MMC static void mmc_pinmux_setup(int sdc);

On Fri, 15 Apr 2022 12:28:22 -0500 Chris Morgan macroalpha82@gmail.com wrote:
Hi Chris,
On Tue, Jan 11, 2022 at 12:46:04PM +0000, Andre Przywara wrote:
Currently we only support to load the environment from raw MMC or FAT locations on Allwinner boards. With the advent of SPI flash we probably also want to support using the environment there, so we need to become a bit more flexible.
Change the environment priority function to take the boot source into account. When booted from eMMC or SD card, we use FAT or MMC, if configured, as before. If we are booted from SPI flash, we try to use the environment from there, if possible. The same is true for NAND flash booting, although this is somewhat theoretical right now (as untested).
This way we can use the same image for SD and SPI flash booting, which allows us to simply copy a booted image from SD card to the SPI flash, for instance.
Unfortunately after a git-bisect I can confirm this patch breaks booting in FEL mode whenever the environment is set to CONFIG_ENV_IS_NOWHERE. Tested and reproducible on an NTC CHIP or a Source Parts Popcorn (both Allwinner R8 chips).
The curious thing though is that I could never see env_get_location called, but whenever I either set the environment to something like FAT or comment out this change (which I believe causes the non-board specific version of env_get_location to be used) it would boot again. So while I can confirm this patch breaks booting FEL when the env is set to nowhere, I was not able to figure out why that is.
Alright, thanks for the report. I see the problem: The default fallback for the new env_get_location() is ENVL_FAT, as 157 out of the 160 Allwinner boards define CONFIG_ENV_IS_IN_FAT. However the C.H.I.P. boards are one of the three exceptions, and returning FAT when the FAT environment driver is not compiled in will not end well. I don't have any CHIP board, but simulated this by configuring a normal board with just defining CONFIG_ENV_IS_NOWHERE.
I made a patch that tries to choose a matching fallback. It's not very elegant, but seems to fix the problem for me. Please test this once posted.
Cheers, Andre
Thank you.
Signed-off-by: Andre Przywara andre.przywara@arm.com
board/sunxi/board.c | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2790a0f9e8..2472343d00 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -170,21 +170,56 @@ void i2c_init_board(void) #endif }
-#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT) +/*
- Try to use the environment from the boot source first.
- For MMC, this means a FAT partition on the boot device (SD or eMMC).
- If the raw MMC environment is also enabled, this is tried next.
- SPI flash falls back to FAT (on SD card).
- */
enum env_location env_get_location(enum env_operation op, int prio) {
- switch (prio) {
- case 0:
return ENVL_FAT;
- enum env_location boot_loc = ENVL_FAT;
- case 1:
return ENVL_MMC;
gd->env_load_prio = prio;
switch (sunxi_get_boot_device()) {
case BOOT_DEVICE_MMC1:
case BOOT_DEVICE_MMC2:
boot_loc = ENVL_FAT;
break;
case BOOT_DEVICE_NAND:
if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
boot_loc = ENVL_NAND;
break;
case BOOT_DEVICE_SPI:
if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
boot_loc = ENVL_SPI_FLASH;
break;
case BOOT_DEVICE_BOARD:
break;
default:
return ENVL_UNKNOWN;
break;
- }
- /* Always try to access the environment on the boot device first. */
- if (prio == 0)
return boot_loc;
- if (prio == 1) {
switch (boot_loc) {
case ENVL_SPI_FLASH:
return ENVL_FAT;
case ENVL_FAT:
if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
return ENVL_MMC;
break;
default:
break;
}}
- return ENVL_UNKNOWN;
} -#endif
#ifdef CONFIG_DM_MMC static void mmc_pinmux_setup(int sdc);

Will do. Sorry, I stepped away from things for a while but I will test it now that I am back.
On Wed, Apr 20, 2022 at 6:34 PM Andre Przywara andre.przywara@arm.com wrote:
On Fri, 15 Apr 2022 12:28:22 -0500 Chris Morgan macroalpha82@gmail.com wrote:
Hi Chris,
On Tue, Jan 11, 2022 at 12:46:04PM +0000, Andre Przywara wrote:
Currently we only support to load the environment from raw MMC or FAT locations on Allwinner boards. With the advent of SPI flash we probably also want to support using the environment there, so we need to become a bit more flexible.
Change the environment priority function to take the boot source into account. When booted from eMMC or SD card, we use FAT or MMC, if configured, as before. If we are booted from SPI flash, we try to use the environment from there, if possible. The same is true for NAND flash booting, although this is somewhat theoretical right now (as untested).
This way we can use the same image for SD and SPI flash booting, which allows us to simply copy a booted image from SD card to the SPI flash, for instance.
Unfortunately after a git-bisect I can confirm this patch breaks booting in FEL mode whenever the environment is set to CONFIG_ENV_IS_NOWHERE. Tested and reproducible on an NTC CHIP or a Source Parts Popcorn (both Allwinner R8 chips).
The curious thing though is that I could never see env_get_location called, but whenever I either set the environment to something like FAT or comment out this change (which I believe causes the non-board specific version of env_get_location to be used) it would boot again. So while I can confirm this patch breaks booting FEL when the env is set to nowhere, I was not able to figure out why that is.
Alright, thanks for the report. I see the problem: The default fallback for the new env_get_location() is ENVL_FAT, as 157 out of the 160 Allwinner boards define CONFIG_ENV_IS_IN_FAT. However the C.H.I.P. boards are one of the three exceptions, and returning FAT when the FAT environment driver is not compiled in will not end well. I don't have any CHIP board, but simulated this by configuring a normal board with just defining CONFIG_ENV_IS_NOWHERE.
I made a patch that tries to choose a matching fallback. It's not very elegant, but seems to fix the problem for me. Please test this once posted.
Cheers, Andre
Thank you.
Signed-off-by: Andre Przywara andre.przywara@arm.com
board/sunxi/board.c | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2790a0f9e8..2472343d00 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -170,21 +170,56 @@ void i2c_init_board(void) #endif }
-#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT) +/*
- Try to use the environment from the boot source first.
- For MMC, this means a FAT partition on the boot device (SD or eMMC).
- If the raw MMC environment is also enabled, this is tried next.
- SPI flash falls back to FAT (on SD card).
- */
enum env_location env_get_location(enum env_operation op, int prio) {
- switch (prio) {
- case 0:
return ENVL_FAT;
- enum env_location boot_loc = ENVL_FAT;
- case 1:
return ENVL_MMC;
gd->env_load_prio = prio;
switch (sunxi_get_boot_device()) {
case BOOT_DEVICE_MMC1:
case BOOT_DEVICE_MMC2:
boot_loc = ENVL_FAT;
break;
case BOOT_DEVICE_NAND:
if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
boot_loc = ENVL_NAND;
break;
case BOOT_DEVICE_SPI:
if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
boot_loc = ENVL_SPI_FLASH;
break;
case BOOT_DEVICE_BOARD:
break;
default:
return ENVL_UNKNOWN;
break;
- }
- /* Always try to access the environment on the boot device first. */
- if (prio == 0)
return boot_loc;
- if (prio == 1) {
switch (boot_loc) {
case ENVL_SPI_FLASH:
return ENVL_FAT;
case ENVL_FAT:
if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
return ENVL_MMC;
break;
default:
break;
}}
- return ENVL_UNKNOWN;
} -#endif
#ifdef CONFIG_DM_MMC static void mmc_pinmux_setup(int sdc);

Now that sunxi uses CONFIG_SPI more sanely, and can also now properly load the environment from SPI flash, let's enable the symbol that actually considers the SPI flash when accessing the environment.
As this symbol depends on CONFIG_SPI, which we now only enable if the board has a SPI flash, we can make if "default y" for all Allwinner boards.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- env/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/env/Kconfig b/env/Kconfig index 45b7895047..b9d04725a3 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -320,6 +320,7 @@ config ENV_IS_IN_SPI_FLASH default y if NORTHBRIDGE_INTEL_IVYBRIDGE default y if INTEL_QUARK default y if INTEL_QUEENSBAY + default y if ARCH_SUNXI help Define this if you have a SPI Flash memory device which you want to use for the environment.

Some sunxi boards ship with SPI flash, which allows booting through the BootROM. We cover this functionality by a separate SPL "mini" driver. Separately we have a proper DM_SPI driver for U-Boot proper, which provides access to the SPI flash through the "sf" command. That allows to update the firmware on the SPI flash, also to store the environment there.
However only very few boards actually enable support for U-Boot proper, even though that would work and the SPL part is configured.
Use the cleaned up configuration scheme to enable SPI flash on those boards which mention a SPI flash in their .dts, or which use the SPL SPI support.
Out of the box this would enable storing the environment on the SPI flash, and allows people to read or write the flash from U-Boot, for instance to update the SPI flash when booted via an SD card.
For this to actually work there must be a "spi0" alias in the DT, which most boards are missing. But this should be addressed separately.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- configs/orangepi_pc2_defconfig | 2 ++ configs/orangepi_r1_defconfig | 2 ++ configs/orangepi_win_defconfig | 1 + configs/orangepi_zero2_defconfig | 2 ++ configs/orangepi_zero_defconfig | 2 ++ configs/pine64-lts_defconfig | 1 + configs/pine_h64_defconfig | 2 ++ configs/pinecube_defconfig | 2 ++ 8 files changed, 14 insertions(+)
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig index 2eaddcf684..777af8c60e 100644 --- a/configs/orangepi_pc2_defconfig +++ b/configs/orangepi_pc2_defconfig @@ -11,9 +11,11 @@ CONFIG_SPL_SPI_SUNXI=y CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y CONFIG_SY8106A_VOUT1_VOLT=1100 +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_MUSB_GADGET=y diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig index 745451c4bf..4496aa4a45 100644 --- a/configs/orangepi_r1_defconfig +++ b/configs/orangepi_r1_defconfig @@ -8,6 +8,8 @@ CONFIG_DRAM_CLK=624 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig index 133755291a..3b78ad7e52 100644 --- a/configs/orangepi_win_defconfig +++ b/configs/orangepi_win_defconfig @@ -7,6 +7,7 @@ CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y CONFIG_MACPWR="PD14" CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index 22563c864f..54faf6aba2 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -15,5 +15,7 @@ CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f CONFIG_SYS_I2C_SPEED=400000 +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig index 332cd4739e..2dc69d2994 100644 --- a/configs/orangepi_zero_defconfig +++ b/configs/orangepi_zero_defconfig @@ -8,6 +8,8 @@ CONFIG_DRAM_CLK=624 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig index 75a77acc44..45a9e77e0e 100644 --- a/configs/pine64-lts_defconfig +++ b/configs/pine64-lts_defconfig @@ -10,6 +10,7 @@ CONFIG_MMC0_CD_PIN="" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig index 1928509dd7..1e730dd9fa 100644 --- a/configs/pine_h64_defconfig +++ b/configs/pine_h64_defconfig @@ -11,8 +11,10 @@ CONFIG_USB3_VBUS_PIN="PL5" CONFIG_SPL_SPI_SUNXI=y # CONFIG_PSCI_RESET is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y CONFIG_PHY_SUN50I_USB3=y +CONFIG_SPI=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/pinecube_defconfig b/configs/pinecube_defconfig index 0c71d59418..e779663a0d 100644 --- a/configs/pinecube_defconfig +++ b/configs/pinecube_defconfig @@ -12,8 +12,10 @@ CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f CONFIG_SYS_I2C_SPEED=400000 +CONFIG_SPI_FLASH_WINBOND=y # CONFIG_NETDEVICES is not set CONFIG_AXP209_POWER=y CONFIG_AXP_DCDC2_VOLT=1250 CONFIG_AXP_DCDC3_VOLT=3300 CONFIG_CONS_INDEX=3 +CONFIG_SPI=y

On the Allwinner H6 SoC both the SPI0 and the eMMC device share one pin, so cannot be used simultaneously. On Linux this is a showstopper, since only one of them would be able to claim the pin, and the probe order is somewhat random. The DT consequently disables SPI0 in favour of the more useful eMMC.
But a comment in the DT actually suggests that this could be reversed by U-Boot, if no eMMC is actually connected. Let's now implement this: When we fix up the device tree before booting a kernel, we iterate over all MMC devices, and check if there is an eMMC device among them. If none can be found, we enable SPI0 instead, to allow Linux access to the SPI flash. Since this fixup is not really universally applicable to all boards, let's hide it behind a Kconfig option, and enable it only on the one supported board where this makes sense: the Pine H64.
Please note that the SPI functionality is still disabled in U-Boot proper, the pinmux clash affects us too: it would always disable the eMMC and so spoil this algorithm here.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- arch/arm/mach-sunxi/Kconfig | 10 ++++++++ board/sunxi/board.c | 50 +++++++++++++++++++++++++++++++++++++ configs/pine_h64_defconfig | 1 + 3 files changed, 61 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 56ff1e197c..ce66453029 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1047,6 +1047,16 @@ config BLUETOOTH_DT_DEVICE_FIXUP The used address is "bdaddr" if set, and "ethaddr" with the LSB flipped elsewise.
+config SUNXI_H6_ENABLE_SPIFLASH + bool "Enable H6 SPI flash vs. eMMC enablement" + depends on MACH_SUN50I_H6 + default n + help + Enable this option if you want U-Boot check for an eMMC device + on Allwinner H6 boards, and enable the SPI flash if none is found. + SPI0 and MMC2 share one pin, so cannot coexist in Linux. The + DT prefers eMMC, but if none is used, we can safely enable SPI. + endif
config CHIP_DIP_SCAN diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2472343d00..e943a16e16 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -942,6 +942,32 @@ static void bluetooth_dt_fixup(void *blob) "local-bd-address", bdaddr, ETH_ALEN, 1); }
+/* Iterate over all MMC devices to check if there is an eMMC among them. */ +static bool has_emmc_device(void) +{ + struct udevice *dev; + + if (CONFIG_MMC_SUNXI_SLOT_EXTRA == -1) + return false; + + for (uclass_first_device(UCLASS_MMC, &dev); + dev; + uclass_next_device(&dev)) { + struct mmc *mmc = mmc_get_mmc_dev(dev); + + mmc_init(mmc); + if (!mmc->has_init) + continue; + + if (IS_SD(mmc)) + continue; + + return true; + } + + return false; +} + int ft_board_setup(void *blob, struct bd_info *bd) { int __maybe_unused r; @@ -959,6 +985,30 @@ int ft_board_setup(void *blob, struct bd_info *bd) if (r) return r; #endif + + /* + * On the H6 SPI0 and MMC2 share one pin, so cannot be used together + * (in Linux). The DT thus disables SPI0 in favour of the more + * useful eMMC. However if there is no eMMC connected, we can enable + * SPI0, to allows access to a SPI flash, for instance. + */ + if (IS_ENABLED(CONFIG_SUNXI_H6_ENABLE_SPIFLASH)) { + const char *spi_status, *emmc_status; + + if (has_emmc_device()) { + emmc_status = "okay"; + spi_status = "disabled"; + } else { + emmc_status = "disabled"; + spi_status = "okay"; + } + + do_fixup_by_path(blob, "/soc/spi@5010000", "status", + spi_status, strlen(spi_status), 0); + do_fixup_by_path(blob, "/soc/mmc@4022000", "status", + emmc_status, strlen(emmc_status), 0); + } + return 0; }
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig index 1e730dd9fa..9220af1429 100644 --- a/configs/pine_h64_defconfig +++ b/configs/pine_h64_defconfig @@ -9,6 +9,7 @@ CONFIG_MMC0_CD_PIN="PF6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_USB3_VBUS_PIN="PL5" CONFIG_SPL_SPI_SUNXI=y +CONFIG_SUNXI_H6_ENABLE_SPIFLASH=y # CONFIG_PSCI_RESET is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPI_FLASH_WINBOND=y

On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
On the Allwinner H6 SoC both the SPI0 and the eMMC device share one pin, so cannot be used simultaneously. On Linux this is a showstopper, since only one of them would be able to claim the pin, and the probe order is somewhat random. The DT consequently disables SPI0 in favour of the more useful eMMC.
But a comment in the DT actually suggests that this could be reversed by U-Boot, if no eMMC is actually connected. Let's now implement this: When we fix up the device tree before booting a kernel, we iterate over all MMC devices, and check if there is an eMMC device among them. If none can be found, we enable SPI0 instead, to allow Linux access to the SPI flash.
Since this fixup is not really universally applicable to all boards, let's hide it behind a Kconfig option, and enable it only on the one supported board where this makes sense: the Pine H64.
Please note that the SPI functionality is still disabled in U-Boot proper, the pinmux clash affects us too: it would always disable the eMMC and so spoil this algorithm here.
Signed-off-by: Andre Przywara andre.przywara@arm.com
arch/arm/mach-sunxi/Kconfig | 10 ++++++++ board/sunxi/board.c | 50 +++++++++++++++++++++++++++++++++++++ configs/pine_h64_defconfig | 1 + 3 files changed, 61 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 56ff1e197c..ce66453029 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1047,6 +1047,16 @@ config BLUETOOTH_DT_DEVICE_FIXUP The used address is "bdaddr" if set, and "ethaddr" with the LSB flipped elsewise.
+config SUNXI_H6_ENABLE_SPIFLASH
bool "Enable H6 SPI flash vs. eMMC enablement"
depends on MACH_SUN50I_H6
default n
help
Enable this option if you want U-Boot check for an eMMC device
on Allwinner H6 boards, and enable the SPI flash if none is found.
SPI0 and MMC2 share one pin, so cannot coexist in Linux. The
DT prefers eMMC, but if none is used, we can safely enable SPI.
Why we need a separate macro, cannot we check it H6 globally as it SoC design?
Jagan.

On Thu, 20 Jan 2022 19:08:57 +0530 Jagan Teki jagan@amarulasolutions.com wrote:
Hi,
On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
On the Allwinner H6 SoC both the SPI0 and the eMMC device share one pin, so cannot be used simultaneously. On Linux this is a showstopper, since only one of them would be able to claim the pin, and the probe order is somewhat random. The DT consequently disables SPI0 in favour of the more useful eMMC.
But a comment in the DT actually suggests that this could be reversed by U-Boot, if no eMMC is actually connected. Let's now implement this: When we fix up the device tree before booting a kernel, we iterate over all MMC devices, and check if there is an eMMC device among them. If none can be found, we enable SPI0 instead, to allow Linux access to the SPI flash.
Since this fixup is not really universally applicable to all boards, let's hide it behind a Kconfig option, and enable it only on the one supported board where this makes sense: the Pine H64.
Please note that the SPI functionality is still disabled in U-Boot proper, the pinmux clash affects us too: it would always disable the eMMC and so spoil this algorithm here.
Signed-off-by: Andre Przywara andre.przywara@arm.com
arch/arm/mach-sunxi/Kconfig | 10 ++++++++ board/sunxi/board.c | 50 +++++++++++++++++++++++++++++++++++++ configs/pine_h64_defconfig | 1 + 3 files changed, 61 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 56ff1e197c..ce66453029 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1047,6 +1047,16 @@ config BLUETOOTH_DT_DEVICE_FIXUP The used address is "bdaddr" if set, and "ethaddr" with the LSB flipped elsewise.
+config SUNXI_H6_ENABLE_SPIFLASH
bool "Enable H6 SPI flash vs. eMMC enablement"
depends on MACH_SUN50I_H6
default n
help
Enable this option if you want U-Boot check for an eMMC device
on Allwinner H6 boards, and enable the SPI flash if none is found.
SPI0 and MMC2 share one pin, so cannot coexist in Linux. The
DT prefers eMMC, but if none is used, we can safely enable SPI.
Why we need a separate macro, cannot we check it H6 globally as it SoC design?
This "hack" is board dependent. We don't know if there is a SPI flash or eMMC in the first place, and this whole concept is weird enough that it warrants a separate config option. Probably due to this hardware issue the PineH64 is actually the only board in mainline that has both SPI flash and eMMC, and I don't want to enable SPI flash on every eMMC less board. Also it simplifies the code if we can assume that both DT nodes exist, when that config is enabled.
Cheers, Andre
P.S. Actually I wanted to forgot to mark this one as RFC, as I am not sure that it's justified. The comment in the mainline DT suggests this solution, and I was curious what it would take to make it work, as apparently some people are interested in it.

On Thu, Jan 20, 2022 at 7:36 PM Andre Przywara andre.przywara@arm.com wrote:
On Thu, 20 Jan 2022 19:08:57 +0530 Jagan Teki jagan@amarulasolutions.com wrote:
Hi,
On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
On the Allwinner H6 SoC both the SPI0 and the eMMC device share one pin, so cannot be used simultaneously. On Linux this is a showstopper, since only one of them would be able to claim the pin, and the probe order is somewhat random. The DT consequently disables SPI0 in favour of the more useful eMMC.
But a comment in the DT actually suggests that this could be reversed by U-Boot, if no eMMC is actually connected. Let's now implement this: When we fix up the device tree before booting a kernel, we iterate over all MMC devices, and check if there is an eMMC device among them. If none can be found, we enable SPI0 instead, to allow Linux access to the SPI flash.
Since this fixup is not really universally applicable to all boards, let's hide it behind a Kconfig option, and enable it only on the one supported board where this makes sense: the Pine H64.
Please note that the SPI functionality is still disabled in U-Boot proper, the pinmux clash affects us too: it would always disable the eMMC and so spoil this algorithm here.
Signed-off-by: Andre Przywara andre.przywara@arm.com
arch/arm/mach-sunxi/Kconfig | 10 ++++++++ board/sunxi/board.c | 50 +++++++++++++++++++++++++++++++++++++ configs/pine_h64_defconfig | 1 + 3 files changed, 61 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 56ff1e197c..ce66453029 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1047,6 +1047,16 @@ config BLUETOOTH_DT_DEVICE_FIXUP The used address is "bdaddr" if set, and "ethaddr" with the LSB flipped elsewise.
+config SUNXI_H6_ENABLE_SPIFLASH
bool "Enable H6 SPI flash vs. eMMC enablement"
depends on MACH_SUN50I_H6
default n
help
Enable this option if you want U-Boot check for an eMMC device
on Allwinner H6 boards, and enable the SPI flash if none is found.
SPI0 and MMC2 share one pin, so cannot coexist in Linux. The
DT prefers eMMC, but if none is used, we can safely enable SPI.
Why we need a separate macro, cannot we check it H6 globally as it SoC design?
This "hack" is board dependent. We don't know if there is a SPI flash or eMMC in the first place, and this whole concept is weird enough that it warrants a separate config option. Probably due to this hardware issue the PineH64 is actually the only board in mainline that has both SPI flash and eMMC, and I don't want to enable SPI flash on every eMMC less board. Also it simplifies the code if we can assume that both DT nodes exist, when that config is enabled.
Cheers, Andre
P.S. Actually I wanted to forgot to mark this one as RFC, as I am not sure that it's justified. The comment in the mainline DT suggests this solution, and I was curious what it would take to make it work, as apparently some people are interested in it.
If it board-specific, better switch to RFC or load the overlay by checking on board specific boot script.
Thanks, Jagan.

Hi Andre,
On Thu, Jan 20, 2022 at 8:06 PM Jagan Teki jagan@amarulasolutions.com wrote:
On Thu, Jan 20, 2022 at 7:36 PM Andre Przywara andre.przywara@arm.com wrote:
On Thu, 20 Jan 2022 19:08:57 +0530 Jagan Teki jagan@amarulasolutions.com wrote:
Hi,
On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
On the Allwinner H6 SoC both the SPI0 and the eMMC device share one pin, so cannot be used simultaneously. On Linux this is a showstopper, since only one of them would be able to claim the pin, and the probe order is somewhat random. The DT consequently disables SPI0 in favour of the more useful eMMC.
But a comment in the DT actually suggests that this could be reversed by U-Boot, if no eMMC is actually connected. Let's now implement this: When we fix up the device tree before booting a kernel, we iterate over all MMC devices, and check if there is an eMMC device among them. If none can be found, we enable SPI0 instead, to allow Linux access to the SPI flash.
Since this fixup is not really universally applicable to all boards, let's hide it behind a Kconfig option, and enable it only on the one supported board where this makes sense: the Pine H64.
Please note that the SPI functionality is still disabled in U-Boot proper, the pinmux clash affects us too: it would always disable the eMMC and so spoil this algorithm here.
Signed-off-by: Andre Przywara andre.przywara@arm.com
arch/arm/mach-sunxi/Kconfig | 10 ++++++++ board/sunxi/board.c | 50 +++++++++++++++++++++++++++++++++++++ configs/pine_h64_defconfig | 1 + 3 files changed, 61 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 56ff1e197c..ce66453029 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1047,6 +1047,16 @@ config BLUETOOTH_DT_DEVICE_FIXUP The used address is "bdaddr" if set, and "ethaddr" with the LSB flipped elsewise.
+config SUNXI_H6_ENABLE_SPIFLASH
bool "Enable H6 SPI flash vs. eMMC enablement"
depends on MACH_SUN50I_H6
default n
help
Enable this option if you want U-Boot check for an eMMC device
on Allwinner H6 boards, and enable the SPI flash if none is found.
SPI0 and MMC2 share one pin, so cannot coexist in Linux. The
DT prefers eMMC, but if none is used, we can safely enable SPI.
Why we need a separate macro, cannot we check it H6 globally as it SoC design?
This "hack" is board dependent. We don't know if there is a SPI flash or eMMC in the first place, and this whole concept is weird enough that it warrants a separate config option. Probably due to this hardware issue the PineH64 is actually the only board in mainline that has both SPI flash and eMMC, and I don't want to enable SPI flash on every eMMC less board. Also it simplifies the code if we can assume that both DT nodes exist, when that config is enabled.
Cheers, Andre
P.S. Actually I wanted to forgot to mark this one as RFC, as I am not sure that it's justified. The comment in the mainline DT suggests this solution, and I was curious what it would take to make it work, as apparently some people are interested in it.
If it board-specific, better switch to RFC or load the overlay by checking on board specific boot script.
Anything about this?
Jagan.

On Thu, 24 Feb 2022 13:00:56 +0530 Jagan Teki jagan@amarulasolutions.com wrote:
Hi Jagan,
On Thu, Jan 20, 2022 at 8:06 PM Jagan Teki jagan@amarulasolutions.com wrote:
On Thu, Jan 20, 2022 at 7:36 PM Andre Przywara andre.przywara@arm.com wrote:
On Thu, 20 Jan 2022 19:08:57 +0530 Jagan Teki jagan@amarulasolutions.com wrote:
Hi,
On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
On the Allwinner H6 SoC both the SPI0 and the eMMC device share one pin, so cannot be used simultaneously. On Linux this is a showstopper, since only one of them would be able to claim the pin, and the probe order is somewhat random. The DT consequently disables SPI0 in favour of the more useful eMMC.
But a comment in the DT actually suggests that this could be reversed by U-Boot, if no eMMC is actually connected. Let's now implement this: When we fix up the device tree before booting a kernel, we iterate over all MMC devices, and check if there is an eMMC device among them. If none can be found, we enable SPI0 instead, to allow Linux access to the SPI flash.
Since this fixup is not really universally applicable to all boards, let's hide it behind a Kconfig option, and enable it only on the one supported board where this makes sense: the Pine H64.
Please note that the SPI functionality is still disabled in U-Boot proper, the pinmux clash affects us too: it would always disable the eMMC and so spoil this algorithm here.
Signed-off-by: Andre Przywara andre.przywara@arm.com
arch/arm/mach-sunxi/Kconfig | 10 ++++++++ board/sunxi/board.c | 50 +++++++++++++++++++++++++++++++++++++ configs/pine_h64_defconfig | 1 + 3 files changed, 61 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 56ff1e197c..ce66453029 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1047,6 +1047,16 @@ config BLUETOOTH_DT_DEVICE_FIXUP The used address is "bdaddr" if set, and "ethaddr" with the LSB flipped elsewise.
+config SUNXI_H6_ENABLE_SPIFLASH
bool "Enable H6 SPI flash vs. eMMC enablement"
depends on MACH_SUN50I_H6
default n
help
Enable this option if you want U-Boot check for an eMMC device
on Allwinner H6 boards, and enable the SPI flash if none is found.
SPI0 and MMC2 share one pin, so cannot coexist in Linux. The
DT prefers eMMC, but if none is used, we can safely enable SPI.
Why we need a separate macro, cannot we check it H6 globally as it SoC design?
This "hack" is board dependent. We don't know if there is a SPI flash or eMMC in the first place, and this whole concept is weird enough that it warrants a separate config option. Probably due to this hardware issue the PineH64 is actually the only board in mainline that has both SPI flash and eMMC, and I don't want to enable SPI flash on every eMMC less board. Also it simplifies the code if we can assume that both DT nodes exist, when that config is enabled.
Cheers, Andre
P.S. Actually I wanted to forgot to mark this one as RFC, as I am not sure that it's justified. The comment in the mainline DT suggests this solution, and I was curious what it would take to make it work, as apparently some people are interested in it.
If it board-specific, better switch to RFC or load the overlay by checking on board specific boot script.
Anything about this?
Yeah, I meant to tag this patch as RFC (as I mentioned in the cover letter), but the actually forgot to do it. So overlays would be one solution - for kernels, at least, though not for U-Boot. Is there some framework / functionality in place to automatically apply them (outside of some user specific scripting)?
I will have a think about that, and will drop this patch for now.
Cheers, Andre

On Tue, Jan 11, 2022 at 6:16 PM Andre Przywara andre.przywara@arm.com wrote:
Hi,
despite U-Boot supporting SPI on Allwinner chips and SPI flash in general for a while, it wasn't really working well for many sunxi boards. Booting from SPI is handled by separate SPL code, which works fine, but the "sf" command in U-Boot proper is often just not operational.
This series tries to improve the situation, by:
- cleaning up the SPI Kconfig situation for sunxi (patch 2)
- adding support for environment in SPI flash (patch 3-5)
- trying to enable more boards for U-Boot-proper SPI flash (patch 6)
As an added bonus there is some whacky code to make the SPI flash usable in Linux on H6 boards. Marking this as RFC.
Actually even after this series many boards still miss out, because they are lacking the required "spi0" alias in the DT. We could go with *-u-boot.dtsi fixes for now (as the SoPine does), but even mainline DT support wouldn't help, as we are somewhat stuck with DT updates. But that's a story for another time, let's get this SPI support fixed first.
Cheers, Andre
Andre Przywara (6): sunxi: Kconfig: Fix up SPI configuration env: sunxi: Define location in SPI flash sunxi: use boot source for determining environment location env: sunxi: enable ENV_IS_IN_SPI_FLASH sunxi: boards: Enable SPI flash support in U-Boot proper
Applied to u-boot-spi/master
participants (3)
-
Andre Przywara
-
Chris Morgan
-
Jagan Teki