All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] rpi: copy the eMMC controller configuration from firmware-supplied DT
@ 2022-10-26  7:13 Jian-Hong Pan
  2022-10-27  6:27 ` Peter Robinson
  0 siblings, 1 reply; 3+ messages in thread
From: Jian-Hong Pan @ 2022-10-26  7:13 UTC (permalink / raw)
  To: u-boot; +Cc: linux, Ilya Katsnelson, Jian-Hong Pan

From: Ilya Katsnelson <me@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@0upti.me>
Signed-off-by: Jian-Hong Pan <jhp@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@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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] rpi: copy the eMMC controller configuration from firmware-supplied DT
  2022-10-26  7:13 [PATCH] rpi: copy the eMMC controller configuration from firmware-supplied DT Jian-Hong Pan
@ 2022-10-27  6:27 ` Peter Robinson
       [not found]   ` <1502421666871200@mail.yandex.ru>
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Robinson @ 2022-10-27  6:27 UTC (permalink / raw)
  To: Jian-Hong Pan, Matthias Brugger; +Cc: u-boot, linux, Ilya Katsnelson

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@endlessos.org> wrote:
>
> From: Ilya Katsnelson <me@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@0upti.me>
> Signed-off-by: Jian-Hong Pan <jhp@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@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
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] rpi: copy the eMMC controller configuration from firmware-supplied DT
       [not found]   ` <1502421666871200@mail.yandex.ru>
@ 2022-10-28  3:51     ` Jian-Hong Pan
  0 siblings, 0 replies; 3+ messages in thread
From: Jian-Hong Pan @ 2022-10-28  3:51 UTC (permalink / raw)
  To: Ilya K; +Cc: Peter Robinson, Matthias Brugger, u-boot, linux

Ilya K <me@0upti.me> 於 2022年10月27日 週四 晚上7:48寫道:
>
> FWIW, my vote is for the revised series. Also, we've been shipping both patches downstream in NixOS for a while now, and had no issues with either.
>
> 27.10.2022, 09:27, "Peter Robinson" <pbrobinson@gmail.com>:
>
> 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

Great! This patch series looks nice, too.

Jian-Hong Pan

> On Wed, Oct 26, 2022 at 12:23 PM Jian-Hong Pan <jhp@endlessos.org> wrote:
>
>
>  From: Ilya Katsnelson <me@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@0upti.me>
>  Signed-off-by: Jian-Hong Pan <jhp@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@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
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-10-28 11:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-26  7:13 [PATCH] rpi: copy the eMMC controller configuration from firmware-supplied DT Jian-Hong Pan
2022-10-27  6:27 ` Peter Robinson
     [not found]   ` <1502421666871200@mail.yandex.ru>
2022-10-28  3:51     ` Jian-Hong Pan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.