public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Jeremy Linton" <jeremy.linton@arm.com>
To: devel@edk2.groups.io
Cc: pete@akeo.ie, ardb+tianocore@kernel.org, leif@nuviainc.com,
	awarkentin@vmware.com, Sunny.Wang@arm.com,
	samer.el-haj-mahmoud@arm.com, kettenis@openbsd.org,
	Jeremy Linton <jeremy.linton@arm.com>
Subject: [PATCH v2 1/5] Platform/RaspberryPi: Always use non translating DMA in DT mode
Date: Mon, 18 Oct 2021 15:51:23 -0500	[thread overview]
Message-ID: <20211018205127.7099-2-jeremy.linton@arm.com> (raw)
In-Reply-To: <20211018205127.7099-1-jeremy.linton@arm.com>

One of the many issues with the PCIe on this platform is its inbound
DMA is either constrained to the lower 3G, or on later SOC's a
translation may be used. That translation is problematic with some of
the OS's expected to boot on this platform. So, across the board a 3G
DMA limit is enforced during boot when in ACPI mode. This itself
causes problems because the later boards removed the SPI EEPROM used
by the onboard XHCI controller, instead favoring using a block of RAM
to load its firmware. Hence it is the lower level firmware's
responsibility via a mailbox call, to read the bridge
translation/configuration before telling the XHCI controller where it
can find its firmware.

Everything is great in ACPI land. Now it appears that Linux after
reprogramming the bridge to match the DT (when using a translation)
can't actually get the XHCI/quirk/reset to function. Apparently,
because the firmware only reads the bridge configuration the first
time its called(?), or the kernel reset sequence isn't correct. Worse,
with just the DMA ranges corrected, the XHCI/QUIRK itself then causes
the controller to start having what appear to be DMA issues.

Lets simplify the situation and make all DT's provided by this
firmware have a 3G DMA limit on the PCIe bus. Then remove the ability
for Linux/etc to trigger the quirk by remove the DT node attaching the
reset controller to the XHCI. The latter seems somewhat questionable,
since the DT/PCIe host bridge driver is doing what appears to be a
PERST which might then require a firmware reload, but at the
moment seems to work without.

The first part of this patch also appears to fix a problem with
OpenBSD which interprets the DT as describing how the firmware
has configured the device, and makes no attempt to reconfigure it.
Hence the newer SOC's implementing a translation fail to boot
since the DT being passed to the OS doesn't match the translation
the firmware has setup.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 Platform/RaspberryPi/Drivers/FdtDxe/FdtDxe.c | 75 ++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/Platform/RaspberryPi/Drivers/FdtDxe/FdtDxe.c b/Platform/RaspberryPi/Drivers/FdtDxe/FdtDxe.c
index 0472d8ecf6..a4816d4295 100644
--- a/Platform/RaspberryPi/Drivers/FdtDxe/FdtDxe.c
+++ b/Platform/RaspberryPi/Drivers/FdtDxe/FdtDxe.c
@@ -334,6 +334,76 @@ CleanSimpleFramebuffer (
   return EFI_SUCCESS;
 }
 
+STATIC
+EFI_STATUS
+SyncPcie (
+  VOID
+  )
+{
+#if (RPI_MODEL == 4)
+  INTN          Node;
+  INTN          Retval;
+  UINT32        DmaRanges[7];
+
+  Node = fdt_path_offset (mFdtImage, "pcie0");
+  if (Node < 0) {
+    DEBUG ((DEBUG_ERROR, "%a: failed to locate 'pcie0' alias\n", __FUNCTION__));
+    return EFI_NOT_FOUND;
+  }
+
+  // non translated 32-bit DMA window with a limit of 0xc0000000
+  DmaRanges[0] = cpu_to_fdt32 (0x02000000); 
+  DmaRanges[1] = cpu_to_fdt32 (0x00000000); 
+  DmaRanges[2] = cpu_to_fdt32 (0x00000000);
+  DmaRanges[3] = cpu_to_fdt32 (0x00000000);
+  DmaRanges[4] = cpu_to_fdt32 (0x00000000);
+  DmaRanges[5] = cpu_to_fdt32 (0x00000000);
+  DmaRanges[6] = cpu_to_fdt32 (0xc0000000);
+
+  DEBUG ((DEBUG_INFO, "%a: Updating PCIe dma-ranges\n",  __FUNCTION__));
+
+  /* 
+   * Match dma-ranges with the EDK2+ACPI setup we are using.  This works
+   * around a failure in Linux and OpenBSD to reset the PCIe/XHCI correctly
+   * when in DT mode.
+   */
+  Retval = fdt_setprop (mFdtImage, Node, "dma-ranges",
+                        DmaRanges,  sizeof DmaRanges);
+  if (Retval != 0) {
+    DEBUG ((DEBUG_ERROR, "%a: failed to locate PCIe 'dma-ranges' property (%d)\n",
+      __FUNCTION__, Retval));
+    return EFI_NOT_FOUND;
+  }
+
+  /*
+   * Now that we are always running without DMA translation, and with a 3G
+   * limit, there shouldn't be a need to reset/reload the XHCI. The
+   * possible problem is that the PCIe root port is itself being reset (by
+   * Linux+DT). The RPi foundation claims this is needed as a pre-req to
+   * reloading the XHCI firmware, which also implies that a PCI fundamental
+   * reset should cause the XHCI itself to reset.  This isn't happening
+   * fully, otherwise reloading the firmware would be mandatory. As it is,
+   * recent kernels actually start to have problems following the XHCI
+   * reset notification mailbox!  Instead lets stop the kernel from
+   * triggering the mailbox by removing the node.
+   */
+
+  Node = fdt_path_offset (mFdtImage, "/scb/pcie@7d500000/pci@1,0");
+  if (Node < 0) {
+    // This can happen on CM4/etc which doesn't have an onboard XHCI
+    DEBUG ((DEBUG_INFO, "%a: failed to locate /scb/pcie@7d500000/pci@1/usb@1\n", __FUNCTION__));
+  } else {
+    Retval = fdt_del_node (mFdtImage, Node);
+    if (Retval != 0) {
+      DEBUG ((DEBUG_ERROR, "Failed to remove /scb/pcie@7d500000/pci@1/usb@1\n"));
+      return EFI_NOT_FOUND;
+    }
+  }
+
+#endif
+  return EFI_SUCCESS;
+}
+
 /**
   @param  ImageHandle   of the loaded driver
   @param  SystemTable   Pointer to the System Table
@@ -431,6 +501,11 @@ FdtDxeInitialize (
     Print (L"Failed to update USB compatible properties: %r\n", Status);
   }
 
+  SyncPcie ();
+  if (EFI_ERROR (Status)) {
+    Print (L"Failed to update PCIe address ranges: %r\n", Status);
+  }
+
   DEBUG ((DEBUG_INFO, "Installed devicetree at address %p\n", mFdtImage));
   Status = gBS->InstallConfigurationTable (&gFdtTableGuid, mFdtImage);
   if (EFI_ERROR (Status)) {
-- 
2.13.7


  reply	other threads:[~2021-10-18 20:51 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-18 20:51 [PATCH v2 0/5] Platform/Rpi: Various cleanups + DT booting Jeremy Linton
2021-10-18 20:51 ` Jeremy Linton [this message]
2021-10-18 20:51 ` [PATCH v2 2/5] Platform/RaspberryPi: Fix vfr warning caused by two defaults Jeremy Linton
2021-10-18 20:51 ` [PATCH v2 3/5] Platform/RaspberryPi: Expand locking to cover return data Jeremy Linton
2021-10-18 20:51 ` [PATCH v2 4/5] Platform/RaspberryPi: Normal memory should not be marked as uncached Jeremy Linton
2021-10-18 20:51 ` [PATCH v2 5/5] Platform/RaspberryPi: Disconnect/shutdown all drivers before reboot Jeremy Linton
2021-10-19  7:23 ` [PATCH v2 0/5] Platform/Rpi: Various cleanups + DT booting Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211018205127.7099-2-jeremy.linton@arm.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox