| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
|
|
||
| #include <acpi/acpigen.h> | ||
| #include <string.h> | ||
| #include "i915.h" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
|
|
||
| #include <device/device.h> | ||
|
|
||
| #ifndef _IPMI_CHIP_H_ | ||
| #define _IPMI_CHIP_H_ | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,3 @@ | ||
| ifeq ($(CONFIG_MEMORY_MAPPED_TPM),y) | ||
| all-y += tis.c | ||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,17 +12,3 @@ config DRIVER_TPM_SPI_CHIP | |
| int "Chip Select of the TPM chip on its SPI bus" | ||
| default 0 | ||
| depends on SPI_TPM | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,3 @@ | ||
| ifeq ($(CONFIG_TPM)$(CONFIG_SPI_TPM),yy) | ||
| all-y += tis.c tpm.c | ||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| config DRIVERS_USB_HUB | ||
| bool | ||
| default n | ||
| depends on HAVE_ACPI_TABLES | ||
| help | ||
| This driver is for soldered down USB Hub in the mainboard. When enabled, | ||
| this driver will add ACPI support for the USB hub and any devices on the | ||
| downstream facing ports. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_DRIVERS_USB_HUB) += acpi.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
|
|
||
| #include <acpi/acpigen.h> | ||
| #include <acpi/acpi_device.h> | ||
| #include <stdlib.h> | ||
|
|
||
| #include "chip.h" | ||
|
|
||
| static const char *usb_hub_acpi_name(const struct device *dev) | ||
| { | ||
| char *name; | ||
| const char *pattern; | ||
|
|
||
| /* USB ACPI driver does not have acpi_name operation defined. Hence return | ||
| the ACPI name for both the hub and any downstream facing ports. */ | ||
| switch (dev->path.usb.port_type) { | ||
| case 0: | ||
| return "EHUB"; | ||
| case 2: | ||
| pattern = "HS%02d"; | ||
| break; | ||
| case 3: | ||
| pattern = "SS%02d"; | ||
| break; | ||
| default: | ||
| return NULL; | ||
| } | ||
|
|
||
| name = malloc(ACPI_NAME_BUFFER_SIZE); | ||
| snprintf(name, ACPI_NAME_BUFFER_SIZE, pattern, dev->path.usb.port_id + 1); | ||
| name[4] = '\0'; | ||
|
|
||
| return name; | ||
| } | ||
|
|
||
| static void usb_hub_add_ports(const struct device *dev) | ||
| { | ||
| const struct drivers_usb_hub_config *config = config_of(dev); | ||
| struct device *port = NULL; | ||
| unsigned int child_count = 0; | ||
|
|
||
| while ((port = dev_bus_each_child(dev->link_list, port)) != NULL) { | ||
| if (child_count++ >= config->port_count) { | ||
| printk(BIOS_WARNING, "%s cannot be added. Port Count limit reached.\n", | ||
| dev_name(port)); | ||
| continue; | ||
| } | ||
| acpigen_write_device(usb_hub_acpi_name(port)); | ||
| acpigen_write_name_byte("_ADR", port->path.usb.port_id + 1); | ||
| acpigen_write_device_end(); | ||
| } | ||
| } | ||
|
|
||
| static void usb_hub_acpi_fill_ssdt(const struct device *dev) | ||
| { | ||
| const struct drivers_usb_hub_config *config = config_of(dev); | ||
| const char *scope = acpi_device_scope(dev); | ||
| const char *name = acpi_device_name(dev); | ||
|
|
||
| acpigen_write_scope(scope); | ||
| acpigen_write_device(name); | ||
| acpigen_write_ADR(0); | ||
| if (config->name) | ||
| acpigen_write_name_string("_DDN", config->name); | ||
| if (config->desc) | ||
| acpigen_write_name_unicode("_STR", config->desc); | ||
| usb_hub_add_ports(dev); | ||
| acpigen_write_device_end(); | ||
| acpigen_write_scope_end(); | ||
| } | ||
|
|
||
| static struct device_operations usb_hub_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .scan_bus = scan_static_bus, | ||
| .acpi_fill_ssdt = usb_hub_acpi_fill_ssdt, | ||
| .acpi_name = usb_hub_acpi_name | ||
| }; | ||
|
|
||
| static void usb_hub_acpi_enable(struct device *dev) | ||
| { | ||
| dev->ops = &usb_hub_ops; | ||
| } | ||
|
|
||
| struct chip_operations drivers_usb_hub_ops = { | ||
| CHIP_NAME("USB Hub") | ||
| .enable_dev = usb_hub_acpi_enable | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __DRIVERS_USB_HUB_CHIP_H__ | ||
| #define __DRIVERS_USB_HUB_CHIP_H__ | ||
|
|
||
| struct drivers_usb_hub_config { | ||
| const char *name; | ||
| const char *desc; | ||
| unsigned int port_count; /* Number of Super-speed or High-speed ports */ | ||
| }; | ||
|
|
||
| #endif /* __DRIVERS_USB_HUB_CHIP_H__ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| if EC_GOOGLE_CHROMEEC | ||
|
|
||
| config EC_GOOGLE_CHROMEEC_MUX | ||
| bool | ||
| depends on HAVE_ACPI_TABLES | ||
| help | ||
| This enables the Cros EC Mux driver that is required to fill the | ||
| SSDT nodes for the EC Mux platform device which is used to | ||
| configure Type C muxes and retimers. | ||
|
|
||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| subdirs-y += conn | ||
| ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC_MUX) += mux.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC_MUX) += conn.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
|
|
||
| #include <acpi/acpigen.h> | ||
|
|
||
| static const char *conn_acpi_name(const struct device *dev) | ||
| { | ||
| static char name[5]; | ||
| snprintf(name, sizeof(name), "CON%1X", dev->path.generic.id); | ||
| return name; | ||
| } | ||
|
|
||
| static void conn_fill_ssdt(const struct device *dev) | ||
| { | ||
| const char *name; | ||
| name = acpi_device_name(dev); | ||
| if (!name) | ||
| return; | ||
|
|
||
| acpigen_write_scope(acpi_device_scope(dev)); | ||
| acpigen_write_device(name); | ||
|
|
||
| acpigen_write_name_integer("_ADR", dev->path.generic.id); | ||
|
|
||
| acpigen_write_device_end(); | ||
| acpigen_write_scope_end(); | ||
| } | ||
|
|
||
| static struct device_operations conn_dev_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .acpi_name = conn_acpi_name, | ||
| .acpi_fill_ssdt = conn_fill_ssdt, | ||
| }; | ||
|
|
||
| static void conn_enable(struct device *dev) | ||
| { | ||
| dev->ops = &conn_dev_ops; | ||
| } | ||
|
|
||
| struct chip_operations ec_google_chromeec_mux_conn_ops = { | ||
| CHIP_NAME("CrosEC Type C Mux device") | ||
| .enable_dev = conn_enable, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
|
|
||
| #include <acpi/acpigen.h> | ||
|
|
||
| #define GOOGLE_CHROMEEC_MUX_DEVICE_HID "GOOG001A" | ||
| #define GOOGLE_CHROMEEC_MUX_DEVICE_NAME "ECMX" | ||
|
|
||
| static void mux_fill_ssdt(const struct device *dev) | ||
| { | ||
| acpigen_write_scope(acpi_device_scope(dev)); | ||
| acpigen_write_device(GOOGLE_CHROMEEC_MUX_DEVICE_NAME); | ||
| acpigen_write_name_string("_HID", GOOGLE_CHROMEEC_MUX_DEVICE_HID); | ||
| acpigen_write_name_string("_DDN", "ChromeOS EC Embedded Controller " | ||
| "Mux & Retimer control"); | ||
|
|
||
| acpigen_write_device_end(); | ||
| acpigen_write_scope_end(); | ||
| } | ||
|
|
||
| static const char *mux_acpi_name(const struct device *dev) | ||
| { | ||
| return GOOGLE_CHROMEEC_MUX_DEVICE_NAME; | ||
| } | ||
|
|
||
| static struct device_operations mux_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .acpi_name = mux_acpi_name, | ||
| .acpi_fill_ssdt = mux_fill_ssdt, | ||
| .scan_bus = scan_static_bus, | ||
| }; | ||
|
|
||
| static void mux_enable(struct device *dev) | ||
| { | ||
| dev->ops = &mux_ops; | ||
| } | ||
|
|
||
| struct chip_operations ec_google_chromeec_mux_ops = { | ||
| CHIP_NAME("CrosEC Type C Mux device") | ||
| .enable_dev = mux_enable | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -304,7 +304,7 @@ Device (HKEY) | |
| } | ||
| } | ||
|
|
||
| #if CONFIG(H8_HAS_BAT_THRESHOLDS_IMPL) | ||
| #include "thinkpad_bat_thresholds.asl" | ||
| #endif | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,6 @@ | |
|
|
||
| struct global_nvs; | ||
|
|
||
| size_t size_of_dnvs(void); | ||
|
|
||
| #if CONFIG(ACPI_SOC_NVS) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <endian.h> | ||
| #include <fmap_config.h> | ||
| #include <commonlib/bsd/cbfs_serialized.h> | ||
|
|
||
| struct cbfs_header header = { | ||
| .magic = cpu_to_be32(CBFS_HEADER_MAGIC), | ||
| .version = cpu_to_be32(CBFS_HEADER_VERSION), | ||
| /* | ||
| * The offset and romsize fields within the master header are absolute | ||
| * values within the boot media. As such, romsize needs to reflect | ||
| * the end 'offset' for a CBFS. To achieve that the current buffer | ||
| * representing the CBFS region's size is added to the offset of | ||
| * the region within a larger image. | ||
| */ | ||
| .romsize = cpu_to_be32(FMAP_SECTION_COREBOOT_START + FMAP_SECTION_COREBOOT_SIZE | ||
| - FMAP_SECTION_FLASH_START), | ||
| /* | ||
| * The 4 bytes are left out for two reasons: | ||
| * 1. the cbfs master header pointer resides there | ||
| * 2. some cbfs implementations assume that an image that resides | ||
| * below 4GB has a bootblock and get confused when the end of the | ||
| * image is at 4GB == 0. | ||
| */ | ||
| .bootblocksize = cpu_to_be32(4), | ||
| .align = cpu_to_be32(CBFS_ALIGNMENT), | ||
| .offset = cpu_to_be32(FMAP_SECTION_COREBOOT_START - FMAP_SECTION_FLASH_START), | ||
| .architecture = cpu_to_be32(CBFS_ARCHITECTURE_UNKNOWN), | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <commonlib/bsd/cbfs_serialized.h> | ||
| #include <endian.h> | ||
| #include <fmap_config.h> | ||
| #include <stdint.h> | ||
|
|
||
| #if CONFIG(BOOTBLOCK_IN_CBFS) | ||
| __attribute__((used, __section__(".header_pointer"))) | ||
| #endif | ||
|
|
||
| #if FMAP_SECTION_COREBOOT_START < (0xffffffff - CONFIG_ROM_SIZE + 1) | ||
| #define COREBOOT_CBFS_START (0xffffffff - CONFIG_ROM_SIZE + 1 + FMAP_SECTION_COREBOOT_START) | ||
| #else | ||
| #define COREBOOT_CBFS_START FMAP_SECTION_COREBOOT_START | ||
| #endif | ||
|
|
||
| uint32_t header_pointer = | ||
| cpu_to_le32(COREBOOT_CBFS_START + ALIGN_UP(sizeof(struct cbfs_file) | ||
| + sizeof("cbfs_master_header"), | ||
| CBFS_ATTRIBUTE_ALIGN)); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,18 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <bootblock_common.h> | ||
| #include <soc/espi.h> | ||
| #include "ec.h" | ||
| #include "gpio.h" | ||
|
|
||
| void bootblock_mainboard_early_init(void) | ||
| { | ||
| mainboard_program_early_gpios(); | ||
|
|
||
| espi_switch_to_spi1_pads(); | ||
| } | ||
|
|
||
| void bootblock_mainboard_init(void) | ||
| { | ||
| chausie_ec_init(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <ec/acpi/ec.h> | ||
| #include "ec.h" | ||
|
|
||
| #define CHAUSIE_EC_CMD 0x666 | ||
| #define CHAUSIE_EC_DATA 0x662 | ||
|
|
||
| #define EC_GPIO_3_ADDR 0xA3 | ||
| #define EC_GPIO_LOM_RESET_AUX (1 << 1) | ||
|
|
||
| #define EC_GPIO_7_ADDR 0xA7 | ||
| #define EC_GPIO_DT_PWREN (1 << 2) | ||
| #define EC_GPIO_WWAN_MODULE_RST (1 << 5) | ||
|
|
||
| #define EC_GPIO_8_ADDR 0xA8 | ||
| #define EC_GPIO_SMBUS0_EN (1 << 0) | ||
|
|
||
| #define EC_GPIO_A_ADDR 0xAA | ||
| #define EC_GPIO_WWAN_PWREN (1 << 3) | ||
| #define EC_GPIO_M2_SSD0_PWREN (1 << 6) | ||
| #define EC_GPIO_LOM_PWREN (1 << 7) | ||
|
|
||
| #define EC_GPIO_C_ADDR 0xAC | ||
| #define EC_GPIO_DT_N_WLAN_SW (1 << 1) | ||
| #define EC_GPIO_MP2_SEL (1 << 2) | ||
| #define EC_GPIO_WWAN_N_LOM_SW (1 << 3) | ||
|
|
||
| static void configure_ec_gpio(void) | ||
| { | ||
| uint8_t tmp; | ||
|
|
||
| tmp = ec_read(EC_GPIO_3_ADDR); | ||
| tmp |= EC_GPIO_LOM_RESET_AUX; | ||
| ec_write(EC_GPIO_3_ADDR, tmp); | ||
|
|
||
| tmp = ec_read(EC_GPIO_7_ADDR); | ||
| tmp |= EC_GPIO_WWAN_MODULE_RST | EC_GPIO_DT_PWREN; | ||
| ec_write(EC_GPIO_7_ADDR, tmp); | ||
|
|
||
| tmp = ec_read(EC_GPIO_8_ADDR); | ||
| tmp |= EC_GPIO_SMBUS0_EN; | ||
| ec_write(EC_GPIO_8_ADDR, tmp); | ||
|
|
||
| tmp = ec_read(EC_GPIO_A_ADDR); | ||
| tmp |= EC_GPIO_M2_SSD0_PWREN | EC_GPIO_LOM_PWREN | EC_GPIO_WWAN_PWREN; | ||
| ec_write(EC_GPIO_A_ADDR, tmp); | ||
|
|
||
| tmp = ec_read(EC_GPIO_C_ADDR); | ||
| tmp |= EC_GPIO_WWAN_N_LOM_SW | EC_GPIO_MP2_SEL | EC_GPIO_DT_N_WLAN_SW; | ||
| ec_write(EC_GPIO_C_ADDR, tmp); | ||
| } | ||
|
|
||
| void chausie_ec_init(void) | ||
| { | ||
| ec_set_ports(CHAUSIE_EC_CMD, CHAUSIE_EC_DATA); | ||
| configure_ec_gpio(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef CHAUSIE_EC_H | ||
| #define CHAUSIE_EC_H | ||
|
|
||
| void chausie_ec_init(void); | ||
|
|
||
| #endif /* CHAUSIE_EC_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,9 +2,6 @@ | |
|
|
||
| if BOARD_ODE_E20XX | ||
|
|
||
| config BOARD_SPECIFIC_OPTIONS | ||
| def_bool y | ||
| select CPU_AMD_AGESA_FAMILY16_KB | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,3 +6,4 @@ romstage-y += gpio.c | |
| romstage-y += memory.c | ||
|
|
||
| ramstage-y += gpio.c | ||
| ramstage-y += variant.c | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <acpi/acpi.h> | ||
| #include <acpi/acpigen.h> | ||
| #include <baseboard/variants.h> | ||
| #include <delay.h> | ||
| #include <gpio.h> | ||
| #include <timer.h> | ||
| #include <types.h> | ||
|
|
||
| #define GPU_1V8_PWR_EN GPP_E18 | ||
| #define GPU_1V8_PG GPP_E20 | ||
| #define NV33_PWR_EN GPP_A21 | ||
| #define NV33_PG GPP_A22 | ||
| #define NVVDD_PWR_EN GPP_E0 | ||
| #define NVVDD_PG GPP_E16 | ||
| #define PEXVDD_PWR_EN GPP_E10 | ||
| #define PEXVDD_PG GPP_E17 | ||
| #define FBVDD_PWR_EN GPP_A17 | ||
| #define FBVDD_PG GPP_E4 | ||
| #define GPU_PERST_L GPP_B3 | ||
| #define GPU_ALLRAILS_PG GPP_E5 | ||
|
|
||
| #define DEFAULT_PG_TIMEOUT_US 20000 | ||
|
|
||
| #define VGAR_BYTE_OFFSET 5 | ||
|
|
||
| /* Maximum size of PCI config space to save. */ | ||
| #define GPU_CONFIG_SAVE_SPACE_BYTES 0x100 | ||
|
|
||
| static bool gpu_powered_on; | ||
|
|
||
| struct power_rail_sequence { | ||
| const char *name; | ||
|
|
||
| /* This is the GPIO (output) connected to the VR's enable pin. */ | ||
| gpio_t pwr_en_gpio; | ||
| bool pwr_en_active_low; | ||
|
|
||
| /* This is the GPIO (input) connected to the VR's power-good pin. */ | ||
| gpio_t pg_gpio; | ||
| }; | ||
|
|
||
| /* In GCOFF exit order (i.e., power-on order) */ | ||
| static const struct power_rail_sequence gpu_rails[] = { | ||
| { "GPU 1.8V", GPU_1V8_PWR_EN, false, GPU_1V8_PG, }, | ||
| { "NV3_3", NV33_PWR_EN, false, NV33_PG, }, | ||
| { "NVVDD+MSVDD", NVVDD_PWR_EN, true, NVVDD_PG, }, | ||
| { "PEXVDD", PEXVDD_PWR_EN, false, PEXVDD_PG, }, | ||
| { "FBVDD", FBVDD_PWR_EN, false, FBVDD_PG, }, | ||
| }; | ||
|
|
||
| enum rail_state { | ||
| RAIL_OFF = 0, | ||
| RAIL_ON = 1, | ||
| }; | ||
|
|
||
| /* Assert the VR's enable pin, and wait until the VR's power-good is asserted. */ | ||
| static bool sequence_rail(const struct power_rail_sequence *seq, enum rail_state state) | ||
| { | ||
| if (seq->pwr_en_active_low) | ||
| state = !state; | ||
|
|
||
| gpio_output(seq->pwr_en_gpio, state); | ||
| return wait_us(DEFAULT_PG_TIMEOUT_US, gpio_get(seq->pg_gpio) == state) > 0; | ||
| } | ||
|
|
||
| static void dgpu_power_sequence_off(void) | ||
| { | ||
| /* Assert reset and clear power-good */ | ||
| gpio_output(GPU_PERST_L, 0); | ||
| mdelay(5); | ||
|
|
||
| /* Inform the GPU that the power is no longer good. */ | ||
| gpio_output(GPU_ALLRAILS_PG, 0); | ||
|
|
||
| for (int i = (int)ARRAY_SIZE(gpu_rails) - 1; i >= 0; i--) { | ||
| if (!sequence_rail(&gpu_rails[i], RAIL_OFF)) { | ||
| printk(BIOS_ERR, "Failed to disable %s rail, continuing!\n", | ||
| gpu_rails[i].name); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static void dgpu_power_sequence_on(void) | ||
| { | ||
| /* Assert PERST# */ | ||
| gpio_output(GPU_PERST_L, 0); | ||
|
|
||
| for (size_t i = 0; i < ARRAY_SIZE(gpu_rails); i++) { | ||
| if (!sequence_rail(&gpu_rails[i], RAIL_ON)) { | ||
| printk(BIOS_ERR, "Failed to enable %s rail, sequencing back down!\n", | ||
| gpu_rails[i].name); | ||
|
|
||
| /* If an error occurred, then perform the power-off sequence and | ||
| return early to avoid setting GPU_ALLRAILS_PG and PERST_L. */ | ||
| dgpu_power_sequence_off(); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| /* Set power-good and release PERST# */ | ||
| gpio_output(GPU_ALLRAILS_PG, 1); | ||
| mdelay(1); | ||
| gpio_output(GPU_PERST_L, 1); | ||
|
|
||
| printk(BIOS_INFO, "Sequenced GPU successfully\n"); | ||
| gpu_powered_on = true; | ||
| } | ||
|
|
||
| void variant_init(void) | ||
| { | ||
| if (acpi_is_wakeup_s3()) | ||
| return; | ||
|
|
||
| dgpu_power_sequence_on(); | ||
| } | ||
|
|
||
| void variant_finalize(void) | ||
| { | ||
| if (acpi_is_wakeup_s3() || !gpu_powered_on) | ||
| return; | ||
|
|
||
| /* | ||
| * Because the dGPU is used here in a way similar to "hybrid graphics" | ||
| * modes, it is powered down here. The DRIVERS_GFX_NVIDIA_SAVE_BARS | ||
| * option is selected for agah, so the BARs will be saved to ACPI memory | ||
| * during its finalize routine. Thus, it is powered down here, as the | ||
| * proper resources have already been allocated. | ||
| */ | ||
| dgpu_power_sequence_off(); | ||
|
|
||
| printk(BIOS_INFO, "GPU power sequenced off.\n"); | ||
| } | ||
|
|
||
| /* Save PCI BARs to the ACPI copy of the "saved PCI config space" */ | ||
| void variant_fill_ssdt(const struct device *unused) | ||
| { | ||
| if (!gpu_powered_on) | ||
| return; | ||
|
|
||
| const struct device *dgpu = DEV_PTR(dgpu); | ||
| acpigen_write_scope("\\_SB.PCI0.PEG0.PEGP"); | ||
| acpigen_write_method("_INI", 0); | ||
| { | ||
| /* Local0 = VGAR */ | ||
| acpigen_write_store(); | ||
| acpigen_emit_namestring("VGAR"); | ||
| acpigen_emit_byte(LOCAL0_OP); | ||
|
|
||
| /* | ||
| * CreateDWordField(Local0, 11, BAR0) | ||
| * BAR0 = bases[0] | ||
| * CreateDWordField(Local0, 15, BAR1) | ||
| * BAR1 = bases[1] | ||
| * ... | ||
| */ | ||
| for (unsigned int idx = PCI_BASE_ADDRESS_0, i = 0; idx <= PCI_BASE_ADDRESS_5; | ||
| idx += sizeof(uint32_t), ++i) { | ||
| char name[ACPI_NAME_BUFFER_SIZE]; | ||
| const struct resource *res; | ||
|
|
||
| res = probe_resource(dgpu, idx); | ||
| if (!res) | ||
| continue; | ||
|
|
||
| snprintf(name, sizeof(name), "BAR%1d", i); | ||
| acpigen_write_create_dword_field(LOCAL0_OP, idx - VGAR_BYTE_OFFSET, | ||
| name); | ||
| acpigen_write_store_int_to_namestr(res->base & 0xffffffff, name); | ||
| } | ||
|
|
||
| /* VGAR = Local0 */ | ||
| acpigen_write_store_op_to_namestr(LOCAL0_OP, "VGAR"); | ||
| } | ||
|
|
||
| acpigen_write_method_end(); | ||
| acpigen_write_scope_end(); | ||
| } |