瀏覽代碼

x86: pci: Allow binding of some devices before relocation

At present only bridge devices are bound before relocation, to save space
in pre-relocation memory. In some cases we do actually want to bind a
device, e.g. because it provides the console UART. Add a devicetree
binding to support this.

Use the PCI_VENDEV() macro to encode the cell value. This is present in
U-Boot but not used, so move it to the binding header-file.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Simon Glass 2 年之前
父節點
當前提交
f5cbb5c7cd
共有 4 個文件被更改,包括 50 次插入3 次删除
  1. 6 1
      doc/device-tree-bindings/pci/x86-pci.txt
  2. 32 1
      drivers/pci/pci-uclass.c
  3. 12 0
      include/dt-bindings/pci/pci.h
  4. 0 1
      include/pci.h

+ 6 - 1
doc/device-tree-bindings/pci/x86-pci.txt

@@ -20,6 +20,10 @@ For PCI devices the following optional property is available:
 	output to be lost. This should not generally be used in production code,
 	output to be lost. This should not generally be used in production code,
 	although it is often harmless.
 	although it is often harmless.
 
 
+- u-boot,pci-pre-reloc : List of vendor/device IDs to bind before relocation, even
+	if they are not bridges. This is useful if the device is needed (e.g. a
+	UART). The format is 0xvvvvdddd where d is the device ID and v is the
+	vendor ID.
 
 
 Example:
 Example:
 
 
@@ -32,7 +36,8 @@ pci {
 		0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000
 		0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000
 		0x01000000 0x0 0x1000 0x1000 0 0xefff>;
 		0x01000000 0x0 0x1000 0x1000 0 0xefff>;
 	u-boot,skip-auto-config-until-reloc;
 	u-boot,skip-auto-config-until-reloc;
-
+	u-boot,pci-pre-reloc = <
+		PCI_VENDEV(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL_UART2)>;
 
 
 	serial: serial@18,2 {
 	serial: serial@18,2 {
 		reg = <0x0200c210 0 0 0 0>;
 		reg = <0x0200c210 0 0 0 0>;

+ 32 - 1
drivers/pci/pci-uclass.c

@@ -21,6 +21,7 @@
 #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
 #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
 #include <asm/fsp/fsp_support.h>
 #include <asm/fsp/fsp_support.h>
 #endif
 #endif
+#include <dt-bindings/pci/pci.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include "pci_internal.h"
 #include "pci_internal.h"
 
 
@@ -681,6 +682,34 @@ static bool pci_match_one_id(const struct pci_device_id *id,
 	return false;
 	return false;
 }
 }
 
 
+/**
+ * pci_need_device_pre_reloc() - Check if a device should be bound
+ *
+ * This checks a list of vendor/device-ID values indicating devices that should
+ * be bound before relocation.
+ *
+ * @bus: Bus to check
+ * @vendor: Vendor ID to check
+ * @device: Device ID to check
+ * @return true if the vendor/device is in the list, false if not
+ */
+static bool pci_need_device_pre_reloc(struct udevice *bus, uint vendor,
+				      uint device)
+{
+	u32 vendev;
+	int index;
+
+	for (index = 0;
+	     !dev_read_u32_index(bus, "u-boot,pci-pre-reloc", index,
+				 &vendev);
+	     index++) {
+		if (vendev == PCI_VENDEV(vendor, device))
+			return true;
+	}
+
+	return false;
+}
+
 /**
 /**
  * pci_find_and_bind_driver() - Find and bind the right PCI driver
  * pci_find_and_bind_driver() - Find and bind the right PCI driver
  *
  *
@@ -769,7 +798,9 @@ static int pci_find_and_bind_driver(struct udevice *parent,
 	 * precious memory space as on some platforms as that space is pretty
 	 * precious memory space as on some platforms as that space is pretty
 	 * limited (ie: using Cache As RAM).
 	 * limited (ie: using Cache As RAM).
 	 */
 	 */
-	if (!(gd->flags & GD_FLG_RELOC) && !bridge)
+	if (!(gd->flags & GD_FLG_RELOC) && !bridge &&
+	    !pci_need_device_pre_reloc(parent, find_id->vendor,
+				       find_id->device))
 		return log_msg_ret("notbr", -EPERM);
 		return log_msg_ret("notbr", -EPERM);
 
 
 	/* Bind a generic driver so that the device can be used */
 	/* Bind a generic driver so that the device can be used */

+ 12 - 0
include/dt-bindings/pci/pci.h

@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * This header provides common constants for PCI bindings.
+ */
+
+#ifndef _DT_BINDINGS_PCI_PCI_H
+#define _DT_BINDINGS_PCI_PCI_H
+
+/* Encode a vendor and device ID into a single cell */
+#define PCI_VENDEV(v, d)	(((v) << 16) | (d))
+
+#endif /* _DT_BINDINGS_PCI_PCI_H */

+ 0 - 1
include/pci.h

@@ -578,7 +578,6 @@ typedef int pci_dev_t;
 #define PCI_MASK_BUS(bdf)	((bdf) & 0xffff)
 #define PCI_MASK_BUS(bdf)	((bdf) & 0xffff)
 #define PCI_ADD_BUS(bus, devfn)	(((bus) << 16) | (devfn))
 #define PCI_ADD_BUS(bus, devfn)	(((bus) << 16) | (devfn))
 #define PCI_BDF(b, d, f)	((b) << 16 | PCI_DEVFN(d, f))
 #define PCI_BDF(b, d, f)	((b) << 16 | PCI_DEVFN(d, f))
-#define PCI_VENDEV(v, d)	(((v) << 16) | (d))
 #define PCI_ANY_ID		(~0)
 #define PCI_ANY_ID		(~0)
 
 
 /* Convert from Linux format to U-Boot format */
 /* Convert from Linux format to U-Boot format */