From 289a67d1600d98593d6f417eac76e836d6dcbecd Mon Sep 17 00:00:00 2001 From: Benjamin Doron Date: Sun, 22 Sep 2019 17:33:12 +1000 Subject: mb/acer: Add Acer Aspire VN7-572G Add initial support for Acer Aspire VN7-572G (Skylake-U). Also note that there are two similar boards, Aspire VN7-792G and Aspire VN7-592G; both are Skylake-H. These are not supported (yet). Do not flash images intended for Aspire VN7-572G on those boards: the GPIOs and HSIO routing will be different and may risk damage to the hardware. Working: - Payload - TianoCore (custom fork of MrChromebox's UefiPayloadPkg; edk2-202102) - OS - Fedora 35 (kernel 5.14.15) - Windows 10 20H1 (bugs present: battery paging fixed; abandoning testing) - Both DIMM slots - eDP and HDMI display (VBT partially matches vendor's configuration) - with FSP GOP - with IntelGopDriver (in payload: TianoCore) - with libgfxinit - Audio - Speakers and headphone jack - Internal microphone - HDMI audio - Devices - PCIe and SATA (unable to test M.2 SATA) - Discrete graphics, Ethernet and WiFi - USB ports (unable to test type-C, touchscreen and fingerprint reader) - Includes internal devices (Bluetooth, SD card reader and webcam) - TPM - Keyboard and touchpad - Optimus (see CB:28380, CB:40625 and CB:40628) - ACPI functionality - S3 suspend and resume - EC support - Internal flashing with flashrom - CMOS settings In progress: - EC SMM functionality Not working: - vboot (breaks boot): See CB:58249 Notes: - `tpm2_pcrallocate` to enable SHA256 PCR bank Not implemented: - WMI Change-Id: I6340116abfeb2fbd280d143b74d323e4da3566f6 Signed-off-by: Benjamin Doron Reviewed-on: https://review.coreboot.org/c/coreboot/+/35523 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/mainboard/acer/aspire_vn7_572g/Kconfig | 110 ++++++ src/mainboard/acer/aspire_vn7_572g/Kconfig.name | 2 + src/mainboard/acer/aspire_vn7_572g/Makefile.inc | 20 + src/mainboard/acer/aspire_vn7_572g/acpi/ac.asl | 16 + .../acer/aspire_vn7_572g/acpi/battery.asl | 416 ++++++++++++++++++++ .../aspire_vn7_572g/acpi/brightness_levels.asl | 113 ++++++ src/mainboard/acer/aspire_vn7_572g/acpi/ec.asl | 422 +++++++++++++++++++++ .../acer/aspire_vn7_572g/acpi/mainboard.asl | 83 ++++ .../acer/aspire_vn7_572g/acpi/superio.asl | 3 + .../acer/aspire_vn7_572g/acpi/thermal.asl | 121 ++++++ src/mainboard/acer/aspire_vn7_572g/board.fmd | 16 + src/mainboard/acer/aspire_vn7_572g/board_info.txt | 8 + src/mainboard/acer/aspire_vn7_572g/bootblock.c | 88 +++++ src/mainboard/acer/aspire_vn7_572g/cmos.default | 4 + src/mainboard/acer/aspire_vn7_572g/cmos.layout | 58 +++ src/mainboard/acer/aspire_vn7_572g/data.vbt | Bin 0 -> 4608 bytes src/mainboard/acer/aspire_vn7_572g/devicetree.cb | 336 ++++++++++++++++ src/mainboard/acer/aspire_vn7_572g/die.c | 20 + src/mainboard/acer/aspire_vn7_572g/dsdt.asl | 55 +++ src/mainboard/acer/aspire_vn7_572g/ec.c | 95 +++++ .../acer/aspire_vn7_572g/gma-mainboard.ads | 16 + src/mainboard/acer/aspire_vn7_572g/gpio.c | 374 ++++++++++++++++++ src/mainboard/acer/aspire_vn7_572g/gpio_early.c | 27 ++ src/mainboard/acer/aspire_vn7_572g/hda_verb.c | 118 ++++++ src/mainboard/acer/aspire_vn7_572g/include/ec.h | 14 + src/mainboard/acer/aspire_vn7_572g/include/gpio.h | 8 + src/mainboard/acer/aspire_vn7_572g/mainboard.c | 159 ++++++++ src/mainboard/acer/aspire_vn7_572g/romstage.c | 38 ++ src/mainboard/acer/aspire_vn7_572g/smihandler.c | 188 +++++++++ 29 files changed, 2928 insertions(+) create mode 100644 src/mainboard/acer/aspire_vn7_572g/Kconfig create mode 100644 src/mainboard/acer/aspire_vn7_572g/Kconfig.name create mode 100644 src/mainboard/acer/aspire_vn7_572g/Makefile.inc create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/ac.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/battery.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/brightness_levels.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/ec.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/mainboard.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/superio.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/acpi/thermal.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/board.fmd create mode 100644 src/mainboard/acer/aspire_vn7_572g/board_info.txt create mode 100644 src/mainboard/acer/aspire_vn7_572g/bootblock.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/cmos.default create mode 100644 src/mainboard/acer/aspire_vn7_572g/cmos.layout create mode 100644 src/mainboard/acer/aspire_vn7_572g/data.vbt create mode 100644 src/mainboard/acer/aspire_vn7_572g/devicetree.cb create mode 100644 src/mainboard/acer/aspire_vn7_572g/die.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/dsdt.asl create mode 100644 src/mainboard/acer/aspire_vn7_572g/ec.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/gma-mainboard.ads create mode 100644 src/mainboard/acer/aspire_vn7_572g/gpio.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/gpio_early.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/hda_verb.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/include/ec.h create mode 100644 src/mainboard/acer/aspire_vn7_572g/include/gpio.h create mode 100644 src/mainboard/acer/aspire_vn7_572g/mainboard.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/romstage.c create mode 100644 src/mainboard/acer/aspire_vn7_572g/smihandler.c diff --git a/src/mainboard/acer/aspire_vn7_572g/Kconfig b/src/mainboard/acer/aspire_vn7_572g/Kconfig new file mode 100644 index 0000000000..449eeee39a --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/Kconfig @@ -0,0 +1,110 @@ +## SPDX-License-Identifier: GPL-2.0-only + +if BOARD_ACER_VN7_572G + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select BOARD_ROMSIZE_KB_8192 + select DRIVERS_I2C_HID + select DRIVERS_USB_ACPI + select EC_ACPI + select HAVE_ACPI_RESUME + select HAVE_ACPI_TABLES + select HAVE_CMOS_DEFAULT + select HAVE_INTEL_PTT + select HAVE_OPTION_TABLE + select INTEL_GMA_HAVE_VBT + select INTEL_INT15 + select INTEL_LPSS_UART_FOR_CONSOLE + select MAINBOARD_HAS_CRB_TPM + select MAINBOARD_HAS_LIBGFXINIT + select MAINBOARD_HAS_TPM2 + select NO_UART_ON_SUPERIO + select SOC_INTEL_COMMON_BLOCK_HDA_VERB + select SOC_INTEL_SKYLAKE + select SPD_READ_BY_WORD + select SYSTEM_TYPE_LAPTOP + +config CBFS_SIZE + default 0x600000 + +config CONSOLE_SERIAL + default n + +config DIMM_MAX + default 2 + +config DIMM_SPD_SIZE + default 512 + +config FMDFILE + default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/board.fmd" if INCLUDE_EC_FIRMWARE + +config INCLUDE_EC_FIRMWARE + bool "Include EC firmware blob" + help + If corrupted, the EC can recover its firmware from the SPI flash. + +config EC_FIRMWARE_FILE + string "Location of EC firmware blob" + depends on INCLUDE_EC_FIRMWARE + default "3rdparty/blobs/mainboard/\$(MAINBOARDDIR)/ec.bin" + +config EC_USE_LGMR + bool "Use LPC generic memory range for EC" + help + Using MMIO accesses for EC range can improve performance. + +config INCLUDE_NHLT_BLOBS + bool "Include blobs for audio" + select NHLT_DMIC_1CH + # It appears OS chooses blob? + select NHLT_DMIC_2CH +# select NHLT_DMIC_4CH # Wrong lie to tell? Double-check blob. + +config LINEAR_FRAMEBUFFER_MAX_HEIGHT + default 1080 + +config LINEAR_FRAMEBUFFER_MAX_WIDTH + default 1920 + +config MAINBOARD_DIR + default "acer/aspire_vn7_572g" + +config MAINBOARD_FAMILY + default "Aspire V Nitro" + +config MAINBOARD_PART_NUMBER + default "Aspire VN7-572G" + +config MAINBOARD_SUPPORTS_KABYLAKE_DUAL + default n + +config MAINBOARD_SUPPORTS_KABYLAKE_QUAD + default n + +config MAX_CPUS + default 4 + +config ME_CLEANER_ARGS + default "-s" + +config ONBOARD_VGA_IS_PRIMARY + default y + +config POST_DEVICE + default n + +config POST_IO + default n + +config UART_FOR_CONSOLE + default 2 + +config VGA_BIOS_DGPU_ID + default "10de,139a" + +config VGA_BIOS_ID + default "8086,1916" + +endif diff --git a/src/mainboard/acer/aspire_vn7_572g/Kconfig.name b/src/mainboard/acer/aspire_vn7_572g/Kconfig.name new file mode 100644 index 0000000000..b881680e4e --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/Kconfig.name @@ -0,0 +1,2 @@ +config BOARD_ACER_VN7_572G + bool "Aspire VN7-572G" diff --git a/src/mainboard/acer/aspire_vn7_572g/Makefile.inc b/src/mainboard/acer/aspire_vn7_572g/Makefile.inc new file mode 100644 index 0000000000..79c66c597e --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/Makefile.inc @@ -0,0 +1,20 @@ +## SPDX-License-Identifier: GPL-2.0-only + +all-y += die.c + +bootblock-y += bootblock.c +bootblock-y += ec.c +bootblock-y += gpio_early.c + +ramstage-y += ec.c +ramstage-y += gpio.c + +smm-y += die.c +smm-y += ec.c + +ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads + +files_added:: +ifeq ($(CONFIG_INCLUDE_EC_FIRMWARE),y) + $(CBFSTOOL) $(obj)/coreboot.rom write -r EC -f $(CONFIG_EC_FIRMWARE_FILE) --fill-upward +endif diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/ac.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/ac.asl new file mode 100644 index 0000000000..c92cbd9c76 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/ac.asl @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Device (ADP1) +{ + Name (_HID, "ACPI0003" /* Power Source Device */) // _HID: Hardware ID + Name (_PCL, Package () { \_SB }) // _PCL: Power Consumer List + + Method (_PSR, 0, NotSerialized) // _PSR: Power Source + { +#if CONFIG(EC_USE_LGMR) + Return (MACS) +#else + Return (EACS) +#endif + } +} diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/battery.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/battery.asl new file mode 100644 index 0000000000..1f4fb47ba5 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/battery.asl @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#if !CONFIG(EC_USE_LGMR) +/* TODO: Consider actually enforcing mutex? */ +Mutex (BMTX, 0) +#endif +Name (B0ST, 0) /* Battery 0 status */ + +/* + * EC Registers + * + * "EBID" is the battery page selector. + * + * + * Data on the 128 bits following offset + * 0xE0 is accessed in the following order: + * + * Information: + * Page 0: EBCM # start on page 0 # + * Page 0: EBFC + * Page 1: EBDC # switch to page 1 # + * Page 1: EBDV + * Page 1: EBSN + * Page 3: EBDN # switch to page 3 # + * Page 4: EBCH # switch to page 4 # + * Page 2: EBMN # switch to page 2 # + * + * Status: + * Page 0: EBAC # start on page 0 # + * Page 0: EBRC + * Page 0: EBFC + * Page 0: EBVO + */ +/* Page 0 */ +Field (RAM, ByteAcc, Lock, Preserve) +{ + Offset (0xE0), + EBRC, 16, /* Battery remaining capacity */ + EBFC, 16, /* Battery full charge capacity */ + EBPE, 16, + EBAC, 16, /* Battery present rate */ + EBVO, 16, /* Battery voltage */ + , 15, + EBCM, 1, /* Battery charging */ + EBCU, 16, + EBTV, 16, +} + +/* Page 1 */ +Field (RAM, ByteAcc, Lock, Preserve) +{ + Offset (0xE0), + EBDC, 16, /* Battery design capacity */ + EBDV, 16, /* Battery design voltage */ + EBSN, 16, /* Battery serial number */ +} + +/* Page 2 */ +Field (RAM, ByteAcc, NoLock, Preserve) +{ + Offset (0xE0), + EBMN, 128, /* Battery manufacturer */ +} + +/* Page 3 */ +Field (RAM, ByteAcc, NoLock, Preserve) +{ + Offset (0xE0), + EBDN, 128, /* Battery model */ +} + +/* Page 4 */ +Field (RAM, ByteAcc, NoLock, Preserve) +{ + Offset (0xE0), + EBCH, 128, /* Battery type */ +} + +#if CONFIG(EC_USE_LGMR) +OperationRegion (MBB0, SystemMemory, (LGMR + 0x80), 0xFF) +Field (MBB0, ByteAcc, Lock, Preserve) +{ + MBRC, 16, + MBFC, 16, + MBPE, 16, + MBAC, 16, + MBVO, 16, + , 15, + MBCM, 1, + MBCU, 16, + MBTV, 16, +} + +Field (MBB0, ByteAcc, Lock, Preserve) +{ + Offset (0x10), + MBDC, 16, + MBDV, 16, + MBSN, 16, +} + +Field (MBB0, ByteAcc, Lock, Preserve) +{ + Offset (0x40), + MBMN, 128, +} + +Field (MBB0, ByteAcc, Lock, Preserve) +{ + Offset (0x50), + MBDN, 256, +} + +Field (MBB0, ByteAcc, Lock, Preserve) +{ + Offset (0x70), + MBCH, 128, +} +#endif + +/* + * Arg0: Battery number + * Arg1: Battery Information Package + * Arg2: Status + */ +#if !CONFIG(EC_USE_LGMR) +Method (GBIF, 3, Serialized) +{ + Acquire (BMTX, 0xFFFF) // Due to EC paging, don't run this with another function +#else +Method (GBIF, 3, NotSerialized) +{ +#endif + If (Arg2) + { + Arg1[1] = 0xFFFFFFFF + Arg1[2] = 0xFFFFFFFF + Arg1[4] = 0xFFFFFFFF + Arg1[5] = 0 + Arg1[6] = 0 + } + Else + { +#if CONFIG(EC_USE_LGMR) + Local0 = MBCM +#else + EBID = 0 // We don't know which page was active + Local0 = EBCM +#endif + Arg1[0] = (Local0 ^ 1) + +#if CONFIG(EC_USE_LGMR) + Local2 = MBFC + Local1 = MBDC +#else + Local2 = EBFC + EBID = 1 + Local1 = EBDC +#endif + If (Local0) + { + Local2 *= 10 + Local1 *= 10 + } + + Arg1[1] = Local1 // Design capacity + Arg1[2] = Local2 // Last full charge capacity +#if CONFIG(EC_USE_LGMR) + Arg1[4] = MBDV // Design voltage +#else + Arg1[4] = EBDV // Design voltage +#endif + Local6 = (Local2 / 100) // Warning capacities; Remainders ignored + Arg1[5] = (Local6 * 7) /* Low: 7% */ + Arg1[6] = ((Local6 * 11) / 2) /* Very low: 5.5% */ +#if CONFIG(EC_USE_LGMR) + Local7 = MBSN +#else + Local7 = EBSN +#endif + Name (SERN, Buffer (0x06) { " " }) + /* + * Convert hex to decimal. + * - There appears to be a bug in the vendor's implementation: + * The correct answer has, or can have, 5 digits, so Local6 = 5. + * Also see "SERN" buffer. + * - Userspace prints reversed serial number? + */ + Local6 = 4 + While (Local7) + { + Divide (Local7, 10, Local5, Local7) + SERN[Local6] = (Local5 + 0x30) // Add 0x30 to get numeric ASCII + Local6-- + } + + Arg1[10] = SERN // Serial number +#if CONFIG(EC_USE_LGMR) + Arg1[9] = MBDN // Model number + Arg1[11] = MBCH // Battery type + Arg1[12] = MBMN // OEM information +#else + EBID = 3 + Arg1[9] = EBDN // Model number + EBID = 4 + Arg1[11] = EBCH // Battery type + EBID = 2 + Arg1[12] = EBMN // OEM information +#endif + } + +#if !CONFIG(EC_USE_LGMR) + Release (BMTX) +#endif + Return (Arg1) +} + +/* + * Arg0: Battery number + * Arg1: State information + * Arg2: Power units + * Arg3: Battery Status Package + */ +Method (GBST, 4, NotSerialized) // All on one page +{ +#if !CONFIG(EC_USE_LGMR) + Acquire (BMTX, 0xFFFF) // Due to EC paging, don't run this with another function +#endif + If (Arg1 & 0x02) // BIT1 in "MB0S/EB0S" + { + Local0 = 2 + If (Arg1 & 0x20) // "EB0F" + { + Local0 = 0 + } + } + ElseIf (Arg1 & 0x04) // BIT2 in "MB0S/EB0S" + { + Local0 = 1 + } + Else + { + Local0 = 0 + } + + If (Arg1 & 0x10) // "EB0L" + { + Local0 |= 0x04 + } + + If (Arg1 & 0x01) // "EB0A" + { + /* + * Present rate is a 16bit signed int, positive while charging + * and negative while discharging. + */ +#if CONFIG(EC_USE_LGMR) + Local1 = MBAC + Local2 = MBRC + If (MACS) // Charging +#else + EBID = 0 // We don't know which page was active + Local1 = EBAC + Local2 = EBRC + If (EACS) // Charging +#endif + { + If (Arg1 & 0x20) // "EB0F" + { +#if CONFIG(EC_USE_LGMR) + Local2 = MBFC +#else + Local2 = EBFC +#endif + } + } + + If (Arg2) + { + Local2 *= 10 + } + +#if CONFIG(EC_USE_LGMR) + Local3 = MBVO +#else + Local3 = EBVO +#endif + /* + * The present rate value should be positive unless discharging. If so, + * negate present rate. + */ + If (Local1 >= 0x8000) + { + If (Local0 & 0x01) + { + Local1 = (0x00010000 - Local1) + } + Else + { + Local1 = 0 // Full battery, force to 0 + } + } + /* + * If that was not the case, we have an EC bug or inconsistency + * and force the value to 0. + */ + ElseIf ((Local0 & 0x02) == 0) + { + Local1 = 0 + } + + If (Arg2) + { + Local1 *= Local3 + Local1 /= 1000 /* Remainder ignored by vendor */ + } + } + Else + { + Local0 = 0 + Local1 = 0xFFFFFFFF + Local2 = 0xFFFFFFFF + Local3 = 0xFFFFFFFF + } + + Arg3[0] = Local0 + Arg3[1] = Local1 + Arg3[2] = Local2 + Arg3[3] = Local3 + +#if !CONFIG(EC_USE_LGMR) + Release (BMTX) +#endif + Return (Arg3) +} + +Device (BAT0) +{ + Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */) // _HID: Hardware ID + Name (_UID, 0) // _UID: Unique ID + Name (_PCL, Package () { \_SB }) // _PCL: Power Consumer List + + Name (B0IP, Package (0x0D) + { + 1, /* 0x00: Power Unit: mAh */ + 0xFFFFFFFF, /* 0x01: Design Capacity */ + 0xFFFFFFFF, /* 0x02: Last Full Charge Capacity */ + 1, /* 0x03: Battery Technology: Rechargeable */ + 0xFFFFFFFF, /* 0x04: Design Voltage */ + 0, /* 0x05: Design Capacity of Warning */ + 0, /* 0x06: Design Capacity of Low */ + 1, /* 0x07: Capacity Granularity 1 */ + 1, /* 0x08: Capacity Granularity 2 */ + "", /* 0x09: Model Number */ + "100", /* 0x0a: Serial Number */ + "Lion", /* 0x0b: Battery Type */ + 0 /* 0x0c: OEM Information */ + }) + Name (B0SP, Package (0x04) + { + 0, /* 0x00: Battery State */ + 0xFFFFFFFF, /* 0x01: Battery Present Rate */ + 0xFFFFFFFF, /* 0x02: Battery Remaining Capacity */ + 0xFFFFFFFF /* 0x03: Battery Present Voltage */ + }) + Method (_STA, 0, NotSerialized) // _STA: Status + { + /* Bitwise AND by vendor is lossy? */ + Local1 = EB0A + If (Local1 & 0x40) + { + Local1 = 0 + } + + B0ST = Local1 + If (Local1) + { + Return (0x1F) + } + Else + { + Return (0x0F) + } + } + + Method (_BIF, 0, NotSerialized) // _BIF: Battery Information + { + Local6 = B0ST + Local7 = 20 + While (Local6 && Local7) + { + If (EB0R) + { + Local6 = 0 + } + Else + { + Sleep (500) + Local7-- + } + } + + Return (GBIF (0, B0IP, Local6)) + } + + Method (_BST, 0, NotSerialized) // _BST: Battery Status + { + Local0 = (DerefOf (B0IP[0]) ^ 1) +#if CONFIG(EC_USE_LGMR) + Local5 = MB0S +#else + Local5 = EB0S +#endif + Return (GBST (0, Local5, Local0, B0SP)) + } +} diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/brightness_levels.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/brightness_levels.asl new file mode 100644 index 0000000000..14c5e303d1 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/brightness_levels.asl @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +Scope (GFX0) +{ + Name (BRIG, Package (0x67) + { + 80, /* default AC */ + 50, /* default battery */ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + }) +} diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/ec.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/ec.asl new file mode 100644 index 0000000000..3a22d389b3 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/ec.asl @@ -0,0 +1,422 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * Global TODO: (externally: Optimus GC6 and GPS) + * - TRPS: This is SMI 0xDD, likely in SmmOemDriver. This SW SMI adds to and executes + * a table of function pointers produced throughout the OEM 'value-add' stack. + * - Arg0 - "SFUN" - is index into "$FNC" pointer table? It's easier to + * correlate *CommonService use: Offset 13 creates TRPS handlers. + * - Known functions: + * - 0x80 calls offset 0 in ACER_BOOT_DEVICE_SERVICE_PROTOCOL_GUID. + * - NB: efiXplorer can miss InstallProtocolInterface() when Interface is local + * - 0x81 toggles Intel Dynamic Acceleration in IA32_MISC_ENABLE MSR. + * - 0x82 does switch on "OSYS" to set EC byte. Suspect this is for OS features. + * (A CVE exists in the vendor code only if it never sets the offset in the buffer.) + * - RBEC/WBEC/MBEC: This is SMI 0xDD, "functions" 0x10, 0x11 and 0x12 in SmmKbcDriver, + * added into SmmCommonService table at its protocol notify. Performs read, write + * and read-modify-write from buffer. We will use ACPI instead. + * - WMI: This is likely SMI 0xD0 in A01WMISmmCallback. This SW SMI likely uses the WMI + * object and consumes the OEM 'value-add' stack for EC and presumably the A01* + * OEM/ODM 'value-add' stack. An SSDT contains the device and EC0 provides "GCMS" + * and "GOTS" method helpers. + * + * Generally, more information is needed. + * TODO: Implement more board features: lid and touchpad trigger wake from S3, + * Fn-Ctrl swap, sticky Fn keys and always-on USB charger. + */ + +Device (EC0) +{ + Name (_HID, EisaId ("PNP0C09") /* Embedded Controller Device */) // _HID: Hardware ID + Name (_GPE, 0x50) // _GPE: General Purpose Events + Name (\ECOK, 0) +#if CONFIG(EC_USE_LGMR) + Name (LGMR, 0xFE800000) // Static, may depend on EC configuration. Unsure which register. +#endif + + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, 0x62, 0x62, 0, 1) + IO (Decode16, 0x66, 0x66, 0, 1) + }) + + #define EC_SC_IO 0x66 + #define EC_DATA_IO 0x62 + #include + +#if CONFIG(EC_USE_LGMR) + OperationRegion (ECMB, SystemMemory, LGMR, 0x200) +#endif + OperationRegion (RAM, EmbeddedControl, 0, 0xFF) + Field (RAM, ByteAcc, Lock, Preserve) + { + CMDB, 8, /* EC commands */ + ETID, 8, /* Thermal page selector */ + EBID, 8, /* Battery page selector */ + Offset (0x06), + CMD2, 8, /* param 2: UNUSED */ + CMD1, 8, /* param 1: UNUSED */ + CMD0, 8, /* param 0 to EC command */ + Offset (0x0A), + , 1, + , 1, + Offset (0x10), + EQEN, 1, /* EQ enable */ + ETEE, 1, /* TODO */ + Offset (0x4E), + ISEN, 1, /* TODO */ + Offset (0x4F), + ECTP, 8, /* Touchpad ID */ + Offset (0x51), + , 3, + TPEN, 1, /* Touchpad enable */ + Offset (0x52), + WLEX, 1, /* WLAN present */ + BTEX, 1, /* Bluetooth present */ + EX3G, 1, /* 3G */ + , 3, + RFEX, 1, /* RF present */ +/* + * NOTE: Some reverse engineering, as well as corroborating vendor's hidden SetupUtility + * options with the EC's memory space, suggests that offset 0x55 might be the battery + * threshold + * - TODO: Actually diff changes in modified vendor FW + */ + Offset (0x57), + , 7, + AHKB, 1, /* Hotkey triggered */ + AHKE, 8, /* Hotkey data */ + Offset (0x5C), + Offset (0x5D), + Offset (0x6C), + PWLT, 1, /* NVIDIA GPS: Panel? */ + , 3, + GCON, 1, /* Enter Optimus GC6 */ + Offset (0x70), + , 1, + ELID, 1, /* Lid state */ + , 3, + EACS, 1, /* AC state */ + Offset (0x71), + WLEN, 1, /* WLAN enable */ + BTEN, 1, /* Bluetooth enable */ + , 3, + ISS3, 1, + ISS4, 1, + ISS5, 1, + , 4, + EIDW, 1, /* Device wake */ + Offset (0x74), + , 2, + , 1, + TPEX, 1, /* Touchpad present */ + Offset (0x75), + BLST, 1, /* Bluetooth state */ + LMIB, 1, /* TODO */ + Offset (0x76), + ECSS, 4, /* EC Notify of power state */ + EOSS, 4, /* EC Notify of power state */ + Offset (0x88), /* TODO: Aliased to "EB0S" */ + EB0A, 1, + , 2, + EB0R, 1, + EB0L, 1, + EB0F, 1, + EB0N, 1, + Offset (0x90), + SCPM, 1, /* Set cooling policy */ + Offset (0x92), /* TODO: Aliased to "ETAF" */ + ESSF, 1, + ECTT, 1, + EDTT, 1, + EOSD, 1, /* Trip */ + EVTP, 1, + ECP1, 1, + , 1, + ECP2, 1, + Offset (0xA8), + ES0T, 8, /* Temperature */ + ES1T, 8, /* Temperature */ + Offset (0xD0), + ESP0, 8, /* Passive temp */ + ESC0, 8, /* Critical temp */ + ESP1, 8, /* Passive temp */ + ESC1, 8, /* Critical temp */ + } + /* Aliases several battery registers */ + Field (RAM, ByteAcc, Lock, Preserve) + { + Offset (0x88), + EB0S, 8, /* Battery 0 state */ + } + /* Aliases several thermal registers */ + Field (RAM, ByteAcc, Lock, Preserve) + { + Offset (0x92), + ETAF, 8, + } + +#if CONFIG(EC_USE_LGMR) + Field (ECMB, ByteAcc, Lock, Preserve) + { + Offset (0x02), + , 1, + MLID, 1, + , 3, + MACS, 1, + Offset (0x06), + MBTP, 8, + Offset (0x08), + MB0S, 8, + Offset (0x20), + MS0T, 8, + MS1T, 8, + MS2T, 8, + MS3T, 8, + MS4T, 8, + MS5T, 8, + Offset (0x53), + MCSS, 1, + MCTT, 1, + MDTT, 1, + MOSD, 1, + MVTP, 1, + Offset (0x54), + MSP0, 8, + MSC0, 8, + MCC0, 8, + MSC1, 8, + } +#endif + + Method (_REG, 2, NotSerialized) // _REG: Region Availability + { + If (Arg0 == 3) + { + ECOK = Arg1 // OS can clear region availability + If (Arg1 == 1) // On initialise + { + TINI () + EOSS = 0x05 + /* OSYS retrieved by SMM, Arg3 is unused */ +// TRPS (0x82, 1, 0) + + /* + * Other pages return valid data too, but this seems to be + * the page we are expecting - persistently in ectool dump + * with vendor firmware + * FIXME: Contents of other pages? + */ + ETID = 0x20 + } + } + + /* iGFX RC method call stripped */ + } + + Method (TINI, 0, NotSerialized) + { + If (ECOK) + { + ETAF = 0 + ETEE = 1 + } + Else + { + EC_WRITE (0x92, 0) // ETAF = 0 + MBEC (0x10, 0xFD, 0x02) // ETEE = 1 + } + } + + Name (RFST, 0) /* RF state */ + Method (ECPS, 1, NotSerialized) // _PTS: Prepare To Sleep + { + ECSS = Arg0 + /* OSYS retrieved by SMM */ +// TRPS (0x82, 0x02, Arg0) + If ((Arg0 == 3) || (Arg0 == 4)) + { + RFST = RFEX + } + } + + Method (ECWK, 1, NotSerialized) // _WAK: Wake + { + EQEN = 1 + EOSS = Arg0 + TINI () + Notify (BAT0, 0x81) // Information Change + /* OSYS retrieved by SMM */ +// TRPS (0x82, 0x03, Arg0) + If ((Arg0 == 3) || (Arg0 == 4)) + { + RFEX = RFST + Notify (SLPB, 0x02) // Device Wake + } + /* iGFX RC method call stripped */ + } + + Method (MBEC, 3, Serialized) + { + Local0 = EC_READ (Arg0) + Local0 &= Arg1 + Local0 |= Arg2 + EC_WRITE (Arg0, Local0) + } + + /* Graphical hotkey */ + Method (_Q19, 0, NotSerialized) + { + Debug = "Graphical hotkey display switching not implemented in coreboot!" + } + + /* Increase brightness */ + Method (_Q1C, 0, NotSerialized) + { + ^^^GFX0.INCB () + } + + /* Decrease brightness */ + Method (_Q1D, 0, NotSerialized) + { + ^^^GFX0.DECB () + } + + /* Hotkeys */ + Method (_Q2C, 0, NotSerialized) + { + If (LMIB) + { + If (!AHKB) /* Else, WMI clears its buffer? */ + { + Local1 = AHKE + If ((Local1 > 0) && (Local1 < 0x80)) + { + Debug = "Hotkeys - TODO: Airplane mode?" + /* WMI -> "GCMS" method */ + } + ElseIf ((Local1 > 0x80) && (Local1 < 0xA0)) + { + /* TODO: Not working when called by HID mode. What does WMI do here? */ + TPEN ^= 1 + } + } + } + } + + Method (_Q36, 0, NotSerialized) + { + If (ECOK) + { + EOSD = 1 // Thermal trip + } + Else + { + MBEC (0x92, 0xF7, 0x08) // EOSD = 1 + } + + Sleep (500) + Notify (\_TZ.TZ01, 0x80) // Thermal Status Change + Notify (\_TZ.TZ00, 0x80) // Thermal Status Change + } + + Method (_Q3F, 0, NotSerialized) + { + /* Arg3 is unused */ +// TRPS (0x80, 0, 0) + } + + Method (_Q40, 0, NotSerialized) + { + Notify (BAT0, 0x81) // Information Change + } + + Method (_Q41, 0, NotSerialized) + { + Notify (BAT0, 0x81) // Information Change + } + + /* Battery status change */ + Method (_Q48, 0, NotSerialized) + { + Notify (BAT0, 0x80) + } + + /* Battery critical? */ + Method (_Q4C, 0, NotSerialized) + { + If (B0ST) + { + Notify (BAT0, 0x80) // Status Change + } + } + + /* AC status change: present */ + Method (_Q50, 0, NotSerialized) + { + Notify (ADP1, 0x80) + } + + /* AC status change: not present */ + Method (_Q51, 0, NotSerialized) + { + Notify (ADP1, 0x80) + } + + /* Lid status change: open */ + Method (_Q52, 0, NotSerialized) + { + Notify (LID0, 0x80) + } + + /* Lid status change: close */ + Method (_Q53, 0, NotSerialized) + { + Notify (LID0, 0x80) + } + + Method (_Q60, 0, NotSerialized) + { + Debug = "EC Query (0x60): WMI" + } + + Method (_Q61, 0, NotSerialized) + { + Debug = "EC Query (0x61): WMI" + } + + Method (_Q62, 0, NotSerialized) + { + Debug = "EC Query (0x62): Optimus GC6 or NVIDIA GPS" + } + + Method (_Q63, 0, NotSerialized) + { + Debug = "EC Query (0x63): Optimus GC6 or NVIDIA GPS" + } + + Method (_Q67, 0, NotSerialized) + { + Debug = "EC Query (0x67): NVIDIA GPS" + } + + Method (_Q68, 0, NotSerialized) + { + Debug = "EC Query (0x68): NVIDIA GPS" + } + + Method (_Q6C, 0, NotSerialized) + { + /* Arg3 is unused */ +// TRPS (0x81, 0, 0) + } + + Method (_Q6D, 0, NotSerialized) + { + /* Arg3 is unused */ +// TRPS (0x81, 1, 0) + } + + #include "ac.asl" + #include "battery.asl" +} diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/mainboard.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/mainboard.asl new file mode 100644 index 0000000000..a3c48b290d --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/mainboard.asl @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +// TODO: Does board actually support DPTF? +#include "thermal.asl" + +Scope (_SB) +{ + Method (MPTS, 1, NotSerialized) // _PTS: Prepare To Sleep + { + ^PCI0.LPCB.EC0.ECPS (Arg0) + /* TBT and DTS not supported, TPM.PTS can be called elsewhere */ + } + + Method (MWAK, 1, Serialized) // _WAK: Wake + { + ^PCI0.LPCB.EC0.ECWK (Arg0) + /* No GPIO expander, 8254 clock-gating and PCIe PME can be performed elsewhere */ + + If ((Arg0 == 3) || (Arg0 == 4)) + { + /* DTS and TBT not supported, iGFX RC variable update stripped */ + LIDS = ^LID0._LID () + Notify (LID0, 0x80) // Status Change + /* TODO: Bus checks? Based on KabylakeOpenBoardPkg - Platform.asl + perhaps not (Warm insertion/removal not possible on mobile */ + } + } + + Method (MS0X, 1, Serialized) // S0ix hook. Porting "GUAM" method - "Global User Absent Mode" + { + If (Arg0 == 0) + { + /* Exit "Connected Standby" */ +#if 1 // EC Notification + ^PCI0.LPCB.EC0.EOSS = 0 +#endif + /* TODO: P-state capping, PL setting? */ + } + ElseIf (Arg0 == 1) + { + /* Enter "Connected Standby" */ +#if 1 // EC Notification + ^PCI0.LPCB.EC0.ECSS = 0x08 +#endif + /* TODO: P-state capping, PL setting? */ + } + } + + Device (LID0) + { + Name (_HID, EisaId ("PNP0C0D") /* Lid Device */) // _HID: Hardware ID + Method (_LID, 0, NotSerialized) // _LID: Lid Status + { +#if CONFIG(EC_USE_LGMR) + Return (^^PCI0.LPCB.EC0.MLID) +#else + Return (^^PCI0.LPCB.EC0.ELID) +#endif + } + + Method (_PSW, 1, NotSerialized) // _PSW: Power State Wake + { + ^^PCI0.LPCB.EC0.EIDW = Arg0 + } + + Name (_PRW, Package () { 0x0A, 3 }) // _PRW: Power Resources for Wake + } + + Device (SLPB) + { + Name (_HID, EisaId ("PNP0C0E") /* Sleep Button Device */) // _HID: Hardware ID + Name (_PRW, Package () { 0x0A, 3 }) // _PRW: Power Resources for Wake + } +} + +Scope (_GPE) +{ + /* TODO - Remaining Level-Triggered GPEs: PCH GPE, PCIe PME, TBT, DTS, GFX SCI and tier-2 (RTD3) */ + Method (_L0A, 0, NotSerialized) + { + Notify (\_SB.SLPB, 0x02) // Device Wake + } +} diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/superio.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/superio.asl new file mode 100644 index 0000000000..55b1db5b11 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/superio.asl @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include diff --git a/src/mainboard/acer/aspire_vn7_572g/acpi/thermal.asl b/src/mainboard/acer/aspire_vn7_572g/acpi/thermal.asl new file mode 100644 index 0000000000..7d175a23e5 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/acpi/thermal.asl @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Scope (_TZ) +{ + Name (CRT0, 0) + Name (PSV0, 0) + ThermalZone (TZ01) + { + Method (_TMP, 0, Serialized) // _TMP: Temperature + { +#if CONFIG(EC_USE_LGMR) + Local0 = \_SB.PCI0.LPCB.EC0.MS0T + Local1 = \_SB.PCI0.LPCB.EC0.MCSS + /* Suppress warning over reading status flag by dummy OR */ + Or (Local1, 1, Local1) + Local2 = \_SB.PCI0.LPCB.EC0.MOSD +#else + Local0 = \_SB.PCI0.LPCB.EC0.ES0T + /* "MCSS": Considering neighbouring bits, likely + "ESSF" in thermals, not "ECSS" in power notifications */ + Local1 = \_SB.PCI0.LPCB.EC0.ESSF + Or (Local1, 1, Local1) + Local2 = \_SB.PCI0.LPCB.EC0.EOSD +#endif + If (Local2) // Thermal trip + { + If (Local0 <= CRT0) + { + Local0 = (CRT0 + 2) + } + } + + Return (C2K (Local0)) + } + + Method (_CRT, 0, Serialized) // _CRT: Critical Temperature + { +#if CONFIG(EC_USE_LGMR) + Local0 = \_SB.PCI0.LPCB.EC0.MSC0 +#else + Local0 = \_SB.PCI0.LPCB.EC0.ESC0 +#endif + If ((Local0 >= 128) || (Local0 < 30)) + { + Local0 = 120 + } + + CRT0 = Local0 + Return (C2K (Local0)) + } + + Method (_SCP, 1, Serialized) // _SCP: Set Cooling Policy + { + If (ECOK) + { + \_SB.PCI0.LPCB.EC0.SCPM = Arg0 + } + Else + { + /* MBEC: Called SMI function 0x12 */ + \_SB.PCI0.LPCB.EC0.MBEC (0x90, 0xFE, Arg0) // SCPM = Arg0 + } + } + + Method (_PSV, 0, Serialized) // _PSV: Passive Temperature + { +#if CONFIG(EC_USE_LGMR) + Local0 = \_SB.PCI0.LPCB.EC0.MSP0 +#else + Local0 = \_SB.PCI0.LPCB.EC0.ESP0 +#endif + If ((Local0 >= 128) || (Local0 < 30)) + { + Local0 = 30 + } + + PSV0 = Local0 + Return (C2K (Local0)) + } + } + + ThermalZone (TZ00) + { + Method (_TMP, 0, Serialized) // _TMP: Temperature + { +#if CONFIG(EC_USE_LGMR) + Local0 = \_SB.PCI0.LPCB.EC0.MS1T +#else + Local0 = \_SB.PCI0.LPCB.EC0.ES1T +#endif + + Return (C2K (Local0)) + } + + Method (_CRT, 0, Serialized) // _CRT: Critical Temperature + { +#if CONFIG(EC_USE_LGMR) + Local0 = \_SB.PCI0.LPCB.EC0.MSC1 +#else + Local0 = \_SB.PCI0.LPCB.EC0.ESC1 +#endif + If ((Local0 >= 128) || (Local0 < 30)) + { + Local0 = 120 + } + + Return (C2K (Local0)) + } + } + + Method (C2K, 1, NotSerialized) + { + Local0 = Arg0 + If ((Local0 >= 127) || (Local0 <= 16)) + { + Local0 = 30 + } + + Return ((Local0 * 10) + 2732) // Celsius to centi-Kelvin + } +} diff --git a/src/mainboard/acer/aspire_vn7_572g/board.fmd b/src/mainboard/acer/aspire_vn7_572g/board.fmd new file mode 100644 index 0000000000..44d8a0cd13 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/board.fmd @@ -0,0 +1,16 @@ +# NOTE: Use CONSOLE for SMM debugging +FLASH 8M { + SI_ALL 2M { + SI_DESC 0x1000 + SI_ME 0x1ff000 + } + SI_BIOS 6M { + EC 0x20000 + RW_MRC_CACHE 0x10000 + # SMMSTORE requires 64k alignment + SMMSTORE 0x40000 + CONSOLE 0x20000 + FMAP 0x200 + COREBOOT(CBFS) 0x56fe00 + } +} diff --git a/src/mainboard/acer/aspire_vn7_572g/board_info.txt b/src/mainboard/acer/aspire_vn7_572g/board_info.txt new file mode 100644 index 0000000000..f16707ed89 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/board_info.txt @@ -0,0 +1,8 @@ +Vendor name: Acer +Board name: Aspire VN7-572G +Category: laptop +ROM package: SOIC8 +ROM protocol: SPI +ROM socketed: n +Flashrom support: y +Release year: 2015 diff --git a/src/mainboard/acer/aspire_vn7_572g/bootblock.c b/src/mainboard/acer/aspire_vn7_572g/bootblock.c new file mode 100644 index 0000000000..ce150fdce7 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/bootblock.c @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include "include/ec.h" +#include "include/gpio.h" + +#define ADC_3V_10BIT_GRANULARITY_MAX (3005 / 1023) +#define PCB_VER_AD 1 +#define MODEL_ID_AD 3 + +#define DGPU_PRESENT GPP_A20 /* Active low */ +#define DGPU_HOLD_RST GPP_B4 /* Active low */ +#define DGPU_PWR_EN GPP_B21 /* Active low */ + +/* TODO/NB: Detection is still unreliable. Is a wait required? */ +static void board_detect(void) +{ + printk(BIOS_DEBUG, "Mainboard: Detecting board SKU\n"); + + uint16_t data_buffer = read_ec_adc_converter(MODEL_ID_AD); + printk(BIOS_DEBUG, "BoardId (raw) = 0x%x\n", data_buffer); + printk(BIOS_DEBUG, "BoardId: "); + /* Board by max millivoltage range (of 10-bit, 3.005 V ADC) */ + if (data_buffer <= (1374 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_ERR, "Reserved?\n"); + } else if (data_buffer <= (2017 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_DEBUG, "Aspire VN7-792G (Newgate-SLS_dGPU)\n"); + printk(BIOS_CRIT, "WARNING: This board is unsupported!\n"); + printk(BIOS_CRIT, "Damage may result from programming incorrect GPIO table!\n"); + } else if (data_buffer <= (2259 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_DEBUG, "Aspire VN7-592G (Rayleigh-SLS_960M)\n"); + printk(BIOS_CRIT, "WARNING: This board is unsupported!\n"); + printk(BIOS_CRIT, "Damage may result from programming incorrect GPIO table!\n"); + } else { + printk(BIOS_DEBUG, "Aspire VN7-572G (Rayleigh-SL_dGPU)\n"); + } + + data_buffer = read_ec_adc_converter(PCB_VER_AD); + printk(BIOS_DEBUG, "PCB version (raw) = 0x%x\n", data_buffer); + printk(BIOS_DEBUG, "PCB version: "); + /* PCB by max millivoltage range (of 10-bit, 3.005 V ADC) */ + if (data_buffer <= (2017 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_ERR, "Reserved?\n"); + } else if (data_buffer <= (2259 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_DEBUG, "-1\n"); + } else if (data_buffer <= (2493 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_DEBUG, "SC\n"); + } else if (data_buffer <= (2759 / ADC_3V_10BIT_GRANULARITY_MAX)) { + printk(BIOS_DEBUG, "SB\n"); + } else { + printk(BIOS_DEBUG, "SA\n"); + } +} + +static void dgpu_power_on(void) +{ + if (!gpio_get(DGPU_PRESENT)) { + printk(BIOS_DEBUG, "dGPU present, enable power...\n"); + gpio_set(DGPU_HOLD_RST, 0); // Assert dGPU_HOLD_RST# + mdelay(2); + gpio_set(DGPU_PWR_EN, 0); // Assert dGPU_PWR_EN# + mdelay(7); + gpio_set(DGPU_HOLD_RST, 1); // Deassert dGPU_HOLD_RST# + mdelay(30); + } else { + printk(BIOS_DEBUG, "dGPU not present, disable power...\n"); + gpio_set(DGPU_HOLD_RST, 0); // Assert dGPU_HOLD_RST# + gpio_set(DGPU_PWR_EN, 1); // Deassert dGPU_PWR_EN# + } +} + +void bootblock_mainboard_init(void) +{ + /* NB: Relocated from _early_init() so that debug logging works. + * However, if we use this to ensure that the user flashed the correct + * (future) variant, this must occur before any GPIOs are programmed. + */ + board_detect(); + dgpu_power_on(); +} + +void bootblock_mainboard_early_init(void) +{ + mainboard_config_stage_gpios(); +} diff --git a/src/mainboard/acer/aspire_vn7_572g/cmos.default b/src/mainboard/acer/aspire_vn7_572g/cmos.default new file mode 100644 index 0000000000..642e3414c3 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/cmos.default @@ -0,0 +1,4 @@ +boot_option=Fallback +debug_level=Debug +power_on_after_fail=Disable +legacy_8254_timer=Disable diff --git a/src/mainboard/acer/aspire_vn7_572g/cmos.layout b/src/mainboard/acer/aspire_vn7_572g/cmos.layout new file mode 100644 index 0000000000..7afff9ccf3 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/cmos.layout @@ -0,0 +1,58 @@ +## SPDX-License-Identifier: GPL-2.0-only + +# ----------------------------------------------------------------- +entries + +# start-bit length config config-ID name +0 120 r 0 reserved_memory + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 1 boot_option +388 4 h 0 reboot_counter + +# ----------------------------------------------------------------- +# coreboot config options: console +392 24 r 0 cmos_post_offset +416 4 e 2 debug_level + +# ----------------------------------------------------------------- +# coreboot config options: southbridge +420 2 e 3 power_on_after_fail +422 1 e 4 legacy_8254_timer + +# ----------------------------------------------------------------- +# vboot nv area +816 64 r 0 boot_count_offset +880 128 r 0 vbnv + +# ----------------------------------------------------------------- +# coreboot config options: check sums +1008 16 h 0 check_sum +#1024 1024 r 0 upper_bank + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Fallback +1 1 Normal +2 0 Emergency +2 1 Alert +2 2 Critical +2 3 Error +2 4 Warning +2 5 Notice +2 6 Info +2 7 Debug +2 8 Spew +3 0 Disable +3 1 Enable +3 2 Keep +4 0 Disable +4 1 Enable +# ----------------------------------------------------------------- +checksums + +checksum 416 815 1008 diff --git a/src/mainboard/acer/aspire_vn7_572g/data.vbt b/src/mainboard/acer/aspire_vn7_572g/data.vbt new file mode 100644 index 0000000000..b8a0ab84de Binary files /dev/null and b/src/mainboard/acer/aspire_vn7_572g/data.vbt differ diff --git a/src/mainboard/acer/aspire_vn7_572g/devicetree.cb b/src/mainboard/acer/aspire_vn7_572g/devicetree.cb new file mode 100644 index 0000000000..409e3097bc --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/devicetree.cb @@ -0,0 +1,336 @@ +## SPDX-License-Identifier: GPL-2.0-only + +chip soc/intel/skylake + + # Intel Common SoC Config + #+-------------------+---------------------------+ + #| Field | Value | + #+-------------------+---------------------------+ + #| chipset_lockdown | CHIPSET_LOCKDOWN_COREBOOT | + #| I2C0 | Touchscreen | + #| I2C1 | Touchpad | + #+-------------------+---------------------------+ + register "common_soc_config" = "{ + .i2c[0] = { + .speed = I2C_SPEED_FAST, + }, + .i2c[1] = { + .speed = I2C_SPEED_FAST, + .speed_config[0] = { + .speed = I2C_SPEED_FAST, + .scl_lcnt = 128, + .scl_hcnt = 160, + .sda_hold = 30, + } + }, + }" + + # TODO: Drop once CB:55224 is merged + register "SerialIoDevMode" = "{ + [PchSerialIoIndexI2C0] = PchSerialIoPci, + [PchSerialIoIndexI2C1] = PchSerialIoPci, + [PchSerialIoIndexI2C4] = PchSerialIoDisabled, + [PchSerialIoIndexUart2] = PchSerialIoSkipInit, + }" + + device cpu_cluster 0 on + device lapic 0 on end + end + device domain 0 on + subsystemid 0x1025 0x1037 inherit + device ref system_agent on + # Enable "Enhanced Intel SpeedStep" + register "eist_enable" = "1" + + # Set the Thermal Control Circuit (TCC) activation value to 97C + # even though FSP integration guide says to set it to 100C for SKL-U + # (offset at 0), because when the TCC activates at 100C, the CPU + # will have already shut itself down from overheating protection. + register "tcc_offset" = "3" # TCC of 97C + + register "SaGv" = "SaGv_Enabled" + + # VR Slew rate setting for improving audible noise + register "AcousticNoiseMitigation" = "1" + register "SlowSlewRateForIa" = "3" # Fast/16 + register "SlowSlewRateForGt" = "3" # Fast/16 + register "SlowSlewRateForSa" = "0" # Fast/2 + register "FastPkgCRampDisableIa" = "0" + register "FastPkgCRampDisableGt" = "0" + register "FastPkgCRampDisableSa" = "0" + + # PL1, PL2 override 35W, PL4 override 43W + register "power_limits_config" = "{ + .tdp_pl1_override = 35, + .tdp_pl2_override = 35, + .tdp_pl4 = 43, + }" + + # ISL95857 VR + # Send VR specific command for PS4 exit issue + register "SendVrMbxCmd" = "2" + # Send VR mailbox command for IA/GT/SA rails + register "IslVrCmd" = "2" + end + device ref igpu on + register "panel_cfg" = "{ + .up_delay_ms = 150, // T3 + .down_delay_ms = 50, // T10 + .cycle_delay_ms = 500, // T12 + .backlight_on_delay_ms = 1, // T7 + .backlight_off_delay_ms = 200, // T9 + .backlight_pwm_hz = 1000, + }" + + # IGD Displays; LFP and 3*EFP + # FIXME: VBT does not define EFP3, board has no EFP2? + register "gfx" = "{ + .use_spread_spectrum_clock = 1, + .ndid = 4, .did = { 0x0400, 0x0300, 0x0301, 0x0302 } + }" + + register "PrimaryDisplay" = "Display_Switchable" + end + device ref sa_thermal off end + device ref chap off end + device ref gmm off end + device ref south_xhci on + register "usb2_ports[0]" = "{ + .enable = 1, + .ocpin = OC_SKIP, + .tx_bias = USB2_BIAS_17MV, + .tx_emp_enable = USB2_DE_EMP_ON, + .pre_emp_bias = USB2_BIAS_28MV, + .pre_emp_bit = USB2_HALF_BIT_PRE_EMP, + }" # Type-A Port (right) + register "usb2_ports[1]" = "{ + .enable = 1, + .ocpin = OC_SKIP, + .tx_bias = USB2_BIAS_17MV, + .tx_emp_enable = USB2_DE_EMP_ON, + .pre_emp_bias = USB2_BIAS_28MV, + .pre_emp_bit = USB2_HALF_BIT_PRE_EMP, + }" # Type-A Port (right) + register "usb2_ports[2]" = "{ + .enable = 1, + .ocpin = OC_SKIP, + .tx_bias = USB2_BIAS_17MV, + .tx_emp_enable = USB2_DE_EMP_ON, + .pre_emp_bias = USB2_BIAS_28MV, + .pre_emp_bit = USB2_HALF_BIT_PRE_EMP, + }" # Type-C Port + register "usb2_ports[3]" = "USB2_PORT_FLEX(OC_SKIP)" # Type-A Port (left) + register "usb2_ports[4]" = "USB2_PORT_FLEX(OC_SKIP)" # Bluetooth + register "usb2_ports[5]" = "USB2_PORT_FLEX(OC_SKIP)" # Touchscreen + register "usb2_ports[6]" = "USB2_PORT_FLEX(OC_SKIP)" # Webcam + register "usb2_ports[7]" = "USB2_PORT_FLEX(OC_SKIP)" # SD + register "usb2_ports[8]" = "USB2_PORT_FLEX(OC_SKIP)" # Finger-printer + + register "usb3_ports[0]" = "USB3_PORT_DEFAULT(OC_SKIP)" # Type-A Port (right); Capable of OTG + register "usb3_ports[1]" = "USB3_PORT_DEFAULT(OC_SKIP)" # Type-A Port (right) + register "usb3_ports[2]" = "USB3_PORT_DEFAULT(OC_SKIP)" # Type-C Port + register "usb3_ports[3]" = "USB3_PORT_DEFAULT(OC_SKIP)" # Type-C Port + chip drivers/usb/acpi + register "desc" = ""Root Hub"" + register "type" = "UPC_TYPE_HUB" + device usb 0.0 on + chip drivers/usb/acpi + register "desc" = ""USB2 Type-A Right"" + register "type" = "UPC_TYPE_USB3_A" + register "group" = "ACPI_PLD_GROUP(0, 1)" + device usb 2.0 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Type-A Right"" + register "type" = "UPC_TYPE_USB3_A" + register "group" = "ACPI_PLD_GROUP(0, 2)" + device usb 2.1 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Type-C"" + register "type" = "UPC_TYPE_C_USB2_SS" + register "group" = "ACPI_PLD_GROUP(0, 3)" + device usb 2.2 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Type-A Left"" + register "type" = "UPC_TYPE_A" + register "group" = "ACPI_PLD_GROUP(0, 4)" + device usb 2.3 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Bluetooth"" + register "type" = "UPC_TYPE_UNUSED" + register "group" = "ACPI_PLD_GROUP(0, 5)" + device usb 2.4 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Touchscreen"" + register "type" = "UPC_TYPE_UNUSED" + register "group" = "ACPI_PLD_GROUP(0, 6)" + device usb 2.5 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Webcam"" + register "type" = "UPC_TYPE_UNUSED" + register "group" = "ACPI_PLD_GROUP(0, 7)" + device usb 2.6 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 SD"" + register "type" = "UPC_TYPE_UNUSED" + register "group" = "ACPI_PLD_GROUP(0, 8)" + device usb 2.7 on end + end + chip drivers/usb/acpi + register "desc" = ""USB2 Finger-printer"" + register "type" = "UPC_TYPE_UNUSED" + register "group" = "ACPI_PLD_GROUP(0, 9)" + device usb 2.8 on end + end + chip drivers/usb/acpi + register "desc" = ""USB3 Type-A Right"" + register "type" = "UPC_TYPE_USB3_A" + register "group" = "ACPI_PLD_GROUP(0, 1)" + device usb 3.0 on end + end + chip drivers/usb/acpi + register "desc" = ""USB3 Type-A Right"" + register "type" = "UPC_TYPE_USB3_A" + register "group" = "ACPI_PLD_GROUP(0, 2)" + device usb 3.1 on end + end + chip drivers/usb/acpi + register "desc" = ""USB3 Type-C"" + register "type" = "UPC_TYPE_C_USB2_SS" + register "group" = "ACPI_PLD_GROUP(0, 3)" + device usb 3.2 on end + end + chip drivers/usb/acpi + register "desc" = ""USB3 Type-C"" + register "type" = "UPC_TYPE_C_USB2_SS" + register "group" = "ACPI_PLD_GROUP(0, 3)" + device usb 3.3 on end + end + end + end + end + device ref south_xdci off end + device ref thermal on end + device ref cio off end + device ref i2c0 on + chip drivers/i2c/hid + register "generic.name" = ""TPL0"" + register "generic.hid" = ""ELAN2259"" + register "generic.desc" = ""ELAN Touchscreen"" + register "generic.irq" = "ACPI_IRQ_LEVEL_LOW(GPP_E7_IRQ)" + register "generic.device_present_gpio" = "GPP_B15" + register "hid_desc_reg_offset" = "0x01" + device i2c 0x10 on end + end + end + device ref i2c1 on + chip drivers/i2c/hid + register "generic.name" = ""TPD0"" + register "generic.hid" = ""SYN1B7F"" + register "generic.desc" = ""Synaptics Touchpad"" + register "generic.irq" = "ACPI_IRQ_WAKE_LEVEL_LOW(GPP_B3_IRQ)" +# register "generic.wake" = "GPE0_DW2_16" # FIXME: Use EC's GPE? + register "generic.probed" = "1" + register "hid_desc_reg_offset" = "0x20" + device i2c 0x2c on end + end + chip drivers/i2c/hid + register "generic.name" = ""TPD1"" + register "generic.hid" = ""ELAN0501"" + register "generic.desc" = ""ELAN Touchpad"" + register "generic.irq" = "ACPI_IRQ_LEVEL_LOW(GPP_B3_IRQ)" + register "generic.probed" = "1" + register "hid_desc_reg_offset" = "0x01" + device i2c 0x15 on end + end + end + device ref heci1 on end + device ref sata on + register "SataMode" = "SATA_AHCI" + register "SataSalpSupport" = "1" + register "SataPortsEnable[1]" = "1" # HDD; BIT1 in 92h-93h + register "SataPortsEnable[2]" = "1" # ODD; BIT2 in 92h-93h + end + device ref uart2 on end + # Board has no GPIO expander on I2C4 (despite SetupUtility claim that it does - this would be static text) + device ref pcie_rp1 on + register "PcieRpEnable[0]" = "1" + register "PcieRpAdvancedErrorReporting[0]" = "1" + register "PcieRpLtrEnable[0]" = "1" + register "PcieRpClkReqSupport[0]" = "1" + register "PcieRpClkReqNumber[0]" = "0" + register "PcieRpMaxPayload[0]" = "RpMaxPayload_256" + end # PCI Express Port 1 (dGPU; x4) + device ref pcie_rp7 on + register "PcieRpEnable[6]" = "1" + register "PcieRpAdvancedErrorReporting[6]" = "1" + register "PcieRpLtrEnable[6]" = "1" + register "PcieRpClkReqSupport[6]" = "1" + register "PcieRpClkReqNumber[6]" = "3" + register "PcieRpMaxPayload[6]" = "RpMaxPayload_256" + end # PCI Express Port 7 (NGFF; x2) + device ref pcie_rp9 on + register "PcieRpEnable[8]" = "1" + register "PcieRpAdvancedErrorReporting[8]" = "1" + register "PcieRpLtrEnable[8]" = "1" + register "PcieRpClkReqSupport[8]" = "1" + register "PcieRpClkReqNumber[8]" = "1" + register "PcieRpMaxPayload[8]" = "RpMaxPayload_256" + end # PCI Express Port 9 (LAN) + device ref pcie_rp10 on + register "PcieRpEnable[9]" = "1" + register "PcieRpAdvancedErrorReporting[9]" = "1" + register "PcieRpLtrEnable[9]" = "1" + register "PcieRpClkReqSupport[9]" = "1" + register "PcieRpClkReqNumber[9]" = "2" + register "PcieRpMaxPayload[9]" = "RpMaxPayload_256" + # ASPM L0s is broken/unsupported on Qualcomm Atheros QCA6174 (AER: corrected errors) + register "pcie_rp_aspm[9]" = "AspmL1" + end # PCI Express Port 10 (WLAN) + # Although vendor's platform NVS area shows SCS is enabled, the SD card reader is actually connected over USB + device ref lpc_espi on + register "lpc_iod" = "0x0010" # 80h-81h; ComB: 2F8h-2FFh (COM 2) + register "lpc_ioe" = "LPC_IOE_COMA_EN | LPC_IOE_COMB_EN | LPC_IOE_KBC_60_64 + | LPC_IOE_EC_62_66 | LPC_IOE_SUPERIO_2E_2F | LPC_IOE_EC_4E_4F" # 82h-83h + register "gen3_dec" = "0x00040069" # 8Ch-8Fh; EC (sideband): Port 68h/6Ch + register "gen4_dec" = "0x000c1201" # 90h-93h; EC (index): Port 1200h + + # EC/KBC requires continuous mode + register "serirq_mode" = "SERIRQ_CONTINUOUS" + end + device ref p2sb on end + device ref pmc on + # Note that GPE events called out in ASL code rely on this + # route. i.e. If this route changes then the affected GPE + # offset bits also need to be changed. + register "gpe0_dw0" = "GPP_C" # 3:0 in pwrmbase+0120h + register "gpe0_dw1" = "GPP_D" # 7:4 in pwrmbase+0120h + register "gpe0_dw2" = "GPP_E" # 11:8 in pwrmbase+0120h + + # Enable S0ix + register "s0ix_enable" = "1" + + register "PmConfigSlpS3MinAssert" = "SLP_S3_MIN_ASSERT_50MS" # 11:10 in A4h-A7h + register "PmConfigSlpS4MinAssert" = "SLP_S4_MIN_ASSERT_4S" # 5:4 in A4h-A7h + register "PmConfigSlpSusMinAssert" = "SLP_SUS_MIN_ASSERT_4S" # 19:18 in pmbase+0018h + register "PmConfigSlpAMinAssert" = "SLP_A_MIN_ASSERT_2S" # 17:16 in pmbase+0018h + end + device ref hda on + register "DspEnable" = "1" + # PchHdaDspEndpointDmic is only to be returned to reference code + # DXE phase as HOB, used to select blob for NHLT + end + device ref smbus on end + device ref fast_spi on end + device ref tracehub off end + end + chip drivers/crb + device mmio 0xfed40000 on end + end +end diff --git a/src/mainboard/acer/aspire_vn7_572g/die.c b/src/mainboard/acer/aspire_vn7_572g/die.c new file mode 100644 index 0000000000..ed459e7602 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/die.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +void die_notify(void) +{ + if (ENV_POSTCAR) { + return; + } + + /* Make SATA LED blink */ + while (1) { + gpio_set(GPP_E8, 1); + mdelay(100); + gpio_set(GPP_E8, 0); + mdelay(100); + } +} diff --git a/src/mainboard/acer/aspire_vn7_572g/dsdt.asl b/src/mainboard/acer/aspire_vn7_572g/dsdt.asl new file mode 100644 index 0000000000..2944688fe1 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/dsdt.asl @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +DefinitionBlock( + "dsdt.aml", + "DSDT", + ACPI_DSDT_REV_2, + OEM_ID, + ACPI_TABLE_CREATOR, + 0x20141018 // OEM revision +) +{ + #include + #include + #include + #include + #include + + /* SW SMI ports */ + OperationRegion (DPRT, SystemIO, 0xB2, 2) + Field (DPRT, ByteAcc, Lock, Preserve) + { + SSMP, 8, + SSDP, 8 + } + + Name (ESMI, 0xDD) // NOTE: Could insert into SSDT at runtime + /* Returns a non-zero integer if SMI function failed */ + Method (TRPS, 3, Serialized) + { + Debug = Concatenate ("SMIF: ", ToHexString (Arg0)) + Debug = Concatenate ("Param0: ", ToHexString (Arg1)) + Debug = Concatenate ("Param1: ", ToHexString (Arg2)) + + Local0 = Arg1 + Local0 |= (Arg2 << 4) + Debug = Concatenate ("Local0: ", ToHexString (Local0)) + + SMIF = Arg0 + SSDP = Local0 + /* NOTE: To use a general IO trap, program the range + into a PCR_PSTH_TRPREGx. Otherwise, this is APM. */ + SSMP = ESMI + Return (SMIF) + } + + Device (\_SB.PCI0) + { + #include + #include + #include "acpi/brightness_levels.asl" + } + + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/acer/aspire_vn7_572g/ec.c b/src/mainboard/acer/aspire_vn7_572g/ec.c new file mode 100644 index 0000000000..570e2829f3 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/ec.c @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include "include/ec.h" + +/* + * Notes: + * - ACPI "CMDB": Writing to this offset is equivalent to sending commands. + * The CMDx bytes contain the command parameters. + * + * TODO - Implement: + * - Commands: 0x58, 0xE1 and 0xE2 + * - 0x51, 0x52: EC flash write? + * - ACPI CMDB: 0x63 and 0x64, 0xC7 + * - 0x0B: Flash lock/write (Set offset 0x0B?) + * - Key/recovery detection? + * + * Vendor's protocols: + * - Only read and write are used. + * - Query, ACPI "CMDB" processing and command 58 are unused. + * - Equivalent KbcPeim is an unused PPI. + * + * NB: Also look for potential EC library + */ + +#define EC_INDEX_IO_PORT 0x1200 +#define EC_INDEX_IO_HIGH_ADDR_PORT (EC_INDEX_IO_PORT + 1) +#define EC_INDEX_IO_LOW_ADDR_PORT (EC_INDEX_IO_PORT + 2) +#define EC_INDEX_IO_DATA_PORT (EC_INDEX_IO_PORT + 3) + +uint8_t ec_cmd_90_read(uint8_t addr) +{ + /* EC ports: 0x62/0x66 */ + send_ec_command(0x90); + send_ec_data(addr); + return recv_ec_data(); +} + +void ec_cmd_91_write(uint8_t addr, uint8_t data) +{ + /* EC ports: 0x62/0x66 */ + send_ec_command(0x91); + send_ec_data(addr); + send_ec_data(data); +} + +uint8_t ec_cmd_94_query(void) +{ + send_ec_command(0x94); + return recv_ec_data(); +} + +uint8_t ec_idx_read(uint16_t addr) +{ + outb((uint8_t) (addr >> 8), EC_INDEX_IO_HIGH_ADDR_PORT); + outb((uint8_t) addr, EC_INDEX_IO_LOW_ADDR_PORT); + return inb(EC_INDEX_IO_DATA_PORT); +} + +void ec_idx_write(uint16_t addr, uint8_t data) +{ + outb((uint8_t) (addr >> 8), EC_INDEX_IO_HIGH_ADDR_PORT); + outb((uint8_t) addr, EC_INDEX_IO_LOW_ADDR_PORT); + outb(data, EC_INDEX_IO_DATA_PORT); +} + +/* TODO: Check if ADC is valid. Are there 4, or actually 8 ADCs? */ +uint16_t read_ec_adc_converter(uint8_t adc) +{ + uint8_t adc_converters_enabled; // Contains some ADCs and some DACs + uint8_t idx_data; + uint16_t adc_data; + + /* Backup enabled ADCs */ + adc_converters_enabled = ec_idx_read(0xff15); // ADDAEN + + /* Enable desired ADC in bitmask (not enabled by EC FW, not used by vendor FW) */ + ec_idx_write(0xff15, adc_converters_enabled | ((1 << adc) & 0xf)); // ADDAEN + + /* Sample the desired ADC in binary field; OR the start bit */ + ec_idx_write(0xff18, ((adc << 1) & 0xf) | 1); // ADCTRL + + /* Read the desired ADC */ + idx_data = ec_idx_read(0xff19); // ADCDAT + adc_data = (idx_data << 2); + /* Lower 2-bits of 10-bit ADC are in high bits of next register */ + idx_data = ec_idx_read(0xff1a); // ECIF + adc_data |= ((idx_data & 0xc0) >> 6); + + /* Restore enabled ADCs */ + ec_idx_write(0xff15, adc_converters_enabled); // ADDAEN + + return adc_data; +} diff --git a/src/mainboard/acer/aspire_vn7_572g/gma-mainboard.ads b/src/mainboard/acer/aspire_vn7_572g/gma-mainboard.ads new file mode 100644 index 0000000000..fc8bacc933 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/gma-mainboard.ads @@ -0,0 +1,16 @@ +-- SPDX-License-Identifier: GPL-2.0-only + +with HW.GFX.GMA; +with HW.GFX.GMA.Display_Probing; + +use HW.GFX.GMA; +use HW.GFX.GMA.Display_Probing; + +private package GMA.Mainboard is + + ports : constant Port_List := + (eDP, + HDMI1, + others => Disabled); + +end GMA.Mainboard; diff --git a/src/mainboard/acer/aspire_vn7_572g/gpio.c b/src/mainboard/acer/aspire_vn7_572g/gpio.c new file mode 100644 index 0000000000..ebb954f3a8 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/gpio.c @@ -0,0 +1,374 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "include/gpio.h" + +/* + * TODO: Vendor configures many NC pads as _TERM_GPO. Why? + * - On direction: Are some of these comments illusory? At least some pads + * are bidirectional on the other side of the GPIO. + */ +/* NB: Do not reconfigure pads used by Optimus, their assertion state may be lost */ + +/* + * TODO: Newgate-SLS and Rayleigh-SLS have PCH-H and use the same ProgramGPIOPei module. + * The GPIO tables retrieved from PCDs are ignored. However, progress on those SKUs + * is held up because the final table passed to function similar to RC's + * GpioConfigureSklPch() is neither, but a zero-assigned variable. The code may be + * computing and dereferencing address pointers from a blob of internal data. + */ + +/* Pad configuration was generated automatically using intelp2m utility */ +static const struct pad_config gpio_table[] = { + + /* ------- GPIO Community 0 ------- */ + + /* ------- GPIO Group GPP_A ------- */ + // RCIN# <= H_RCIN# + PAD_CFG_NF(GPP_A0, NONE, DEEP, NF1), + // LAD0 (ESPI_IO0) <=> LPC_AD_CPU_P0 + PAD_CFG_NF(GPP_A1, NATIVE, DEEP, NF1), + // LAD1 (ESPI_IO1) <=> LPC_AD_CPU_P1 + PAD_CFG_NF(GPP_A2, NATIVE, DEEP, NF1), + // LAD2 (ESPI_IO2) <=> LPC_AD_CPU_P2 + PAD_CFG_NF(GPP_A3, NATIVE, DEEP, NF1), + // LAD3 (ESPI_IO3) <=> LPC_AD_CPU_P3 + PAD_CFG_NF(GPP_A4, NATIVE, DEEP, NF1), + // LFRAME# (ESPI_CS#) => LPC_FRAME#_CPU + PAD_CFG_NF(GPP_A5, NONE, DEEP, NF1), + // SERIRQ <=> INT_SERIRQ + PAD_CFG_NF(GPP_A6, NONE, DEEP, NF1), + // PIRQA# = PIRQA# + PAD_CFG_NF(GPP_A7, NONE, DEEP, NF1), + // CLKRUN# <= PM_CLKRUN#_EC + PAD_CFG_NF(GPP_A8, NONE, DEEP, NF1), + // CLKOUT_LPC0 (ESPI_CLK) <= LPC_CLK_CPU_P0 + PAD_CFG_NF(GPP_A9, DN_20K, DEEP, NF1), + // CLKOUT_LPC1 <= LPC_CLK_CPU_P1 + PAD_CFG_NF(GPP_A10, DN_20K, DEEP, NF1), + // GPIO (PME#) // NC + PAD_CFG_TERM_GPO(GPP_A11, 1, DN_20K, DEEP), + // GPIO (SX_EXIT_HOLDOFF#/BM_BUSY#/ISH_GP6) <= GC6_FB_EN + PAD_CFG_GPI_TRIG_OWN(GPP_A12, NONE, DEEP, OFF, ACPI), + // SUSWARN#/SUSPWRDNACK = PM_SUSACK# + PAD_CFG_NF(GPP_A13, NONE, DEEP, NF1), + // SUS_STAT# (ESPI_RESET#) => PM_SUS_STAT# + PAD_CFG_NF(GPP_A14, NONE, DEEP, NF1), + // SUS_ACK# = PM_SUSACK# + PAD_CFG_NF(GPP_A15, DN_20K, DEEP, NF1), + // GPIO (SD_1P8_SEL) // NC + PAD_NC(GPP_A16, DN_20K), + // GPIO (SD_PWR_EN#/ISH_GP7) // NC + PAD_NC(GPP_A17, DN_20K), + // GPIO (ISH_GP0) => GSENSOR_INT# + PAD_CFG_GPI_TRIG_OWN(GPP_A18, NONE, DEEP, OFF, ACPI), + // GPIO (ISH_GP1) // NC + PAD_NC(GPP_A19, DN_20K), + // GPIO (ISH_GP3) // NC + PAD_NC(GPP_A21, DN_20K), + // GPIO (ISH_GP4) <= GPU_EVENT# + PAD_CFG_GPO(GPP_A22, 1, DEEP), + // GPIO (ISH_GP5) // NC + PAD_NC(GPP_A23, DN_20K), + + /* ------- GPIO Group GPP_B ------- */ + // CORE_VID0 // V0.85A_VID0 + PAD_CFG_NF(GPP_B0, NONE, DEEP, NF1), + // CORE_VID1 // V0.85A_VID1 + PAD_CFG_NF(GPP_B1, NONE, DEEP, NF1), + // GPIO (CPU_GP2) <= TP_IN# + // TODO: APIC-routed pads don't have host owners? + PAD_CFG_GPI_APIC_HIGH(GPP_B3, NONE, DEEP), + // SRCCLKREQ0# <= PEG_CLKREQ_CPU# + PAD_CFG_NF(GPP_B5, NONE, DEEP, NF1), + // SRCCLKREQ1# <= LAN_CLKREQ_CPU# + PAD_CFG_NF(GPP_B6, NONE, DEEP, NF1), + // SRCCLKREQ2# <= WLAN_CLKREQ_CPU# + PAD_CFG_NF(GPP_B7, NONE, DEEP, NF1), + // SRCCLKREQ3# <= MSATA_CLKREQ_CPU# + PAD_CFG_NF(GPP_B8, NONE, DEEP, NF1), + // SRCCLKREQ4# // SRCCLKREQ4# ("Remove TBT") + PAD_CFG_NF(GPP_B9, NONE, DEEP, NF1), + // SRCCLKREQ5# // SRCCLKREQ5# + PAD_CFG_NF(GPP_B10, NONE, DEEP, NF1), + // GPIO (EXT_PWR_GATE#) = EXT_PWR_GATE# + PAD_CFG_TERM_GPO(GPP_B11, 1, DN_20K, DEEP), + // GPIO (SLP_S0#) // NC + PAD_CFG_TERM_GPO(GPP_B12, 1, DN_20K, DEEP), + // PLTRST# => PLT_RST# + PAD_CFG_NF(GPP_B13, NONE, DEEP, NF1), + // GPIO (SPKR) => HDA_SPKR (Strap - Top Swap Override) + PAD_CFG_TERM_GPO(GPP_B14, 1, DN_20K, DEEP), + // GPIO (GSPI0_CS#) = TOUCH_DET# + PAD_CFG_GPO(GPP_B15, 0, DEEP), + // GPIO (GSPI0_CLK) // NC + PAD_CFG_GPO(GPP_B16, 0, DEEP), + // GPIO (GSPI0_MISO) // NC ("Remove TBT") + PAD_CFG_GPI_SCI(GPP_B17, DN_20K, DEEP, EDGE_SINGLE, INVERT), + // GPIO (GSPI0_MOSI) => GPP_B18/GSPI0_MOSI (Strap - No reboot) + PAD_CFG_TERM_GPO(GPP_B18, 1, DN_20K, DEEP), + // GPIO (GSPI1_CS#) => RTC_DET# + PAD_CFG_GPI_TRIG_OWN(GPP_B19, NONE, DEEP, OFF, ACPI), + // GPIO (GSPI1_CLK) <= PSW_CLR# + PAD_CFG_GPI_TRIG_OWN(GPP_B20, DN_20K, DEEP, OFF, ACPI), + // GPIO (GSPI1_MOSI) => GPP_B22/GSPI1_MOSI (Strap - Boot BIOS strap) + PAD_CFG_TERM_GPO(GPP_B22, 1, DN_20K, DEEP), + // GPIO (SML1ALERT#/PCHHOT#) => GPP_B23 (Strap) + PAD_CFG_TERM_GPO(GPP_B23, 1, DN_20K, DEEP), + + /* ------- GPIO Community 1 ------- */ + + /* ------- GPIO Group GPP_C ------- */ + // SMBCLK <= SMB_CLK + PAD_CFG_NF(GPP_C0, NONE, DEEP, NF1), + // SMBDATA = SMB_DATA + PAD_CFG_NF(GPP_C1, DN_20K, DEEP, NF1), + // GPIO (SMBALERT#) => GPP_C2 (Strap - TLS Confidentiality) + PAD_CFG_TERM_GPO(GPP_C2, 1, DN_20K, DEEP), + // GPIO (SML0CLK) // NC + PAD_CFG_TERM_GPO(GPP_C3, 1, DN_20K, DEEP), + // GPIO (SML0DATA) // NC + PAD_CFG_TERM_GPO(GPP_C4, 1, DN_20K, DEEP), + // GPIO (SML0ALERT#) // NC (Strap - eSPI or LPC) + PAD_CFG_TERM_GPO(GPP_C5, 1, DN_20K, DEEP), + // RESERVED (SML1CLK) <=> SML1_CLK (KBC) + // RESERVED (SML1DATA) <=> SML1_DATA (KBC) + // GPIO (UART0_RXD) // NC + PAD_CFG_TERM_GPO(GPP_C8, 1, DN_20K, DEEP), + // GPIO (UART0_TXD) // NC + PAD_CFG_TERM_GPO(GPP_C9, 1, DN_20K, DEEP), + // GPIO (UART0_RTS#) // NC + PAD_CFG_TERM_GPO(GPP_C10, 1, DN_20K, DEEP), + // GPIO (UART0_CTS#) // NC + PAD_CFG_TERM_GPO(GPP_C11, 1, DN_20K, DEEP), + // GPIO (UART1_RXD/ISH_UART1_RXD) // NC + PAD_NC(GPP_C12, DN_20K), + // GPIO (UART1_TXD/ISH_UART1_TXD) // NC + PAD_NC(GPP_C13, DN_20K), + // GPIO (UART1_RTS#/ISH_UART1_RTS#) // NC + PAD_NC(GPP_C14, DN_20K), + // GPIO (UART1_CTS#/ISH_UART1_CTS#) // NC + PAD_NC(GPP_C15, DN_20K), + // I2C0_SDA <=> I2C0_DATA_CPU (Touch Panel) + PAD_CFG_NF(GPP_C16, NONE, DEEP, NF1), + // I2C0_SCL <=> I2C0_CLK_CPU (Touch Panel) + PAD_CFG_NF(GPP_C17, NONE, DEEP, NF1), + // I2C1_SDA <=> I2C1_DATA_CPU (Touch Pad) + PAD_CFG_NF(GPP_C18, NONE, DEEP, NF1), + // I2C1_SCL <=> I2C1_CLK_CPU (Touch Pad) + PAD_CFG_NF(GPP_C19, NONE, DEEP, NF1), + // UART2_RXD = LPSS_UART2_RXD + PAD_CFG_NF(GPP_C20, NONE, DEEP, NF1), + // UART2_TXD = LPSS_UART2_TXD + PAD_CFG_NF(GPP_C21, NONE, DEEP, NF1), + // UART2_RTS# = LPSS_UART2_RTS# + PAD_CFG_NF(GPP_C22, NONE, DEEP, NF1), + // UART2_CTS# = LPSS_UART2_CTS# + PAD_CFG_NF(GPP_C23, NONE, DEEP, NF1), + + /* ------- GPIO Group GPP_D ------- */ + // GPIO (SPI1_CS#) // NC + PAD_CFG_TERM_GPO(GPP_D0, 1, DN_20K, DEEP), + // GPIO (SPI1_CLK) // NC + PAD_CFG_TERM_GPO(GPP_D1, 1, DN_20K, DEEP), + // SPI1_MISO // NC + PAD_CFG_NF(GPP_D2, NONE, DEEP, NF1), + // SPI1_MOSI // NC + PAD_CFG_NF(GPP_D3, NONE, DEEP, NF1), + // GPIO (FLASHTRIG) // NC + PAD_CFG_TERM_GPO(GPP_D4, 1, DN_20K, DEEP), + // GPIO (ISH_I2C0_SDA) // NC + PAD_NC(GPP_D5, DN_20K), + // GPIO (ISH_I2C0_SCL) // NC + PAD_NC(GPP_D6, DN_20K), + // GPIO (ISH_I2C1_SDA) // NC + PAD_NC(GPP_D7, DN_20K), + // GPIO (ISH_I2C1_SCL) // NC + PAD_NC(GPP_D8, DN_20K), + // GPIO // NC + PAD_CFG_GPI_TRIG_OWN(GPP_D9, NONE, DEEP, LEVEL, ACPI), + // GPIO => TOUCH_S_RST# + PAD_CFG_GPI_TRIG_OWN(GPP_D10, NONE, DEEP, LEVEL, ACPI), + // GPIO // NC + PAD_CFG_GPI_TRIG_OWN(GPP_D11, NONE, DEEP, LEVEL, ACPI), + // GPIO // NC ("Remove TBT") + PAD_CFG_GPI_TRIG_OWN(GPP_D12, NONE, DEEP, LEVEL, ACPI), + // GPIO (ISH_UART0_RXD/SML0BDATA/I2C4B_SDA) // NC + PAD_CFG_TERM_GPO(GPP_D13, 1, DN_20K, DEEP), + // GPIO (ISH_UART0_TXD/SML0BCLK/I2C4B_SCL) // NC + PAD_CFG_TERM_GPO(GPP_D14, 1, DN_20K, DEEP), + // GPIO (ISH_UART0_RTS#) // NC + PAD_CFG_TERM_GPO(GPP_D15, 1, DN_20K, DEEP), + // GPIO (ISH_UART0_CTS#/SML0BALERT#) // NC + PAD_CFG_TERM_GPO(GPP_D16, 1, DN_20K, DEEP), + // GPIO (DMIC_CLK1) // NC + PAD_NC(GPP_D17, DN_20K), + // GPIO (DMIC_DATA1) // NC + PAD_NC(GPP_D18, DN_20K), + // DMIC_CLK0 => DMIC_CLK_CON_R + PAD_CFG_NF(GPP_D19, NONE, DEEP, NF1), + // DMIC_DATA0 => DMIC_PCH_DATA + PAD_CFG_NF(GPP_D20, NONE, DEEP, NF1), + // SPI1_IO2 // NC + PAD_CFG_NF(GPP_D21, NONE, DEEP, NF1), + // SPI1_IO3 // NC + PAD_CFG_NF(GPP_D22, NONE, DEEP, NF1), + // GPIO (I2S_MCLK) // NC + PAD_NC(GPP_D23, DN_20K), + + /* ------- GPIO Group GPP_E ------- */ + // SATAXPCIE0 (SATAGP0) = SATAGP0 + PAD_CFG_NF(GPP_E0, NONE, DEEP, NF1), + // SATAXPCIE1 (SATAGP1) // NC + PAD_CFG_NF(GPP_E1, NONE, DEEP, NF1), + // SATAXPCIE2 (SATAGP2) = SATAGP2 + PAD_CFG_NF(GPP_E2, NONE, DEEP, NF1), + // GPIO (CPU_GP0) // NC + PAD_CFG_GPO(GPP_E3, 1, DEEP), + // GPIO (DEVSLP0) // NC ("Remove DEVSLP_PCH") + PAD_CFG_TERM_GPO(GPP_E4, 1, DN_20K, DEEP), + // GPIO (DEVSLP1) // NC + PAD_CFG_TERM_GPO(GPP_E5, 1, DN_20K, DEEP), + // GPIO (DEVSLP2) // NC + PAD_CFG_TERM_GPO(GPP_E6, 1, DN_20K, DEEP), + // GPIO (CPU_GP1) <= TOUCH_INT# + PAD_CFG_GPI_APIC_LOW(GPP_E7, NONE, DEEP), + // SATALED# = SATA_LED# + PAD_CFG_NF(GPP_E8, NONE, DEEP, NF1), + // USB2_OC0# = USB_OC# + PAD_CFG_NF(GPP_E9, NONE, DEEP, NF1), + // USB2_OC1# // USB_OC# + PAD_CFG_NF(GPP_E10, NONE, DEEP, NF1), + // USB2_OC2# // USB_OC# + PAD_CFG_NF(GPP_E11, NONE, DEEP, NF1), + // USB2_OC3# // USB_OC# + PAD_CFG_NF(GPP_E12, NONE, DEEP, NF1), + // DDPB_HPD0 <= DDI1_HDMI_HPD_CPU + PAD_CFG_NF(GPP_E13, NONE, DEEP, NF1), + // DDPC_HPD1 // NC ("Remove HPD") + PAD_CFG_NF(GPP_E14, NONE, DEEP, NF1), + // GPIO (DDPD_HPD2) <= EC_SMI# + // FIXME: Vendor configures as _TERM_GPO. Why? + PAD_CFG_GPI_SMI(GPP_E15, NONE, DEEP, LEVEL, INVERT), + // GPIO (DDPE_HPD3) <= EC_SCI# + PAD_CFG_GPI_SCI(GPP_E16, NONE, PLTRST, LEVEL, INVERT), + // EDP_HPD <= eDP_HPD_CPU + PAD_CFG_NF(GPP_E17, NONE, DEEP, NF1), + // DDPB_CTRLCLK <=> DDI1_HDMI_CLK_CPU + PAD_CFG_NF(GPP_E18, NONE, DEEP, NF1), + // DDPB_CTRLDATA <=> DDI1_HDMI_DATA_CPU (Strap - Display Port B Detected) + PAD_CFG_NF(GPP_E19, DN_20K, DEEP, NF1), + // DDPC_CTRLCLK // NC + PAD_CFG_NF(GPP_E20, NONE, DEEP, NF1), + // DDPC_CTRLDATA => DDPC_CDA (Strap - Display Port C Detected) + PAD_CFG_NF(GPP_E21, DN_20K, DEEP, NF1), + // GPIO // NC + // TODO: Vendor configures as _GPIO_BIDIRECT. Why? + PAD_NC(GPP_E22, NONE), + // GPIO => DDPD_CDA (Strap - Display Port D Detected) + PAD_CFG_TERM_GPO(GPP_E23, 1, DN_20K, DEEP), + + /* ------- GPIO Community 2 ------- */ + + /* -------- GPIO Group GPD -------- */ + // GPIO (BATLOW#) = BATLOW + PAD_CFG_TERM_GPO(GPD0, 1, DN_20K, PWROK), + // ACPRESENT <= AC_PRESENT + PAD_CFG_NF(GPD1, NONE, PWROK, NF1), + // GPIO (LAN_WAKE#) = GPD2/LAN_WAKE# + PAD_CFG_TERM_GPO(GPD2, 1, DN_20K, PWROK), + // PWRBTN# <= PM_PWRBTN# + PAD_CFG_NF(GPD3, UP_20K, PWROK, NF1), + // SLP_S3# => PM_SLP_S3# + PAD_CFG_NF(GPD4, NONE, PWROK, NF1), + // SLP_S4# => PM_SLP_S4# + PAD_CFG_NF(GPD5, NONE, PWROK, NF1), + // SLP_A# // NC + PAD_CFG_NF(GPD6, DN_20K, PWROK, NF1), + // GPIO (RSVD#AT15) // NC + PAD_CFG_TERM_GPO(GPD7, 1, DN_20K, PWROK), + // SUSCLK => SUS_CLK_CPU + PAD_CFG_NF(GPD8, NONE, PWROK, NF1), + // SLP_WLAN# // NC + PAD_CFG_NF(GPD9, DN_20K, PWROK, NF1), + // SLP_S5# // NC + PAD_CFG_NF(GPD10, DN_20K, PWROK, NF1), + // GPIO (LANPHYPC) // NC + PAD_CFG_TERM_GPO(GPD11, 1, DN_20K, PWROK), + + /* ------- GPIO Community 3 ------- */ + + /* ------- GPIO Group GPP_F ------- */ + // GPIO (I2S2_SCLK) // NC + PAD_NC(GPP_F0, DN_20K), + // GPIO (I2S2_SFRM) // NC + PAD_NC(GPP_F1, DN_20K), + // GPIO (I2S2_TXD) // NC + PAD_NC(GPP_F2, DN_20K), + // GPIO (I2S2_RXD) // NC + PAD_NC(GPP_F3, DN_20K), + // GPIO (I2C2_SDA) // NC + PAD_NC(GPP_F4, DN_20K), + // GPIO (I2C2_SCL) // NC + PAD_NC(GPP_F5, DN_20K), + // GPIO (I2C3_SDA) // NC + PAD_NC(GPP_F6, DN_20K), + // GPIO (I2C3_SCL) // NC + PAD_NC(GPP_F7, DN_20K), + // GPIO (I2C4_SDA) // NC + PAD_CFG_TERM_GPO(GPP_F8, 1, DN_20K, DEEP), + // GPIO (I2C4_SCL) // NC + PAD_CFG_TERM_GPO(GPP_F9, 1, DN_20K, DEEP), + // GPIO (I2C5_SDA/ISH_I2C2_SDA) // NC + PAD_NC(GPP_F10, DN_20K), + // GPIO (I2C5_SCL/ISH_I2C2_SCL) // NC + PAD_NC(GPP_F11, DN_20K), + // GPIO (EMMC_CMD) // NC + PAD_NC(GPP_F12, DN_20K), + // GPIO (EMMC_DATA0) // NC + PAD_NC(GPP_F13, DN_20K), + // GPIO (EMMC_DATA1) // NC + PAD_NC(GPP_F14, DN_20K), + // GPIO (EMMC_DATA2) // NC + PAD_NC(GPP_F15, DN_20K), + // GPIO (EMMC_DATA3) // NC + PAD_NC(GPP_F16, DN_20K), + // GPIO (EMMC_DATA4) // NC + PAD_NC(GPP_F17, DN_20K), + // GPIO (EMMC_DATA5) // NC + PAD_NC(GPP_F18, DN_20K), + // GPIO (EMMC_DATA6) // NC + PAD_NC(GPP_F19, DN_20K), + // GPIO (EMMC_DATA7) // NC + PAD_NC(GPP_F20, DN_20K), + // GPIO (EMMC_RCLK) // NC + PAD_NC(GPP_F21, DN_20K), + // GPIO (EMMC_CLK) // NC + PAD_NC(GPP_F22, DN_20K), + // GPIO // NC + PAD_CFG_GPI_APIC_HIGH(GPP_F23, NONE, DEEP), + + /* ------- GPIO Group GPP_G ------- */ + // GPIO (SD_CMD) // NC + PAD_NC(GPP_G0, DN_20K), + // GPIO (SD_DATA0) // NC + PAD_NC(GPP_G1, DN_20K), + // GPIO (SD_DATA1) // NC + PAD_NC(GPP_G2, DN_20K), + // GPIO (SD_DATA2) // NC + PAD_NC(GPP_G3, DN_20K), + // GPIO (SD_DATA3) // NC + // TODO: Vendor configures as _GPO. Why? + PAD_NC(GPP_G4, NONE), + // GPIO (SD_CD#) // NC + PAD_NC(GPP_G5, DN_20K), + // GPIO (SD_CLK) // NC + PAD_NC(GPP_G6, DN_20K), + // GPIO (SD_WP) // NC + PAD_NC(GPP_G7, DN_20K), +}; + +void mainboard_config_stage_gpios(void) +{ + gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); +} diff --git a/src/mainboard/acer/aspire_vn7_572g/gpio_early.c b/src/mainboard/acer/aspire_vn7_572g/gpio_early.c new file mode 100644 index 0000000000..ad66661273 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/gpio_early.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "include/gpio.h" + +/* Early pad configuration */ +static const struct pad_config early_gpio_table[] = { + // GPIO (ISH_GP2) = DGPU_PRESENT + PAD_CFG_GPI_TRIG_OWN(GPP_A20, NONE, DEEP, OFF, ACPI), + // GPIO (VRALERT#) <= DGPU_PWROK + PAD_CFG_GPI_TRIG_OWN(GPP_B2, NONE, DEEP, OFF, ACPI), + // GPIO (CPU_GP3) => DGPU_HOLD_RST# + PAD_CFG_GPO(GPP_B4, 1, DEEP), + // GPIO (GSPI1_MISO) => DGPU_PWR_EN# + PAD_CFG_TERM_GPO(GPP_B21, 1, DN_20K, DEEP), + // UART2_RXD = LPSS_UART2_RXD + PAD_CFG_NF(GPP_C20, NONE, DEEP, NF1), + // UART2_TXD = LPSS_UART2_TXD + PAD_CFG_NF(GPP_C21, NONE, DEEP, NF1), + // SATALED# = SATA_LED# + PAD_CFG_NF(GPP_E8, NONE, DEEP, NF1), +}; + +void mainboard_config_stage_gpios(void) +{ + gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table)); +} diff --git a/src/mainboard/acer/aspire_vn7_572g/hda_verb.c b/src/mainboard/acer/aspire_vn7_572g/hda_verb.c new file mode 100644 index 0000000000..20197d1d22 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/hda_verb.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* TODO: Convert to macros */ + +#include + +const u32 cim_verb_data[] = { + /* --- Codec #0 --- */ + /* coreboot specific header */ + 0x10ec0255, /* Codec Vendor / Device ID: Realtek ALC255 */ + 0x10251037, /* Subsystem ID */ + 20, /* Number of jacks (NID entries) */ + + /* Codec Address: Bits 31:28 */ + /* Node ID: Bits 27:20 */ + /* Verb ID: Bits 19:8 / Bits 19:16 */ + /* Payload: Bits 7:0 / Bits 15:0 */ + + /* Reset Codec */ + AZALIA_RESET(0x1), + /* NOTE: Corrected the table in vendor FW, programming subsystem after reset */ + /* HDA Codec Subsystem ID Verb Table */ + AZALIA_SUBVENDOR(0, 0x10251037), + + /* Pin Widget Verb Table */ + AZALIA_PIN_CFG(0, 0x12, 0x411111c0), + AZALIA_PIN_CFG(0, 0x14, 0x90172120), /* Speaker */ + AZALIA_PIN_CFG(0, 0x17, 0x40000000), + AZALIA_PIN_CFG(0, 0x18, AZALIA_PIN_CFG_NC(0)), + AZALIA_PIN_CFG(0, 0x19, AZALIA_PIN_CFG_NC(0)), + AZALIA_PIN_CFG(0, 0x1a, AZALIA_PIN_CFG_NC(0)), + AZALIA_PIN_CFG(0, 0x1b, AZALIA_PIN_CFG_NC(0)), + AZALIA_PIN_CFG(0, 0x1d, 0x40700001), + AZALIA_PIN_CFG(0, 0x1e, AZALIA_PIN_CFG_NC(0)), + AZALIA_PIN_CFG(0, 0x21, 0x02211030), /* Headphone */ + + /* + * See data blob in "InstallPchHdaVerbTablePei" of vendor firmware + * (some appear in https://github.com/torvalds/linux/blob/master/sound/pci/hda/patch_realtek.c). + * - Largely coefficient programming (undocumented): Select coeff; write data + * - Also programs speaker amplifier gain + * - Sets speaker output + * NOTE: NID 0x20 holds the "Realtek Defined Hidden registers" + */ + 0x02050038, /* Set coeff idx: 0x38 */ + 0x02048981, /* Set processing coeff: 0x8981 */ + 0x02050045, /* Set coeff idx: 0x45 */ + 0x0204c489, /* Set processing coeff: 0xc489 */ + + 0x02050037, /* Set coeff idx: 0x37 */ + 0x02044a05, /* Set processing coeff: 0x4a05 */ + 0x05750003, /* Set coeff idx on NID 0x57?: 0x3 */ + 0x057486a6, /* Set processing coeff on NID 0x57?: 0x86a6 */ + + 0x02050046, /* Set coeff idx: 0x46 */ + 0x02040004, /* Set processing coeff: 0x4 */ + 0x0205001b, /* Set coeff idx: 0x1b */ + 0x02040a0b, /* Set processing coeff: 0xa0b */ + + 0x02050008, /* Set coeff idx: 0x8 */ + 0x02046a0c, /* Set processing coeff: 0x6a0c */ + 0x02050009, /* Set coeff idx: 0x9 */ + 0x0204e003, /* Set processing coeff: 0xe003 */ + + 0x0205000a, /* Set coeff idx: 0xa */ + 0x02047770, /* Set processing coeff: 0x7770 */ + 0x02050040, /* Set coeff idx: 0x40 */ + 0x02049800, /* Set processing coeff: 0x9800 */ + + 0x02050010, /* Set coeff idx: 0x10 */ + 0x02040e20, /* Set processing coeff: 0xe20 */ + 0x0205000d, /* Set coeff idx: 0xd */ + 0x02042801, /* Set processing coeff: 0x2801 */ + + 0x0143b000, /* Sends unknown verb 0x3B to speaker */ + 0x0143b000, /* Repeated for units? */ + 0x01470740, /* Set widget control on speaker: Output; VrefEn: Hi-Z (disabled) */ + 0x01470740, /* Repeated for units? */ + + 0x01470740, /* Repeated for units? */ + 0x01470740, /* Repeated for units? */ + 0x02050010, /* Set coeff idx: 0x10 */ + 0x02040f20, /* Set processing coeff: 0xf20 */ + + /* --- Codec #2 --- */ + /* coreboot specific header */ + 0x80862809, /* Codec Vendor / Device ID: Intel Skylake HDMI */ + 0x80860101, /* Subsystem ID */ + 5, /* Number of jacks (NID entries) */ + + /* Codec Address: Bits 31:28 */ + /* Node ID: Bits 27:20 */ + /* Verb ID: Bits 19:8 */ + /* Payload: Bits 7:0 */ + + /* NOTE: Corrected the table in vendor FW, using codec address 0x2, not 0x0 */ + + /* Enable the third converter and pin first */ + 0x20878101, + 0x20878101, + 0x20878101, + 0x20878101, + + /* Pin Widget Verb Table */ + AZALIA_PIN_CFG(2, 0x05, 0x18560010), + AZALIA_PIN_CFG(2, 0x06, 0x18560020), + AZALIA_PIN_CFG(2, 0x07, 0x18560030), + + /* Disable the third converter and third pin */ + 0x20878100, + 0x20878100, + 0x20878100, + 0x20878100, +}; + +const u32 pc_beep_verbs[] = {}; + +AZALIA_ARRAY_SIZES; diff --git a/src/mainboard/acer/aspire_vn7_572g/include/ec.h b/src/mainboard/acer/aspire_vn7_572g/include/ec.h new file mode 100644 index 0000000000..49651decfb --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/include/ec.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +uint8_t ec_cmd_90_read(uint8_t addr); +void ec_cmd_91_write(uint8_t addr, uint8_t data); +uint8_t ec_cmd_94_query(void); +uint8_t ec_idx_read(uint16_t addr); +void ec_idx_write(uint16_t addr, uint8_t data); +/* TODO: Check if ADC is valid. */ +uint16_t read_ec_adc_converter(uint8_t adc); + +#endif diff --git a/src/mainboard/acer/aspire_vn7_572g/include/gpio.h b/src/mainboard/acer/aspire_vn7_572g/include/gpio.h new file mode 100644 index 0000000000..ed8518ed64 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/include/gpio.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef MAINBOARD_GPIO_H +#define MAINBOARD_GPIO_H + +void mainboard_config_stage_gpios(void); + +#endif diff --git a/src/mainboard/acer/aspire_vn7_572g/mainboard.c b/src/mainboard/acer/aspire_vn7_572g/mainboard.c new file mode 100644 index 0000000000..eba9e9856e --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/mainboard.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "include/ec.h" +#include "include/gpio.h" + +static unsigned long mainboard_write_acpi_tables( + const struct device *device, unsigned long current, acpi_rsdp_t *rsdp) +{ + uintptr_t start_addr; + uintptr_t end_addr; + struct nhlt *nhlt; + + start_addr = current; + + nhlt = nhlt_init(); + if (!nhlt) { + return start_addr; + } + + /* Override subsystem ID */ + nhlt->subsystem_id = 0x10251037; + + /* 1 Channel DMIC array. */ + if (nhlt_soc_add_dmic_array(nhlt, 1) != 0) { + printk(BIOS_ERR, "Couldn't add 1CH DMIC array.\n"); + } + + /* 2 Channel DMIC array. */ + if (nhlt_soc_add_dmic_array(nhlt, 2) != 0) { + printk(BIOS_ERR, "Couldn't add 2CH DMIC array.\n"); + } + + end_addr = nhlt_soc_serialize(nhlt, start_addr); + + if (end_addr != start_addr) { + acpi_add_table(rsdp, (void *)start_addr); + } + + return end_addr; +} + +static void mainboard_enable(struct device *dev) +{ + install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_EDP, + GMA_INT15_PANEL_FIT_DEFAULT, + GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); + + if (CONFIG(INCLUDE_NHLT_BLOBS)) { + dev->ops->write_acpi_tables = mainboard_write_acpi_tables; + } +} + +/* Update the EC's clock. */ +static void ec_send_time(void) +{ + struct rtc_time time; + uint8_t ec_time_byte; + + rtc_get(&time); + + /* RTC time could be negative (before 2016) */ + int32_t ec_time = ((time.year << 26) + (time.mon << 22) + (time.mday << 17) + + (time.hour << 12) + (time.min << 6) + (time.sec) + /* 16 years */ + - 0x40000000); + + printk(BIOS_DEBUG, "EC: reporting present time 0x%x\n", ec_time); + send_ec_command(0xE0); + for (int i = 0; i < 4; i++) { + /* Shift bytes */ + ec_time_byte = (uint8_t) (ec_time >> (i * 8)); + printk(BIOS_DEBUG, "EC: Sending 0x%x (iteration %d)\n", ec_time_byte, i); + send_ec_data(ec_time_byte); + } + + printk(BIOS_DEBUG, "EC: response 0x%x\n", recv_ec_data()); +} + +static void ec_requests_time(void) +{ + /* This is executed as protocol notify in vendor's RtKbcDriver + when *CommonService protocol is installed. Effectively, + this code could execute from the entrypoint */ + uint8_t dat = ec_cmd_90_read(0x79); + if (dat & 1) { + ec_send_time(); + } +} + +/* + * Init from vendor's PeiOemModule. KbcPeim does not appear to be used + * (It implements commands also found in RtKbcDriver and SmmKbcDriver). + * + * Mostly, this puts the system back to sleep if the lid is closed during + * an S3 resume. + */ +static void ec_init(void) +{ + /* This is called via a "$FNC" in a PeiOemModule pointer table, + with "$DPX" on SiInit */ + outb(0x5A, 0x6C); // 6Ch is the EC sideband port + if (acpi_is_wakeup_s3()) { + /* "MLID" in LGMR-based memory map is equivalent to "ELID" in EC-based + memory map. Vendor firmware accesses through LGMR; remapped + - ec_cmd* function calls will not remapped */ + uint8_t power_state = ec_read(0x70); + if (!(power_state & 2)) { // Lid is closed + uint8_t out_data = ec_cmd_90_read(0x0A); + if (!(out_data & 2)) { + ec_cmd_91_write(0x0A, out_data | 2); + } + + /* Clear below events and go back to sleep */ + /* Clear ABase PM1_STS - RW/1C set bits */ + pmc_clear_pm1_status(); + /* Clear ABase GPE0_STS[127:96] - RW/1C set bits */ + uint32_t gpe_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS(GPE_STD)); + outl(gpe_sts, ACPI_BASE_ADDRESS + GPE0_STS(GPE_STD)); + /* Clear xHCI PM_CS[PME_Status] - RW/1C - + and disable xHCI PM_CS[PME_En] */ + pci_update_config16(PCH_DEV_XHCI, 0x74, ~0x100, 0x8000); + + /* Enter S3 sleep */ + pmc_enable_pm1_control(SLP_EN | (SLP_TYP_S3 << SLP_TYP_SHIFT)); + halt(); + } + } +} + +static void mainboard_init(void *chip_info) +{ + mainboard_config_stage_gpios(); + /* Notify EC */ + ec_init(); + /* Program the same 64K range of EC memory as vendor FW + - Open unconditionally, user can select whether ACPI uses LGMR */ + lpc_open_mmio_window(0xFE800000, 0x10000); + /* EC is notified of platform resets with UEFI firmware, but coreboot + does not offer this service to boards */ + ec_requests_time(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, + .init = mainboard_init, +}; diff --git a/src/mainboard/acer/aspire_vn7_572g/romstage.c b/src/mainboard/acer/aspire_vn7_572g/romstage.c new file mode 100644 index 0000000000..74e1438118 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/romstage.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +void mainboard_memory_init_params(FSPM_UPD *mupd) +{ + FSP_M_CONFIG *const mem_cfg = &mupd->FspmConfig; + + /* TODO: Search vendor FW for Dq/Dqs */ + struct spd_block blk = { + .addr_map = { 0x50, 0x52 }, + }; + const uint16_t rcomp_resistors[3] = { 121, 80, 100 }; + /* Also the default values in FSP binary */ + const uint16_t rcomp_targets[5] = { 100, 40, 40, 23, 40 }; + + get_spd_smbus(&blk); + dump_spd_info(&blk); + assert(blk.spd_array[0][0] != 0); + + assert(sizeof(mem_cfg->RcompResistor) == sizeof(rcomp_resistors)); + assert(sizeof(mem_cfg->RcompTarget) == sizeof(rcomp_targets)); + memcpy(mem_cfg->RcompResistor, rcomp_resistors, sizeof(mem_cfg->RcompResistor)); + memcpy(mem_cfg->RcompTarget, rcomp_targets, sizeof(mem_cfg->RcompTarget)); + + mem_cfg->CaVrefConfig = 2; + mem_cfg->DqPinsInterleaved = 1; + mem_cfg->MemorySpdDataLen = blk.len; + mem_cfg->MemorySpdPtr00 = (uintptr_t) blk.spd_array[0]; + mem_cfg->MemorySpdPtr10 = (uintptr_t) blk.spd_array[1]; + + mem_cfg->PchSataHsioRxGen3EqBoostMagEnable[1] = 1; + mem_cfg->PchSataHsioRxGen3EqBoostMag[1] = 1; +} diff --git a/src/mainboard/acer/aspire_vn7_572g/smihandler.c b/src/mainboard/acer/aspire_vn7_572g/smihandler.c new file mode 100644 index 0000000000..88ec10d190 --- /dev/null +++ b/src/mainboard/acer/aspire_vn7_572g/smihandler.c @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +/* + * TODO: Perform RE of protocols in vendor firmware: + * - gEfiSmmSxDispatch2ProtocolGuid + * - gEfiSmmPowerButtonDispatch2ProtocolGuid + * + * However, note that first glance suggests that no handlers + * will be very interesting and that gEfiSmmGpiDispatch2ProtocolGuid + * was unused (as I recall). + * + * Also, consider gEfiSmmIoTrapDispatch2ProtocolGuid, but + * this is less likely. + */ + +/* Keep in sync with dsdt.asl; could insert into SSDT at runtime */ +#define APM_CNT_BOARD_SMI 0xDD + +/* Toggle TURBO_MODE_DISABLE bit in IA32_MISC_ENABLE MSR + when requested by EC. */ +static void toggle_turbo_disable(uint8_t function_parameter_0) +{ + if (function_parameter_0 == 1) { + printk(BIOS_DEBUG, "EC: Enabling Intel Turbo Mode\n"); + msr_unset(IA32_MISC_ENABLE, 0x4000000000); + } else if (function_parameter_0 == 0) { + printk(BIOS_DEBUG, "EC: Disabling Intel Turbo Mode\n"); + msr_set(IA32_MISC_ENABLE, 0x4000000000); + } +} + +/* Set WiFi and BT enable bits in EC RAM. */ +static void enable_rf_by_capability(void) +{ + /* FIXME: We're not tracking (driver) 'capabilities' at the moment (must we?), + so we just enable WiFi and BT here. If this was tracked, then + bits may be cleared here */ + uint8_t rf_register = ec_read(0x71); + ec_write(0x71, rf_register | 0x03); +} + +/* Set OS capability bits in EC RAM. */ +static void handle_acpi_osys(void) +{ + uint8_t os_support; + + /* TODO: Add _OSI method support to coreboot and make this work */ + printk(BIOS_DEBUG, "GNVS.OSYS = %d\n", gnvs->unused_was_osys); + switch (gnvs->unused_was_osys) { + /* Linux */ + case 1000: + os_support = 64; + break; + /* Windows versions by year */ + case 2009: + os_support = 3; + break; + case 2012: + os_support = 4; + break; + case 2013: + os_support = 5; + break; + case 2015: + os_support = 6; + break; + /* Operating system unknown */ + default: + printk(BIOS_DEBUG, "GNVS.OSYS not supported!\n"); + printk(BIOS_DEBUG, "No capabilities!\n"); + os_support = 0; + break; + } + + ec_write(0x5C, os_support); +} + +/* Handles EC's _REG, _PTS and _WAK methods. + Partially involves setting EC RAM offsets based on GNVS.OSYS - OS capabilities? */ +static void handle_acpi_wake_event( + uint8_t function_parameter_0, uint8_t function_parameter_1) +{ + switch (function_parameter_0) { + case 1: + printk(BIOS_DEBUG, "EC: Called for _REG method - OS initialise\n"); + enable_rf_by_capability(); + handle_acpi_osys(); + // NOTE: Not handling (driver) 'capabilities' + break; + case 2: + printk(BIOS_DEBUG, "EC: Called for _PTS method - Entering sleep\n"); + // NOTE: Not saving (driver) 'capabilities' + // NOTE: Not saving and restoring EC RAM offset 0x4F + break; + case 3: + printk(BIOS_DEBUG, "EC: Called for _WAK method - Sleep resume\n"); + enable_rf_by_capability(); + handle_acpi_osys(); + // NOTE: Not saving and restoring EC RAM offset 0x4F + break; + default: + printk(BIOS_DEBUG, "function_parameter_0 is invalid!\n"); + break; + } +} + +/* TODO: Reverse engineer 0x80 function and implement if necessary */ +static void ec_smi_handler(uint8_t smif) +{ + uint8_t smm_data_port; + uint8_t function_parameter_0; + uint8_t function_parameter_1; + + /* Parameters encoded onto SMI data port because PRMx NVS are not present + - Callers must only use 4 bits per argument + - _PTS and _WAK are required to call in spec-compliant way */ + smm_data_port = inb(APM_STS); + function_parameter_0 = smm_data_port & ~0xF0; + function_parameter_1 = smm_data_port >> 4; + + printk(BIOS_DEBUG, "Function 0x%x(0x%x, 0x%x) called\n", + smif, function_parameter_0, function_parameter_1); + switch (smif) { + case 0x80: + printk(BIOS_WARNING, "Function 0x80 is unimplemented!\n"); + printk(BIOS_DEBUG, "Function calls offset 0 in ACER_BOOT_DEVICE_SERVICE_PROTOCOL_GUID\n"); + break; + case 0x81: + toggle_turbo_disable(function_parameter_0); + break; + case 0x82: + handle_acpi_wake_event(function_parameter_0, function_parameter_1); + break; + default: + /* Not handled */ + printk(BIOS_DEBUG, "Requested function is unknown!\n"); + return; + } + + /* + * gnvs->smif: + * - On success, the handler returns 0 + * - On failure, the handler returns a value != 0 + */ + gnvs->smif = 0; +} + +int mainboard_smi_apmc(u8 data) +{ + /* TODO: Continue SmmKbcDriver RE of common service registration and confirm */ + switch (data) { + case APM_CNT_BOARD_SMI: + if (gnvs) { + ec_smi_handler(gnvs->smif); + } + break; + case APM_CNT_ACPI_ENABLE: /* Events generate SCIs for OS */ + /* use 0x68/0x6C to prevent races with userspace */ + ec_set_ports(0x6C, 0x68); + /* discard all events */ + ec_clear_out_queue(); + /* Tests at runtime show this re-enables charging and battery reporting */ + send_ec_command(0xE9); /* Vendor implements using ACPI "CMDB" register" */ + send_ec_data(0x81); + /* TODO: Set touchpad GPP owner to ACPI? */ + break; + case APM_CNT_ACPI_DISABLE: /* Events generate SMIs for SMM */ + /* use 0x68/0x6C to prevent races with userspace */ + ec_set_ports(0x6C, 0x68); + /* discard all events */ + ec_clear_out_queue(); + /* Tests at runtime show this disables charging and battery reporting */ + send_ec_command(0xE9); /* Vendor implements using ACPI "CMDB" register" */ + send_ec_data(0x80); + /* TODO: Set touchpad GPP owner to GPIO? */ + break; + default: + break; + } + return 0; +} -- cgit v1.2.3