WIP Thunderbolt support
This commit is contained in:
@@ -1218,6 +1218,7 @@ static void pci_bridge_route(struct bus *link, scan_state state)
|
|||||||
if (state == PCI_ROUTE_SCAN) {
|
if (state == PCI_ROUTE_SCAN) {
|
||||||
link->secondary = parent->subordinate + 1;
|
link->secondary = parent->subordinate + 1;
|
||||||
link->subordinate = link->secondary;
|
link->subordinate = link->secondary;
|
||||||
|
printk(BIOS_DEBUG, "system76: pci_bridge_route: assigning link secondary %d subordinate %d\n", link->secondary, link->subordinate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == PCI_ROUTE_CLOSE) {
|
if (state == PCI_ROUTE_CLOSE) {
|
||||||
|
@@ -92,6 +92,8 @@ void scan_generic_bus(struct device *bus)
|
|||||||
|
|
||||||
link->secondary = ++bus_max;
|
link->secondary = ++bus_max;
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "system76: scan_generic_bus: assigning link secondary %d\n", link->secondary);
|
||||||
|
|
||||||
for (child = link->children; child; child = child->sibling) {
|
for (child = link->children; child; child = child->sibling) {
|
||||||
|
|
||||||
if (child->chip_ops && child->chip_ops->enable_dev)
|
if (child->chip_ops && child->chip_ops->enable_dev)
|
||||||
|
4
src/drivers/thunderbolt/Kconfig
Normal file
4
src/drivers/thunderbolt/Kconfig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
config DRIVERS_THUNDERBOLT
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Thunderbolt support
|
1
src/drivers/thunderbolt/Makefile.inc
Normal file
1
src/drivers/thunderbolt/Makefile.inc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ramstage-$(CONFIG_DRIVERS_THUNDERBOLT) += thunderbolt.c
|
93
src/drivers/thunderbolt/thunderbolt.c
Normal file
93
src/drivers/thunderbolt/thunderbolt.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
resource = new_resource(dev, 0x10);
|
||||||
|
resource->size = 1 << 28;
|
||||||
|
resource->align = 22;
|
||||||
|
resource->gran = 22;
|
||||||
|
resource->limit = 0xffffffff;
|
||||||
|
resource->flags |= IORESOURCE_MEM;
|
||||||
|
|
||||||
|
resource = new_resource(dev, 0x14);
|
||||||
|
resource->size = 1 << 28;
|
||||||
|
resource->align = 22;
|
||||||
|
resource->gran = 22;
|
||||||
|
resource->limit = 0xffffffff;
|
||||||
|
resource->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||||
|
|
||||||
|
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 void tbt_pciexp_scan_bridge(struct device *dev) {
|
||||||
|
printk(BIOS_DEBUG, "tbt_pciexp_scan_bridge\n");
|
||||||
|
|
||||||
|
/* Normal PCIe Scan */
|
||||||
|
pciexp_scan_bridge(dev);
|
||||||
|
|
||||||
|
/* Add dummy slot to preserve resources */
|
||||||
|
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,
|
||||||
|
};
|
@@ -4,6 +4,7 @@ config BOARD_SPECIFIC_OPTIONS
|
|||||||
def_bool y
|
def_bool y
|
||||||
select ADD_FSP_BINARIES
|
select ADD_FSP_BINARIES
|
||||||
select BOARD_ROMSIZE_KB_16384
|
select BOARD_ROMSIZE_KB_16384
|
||||||
|
select DRIVERS_THUNDERBOLT
|
||||||
select EC_ACPI
|
select EC_ACPI
|
||||||
select EXCLUDE_EMMC_INTERFACE
|
select EXCLUDE_EMMC_INTERFACE
|
||||||
select HAVE_ACPI_RESUME
|
select HAVE_ACPI_RESUME
|
||||||
|
@@ -209,7 +209,13 @@ chip soc/intel/cannonlake
|
|||||||
device pci 19.1 off end # I2C #5
|
device pci 19.1 off end # I2C #5
|
||||||
device pci 19.2 off end # UART #2
|
device pci 19.2 off end # UART #2
|
||||||
device pci 1a.0 off end # eMMC
|
device pci 1a.0 off end # eMMC
|
||||||
device pci 1c.0 on end # PCI Express Port 1
|
device pci 1c.0 on
|
||||||
|
chip drivers/thunderbolt
|
||||||
|
device pci 00.0 on end # Thunderbolt 3 NHI
|
||||||
|
device pci 01.0 on end # Thunderbolt 3 PCI bridge
|
||||||
|
device pci 02.0 on end # Thunderbolt 3 USB controller
|
||||||
|
end
|
||||||
|
end # PCI Express Port 1
|
||||||
device pci 1c.1 off end # PCI Express Port 2
|
device pci 1c.1 off end # PCI Express Port 2
|
||||||
device pci 1c.2 off end # PCI Express Port 3
|
device pci 1c.2 off end # PCI Express Port 3
|
||||||
device pci 1c.3 off end # PCI Express Port 4
|
device pci 1c.3 off end # PCI Express Port 4
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <arch/acpi.h>
|
||||||
|
#include <arch/acpigen.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <device/device.h>
|
#include <device/device.h>
|
||||||
#include <option.h>
|
#include <option.h>
|
||||||
@@ -75,8 +78,128 @@ static void mainboard_init(struct device *dev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool mainboard_pcie_hotplug(int port_number) {
|
||||||
|
printk(BIOS_DEBUG, "system76: pcie_hotplug(%d)\n", port_number);
|
||||||
|
/* RP01 and RP05 */
|
||||||
|
return port_number == 0 || port_number == 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pcie_hotplug_generator(int port_number)
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
int have_hotplug = 0;
|
||||||
|
|
||||||
|
for (port = 0; port < port_number; port++) {
|
||||||
|
if (mainboard_pcie_hotplug(port)) {
|
||||||
|
have_hotplug = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_hotplug) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (port = 0; port < port_number; port++) {
|
||||||
|
if (mainboard_pcie_hotplug(port)) {
|
||||||
|
char scope_name[] = "\\_SB.PCI0.RP0x";
|
||||||
|
scope_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port;
|
||||||
|
acpigen_write_scope(scope_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Device (SLOT)
|
||||||
|
{
|
||||||
|
Name (_ADR, 0x00)
|
||||||
|
Method (_RMV, 0, NotSerialized)
|
||||||
|
{
|
||||||
|
Return (0x01)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
acpigen_write_device("SLOT");
|
||||||
|
|
||||||
|
acpigen_write_name_byte("_ADR", 0x00);
|
||||||
|
|
||||||
|
acpigen_write_method("_RMV", 0);
|
||||||
|
/* ReturnOp */
|
||||||
|
acpigen_emit_byte (0xa4);
|
||||||
|
/* One */
|
||||||
|
acpigen_emit_byte (0x01);
|
||||||
|
acpigen_pop_len();
|
||||||
|
acpigen_pop_len();
|
||||||
|
acpigen_pop_len();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Method (_L01, 0, NotSerialized)
|
||||||
|
{
|
||||||
|
If (\_SB.PCI0.RP04.HPCS)
|
||||||
|
{
|
||||||
|
Sleep (100)
|
||||||
|
Store (0x01, \_SB.PCI0.RP04.HPCS)
|
||||||
|
If (\_SB.PCI0.RP04.PDC)
|
||||||
|
{
|
||||||
|
Store (0x01, \_SB.PCI0.RP04.PDC)
|
||||||
|
Notify (\_SB.PCI0.RP04, 0x00)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
acpigen_write_scope("\\_GPE");
|
||||||
|
acpigen_write_method("_L01", 0);
|
||||||
|
for (port = 0; port < port_number; port++) {
|
||||||
|
if (mainboard_pcie_hotplug(port)) {
|
||||||
|
char reg_name[] = "\\_SB.PCI0.RP0x.HPCS";
|
||||||
|
reg_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port;
|
||||||
|
acpigen_emit_byte(0xa0); /* IfOp. */
|
||||||
|
acpigen_write_len_f();
|
||||||
|
acpigen_emit_namestring(reg_name);
|
||||||
|
|
||||||
|
/* Sleep (100) */
|
||||||
|
acpigen_emit_byte(0x5b); /* SleepOp. */
|
||||||
|
acpigen_emit_byte(0x22);
|
||||||
|
acpigen_write_byte(100);
|
||||||
|
|
||||||
|
/* Store (0x01, \_SB.PCI0.RP04.HPCS) */
|
||||||
|
acpigen_emit_byte(0x70);
|
||||||
|
acpigen_emit_byte(0x01);
|
||||||
|
acpigen_emit_namestring(reg_name);
|
||||||
|
|
||||||
|
memcpy(reg_name + sizeof("\\_SB.PCI0.RP0x.") - 1, "PDC", 4);
|
||||||
|
|
||||||
|
/* If (\_SB.PCI0.RP04.PDC) */
|
||||||
|
acpigen_emit_byte(0xa0); /* IfOp. */
|
||||||
|
acpigen_write_len_f();
|
||||||
|
acpigen_emit_namestring(reg_name);
|
||||||
|
|
||||||
|
/* Store (0x01, \_SB.PCI0.RP04.PDC) */
|
||||||
|
acpigen_emit_byte(0x70);
|
||||||
|
acpigen_emit_byte(0x01);
|
||||||
|
acpigen_emit_namestring(reg_name);
|
||||||
|
|
||||||
|
reg_name[sizeof("\\_SB.PCI0.RP0x") - 1] = '\0';
|
||||||
|
|
||||||
|
/* Notify(\_SB.PCI0.RP04, 0x00) */
|
||||||
|
acpigen_emit_byte(0x86);
|
||||||
|
acpigen_emit_namestring(reg_name);
|
||||||
|
acpigen_emit_byte(0x00);
|
||||||
|
acpigen_pop_len();
|
||||||
|
acpigen_pop_len();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acpigen_pop_len();
|
||||||
|
acpigen_pop_len();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_ssdt(struct device *device) {
|
||||||
|
printk(BIOS_INFO, "system76: fill_ssdt\n");
|
||||||
|
pcie_hotplug_generator(CONFIG_MAX_ROOT_PORTS);
|
||||||
|
}
|
||||||
|
|
||||||
static void mainboard_enable(struct device *dev) {
|
static void mainboard_enable(struct device *dev) {
|
||||||
dev->ops->init = mainboard_init;
|
dev->ops->init = mainboard_init;
|
||||||
|
dev->ops->acpi_fill_ssdt_generator = fill_ssdt;
|
||||||
|
|
||||||
// Configure pad for DisplayPort
|
// Configure pad for DisplayPort
|
||||||
uint32_t config = 0x44000200;
|
uint32_t config = 0x44000200;
|
||||||
|
Reference in New Issue
Block a user