[PATCH] rpi: copy the eMMC controller configuration from firmware-supplied DT

Peter Robinson pbrobinson at gmail.com
Thu Oct 27 08:27:14 CEST 2022


Adding Matthias as the RPi maintainer.

There was also this patch series which fixed it and a few other things
from the firmware DT [1] which is likely a better fix TBH.

Either way Matthias can we get one of these upstream as even the RPi4
Model B has moved to the newer rev of the SoCs so it's not a nice
experience for users if they're not aware of the differences/problems.

Peter

[1] https://lists.denx.de/pipermail/u-boot/2022-August/491455.html

On Wed, Oct 26, 2022 at 12:23 PM Jian-Hong Pan <jhp at endlessos.org> wrote:
>
> From: Ilya Katsnelson <me at 0upti.me>
>
> The RPi firmware adjusts the onboard eMMC controller's DMA mapping
> ranges of the FDT for each BCM2711 SoC revisions on the Pi 4 and RPi 400
> automatically.
>
> If the following kernel does not boot with the correct eMMC controller's
> DMA mapping ranges, the system on the SD card will boot failed and show
> these error messages:
>
> mmc1: invalid bus width
> mmc1: error -22 whilst initialising SD card
>
> This patch carries the adjustment from RPi firmware to the new loaded
> FDT for the following kernel.
>
> Link: https://lists.denx.de/pipermail/u-boot/2021-September/462006.html
> Fixed: https://bugzilla.kernel.org/show_bug.cgi?id=213753
> Signed-off-by: Ilya Katsnelson <me at 0upti.me>
> Signed-off-by: Jian-Hong Pan <jhp at endlessos.org>
> ---
> The code of this patch comes from "[RFC PATCH] rpi: copy the EMMC
> controller configuration from firmware-supplied DT" [1] basically.
> I only add the message and some modifcation:
>
> * Fix the build failed error:
> board/raspberrypi/rpi/rpi.c: In function 'copy_emmc_config':
> board/raspberrypi/rpi/rpi.c:553:9: warning: dereferencing 'void *' pointer
>   553 |         *fw_value = fdt_getprop(fw_fdt, fw_emmc_node, "dma-ranges", &length);
>       |         ^~~~~~~~~
> board/raspberrypi/rpi/rpi.c:553:19: error: invalid use of void expression
>   553 |         *fw_value = fdt_getprop(fw_fdt, fw_emmc_node, "dma-ranges", &length);
>       |                   ^
> make[1]: *** [scripts/Makefile.build:258: board/raspberrypi/rpi/rpi.o] Error 1
>
> * Replace "EMMC" to "eMMC".
>
> * Replace the printf with log_[levels].
>
> So, I keep "Ilya Katsnelson <me at 0upti.me>" as the author.
>
> [1]: https://lists.denx.de/pipermail/u-boot/2021-September/462006.html
>
>  board/raspberrypi/rpi/rpi.c | 63 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
>
> diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
> index 00afb352bd..d7ff8e269e 100644
> --- a/board/raspberrypi/rpi/rpi.c
> +++ b/board/raspberrypi/rpi/rpi.c
> @@ -504,6 +504,67 @@ void *board_fdt_blob_setup(int *err)
>         return (void *)fw_dtb_pointer;
>  }
>
> +void copy_emmc_config(void *our_fdt)
> +{
> +       /*
> +        * As of 2021-09-28, the Pi 4 has two different revisions, one using a
> +        * B0 stepping of the BCM2711 SoC, and one using a C0 stepping.
> +        *
> +        * The two SoC versions have different, incompatible DMA mappings for
> +        * the on-board eMMC controller, which would normally make them require
> +        * two different DTs.
> +        *
> +        * Unfortunately for us, the different revisions don't actually _use_
> +        * different DTs - instead, the proprietary stage0 bootloader reads the DT,
> +        * patches it in-memory, then passes the corrected DT to the OS.
> +        *
> +        * In our case, the OS is actually U-Boot, and U-Boot can choose to
> +        * completely disregard the firmware-supplied DT and load a custom one
> +        * instead, which is used by, e.g., NixOS.
> +        *
> +        * When that happens, the DT patches applied by the firmware are also
> +        * thrown out, which leads to BCM2711C0 boards being unable to boot
> +        * due to them trying to use the hardcoded DMA mappings in the DT
> +        * (which are for the B0 revision).
> +        *
> +        * Work around that by manually copying the DMA region setup from the
> +        * firmware-provided DT into whatever DT we're actually being asked
> +        * to load.
> +        */
> +       void *fw_fdt = (void *)fw_dtb_pointer;
> +       int fw_emmc_node;
> +       int our_emmc_node;
> +       int length;
> +       const void *fw_value;
> +       int result;
> +
> +       fw_emmc_node = fdt_path_offset(fw_fdt, "emmc2bus");
> +       if (fw_emmc_node < 0) {
> +               log_info("RPi: Failed to find eMMC config in FW DT: %d\n", fw_emmc_node);
> +               return;
> +       }
> +
> +       our_emmc_node = fdt_path_offset(our_fdt, "emmc2bus");
> +       if (our_emmc_node < 0) {
> +               log_info("RPi: Failed to find eMMC config in our DT: %d\n", our_emmc_node);
> +               return;
> +       }
> +
> +       fw_value = fdt_getprop(fw_fdt, fw_emmc_node, "dma-ranges", &length);
> +       if (!fw_value) {
> +               log_info("RPi: Failed to get eMMC DMA ranges property from FW DT: %d\n", length);
> +               return;
> +       }
> +
> +       result = fdt_setprop(our_fdt, our_emmc_node, "dma-ranges", fw_value, length);
> +       if (result != 0) {
> +               log_warning("RPi: Failed to set eMMC DMA ranges property in our DT: %d\n", result);
> +               return;
> +       }
> +
> +       log_debug("RPi: successfully copied FW DT eMMC configuration to our DT!\n");
> +}
> +
>  int ft_board_setup(void *blob, struct bd_info *bd)
>  {
>         int node;
> @@ -518,5 +579,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>                            EFI_RESERVED_MEMORY_TYPE);
>  #endif
>
> +       copy_emmc_config(blob);
> +
>         return 0;
>  }
> --
> 2.38.1
>


More information about the U-Boot mailing list