Refactor DGPU support code into drivers/system76/dgpu

Change-Id: Id29d6ade82b7212a3a68f6f3c27769e17d3fdcdc
This commit is contained in:
Jeremy Soller
2020-07-20 10:02:45 -06:00
parent 65600cdec6
commit 9e729e44a8
41 changed files with 200 additions and 1234 deletions

View File

@@ -0,0 +1,5 @@
config DRIVERS_SYSTEM76_DGPU
bool
default n
help
System76 switchable graphics support

View File

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
ramstage-$(CONFIG_DRIVERS_SYSTEM76_DGPU) += ramstage.c

View File

@@ -1,33 +1,34 @@
// From https://review.coreboot.org/c/coreboot/+/28380 /* SPDX-License-Identifier: GPL-2.0-only */
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2017-2018 Patrick Rudolph <siro@das-labor.org>
*
* 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.
*
* Nvidia Optimus support methods.
*
* Methods defined here are known to work on Lenovo's Sandy Bridge
* and Ivy Bridge series, which have GPIO21 pulled low on installed dGPU and
* GPIO17 to detect dGPU "PowerGood". They use the same PMH7 functions to
* enable dGPU power and handle dGPU reset.
*/
#define DGPU_RST_N GPP_F22 Device (\_SB.PCI0.PEGP) {
#define DGPU_PWR_EN GPP_F23 Name (_ADR, 0x00010000)
#define DGPU_GC6 GPP_K21
Device (\_SB.PCI0.PEGP.DEV0) PowerResource (PWRR, 0, 0) {
{ Name (_STA, 1)
Method (_ON) {
Debug = "PEGP.PWRR._ON"
If (_STA != 1) {
\_SB.PCI0.PEGP.DEV0._ON ()
_STA = 1
}
}
Method (_OFF) {
Debug = "PEGP.PWRR._OFF"
If (_STA != 0) {
\_SB.PCI0.PEGP.DEV0._OFF ()
_STA = 0
}
}
}
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
}
Device (\_SB.PCI0.PEGP.DEV0) {
Name(_ADR, 0x00000000) Name(_ADR, 0x00000000)
Name (_STA, 0xF) Name (_STA, 0xF)
Name (LTRE, 0) Name (LTRE, 0)
@@ -35,8 +36,7 @@ Device (\_SB.PCI0.PEGP.DEV0)
// Memory mapped PCI express registers // Memory mapped PCI express registers
// Not sure what this stuff is, but it is used to get into GC6 // Not sure what this stuff is, but it is used to get into GC6
OperationRegion (RPCX, SystemMemory, 0xE0008000, 0x1000) OperationRegion (RPCX, SystemMemory, 0xE0008000, 0x1000)
Field (RPCX, ByteAcc, NoLock, Preserve) Field (RPCX, ByteAcc, NoLock, Preserve) {
{
PVID, 16, PVID, 16,
PDID, 16, PDID, 16,
CMDR, 8, CMDR, 8,
@@ -85,8 +85,7 @@ Device (\_SB.PCI0.PEGP.DEV0)
LREV, 1 LREV, 1
} }
Method (_ON) Method (_ON) {
{
Debug = "PEGP.DEV0._ON" Debug = "PEGP.DEV0._ON"
If (_STA != 0xF) { If (_STA != 0xF) {
@@ -143,8 +142,7 @@ Device (\_SB.PCI0.PEGP.DEV0)
} }
} }
Method (_OFF) Method (_OFF) {
{
Debug = "PEGP.DEV0._OFF" Debug = "PEGP.DEV0._OFF"
If (_STA != 0x5) { If (_STA != 0x5) {

View File

@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only */
//TODO: do not require this to be included in mainboard bootblock.c
#include <console/console.h>
#include <delay.h>
#include <gpio.h>
static void dgpu_power_enable(int onoff) {
printk(BIOS_DEBUG, "system76: DGPU power %d\n", onoff);
if (onoff) {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 1);
mdelay(4);
gpio_set(DGPU_RST_N, 1);
} else {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 0);
}
mdelay(50);
}

View File

@@ -0,0 +1,81 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci.h>
static void dgpu_read_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_read_resources %s\n", dev_path(dev));
pci_dev_read_resources(dev);
int bar;
// Find all BARs on DGPU, mark them above 4g if prefetchable
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
printk(BIOS_INFO, " BAR at 0x%02x\n", bar);
struct resource *res;
res = probe_resource(dev, bar);
if (res) {
if (res->flags & IORESOURCE_PREFETCH) {
printk(BIOS_INFO, " marked above 4g\n");
res->flags |= IORESOURCE_ABOVE_4G;
} else {
printk(BIOS_INFO, " not prefetch\n");
}
} else {
printk(BIOS_INFO, " not found\n");
}
}
}
static void dgpu_enable_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_enable_resources %s\n", dev_path(dev));
dev->subsystem_vendor = CONFIG_SUBSYSTEM_VENDOR_ID;
dev->subsystem_device = CONFIG_SUBSYSTEM_DEVICE_ID;
printk(BIOS_INFO, " subsystem <- %04x/%04x\n", dev->subsystem_vendor, dev->subsystem_device);
pci_write_config32(dev, 0x40, ((dev->subsystem_device & 0xffff) << 16) | (dev->subsystem_vendor & 0xffff));
pci_dev_enable_resources(dev);
}
static struct device_operations dgpu_pci_ops_dev = {
.read_resources = dgpu_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = dgpu_enable_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = pci_rom_write_acpi_tables,
.acpi_fill_ssdt = pci_rom_ssdt,
#endif
.init = pci_dev_init,
.ops_pci = &pci_dev_ops_pci,
};
static void dgpu_above_4g(void *unused) {
struct device *pdev;
// Find PEG0
pdev = pcidev_on_root(1, 0);
if (!pdev) {
printk(BIOS_ERR, "system76: failed to find PEG0\n");
return;
}
printk(BIOS_INFO, "system76: PEG0 at %p, %04x:%04x\n", pdev, pdev->vendor, pdev->device);
int fn;
for (fn = 0; fn < 8; fn++) {
struct device *dev;
// Find DGPU functions
dev = pcidev_path_behind(pdev->link_list, PCI_DEVFN(0, fn));
if (dev) {
printk(BIOS_INFO, "system76: DGPU fn %d at %p, %04x:%04x\n", fn, dev, dev->vendor, dev->device);
dev->ops = &dgpu_pci_ops_dev;
} else {
printk(BIOS_ERR, "system76: failed to find DGPU fn %d\n", fn);
}
}
}
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, dgpu_above_4g, NULL);

View File

@@ -5,6 +5,7 @@ config BOARD_SPECIFIC_OPTIONS
select BOARD_ROMSIZE_KB_16384 select BOARD_ROMSIZE_KB_16384
select DRIVERS_I2C_HID select DRIVERS_I2C_HID
select DRIVERS_I2C_TAS5825M select DRIVERS_I2C_TAS5825M
select DRIVERS_SYSTEM76_DGPU
select EC_SYSTEM76_EC select EC_SYSTEM76_EC
select HAVE_ACPI_RESUME select HAVE_ACPI_RESUME
select HAVE_ACPI_TABLES select HAVE_ACPI_TABLES

View File

@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include "../gpio.h"
#include <drivers/system76/dgpu/acpi/dgpu.asl>
#define EC_GPE_SCI 0x03 /* GPP_K3 */ #define EC_GPE_SCI 0x03 /* GPP_K3 */
#define EC_GPE_SWI 0x06 /* GPP_K6 */ #define EC_GPE_SWI 0x06 /* GPP_K6 */
#define EC_COLOR_KEYBOARD 1 #define EC_COLOR_KEYBOARD 1
@@ -7,10 +10,6 @@
Scope (\_SB) { Scope (\_SB) {
#include "sleep.asl" #include "sleep.asl"
Scope (PCI0) {
#include "pegp.asl"
#include "dgpu.asl"
}
} }
Scope (\_GPE) { Scope (\_GPE) {

View File

@@ -1,34 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/40625
/* SPDX-License-Identifier: GPL-2.0-only */
Device (PEGP)
{
Name (_ADR, 0x00010000)
PowerResource (PWRR, 0, 0)
{
Name (_STA, 1)
Method (_ON)
{
Debug = "PEGP.PWRR._ON"
If (_STA != 1) {
\_SB.PCI0.PEGP.DEV0._ON ()
_STA = 1
}
}
Method (_OFF)
{
Debug = "PEGP.PWRR._OFF"
If (_STA != 0) {
\_SB.PCI0.PEGP.DEV0._OFF ()
_STA = 0
}
}
}
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
}

View File

@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h> #include <bootblock_common.h>
#include <console/console.h>
#include <delay.h>
#include <gpio.h> #include <gpio.h>
#include "gpio.h" #include "gpio.h"
#include <drivers/system76/dgpu/bootblock.c>
static void dgpu_power_enable(int onoff) { void bootblock_mainboard_init(void) {
printk(BIOS_DEBUG, "system76: DGPU power %d\n", onoff);
if (onoff) {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 1);
mdelay(4);
gpio_set(DGPU_RST_N, 1);
} else {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 0);
}
mdelay(50);
}
void bootblock_mainboard_init(void)
{
gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table)); gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table));
dgpu_power_enable(1); dgpu_power_enable(1);
} }

View File

@@ -14,16 +14,14 @@ DefinitionBlock(
#include <soc/intel/common/block/acpi/acpi/globalnvs.asl> #include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
#include <cpu/intel/common/acpi/cpu.asl> #include <cpu/intel/common/acpi/cpu.asl>
Device (\_SB.PCI0) Device (\_SB.PCI0) {
{
#include <soc/intel/common/block/acpi/acpi/northbridge.asl> #include <soc/intel/common/block/acpi/acpi/northbridge.asl>
#include <soc/intel/cannonlake/acpi/southbridge.asl> #include <soc/intel/cannonlake/acpi/southbridge.asl>
} }
#include <southbridge/intel/common/acpi/sleepstates.asl> #include <southbridge/intel/common/acpi/sleepstates.asl>
Scope (\_SB.PCI0.LPCB) Scope (\_SB.PCI0.LPCB) {
{
#include <drivers/pc80/pc/ps2_controller.asl> #include <drivers/pc80/pc/ps2_controller.asl>
} }

View File

@@ -3,14 +3,15 @@
#ifndef MAINBOARD_GPIO_H #ifndef MAINBOARD_GPIO_H
#define MAINBOARD_GPIO_H #define MAINBOARD_GPIO_H
#include <soc/gpe.h>
#include <soc/gpio.h>
#define DGPU_RST_N GPP_F22 #define DGPU_RST_N GPP_F22
#define DGPU_PWR_EN GPP_F23 #define DGPU_PWR_EN GPP_F23
#define DGPU_GC6 GPP_K21
#ifndef __ACPI__ #ifndef __ACPI__
#include <soc/gpe.h>
#include <soc/gpio.h>
/* Pad configuration in romstage. */ /* Pad configuration in romstage. */
static const struct pad_config early_gpio_table[] = { static const struct pad_config early_gpio_table[] = {
PAD_CFG_TERM_GPO(GPP_F22, 0, NONE, DEEP), // DGPU_RST_N PAD_CFG_TERM_GPO(GPP_F22, 0, NONE, DEEP), // DGPU_RST_N

View File

@@ -1,90 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci.h>
#include <soc/ramstage.h> #include <soc/ramstage.h>
#include "gpio.h" #include "gpio.h"
void mainboard_silicon_init_params(FSP_S_CONFIG *params) void mainboard_silicon_init_params(FSP_S_CONFIG *params) {
{
/* Configure pads prior to SiliconInit() in case there's any /* Configure pads prior to SiliconInit() in case there's any
* dependencies during hardware initialization. */ * dependencies during hardware initialization. */
cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
} }
static void dgpu_read_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_read_resources %s\n", dev_path(dev));
pci_dev_read_resources(dev);
int bar;
// Find all BARs on DGPU, mark them above 4g if prefetchable
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
printk(BIOS_INFO, " BAR at 0x%02x\n", bar);
struct resource *res;
res = probe_resource(dev, bar);
if (res) {
if (res->flags & IORESOURCE_PREFETCH) {
printk(BIOS_INFO, " marked above 4g\n");
res->flags |= IORESOURCE_ABOVE_4G;
} else {
printk(BIOS_INFO, " not prefetch\n");
}
} else {
printk(BIOS_INFO, " not found\n");
}
}
}
static void dgpu_enable_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_enable_resources %s\n", dev_path(dev));
dev->subsystem_vendor = CONFIG_SUBSYSTEM_VENDOR_ID;
dev->subsystem_device = CONFIG_SUBSYSTEM_DEVICE_ID;
printk(BIOS_INFO, " subsystem <- %04x/%04x\n", dev->subsystem_vendor, dev->subsystem_device);
pci_write_config32(dev, 0x40, ((dev->subsystem_device & 0xffff) << 16) | (dev->subsystem_vendor & 0xffff));
pci_dev_enable_resources(dev);
}
static struct device_operations dgpu_pci_ops_dev = {
.read_resources = dgpu_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = dgpu_enable_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = pci_rom_write_acpi_tables,
.acpi_fill_ssdt = pci_rom_ssdt,
#endif
.init = pci_dev_init,
.ops_pci = &pci_dev_ops_pci,
};
static void dgpu_above_4g(void *unused) {
struct device *pdev;
// Find PEG0
pdev = pcidev_on_root(1, 0);
if (!pdev) {
printk(BIOS_ERR, "system76: failed to find PEG0\n");
return;
}
printk(BIOS_INFO, "system76: PEG0 at %p, %04x:%04x\n", pdev, pdev->vendor, pdev->device);
int fn;
for (fn = 0; fn < 8; fn++) {
struct device *dev;
// Find DGPU functions
dev = pcidev_path_behind(pdev->link_list, PCI_DEVFN(0, fn));
if (dev) {
printk(BIOS_INFO, "system76: DGPU fn %d at %p, %04x:%04x\n", fn, dev, dev->vendor, dev->device);
dev->ops = &dgpu_pci_ops_dev;
} else {
printk(BIOS_ERR, "system76: failed to find DGPU fn %d\n", fn);
}
}
}
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, dgpu_above_4g, NULL);

View File

@@ -78,8 +78,7 @@ static const struct cnl_mb_cfg memcfg = {
.ect = 0, .ect = 0,
}; };
void mainboard_memory_init_params(FSPM_UPD *memupd) void mainboard_memory_init_params(FSPM_UPD *memupd) {
{
// Allow memory clocks higher than 2933 MHz // Allow memory clocks higher than 2933 MHz
memupd->FspmConfig.SaOcSupport = 1; memupd->FspmConfig.SaOcSupport = 1;
// Set primary display to internal graphics // Set primary display to internal graphics

View File

@@ -4,6 +4,7 @@ config BOARD_SPECIFIC_OPTIONS
def_bool y def_bool y
select BOARD_ROMSIZE_KB_16384 select BOARD_ROMSIZE_KB_16384
select DRIVERS_I2C_HID select DRIVERS_I2C_HID
select DRIVERS_SYSTEM76_DGPU
select EC_SYSTEM76_EC select EC_SYSTEM76_EC
select HAVE_ACPI_RESUME select HAVE_ACPI_RESUME
select HAVE_ACPI_TABLES select HAVE_ACPI_TABLES

View File

@@ -1,203 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/28380
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2017-2018 Patrick Rudolph <siro@das-labor.org>
*
* 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.
*
* Nvidia Optimus support methods.
*
* Methods defined here are known to work on Lenovo's Sandy Bridge
* and Ivy Bridge series, which have GPIO21 pulled low on installed dGPU and
* GPIO17 to detect dGPU "PowerGood". They use the same PMH7 functions to
* enable dGPU power and handle dGPU reset.
*/
#define DGPU_RST_N GPP_F22
#define DGPU_PWR_EN GPP_F23
#define DGPU_GC6 GPP_K21
Device (\_SB.PCI0.PEGP.DEV0)
{
Name(_ADR, 0x00000000)
Name (_STA, 0xF)
Name (LTRE, 0)
// Memory mapped PCI express registers
// Not sure what this stuff is, but it is used to get into GC6
OperationRegion (RPCX, SystemMemory, 0xE0008000, 0x1000)
Field (RPCX, ByteAcc, NoLock, Preserve)
{
PVID, 16,
PDID, 16,
CMDR, 8,
Offset (0x19),
PRBN, 8,
Offset (0x84),
D0ST, 2,
Offset (0xAA),
CEDR, 1,
Offset (0xAC),
, 4,
CMLW, 6,
Offset (0xB0),
ASPM, 2,
, 2,
P0LD, 1,
RTLK, 1,
Offset (0xC9),
, 2,
LREN, 1,
Offset (0x11A),
, 1,
VCNP, 1,
Offset (0x214),
Offset (0x216),
P0LS, 4,
Offset (0x248),
, 7,
Q0L2, 1,
Q0L0, 1,
Offset (0x504),
Offset (0x506),
PCFG, 2,
Offset (0x508),
TREN, 1,
Offset (0xC20),
, 4,
P0AP, 2,
Offset (0xC38),
, 3,
P0RM, 1,
Offset (0xC74),
P0LT, 4,
Offset (0xD0C),
, 20,
LREV, 1
}
Method (_ON)
{
Debug = "PEGP.DEV0._ON"
If (_STA != 0xF) {
Debug = " If DGPU_PWR_EN low"
If (! GTXS (DGPU_PWR_EN)) {
Debug = " DGPU_PWR_EN high"
STXS (DGPU_PWR_EN)
Debug = " Sleep 16"
Sleep (16)
}
Debug = " DGPU_RST_N high"
STXS(DGPU_RST_N)
Debug = " Sleep 10"
Sleep (10)
Debug = " Q0L0 = 1"
Q0L0 = 1
Debug = " Sleep 16"
Sleep (16)
Debug = " While Q0L0"
Local0 = 0
While (Q0L0) {
If ((Local0 > 4)) {
Debug = " While Q0L0 timeout"
Break
}
Sleep (16)
Local0++
}
Debug = " P0RM = 0"
P0RM = 0
Debug = " P0AP = 0"
P0AP = 0
Debug = Concatenate(" LREN = ", ToHexString(LTRE))
LREN = LTRE
Debug = " CEDR = 1"
CEDR = 1
Debug = " CMDR |= 7"
CMDR |= 7
Debug = " _STA = 0xF"
_STA = 0xF
}
}
Method (_OFF)
{
Debug = "PEGP.DEV0._OFF"
If (_STA != 0x5) {
Debug = Concatenate(" LTRE = ", ToHexString(LREN))
LTRE = LREN
Debug = " Q0L2 = 1"
Q0L2 = 1
Debug = " Sleep 16"
Sleep (16)
Debug = " While Q0L2"
Local0 = Zero
While (Q0L2) {
If ((Local0 > 4)) {
Debug = " While Q0L2 timeout"
Break
}
Sleep (16)
Local0++
}
Debug = " P0RM = 1"
P0RM = 1
Debug = " P0AP = 3"
P0AP = 3
Debug = " Sleep 10"
Sleep (10)
Debug = " DGPU_RST_N low"
CTXS(DGPU_RST_N)
Debug = " While DGPU_GC6 low"
Local0 = Zero
While (! GRXS(DGPU_GC6)) {
If ((Local0 > 4)) {
Debug = " While DGPU_GC6 low timeout"
Debug = " DGPU_PWR_EN low"
CTXS (DGPU_PWR_EN)
Break
}
Sleep (16)
Local0++
}
Debug = " _STA = 0x5"
_STA = 0x5
}
}
}

View File

@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include "../gpio.h"
#include <drivers/system76/dgpu/acpi/dgpu.asl>
#define EC_GPE_SCI 0x03 /* GPP_K3 */ #define EC_GPE_SCI 0x03 /* GPP_K3 */
#define EC_GPE_SWI 0x06 /* GPP_K6 */ #define EC_GPE_SWI 0x06 /* GPP_K6 */
#define EC_COLOR_KEYBOARD 1 #define EC_COLOR_KEYBOARD 1
@@ -9,8 +12,6 @@ Scope (\_SB) {
#include "sleep.asl" #include "sleep.asl"
Scope (PCI0) { Scope (PCI0) {
#include "backlight.asl" #include "backlight.asl"
#include "pegp.asl"
#include "dgpu.asl"
} }
} }

View File

@@ -1,34 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/40625
/* SPDX-License-Identifier: GPL-2.0-only */
Device (PEGP)
{
Name (_ADR, 0x00010000)
PowerResource (PWRR, 0, 0)
{
Name (_STA, 1)
Method (_ON)
{
Debug = "PEGP.PWRR._ON"
If (_STA != 1) {
\_SB.PCI0.PEGP.DEV0._ON ()
_STA = 1
}
}
Method (_OFF)
{
Debug = "PEGP.PWRR._OFF"
If (_STA != 0) {
\_SB.PCI0.PEGP.DEV0._OFF ()
_STA = 0
}
}
}
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
}

View File

@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h> #include <bootblock_common.h>
#include <console/console.h>
#include <delay.h>
#include <gpio.h> #include <gpio.h>
#include "gpio.h" #include "gpio.h"
#include <drivers/system76/dgpu/bootblock.c>
static void dgpu_power_enable(int onoff) { void bootblock_mainboard_init(void) {
printk(BIOS_DEBUG, "system76: DGPU power %d\n", onoff);
if (onoff) {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 1);
mdelay(4);
gpio_set(DGPU_RST_N, 1);
} else {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 0);
}
mdelay(50);
}
void bootblock_mainboard_init(void)
{
gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table)); gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table));
dgpu_power_enable(1); dgpu_power_enable(1);
} }

View File

@@ -14,16 +14,14 @@ DefinitionBlock(
#include <soc/intel/common/block/acpi/acpi/globalnvs.asl> #include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
#include <cpu/intel/common/acpi/cpu.asl> #include <cpu/intel/common/acpi/cpu.asl>
Device (\_SB.PCI0) Device (\_SB.PCI0) {
{
#include <soc/intel/common/block/acpi/acpi/northbridge.asl> #include <soc/intel/common/block/acpi/acpi/northbridge.asl>
#include <soc/intel/cannonlake/acpi/southbridge.asl> #include <soc/intel/cannonlake/acpi/southbridge.asl>
} }
#include <southbridge/intel/common/acpi/sleepstates.asl> #include <southbridge/intel/common/acpi/sleepstates.asl>
Scope (\_SB.PCI0.LPCB) Scope (\_SB.PCI0.LPCB) {
{
#include <drivers/pc80/pc/ps2_controller.asl> #include <drivers/pc80/pc/ps2_controller.asl>
} }

View File

@@ -1,90 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci.h>
#include <soc/ramstage.h> #include <soc/ramstage.h>
#include "gpio.h" #include "gpio.h"
void mainboard_silicon_init_params(FSP_S_CONFIG *params) void mainboard_silicon_init_params(FSP_S_CONFIG *params) {
{
/* Configure pads prior to SiliconInit() in case there's any /* Configure pads prior to SiliconInit() in case there's any
* dependencies during hardware initialization. */ * dependencies during hardware initialization. */
cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
} }
static void dgpu_read_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_read_resources %s\n", dev_path(dev));
pci_dev_read_resources(dev);
int bar;
// Find all BARs on DGPU, mark them above 4g if prefetchable
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
printk(BIOS_INFO, " BAR at 0x%02x\n", bar);
struct resource *res;
res = probe_resource(dev, bar);
if (res) {
if (res->flags & IORESOURCE_PREFETCH) {
printk(BIOS_INFO, " marked above 4g\n");
res->flags |= IORESOURCE_ABOVE_4G;
} else {
printk(BIOS_INFO, " not prefetch\n");
}
} else {
printk(BIOS_INFO, " not found\n");
}
}
}
static void dgpu_enable_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_enable_resources %s\n", dev_path(dev));
dev->subsystem_vendor = CONFIG_SUBSYSTEM_VENDOR_ID;
dev->subsystem_device = CONFIG_SUBSYSTEM_DEVICE_ID;
printk(BIOS_INFO, " subsystem <- %04x/%04x\n", dev->subsystem_vendor, dev->subsystem_device);
pci_write_config32(dev, 0x40, ((dev->subsystem_device & 0xffff) << 16) | (dev->subsystem_vendor & 0xffff));
pci_dev_enable_resources(dev);
}
static struct device_operations dgpu_pci_ops_dev = {
.read_resources = dgpu_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = dgpu_enable_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = pci_rom_write_acpi_tables,
.acpi_fill_ssdt = pci_rom_ssdt,
#endif
.init = pci_dev_init,
.ops_pci = &pci_dev_ops_pci,
};
static void dgpu_above_4g(void *unused) {
struct device *pdev;
// Find PEG0
pdev = pcidev_on_root(1, 0);
if (!pdev) {
printk(BIOS_ERR, "system76: failed to find PEG0\n");
return;
}
printk(BIOS_INFO, "system76: PEG0 at %p, %04x:%04x\n", pdev, pdev->vendor, pdev->device);
int fn;
for (fn = 0; fn < 8; fn++) {
struct device *dev;
// Find DGPU functions
dev = pcidev_path_behind(pdev->link_list, PCI_DEVFN(0, fn));
if (dev) {
printk(BIOS_INFO, "system76: DGPU fn %d at %p, %04x:%04x\n", fn, dev, dev->vendor, dev->device);
dev->ops = &dgpu_pci_ops_dev;
} else {
printk(BIOS_ERR, "system76: failed to find DGPU fn %d\n", fn);
}
}
}
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, dgpu_above_4g, NULL);

View File

@@ -78,8 +78,7 @@ static const struct cnl_mb_cfg memcfg = {
.ect = 0, .ect = 0,
}; };
void mainboard_memory_init_params(FSPM_UPD *memupd) void mainboard_memory_init_params(FSPM_UPD *memupd) {
{
// Set primary display to internal graphics // Set primary display to internal graphics
memupd->FspmConfig.PrimaryDisplay = 0; memupd->FspmConfig.PrimaryDisplay = 0;
cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg); cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg);

View File

@@ -4,6 +4,7 @@ config BOARD_SPECIFIC_OPTIONS
def_bool y def_bool y
select BOARD_ROMSIZE_KB_16384 select BOARD_ROMSIZE_KB_16384
select DRIVERS_I2C_HID select DRIVERS_I2C_HID
select DRIVERS_SYSTEM76_DGPU
select EC_SYSTEM76_EC select EC_SYSTEM76_EC
select HAVE_ACPI_RESUME select HAVE_ACPI_RESUME
select HAVE_ACPI_TABLES select HAVE_ACPI_TABLES

View File

@@ -2,10 +2,8 @@
#include <drivers/intel/gma/acpi/gma.asl> #include <drivers/intel/gma/acpi/gma.asl>
Scope (GFX0) Scope (GFX0) {
{ Name (BRIG, Package (22) {
Name (BRIG, Package (22)
{
40, /* default AC */ 40, /* default AC */
40, /* default Battery */ 40, /* default Battery */
5, 5,

View File

@@ -1,203 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/28380
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2017-2018 Patrick Rudolph <siro@das-labor.org>
*
* 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.
*
* Nvidia Optimus support methods.
*
* Methods defined here are known to work on Lenovo's Sandy Bridge
* and Ivy Bridge series, which have GPIO21 pulled low on installed dGPU and
* GPIO17 to detect dGPU "PowerGood". They use the same PMH7 functions to
* enable dGPU power and handle dGPU reset.
*/
#define DGPU_RST_N GPP_F22
#define DGPU_PWR_EN GPP_F23
#define DGPU_GC6 GPP_K21
Device (\_SB.PCI0.PEGP.DEV0)
{
Name(_ADR, 0x00000000)
Name (_STA, 0xF)
Name (LTRE, 0)
// Memory mapped PCI express registers
// Not sure what this stuff is, but it is used to get into GC6
OperationRegion (RPCX, SystemMemory, 0xE0008000, 0x1000)
Field (RPCX, ByteAcc, NoLock, Preserve)
{
PVID, 16,
PDID, 16,
CMDR, 8,
Offset (0x19),
PRBN, 8,
Offset (0x84),
D0ST, 2,
Offset (0xAA),
CEDR, 1,
Offset (0xAC),
, 4,
CMLW, 6,
Offset (0xB0),
ASPM, 2,
, 2,
P0LD, 1,
RTLK, 1,
Offset (0xC9),
, 2,
LREN, 1,
Offset (0x11A),
, 1,
VCNP, 1,
Offset (0x214),
Offset (0x216),
P0LS, 4,
Offset (0x248),
, 7,
Q0L2, 1,
Q0L0, 1,
Offset (0x504),
Offset (0x506),
PCFG, 2,
Offset (0x508),
TREN, 1,
Offset (0xC20),
, 4,
P0AP, 2,
Offset (0xC38),
, 3,
P0RM, 1,
Offset (0xC74),
P0LT, 4,
Offset (0xD0C),
, 20,
LREV, 1
}
Method (_ON)
{
Debug = "PEGP.DEV0._ON"
If (_STA != 0xF) {
Debug = " If DGPU_PWR_EN low"
If (! GTXS (DGPU_PWR_EN)) {
Debug = " DGPU_PWR_EN high"
STXS (DGPU_PWR_EN)
Debug = " Sleep 16"
Sleep (16)
}
Debug = " DGPU_RST_N high"
STXS(DGPU_RST_N)
Debug = " Sleep 10"
Sleep (10)
Debug = " Q0L0 = 1"
Q0L0 = 1
Debug = " Sleep 16"
Sleep (16)
Debug = " While Q0L0"
Local0 = 0
While (Q0L0) {
If ((Local0 > 4)) {
Debug = " While Q0L0 timeout"
Break
}
Sleep (16)
Local0++
}
Debug = " P0RM = 0"
P0RM = 0
Debug = " P0AP = 0"
P0AP = 0
Debug = Concatenate(" LREN = ", ToHexString(LTRE))
LREN = LTRE
Debug = " CEDR = 1"
CEDR = 1
Debug = " CMDR |= 7"
CMDR |= 7
Debug = " _STA = 0xF"
_STA = 0xF
}
}
Method (_OFF)
{
Debug = "PEGP.DEV0._OFF"
If (_STA != 0x5) {
Debug = Concatenate(" LTRE = ", ToHexString(LREN))
LTRE = LREN
Debug = " Q0L2 = 1"
Q0L2 = 1
Debug = " Sleep 16"
Sleep (16)
Debug = " While Q0L2"
Local0 = Zero
While (Q0L2) {
If ((Local0 > 4)) {
Debug = " While Q0L2 timeout"
Break
}
Sleep (16)
Local0++
}
Debug = " P0RM = 1"
P0RM = 1
Debug = " P0AP = 3"
P0AP = 3
Debug = " Sleep 10"
Sleep (10)
Debug = " DGPU_RST_N low"
CTXS(DGPU_RST_N)
Debug = " While DGPU_GC6 low"
Local0 = Zero
While (! GRXS(DGPU_GC6)) {
If ((Local0 > 4)) {
Debug = " While DGPU_GC6 low timeout"
Debug = " DGPU_PWR_EN low"
CTXS (DGPU_PWR_EN)
Break
}
Sleep (16)
Local0++
}
Debug = " _STA = 0x5"
_STA = 0x5
}
}
}

View File

@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include "../gpio.h"
#include <drivers/system76/dgpu/acpi/dgpu.asl>
#define EC_GPE_SCI 0x03 /* GPP_K3 */ #define EC_GPE_SCI 0x03 /* GPP_K3 */
#define EC_GPE_SWI 0x06 /* GPP_K6 */ #define EC_GPE_SWI 0x06 /* GPP_K6 */
#define EC_COLOR_KEYBOARD 1 #define EC_COLOR_KEYBOARD 1
@@ -9,8 +12,6 @@ Scope (\_SB) {
#include "sleep.asl" #include "sleep.asl"
Scope (PCI0) { Scope (PCI0) {
#include "backlight.asl" #include "backlight.asl"
#include "pegp.asl"
#include "dgpu.asl"
} }
} }

View File

@@ -1,34 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/40625
/* SPDX-License-Identifier: GPL-2.0-only */
Device (PEGP)
{
Name (_ADR, 0x00010000)
PowerResource (PWRR, 0, 0)
{
Name (_STA, 1)
Method (_ON)
{
Debug = "PEGP.PWRR._ON"
If (_STA != 1) {
\_SB.PCI0.PEGP.DEV0._ON ()
_STA = 1
}
}
Method (_OFF)
{
Debug = "PEGP.PWRR._OFF"
If (_STA != 0) {
\_SB.PCI0.PEGP.DEV0._OFF ()
_STA = 0
}
}
}
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
}

View File

@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h> #include <bootblock_common.h>
#include <console/console.h>
#include <delay.h>
#include <gpio.h> #include <gpio.h>
#include "gpio.h" #include "gpio.h"
#include <drivers/system76/dgpu/bootblock.c>
static void dgpu_power_enable(int onoff) { void bootblock_mainboard_init(void) {
printk(BIOS_DEBUG, "system76: DGPU power %d\n", onoff);
if (onoff) {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 1);
mdelay(4);
gpio_set(DGPU_RST_N, 1);
} else {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 0);
}
mdelay(50);
}
void bootblock_mainboard_init(void)
{
gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table)); gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table));
dgpu_power_enable(1); dgpu_power_enable(1);
} }

View File

@@ -14,16 +14,14 @@ DefinitionBlock(
#include <soc/intel/common/block/acpi/acpi/globalnvs.asl> #include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
#include <cpu/intel/common/acpi/cpu.asl> #include <cpu/intel/common/acpi/cpu.asl>
Device (\_SB.PCI0) Device (\_SB.PCI0) {
{
#include <soc/intel/common/block/acpi/acpi/northbridge.asl> #include <soc/intel/common/block/acpi/acpi/northbridge.asl>
#include <soc/intel/cannonlake/acpi/southbridge.asl> #include <soc/intel/cannonlake/acpi/southbridge.asl>
} }
#include <southbridge/intel/common/acpi/sleepstates.asl> #include <southbridge/intel/common/acpi/sleepstates.asl>
Scope (\_SB.PCI0.LPCB) Scope (\_SB.PCI0.LPCB) {
{
#include <drivers/pc80/pc/ps2_controller.asl> #include <drivers/pc80/pc/ps2_controller.asl>
} }

View File

@@ -3,14 +3,15 @@
#ifndef MAINBOARD_GPIO_H #ifndef MAINBOARD_GPIO_H
#define MAINBOARD_GPIO_H #define MAINBOARD_GPIO_H
#include <soc/gpe.h>
#include <soc/gpio.h>
#define DGPU_RST_N GPP_F22 #define DGPU_RST_N GPP_F22
#define DGPU_PWR_EN GPP_F23 #define DGPU_PWR_EN GPP_F23
#define DGPU_GC6 GPP_K21
#ifndef __ACPI__ #ifndef __ACPI__
#include <soc/gpe.h>
#include <soc/gpio.h>
/* Pad configuration in romstage. */ /* Pad configuration in romstage. */
static const struct pad_config early_gpio_table[] = { static const struct pad_config early_gpio_table[] = {
PAD_CFG_GPI(GPP_C20, NONE, DEEP), PAD_CFG_GPI(GPP_C20, NONE, DEEP),

View File

@@ -1,90 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci.h>
#include <soc/ramstage.h> #include <soc/ramstage.h>
#include "gpio.h" #include "gpio.h"
void mainboard_silicon_init_params(FSP_S_CONFIG *params) void mainboard_silicon_init_params(FSP_S_CONFIG *params) {
{
/* Configure pads prior to SiliconInit() in case there's any /* Configure pads prior to SiliconInit() in case there's any
* dependencies during hardware initialization. */ * dependencies during hardware initialization. */
cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
} }
static void dgpu_read_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_read_resources %s\n", dev_path(dev));
pci_dev_read_resources(dev);
int bar;
// Find all BARs on DGPU, mark them above 4g if prefetchable
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
printk(BIOS_INFO, " BAR at 0x%02x\n", bar);
struct resource *res;
res = probe_resource(dev, bar);
if (res) {
if (res->flags & IORESOURCE_PREFETCH) {
printk(BIOS_INFO, " marked above 4g\n");
res->flags |= IORESOURCE_ABOVE_4G;
} else {
printk(BIOS_INFO, " not prefetch\n");
}
} else {
printk(BIOS_INFO, " not found\n");
}
}
}
static void dgpu_enable_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_enable_resources %s\n", dev_path(dev));
dev->subsystem_vendor = CONFIG_SUBSYSTEM_VENDOR_ID;
dev->subsystem_device = CONFIG_SUBSYSTEM_DEVICE_ID;
printk(BIOS_INFO, " subsystem <- %04x/%04x\n", dev->subsystem_vendor, dev->subsystem_device);
pci_write_config32(dev, 0x40, ((dev->subsystem_device & 0xffff) << 16) | (dev->subsystem_vendor & 0xffff));
pci_dev_enable_resources(dev);
}
static struct device_operations dgpu_pci_ops_dev = {
.read_resources = dgpu_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = dgpu_enable_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = pci_rom_write_acpi_tables,
.acpi_fill_ssdt = pci_rom_ssdt,
#endif
.init = pci_dev_init,
.ops_pci = &pci_dev_ops_pci,
};
static void dgpu_above_4g(void *unused) {
struct device *pdev;
// Find PEG0
pdev = pcidev_on_root(1, 0);
if (!pdev) {
printk(BIOS_ERR, "system76: failed to find PEG0\n");
return;
}
printk(BIOS_INFO, "system76: PEG0 at %p, %04x:%04x\n", pdev, pdev->vendor, pdev->device);
int fn;
for (fn = 0; fn < 8; fn++) {
struct device *dev;
// Find DGPU functions
dev = pcidev_path_behind(pdev->link_list, PCI_DEVFN(0, fn));
if (dev) {
printk(BIOS_INFO, "system76: DGPU fn %d at %p, %04x:%04x\n", fn, dev, dev->vendor, dev->device);
dev->ops = &dgpu_pci_ops_dev;
} else {
printk(BIOS_ERR, "system76: failed to find DGPU fn %d\n", fn);
}
}
}
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, dgpu_above_4g, NULL);

View File

@@ -78,8 +78,7 @@ static const struct cnl_mb_cfg memcfg = {
.ect = 0, .ect = 0,
}; };
void mainboard_memory_init_params(FSPM_UPD *memupd) void mainboard_memory_init_params(FSPM_UPD *memupd) {
{
// Set primary display to internal graphics // Set primary display to internal graphics
memupd->FspmConfig.PrimaryDisplay = 0; memupd->FspmConfig.PrimaryDisplay = 0;
cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg); cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg);

View File

@@ -5,6 +5,7 @@ config BOARD_SPECIFIC_OPTIONS
select BOARD_ROMSIZE_KB_16384 select BOARD_ROMSIZE_KB_16384
select DRIVERS_I2C_HID select DRIVERS_I2C_HID
select DRIVERS_I2C_TAS5825M select DRIVERS_I2C_TAS5825M
select DRIVERS_SYSTEM76_DGPU
select EC_SYSTEM76_EC select EC_SYSTEM76_EC
select HAVE_ACPI_RESUME select HAVE_ACPI_RESUME
select HAVE_ACPI_TABLES select HAVE_ACPI_TABLES

View File

@@ -2,10 +2,8 @@
#include <drivers/intel/gma/acpi/gma.asl> #include <drivers/intel/gma/acpi/gma.asl>
Scope (GFX0) Scope (GFX0) {
{ Name (BRIG, Package (22) {
Name (BRIG, Package (22)
{
40, /* default AC */ 40, /* default AC */
40, /* default Battery */ 40, /* default Battery */
5, 5,

View File

@@ -1,203 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/28380
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2017-2018 Patrick Rudolph <siro@das-labor.org>
*
* 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.
*
* Nvidia Optimus support methods.
*
* Methods defined here are known to work on Lenovo's Sandy Bridge
* and Ivy Bridge series, which have GPIO21 pulled low on installed dGPU and
* GPIO17 to detect dGPU "PowerGood". They use the same PMH7 functions to
* enable dGPU power and handle dGPU reset.
*/
#define DGPU_RST_N GPP_F22
#define DGPU_PWR_EN GPP_F23
#define DGPU_GC6 GPP_K21
Device (\_SB.PCI0.PEGP.DEV0)
{
Name(_ADR, 0x00000000)
Name (_STA, 0xF)
Name (LTRE, 0)
// Memory mapped PCI express registers
// Not sure what this stuff is, but it is used to get into GC6
OperationRegion (RPCX, SystemMemory, 0xE0008000, 0x1000)
Field (RPCX, ByteAcc, NoLock, Preserve)
{
PVID, 16,
PDID, 16,
CMDR, 8,
Offset (0x19),
PRBN, 8,
Offset (0x84),
D0ST, 2,
Offset (0xAA),
CEDR, 1,
Offset (0xAC),
, 4,
CMLW, 6,
Offset (0xB0),
ASPM, 2,
, 2,
P0LD, 1,
RTLK, 1,
Offset (0xC9),
, 2,
LREN, 1,
Offset (0x11A),
, 1,
VCNP, 1,
Offset (0x214),
Offset (0x216),
P0LS, 4,
Offset (0x248),
, 7,
Q0L2, 1,
Q0L0, 1,
Offset (0x504),
Offset (0x506),
PCFG, 2,
Offset (0x508),
TREN, 1,
Offset (0xC20),
, 4,
P0AP, 2,
Offset (0xC38),
, 3,
P0RM, 1,
Offset (0xC74),
P0LT, 4,
Offset (0xD0C),
, 20,
LREV, 1
}
Method (_ON)
{
Debug = "PEGP.DEV0._ON"
If (_STA != 0xF) {
Debug = " If DGPU_PWR_EN low"
If (! GTXS (DGPU_PWR_EN)) {
Debug = " DGPU_PWR_EN high"
STXS (DGPU_PWR_EN)
Debug = " Sleep 16"
Sleep (16)
}
Debug = " DGPU_RST_N high"
STXS(DGPU_RST_N)
Debug = " Sleep 10"
Sleep (10)
Debug = " Q0L0 = 1"
Q0L0 = 1
Debug = " Sleep 16"
Sleep (16)
Debug = " While Q0L0"
Local0 = 0
While (Q0L0) {
If ((Local0 > 4)) {
Debug = " While Q0L0 timeout"
Break
}
Sleep (16)
Local0++
}
Debug = " P0RM = 0"
P0RM = 0
Debug = " P0AP = 0"
P0AP = 0
Debug = Concatenate(" LREN = ", ToHexString(LTRE))
LREN = LTRE
Debug = " CEDR = 1"
CEDR = 1
Debug = " CMDR |= 7"
CMDR |= 7
Debug = " _STA = 0xF"
_STA = 0xF
}
}
Method (_OFF)
{
Debug = "PEGP.DEV0._OFF"
If (_STA != 0x5) {
Debug = Concatenate(" LTRE = ", ToHexString(LREN))
LTRE = LREN
Debug = " Q0L2 = 1"
Q0L2 = 1
Debug = " Sleep 16"
Sleep (16)
Debug = " While Q0L2"
Local0 = Zero
While (Q0L2) {
If ((Local0 > 4)) {
Debug = " While Q0L2 timeout"
Break
}
Sleep (16)
Local0++
}
Debug = " P0RM = 1"
P0RM = 1
Debug = " P0AP = 3"
P0AP = 3
Debug = " Sleep 10"
Sleep (10)
Debug = " DGPU_RST_N low"
CTXS(DGPU_RST_N)
Debug = " While DGPU_GC6 low"
Local0 = Zero
While (! GRXS(DGPU_GC6)) {
If ((Local0 > 4)) {
Debug = " While DGPU_GC6 low timeout"
Debug = " DGPU_PWR_EN low"
CTXS (DGPU_PWR_EN)
Break
}
Sleep (16)
Local0++
}
Debug = " _STA = 0x5"
_STA = 0x5
}
}
}

View File

@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include "../gpio.h"
#include <drivers/system76/dgpu/acpi/dgpu.asl>
#define EC_GPE_SCI 0x03 /* GPP_K3 */ #define EC_GPE_SCI 0x03 /* GPP_K3 */
#define EC_GPE_SWI 0x06 /* GPP_K6 */ #define EC_GPE_SWI 0x06 /* GPP_K6 */
#define EC_COLOR_KEYBOARD 1 #define EC_COLOR_KEYBOARD 1
@@ -9,8 +12,6 @@ Scope (\_SB) {
#include "sleep.asl" #include "sleep.asl"
Scope (PCI0) { Scope (PCI0) {
#include "backlight.asl" #include "backlight.asl"
#include "pegp.asl"
#include "dgpu.asl"
} }
} }

View File

@@ -1,34 +0,0 @@
// From https://review.coreboot.org/c/coreboot/+/40625
/* SPDX-License-Identifier: GPL-2.0-only */
Device (PEGP)
{
Name (_ADR, 0x00010000)
PowerResource (PWRR, 0, 0)
{
Name (_STA, 1)
Method (_ON)
{
Debug = "PEGP.PWRR._ON"
If (_STA != 1) {
\_SB.PCI0.PEGP.DEV0._ON ()
_STA = 1
}
}
Method (_OFF)
{
Debug = "PEGP.PWRR._OFF"
If (_STA != 0) {
\_SB.PCI0.PEGP.DEV0._OFF ()
_STA = 0
}
}
}
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
}

View File

@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h> #include <bootblock_common.h>
#include <console/console.h>
#include <delay.h>
#include <gpio.h> #include <gpio.h>
#include "gpio.h" #include "gpio.h"
#include <drivers/system76/dgpu/bootblock.c>
static void dgpu_power_enable(int onoff) { void bootblock_mainboard_init(void) {
printk(BIOS_DEBUG, "system76: DGPU power %d\n", onoff);
if (onoff) {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 1);
mdelay(4);
gpio_set(DGPU_RST_N, 1);
} else {
gpio_set(DGPU_RST_N, 0);
mdelay(4);
gpio_set(DGPU_PWR_EN, 0);
}
mdelay(50);
}
void bootblock_mainboard_init(void)
{
gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table)); gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table));
dgpu_power_enable(1); dgpu_power_enable(1);
} }

View File

@@ -14,16 +14,14 @@ DefinitionBlock(
#include <soc/intel/common/block/acpi/acpi/globalnvs.asl> #include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
#include <cpu/intel/common/acpi/cpu.asl> #include <cpu/intel/common/acpi/cpu.asl>
Device (\_SB.PCI0) Device (\_SB.PCI0) {
{
#include <soc/intel/common/block/acpi/acpi/northbridge.asl> #include <soc/intel/common/block/acpi/acpi/northbridge.asl>
#include <soc/intel/cannonlake/acpi/southbridge.asl> #include <soc/intel/cannonlake/acpi/southbridge.asl>
} }
#include <southbridge/intel/common/acpi/sleepstates.asl> #include <southbridge/intel/common/acpi/sleepstates.asl>
Scope (\_SB.PCI0.LPCB) Scope (\_SB.PCI0.LPCB) {
{
#include <drivers/pc80/pc/ps2_controller.asl> #include <drivers/pc80/pc/ps2_controller.asl>
} }

View File

@@ -3,14 +3,15 @@
#ifndef MAINBOARD_GPIO_H #ifndef MAINBOARD_GPIO_H
#define MAINBOARD_GPIO_H #define MAINBOARD_GPIO_H
#include <soc/gpe.h>
#include <soc/gpio.h>
#define DGPU_RST_N GPP_F22 #define DGPU_RST_N GPP_F22
#define DGPU_PWR_EN GPP_F23 #define DGPU_PWR_EN GPP_F23
#define DGPU_GC6 GPP_K21
#ifndef __ACPI__ #ifndef __ACPI__
#include <soc/gpe.h>
#include <soc/gpio.h>
/* Pad configuration in romstage. */ /* Pad configuration in romstage. */
static const struct pad_config early_gpio_table[] = { static const struct pad_config early_gpio_table[] = {
PAD_CFG_TERM_GPO(GPP_C14, 1, NONE, RSMRST), // M.2_PLT_RST_CNTRL1# PAD_CFG_TERM_GPO(GPP_C14, 1, NONE, RSMRST), // M.2_PLT_RST_CNTRL1#

View File

@@ -1,90 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci.h>
#include <soc/ramstage.h> #include <soc/ramstage.h>
#include "gpio.h" #include "gpio.h"
void mainboard_silicon_init_params(FSP_S_CONFIG *params) void mainboard_silicon_init_params(FSP_S_CONFIG *params) {
{
/* Configure pads prior to SiliconInit() in case there's any /* Configure pads prior to SiliconInit() in case there's any
* dependencies during hardware initialization. */ * dependencies during hardware initialization. */
cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); cnl_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
} }
static void dgpu_read_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_read_resources %s\n", dev_path(dev));
pci_dev_read_resources(dev);
int bar;
// Find all BARs on DGPU, mark them above 4g if prefetchable
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
printk(BIOS_INFO, " BAR at 0x%02x\n", bar);
struct resource *res;
res = probe_resource(dev, bar);
if (res) {
if (res->flags & IORESOURCE_PREFETCH) {
printk(BIOS_INFO, " marked above 4g\n");
res->flags |= IORESOURCE_ABOVE_4G;
} else {
printk(BIOS_INFO, " not prefetch\n");
}
} else {
printk(BIOS_INFO, " not found\n");
}
}
}
static void dgpu_enable_resources(struct device *dev) {
printk(BIOS_INFO, "system76: dgpu_enable_resources %s\n", dev_path(dev));
dev->subsystem_vendor = CONFIG_SUBSYSTEM_VENDOR_ID;
dev->subsystem_device = CONFIG_SUBSYSTEM_DEVICE_ID;
printk(BIOS_INFO, " subsystem <- %04x/%04x\n", dev->subsystem_vendor, dev->subsystem_device);
pci_write_config32(dev, 0x40, ((dev->subsystem_device & 0xffff) << 16) | (dev->subsystem_vendor & 0xffff));
pci_dev_enable_resources(dev);
}
static struct device_operations dgpu_pci_ops_dev = {
.read_resources = dgpu_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = dgpu_enable_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = pci_rom_write_acpi_tables,
.acpi_fill_ssdt = pci_rom_ssdt,
#endif
.init = pci_dev_init,
.ops_pci = &pci_dev_ops_pci,
};
static void dgpu_above_4g(void *unused) {
struct device *pdev;
// Find PEG0
pdev = pcidev_on_root(1, 0);
if (!pdev) {
printk(BIOS_ERR, "system76: failed to find PEG0\n");
return;
}
printk(BIOS_INFO, "system76: PEG0 at %p, %04x:%04x\n", pdev, pdev->vendor, pdev->device);
int fn;
for (fn = 0; fn < 8; fn++) {
struct device *dev;
// Find DGPU functions
dev = pcidev_path_behind(pdev->link_list, PCI_DEVFN(0, fn));
if (dev) {
printk(BIOS_INFO, "system76: DGPU fn %d at %p, %04x:%04x\n", fn, dev, dev->vendor, dev->device);
dev->ops = &dgpu_pci_ops_dev;
} else {
printk(BIOS_ERR, "system76: failed to find DGPU fn %d\n", fn);
}
}
}
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, dgpu_above_4g, NULL);

View File

@@ -78,8 +78,7 @@ static const struct cnl_mb_cfg memcfg = {
.ect = 0, .ect = 0,
}; };
void mainboard_memory_init_params(FSPM_UPD *memupd) void mainboard_memory_init_params(FSPM_UPD *memupd) {
{
// Allow memory clocks higher than 2933 MHz // Allow memory clocks higher than 2933 MHz
memupd->FspmConfig.SaOcSupport = 1; memupd->FspmConfig.SaOcSupport = 1;
// Set primary display to internal graphics // Set primary display to internal graphics