Jeremy Soller has uploaded this change for review.

View Change

driver/thunderbolt: Driver for allocating hotplug resources

This adds a new driver which can be selected with DRIVERS_THUNDERBOLT
that, by default, adds 32 PCI subordinate numbers, 256 MiB of both
prefetchable and non-prefetchable memory, and 8 KiB of I/O space to
matching devices. It currently supports the JHL7540 Thunderbolt 3
bridge, but other devices can be added easily.

In order to support the allocation of hotplugged PCI buses, a new field
was added to struct device called hotplug_buses. This is defaulted to
zero, but when set, it adds the hotplug_buses value to the subordinate
value of the PCI bridge. This allows devices to be plugged in and
unplugged after boot.

This code was tested on the System76 Darter Pro (darp6). Before this
change, there are not enough resources allocated to the Thunderbolt
PCI bridge to allow plugging in new devices after boot. This can be
worked around in the Linux kernel by passing a boot param such as:
pci=assign-buses,hpbussize=32,realloc

This change makes it possible to use Thunderbolt hotplugging without
kernel parameters, and attempts to match closely what our motherboard
manufacturer's firmware does by default.

Signed-off-by: Jeremy Soller <jeremy@system76.com>
Change-Id: I500191626584b83e6a8ae38417fd324b5e803afc
---
M src/device/pci_device.c
A src/drivers/thunderbolt/Kconfig
A src/drivers/thunderbolt/Makefile.inc
A src/drivers/thunderbolt/thunderbolt.c
M src/include/device/device.h
5 files changed, 117 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/46/35946/1
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index c043dd6..1796d81 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -1217,7 +1217,7 @@

if (state == PCI_ROUTE_SCAN) {
link->secondary = parent->subordinate + 1;
- link->subordinate = link->secondary;
+ link->subordinate = link->secondary + dev->hotplug_buses;
}

if (state == PCI_ROUTE_CLOSE) {
diff --git a/src/drivers/thunderbolt/Kconfig b/src/drivers/thunderbolt/Kconfig
new file mode 100644
index 0000000..f64e6cb
--- /dev/null
+++ b/src/drivers/thunderbolt/Kconfig
@@ -0,0 +1,4 @@
+config DRIVERS_THUNDERBOLT
+ bool
+ help
+ Thunderbolt support
diff --git a/src/drivers/thunderbolt/Makefile.inc b/src/drivers/thunderbolt/Makefile.inc
new file mode 100644
index 0000000..623b897
--- /dev/null
+++ b/src/drivers/thunderbolt/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_DRIVERS_THUNDERBOLT) += thunderbolt.c
diff --git a/src/drivers/thunderbolt/thunderbolt.c b/src/drivers/thunderbolt/thunderbolt.c
new file mode 100644
index 0000000..db463e0e
--- /dev/null
+++ b/src/drivers/thunderbolt/thunderbolt.c
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 System76.
+ * Copyright (C) 2017-2018 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pciexp.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+static void slot_dev_read_resources(struct device *dev)
+{
+ struct resource *resource;
+
+ // Add 256 MiB of memory space
+ resource = new_resource(dev, 0x10);
+ resource->size = 1 << 28;
+ resource->align = 22;
+ resource->gran = 22;
+ resource->limit = 0xffffffff;
+ resource->flags |= IORESOURCE_MEM;
+
+ // Add 256 MiB of prefetchable memory space
+ resource = new_resource(dev, 0x14);
+ resource->size = 1 << 28;
+ resource->align = 22;
+ resource->gran = 22;
+ resource->limit = 0xffffffff;
+ resource->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
+
+ // Add 8 KiB of I/O space
+ resource = new_resource(dev, 0x18);
+ resource->size = 1 << 13;
+ resource->align = 12;
+ resource->gran = 12;
+ resource->limit = 0xffff;
+ resource->flags |= IORESOURCE_IO;
+}
+
+static struct device_operations slot_dev_ops = {
+ .read_resources = slot_dev_read_resources,
+};
+
+static bool tbt_is_hotplug_bridge(struct device *dev) {
+ return PCI_SLOT(dev->path.pci.devfn) == 1;
+}
+
+static void tbt_pciexp_scan_bridge(struct device *dev) {
+ printk(BIOS_DEBUG, "%s: %s: scan bridge\n", __func__, dev_path(dev));
+
+ bool is_hotplug = tbt_is_hotplug_bridge(dev);
+ if (is_hotplug) {
+ /* Add hotplug buses, must happen before bus scan */
+ printk(BIOS_DEBUG, "%s: %s: add hotplug buses\n", __func__, dev_path(dev));
+ dev->hotplug_buses = 32;
+ }
+
+ /* Normal PCIe Scan */
+ pciexp_scan_bridge(dev);
+
+ if (is_hotplug) {
+ /* Add dummy slot to preserve resources, must happen after bus scan */
+ printk(BIOS_DEBUG, "%s: %s: add dummy device\n", __func__, dev_path(dev));
+ struct device *slot;
+ struct device_path slot_path = { .type = DEVICE_PATH_NONE };
+ slot = alloc_dev(dev->link_list, &slot_path);
+ slot->ops = &slot_dev_ops;
+ }
+}
+
+static struct pci_operations pcie_ops = {
+ .set_subsystem = pci_dev_set_subsystem,
+};
+
+static struct device_operations device_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = 0,
+ .scan_bus = tbt_pciexp_scan_bridge,
+ .enable = 0,
+ .reset_bus = pci_bus_reset,
+ .ops_pci = &pcie_ops,
+};
+
+static const unsigned short pcie_device_ids[] = {
+ // JHL7540 Thunderbolt 3 Bridge
+ 0x15e7,
+ 0
+};
+
+static const struct pci_driver tbt_pcie __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .devices = pcie_device_ids,
+};
diff --git a/src/include/device/device.h b/src/include/device/device.h
index cb37c09..f22bed5 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -129,6 +129,7 @@
unsigned int disable_pcie_aspm : 1;
unsigned int hidden : 1; /* set if we should hide from UI */
u8 command;
+ uint16_t hotplug_buses; /* hotplug buses to allocate */

/* Base registers for this device. I/O, MEM and Expansion ROM */
DEVTREE_CONST struct resource *resource_list;

To view, visit change 35946. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I500191626584b83e6a8ae38417fd324b5e803afc
Gerrit-Change-Number: 35946
Gerrit-PatchSet: 1
Gerrit-Owner: Jeremy Soller <jeremy@system76.com>
Gerrit-MessageType: newchange