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>
This commit is contained in:
Benjamin Doron 2019-09-22 17:33:12 +10:00 committed by Martin Roth
parent ad3828e3ce
commit 289a67d160
29 changed files with 2928 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,2 @@
config BOARD_ACER_VN7_572G
bool "Aspire VN7-572G"

View File

@ -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

View File

@ -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
}
}

View File

@ -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))
}
}

View File

@ -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,
})
}

View File

@ -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"
}

View File

@ -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
}
}

View File

@ -0,0 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <drivers/pc80/pc/ps2_controller.asl>

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -0,0 +1,4 @@
boot_option=Fallback
debug_level=Debug
power_on_after_fail=Disable
legacy_8254_timer=Disable

View File

@ -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

Binary file not shown.

View File

@ -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

View File

@ -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);
}
}

View File

@ -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"
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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,
};

View File

@ -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;
}

View File

@ -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;
}