Martin Roth submitted this change.

View Change

Approvals: build bot (Jenkins): Verified Martin Roth: Looks good to me, approved
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 <benjamin.doron00@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/35523
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
---
A src/mainboard/acer/aspire_vn7_572g/Kconfig
A src/mainboard/acer/aspire_vn7_572g/Kconfig.name
A src/mainboard/acer/aspire_vn7_572g/Makefile.inc
A src/mainboard/acer/aspire_vn7_572g/acpi/ac.asl
A src/mainboard/acer/aspire_vn7_572g/acpi/battery.asl
A src/mainboard/acer/aspire_vn7_572g/acpi/brightness_levels.asl
A src/mainboard/acer/aspire_vn7_572g/acpi/ec.asl
A src/mainboard/acer/aspire_vn7_572g/acpi/mainboard.asl
A src/mainboard/acer/aspire_vn7_572g/acpi/superio.asl
A src/mainboard/acer/aspire_vn7_572g/acpi/thermal.asl
A src/mainboard/acer/aspire_vn7_572g/board.fmd
A src/mainboard/acer/aspire_vn7_572g/board_info.txt
A src/mainboard/acer/aspire_vn7_572g/bootblock.c
A src/mainboard/acer/aspire_vn7_572g/cmos.default
A src/mainboard/acer/aspire_vn7_572g/cmos.layout
A src/mainboard/acer/aspire_vn7_572g/data.vbt
A src/mainboard/acer/aspire_vn7_572g/devicetree.cb
A src/mainboard/acer/aspire_vn7_572g/die.c
A src/mainboard/acer/aspire_vn7_572g/dsdt.asl
A src/mainboard/acer/aspire_vn7_572g/ec.c
A src/mainboard/acer/aspire_vn7_572g/gma-mainboard.ads
A src/mainboard/acer/aspire_vn7_572g/gpio.c
A src/mainboard/acer/aspire_vn7_572g/gpio_early.c
A src/mainboard/acer/aspire_vn7_572g/hda_verb.c
A src/mainboard/acer/aspire_vn7_572g/include/ec.h
A src/mainboard/acer/aspire_vn7_572g/include/gpio.h
A src/mainboard/acer/aspire_vn7_572g/mainboard.c
A src/mainboard/acer/aspire_vn7_572g/romstage.c
A src/mainboard/acer/aspire_vn7_572g/smihandler.c
29 files changed, 2,928 insertions(+), 0 deletions(-)

diff --git a/src/mainboard/acer/aspire_vn7_572g/Kconfig b/src/mainboard/acer/aspire_vn7_572g/Kconfig
new file mode 100644
index 0000000..449eeee
--- /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 0000000..b881680
--- /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 0000000..79c66c5
--- /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 0000000..c92cbd9
--- /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 0000000..1f4fb47
--- /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 0000000..14c5e30
--- /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 <drivers/intel/gma/acpi/gma.asl>
+
+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 0000000..3a22d38
--- /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 <ec/acpi/ec.asl>
+
+#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 0000000..a3c48b2
--- /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 0000000..55b1db5
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/acpi/superio.asl
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <drivers/pc80/pc/ps2_controller.asl>
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 0000000..7d175a2
--- /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 0000000..44d8a0c
--- /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 0000000..f16707e
--- /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 0000000..ce150fd
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/bootblock.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootblock_common.h>
+#include <console/console.h>
+#include <delay.h>
+#include <gpio.h>
+#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 0000000..642e341
--- /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 0000000..7afff9c
--- /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 0000000..b8a0ab8
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/data.vbt
Binary files 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 0000000..409e309
--- /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 0000000..ed459e7
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/die.c
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <delay.h>
+#include <gpio.h>
+
+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 0000000..2944688
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/dsdt.asl
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+DefinitionBlock(
+ "dsdt.aml",
+ "DSDT",
+ ACPI_DSDT_REV_2,
+ OEM_ID,
+ ACPI_TABLE_CREATOR,
+ 0x20141018 // OEM revision
+)
+{
+ #include <acpi/dsdt_top.asl>
+ #include <soc/intel/common/block/acpi/acpi/platform.asl>
+ #include <soc/intel/common/block/acpi/acpi/globalnvs.asl>
+ #include <cpu/intel/common/acpi/cpu.asl>
+ #include <southbridge/intel/common/acpi/sleepstates.asl>
+
+ /* 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 <soc/intel/skylake/acpi/systemagent.asl>
+ #include <soc/intel/skylake/acpi/pch.asl>
+ #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 0000000..570e282
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/ec.c
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <ec/acpi/ec.h>
+#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 0000000..fc8bacc
--- /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 0000000..ebb954f
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/gpio.c
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <gpio.h>
+#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 0000000..ad66661
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/gpio_early.c
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <gpio.h>
+#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 0000000..20197d1
--- /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 <device/azalia_device.h>
+
+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 0000000..49651de
--- /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 0000000..ed8518e
--- /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 0000000..eba9e98
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/mainboard.c
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ops.h>
+#include <drivers/intel/gma/int15.h>
+#include <ec/acpi/ec.h>
+#include <halt.h>
+#include <intelblocks/lpc_lib.h>
+#include <intelblocks/pmclib.h>
+#include <rtc.h>
+#include <soc/nhlt.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#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 0000000..74e1438
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/romstage.c
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <assert.h>
+#include <soc/romstage.h>
+#include <spd_bin.h>
+#include <stdint.h>
+#include <string.h>
+
+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 0000000..88ec10d
--- /dev/null
+++ b/src/mainboard/acer/aspire_vn7_572g/smihandler.c
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/smm.h>
+#include <ec/acpi/ec.h>
+#include <soc/nvs.h>
+
+/*
+ * 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;
+}

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

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I6340116abfeb2fbd280d143b74d323e4da3566f6
Gerrit-Change-Number: 35523
Gerrit-PatchSet: 197
Gerrit-Owner: Benjamin Doron <benjamin.doron00@gmail.com>
Gerrit-Reviewer: Benjamin Doron <benjamin.doron00@gmail.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Matt DeVillier <matt.devillier@gmail.com>
Gerrit-Reviewer: Michael Niewöhner <foss@mniewoehner.de>
Gerrit-Reviewer: Paul Menzel <paulepanter@mailbox.org>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-CC: Eugene Myers <cedarhouse1@comcast.net>
Gerrit-CC: Nico Huber <nico.h@gmx.de>
Gerrit-MessageType: merged