summaryrefslogtreecommitdiff
path: root/src/ec
diff options
context:
space:
mode:
authorSean Rhodes <sean@starlabs.systems>2021-04-30 16:32:23 +0100
committerTim Wawrzynczak <twawrzynczak@chromium.org>2021-06-04 17:20:56 +0000
commit2d89789337797f4a6ca86e3484bd6934baefa28e (patch)
tree05e32742dbcb27f05d48edee087a42eb8ec4312e /src/ec
parentcbd2abf9b4a2b981dd6b73b2790b7c8a89c82d92 (diff)
ec: Add Star Labs ITE 8987E support
Support for Star Labs labtop series EC Signed-off-by: Sean Rhodes <sean@starlabs.systems> Change-Id: I1967f7c4a7e3cab714f22844bf36749e0c9652b6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/52797 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Diffstat (limited to 'src/ec')
-rw-r--r--src/ec/starlabs/it8987/Kconfig7
-rw-r--r--src/ec/starlabs/it8987/Makefile.inc26
-rw-r--r--src/ec/starlabs/it8987/acpi/ac.asl60
-rw-r--r--src/ec/starlabs/it8987/acpi/battery.asl77
-rw-r--r--src/ec/starlabs/it8987/acpi/cmos.asl18
-rw-r--r--src/ec/starlabs/it8987/acpi/ec.asl379
-rw-r--r--src/ec/starlabs/it8987/acpi/hid.asl251
-rw-r--r--src/ec/starlabs/it8987/acpi/keyboard.asl63
-rw-r--r--src/ec/starlabs/it8987/acpi/lid.asl47
-rw-r--r--src/ec/starlabs/it8987/acpi/thermal.asl14
-rw-r--r--src/ec/starlabs/it8987/chip.h10
-rw-r--r--src/ec/starlabs/it8987/ec.c83
-rw-r--r--src/ec/starlabs/it8987/ec.h48
13 files changed, 1083 insertions, 0 deletions
diff --git a/src/ec/starlabs/it8987/Kconfig b/src/ec/starlabs/it8987/Kconfig
new file mode 100644
index 0000000000..ba9e908077
--- /dev/null
+++ b/src/ec/starlabs/it8987/Kconfig
@@ -0,0 +1,7 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+config EC_STARLABS_IT8987
+ bool
+ select EC_ACPI
+ help
+ Interface to IT8987 embedded controller principally in Star Labs notebooks.
diff --git a/src/ec/starlabs/it8987/Makefile.inc b/src/ec/starlabs/it8987/Makefile.inc
new file mode 100644
index 0000000000..b021d0ff38
--- /dev/null
+++ b/src/ec/starlabs/it8987/Makefile.inc
@@ -0,0 +1,26 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+PHONY+=add_ite_fw
+INTERMEDIATE+=add_ite_fw
+
+ifeq ($(CONFIG_EC_STARLABS_IT8987),y)
+all-y += ec.c
+smm-$(CONFIG_DEBUG_SMI) += ec.c
+endif
+
+ifeq ($(CONFIG_EC_STARLABS_IT8987_BIN),y)
+
+ifeq ($(CONFIG_EC_STARLABS_IT8987_BIN_PATH),)
+files_added:: warn_no_ite_fw
+endif
+
+add_ite_fw: $(obj)/coreboot.pre
+ $(CBFSTOOL) $(obj)/coreboot.pre write -r EC -f $(CONFIG_EC_STARLABS_IT8987_BIN_PATH) -u
+endif
+
+PHONY+=warn_no_ite_fw
+warn_no_ite_fw:
+ printf "\n\t** WARNING **\n"
+ printf "coreboot has been built without the IT8987 EC Firmware.\n"
+ printf "Do not flash this image. Your LabTop Mk IV's power button\n"
+ printf "may not respond when you press it.\n\n"
diff --git a/src/ec/starlabs/it8987/acpi/ac.asl b/src/ec/starlabs/it8987/acpi/ac.asl
new file mode 100644
index 0000000000..97ae1474a7
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/ac.asl
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Device (ADP1)
+{
+ Name (_HID, "ACPI0003")
+ Name (_PCL, Package () { \_SB })
+
+ Method (_STA, 0, NotSerialized) // _STA: Status
+ {
+ If (ECON == 1)
+ {
+ Local0 = 0x0F
+ }
+ Else
+ {
+ Local0 = 0
+ }
+ Return (Local0)
+ }
+
+ Method (_PSR, 0, NotSerialized) // _PSR: Power Source
+ {
+ If (ECWR & 0x01)
+ {
+ \PWRS = 1
+ }
+ Else
+ {
+ \PWRS = 0
+ }
+ Return (\PWRS)
+ }
+}
+
+Method (_QA0, 0, NotSerialized) // AC Power Connected
+{
+ If (ECWR & 0x01)
+ {
+ \PWRS = 1
+ }
+ Else
+ {
+ \PWRS = 0
+ }
+
+ // 500ms delay - Not used in coreboot
+ // Sleep (500)
+ Notify (BAT0, 0x81)
+ // Sleep (500)
+ Notify (ADP1, 0x80)
+}
+
+Method(_Q0B, 0, NotSerialized) // Battery Connected
+{
+ // 500ms delay - Not used in coreboot
+ // Sleep (500)
+ Notify (BAT0, 0x81)
+ // Sleep (500)
+ Notify (BAT0, 0x80)
+}
diff --git a/src/ec/starlabs/it8987/acpi/battery.asl b/src/ec/starlabs/it8987/acpi/battery.asl
new file mode 100644
index 0000000000..8936701d1d
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/battery.asl
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Device (BAT0)
+{
+ Name (_HID, EISAID ("PNP0C0A"))
+ Name (_UID, 1)
+ Name (_PCL, Package () { \_SB })
+
+ // Battery Slot Status
+ Method (_STA, 0, Serialized)
+ {
+ If (ECWR & 0x02)
+ {
+ Return (0x1F)
+ }
+ Return (0x0F)
+ }
+
+ // Default Static Battery Information
+ Name (BPKG, Package (13)
+ {
+ 1, // 0: Power Unit
+ 0xFFFFFFFF, // 1: Design Capacity
+ 0xFFFFFFFF, // 2: Last Full Charge Capacity
+ 1, // 3: Battery Technology(Rechargeable)
+ 0xFFFFFFFF, // 4: Design Voltage 10.8V
+ 0, // 5: Design capacity of warning
+ 0, // 6: Design capacity of low
+ 0x64, // 7: Battery capacity granularity 1
+ 0, // 8: Battery capacity granularity 2
+ "CN6613-2S3P", // 9: Model Number
+ "6UA3", // 10: Serial Number
+ "Real", // 11: Battery Type
+ "GDPT" // 12: OEM Information
+ })
+
+ Method (_BIF, 0, Serialized)
+ {
+ BPKG[1] = B1DC
+ BPKG[2] = B1FC
+ BPKG[4] = B1FV
+ If (B1FC)
+ {
+ BPKG[5] = B1FC / 10
+ BPKG[6] = B1FC / 25
+ BPKG[7] = B1DC / 100
+ }
+
+ Return (BPKG)
+ }
+
+ Name (PKG1, Package (4)
+ {
+ 0xFFFFFFFF, // Battery State
+ 0xFFFFFFFF, // Battery Present Rate
+ 0xFFFFFFFF, // Battery Remaining Capacity
+ 0xFFFFFFFF, // Battery Present Voltage
+ })
+
+ Method (_BST, 0, Serialized)
+ {
+
+
+ PKG1[0] = B1ST & 0x07
+ If (B1ST & 0x01)
+ {
+ PKG1[1] = B1CR
+ }
+ Else
+ {
+ PKG1[1] = B1CR
+ }
+ PKG1[2] = B1RC
+ PKG1[3] = B1VT
+ Return (PKG1)
+ }
+}
diff --git a/src/ec/starlabs/it8987/acpi/cmos.asl b/src/ec/starlabs/it8987/acpi/cmos.asl
new file mode 100644
index 0000000000..052094c2ea
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/cmos.asl
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+OperationRegion (CMOS, SystemIO, 0x70, 0x02)
+Field (CMOS, ByteAcc, NoLock, Preserve)
+{
+ NVRI, 8,
+ NVRD, 8
+}
+
+IndexField (NVRI, NVRD, ByteAcc, NoLock, Preserve)
+{
+ Offset (0x40),
+ KBBL, 8, // Keyboard backlight timeout
+ FNSW, 8, // Ctrl Fn Reverse (make keyboard Apple-like)
+
+ Offset (0x7D),
+ FNLC, 8 // Current state of Fn Lock key.
+}
diff --git a/src/ec/starlabs/it8987/acpi/ec.asl b/src/ec/starlabs/it8987/acpi/ec.asl
new file mode 100644
index 0000000000..451cdf125a
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/ec.asl
@@ -0,0 +1,379 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define ASL_PVOL_DEFOF_NUM 0xe8
+
+Scope(\)
+{
+ // These fields come from the Global NVS area
+ Field (GNVS,AnyAcc,Lock,Preserve)
+ {
+ Offset(33),
+ B2SC, 8, // (33) Battery 2 Stored Capacity
+ Offset(36),
+ B2SS, 8 // (36) Battery 2 Stored Status
+ }
+}
+
+Scope (\_SB)
+{
+ #include "hid.asl"
+}
+
+Scope (\_SB.PCI0)
+{
+ // Add the entries for the PS/2 keyboard and mouse.
+ #include <drivers/pc80/pc/ps2_controller.asl>
+}
+
+Scope (\_SB.PCI0.LPCB)
+{
+ // Include the definitions for accessing CMOS.
+ #include "cmos.asl"
+
+ // Our embedded controller device.
+ Device (H_EC)
+ {
+ Name (_HID, EISAID ("PNP0C09")) // ACPI Embedded Controller
+ Name (_UID, 1)
+ Name (_GPE, EC_GPE_SCI)
+
+ // ECDT (Embedded Controller Boot Resources Table) Check to correct
+ // ECAV flag in the beginning
+ Name(ECTK, 1)
+ Name(ECFG, 0)
+ Name(WIBT, 0)
+ Name(APST, 0)
+
+ Name(ECON, 1) // AC debug
+ Name(BNUM, 0) // Number Of Batteries Present
+ Name(PVOL, ASL_PVOL_DEFOF_NUM)
+ Name(B1CC, 0)
+ Name(B2CC, 0)
+
+ Name(B2ST, 0)
+ Name(CFAN, 0)
+ Name(CMDR, 0)
+ Name(DOCK, 0)
+ Name(EJET, 0)
+ Name(MCAP, 0)
+ Name(PLMX, 0)
+ Name(PECH, 0)
+ Name(PECL, 0)
+ Name(PENV, 0)
+ Name(PINV, 0)
+ Name(PPSH, 0)
+ Name(PPSL, 0)
+ Name(PSTP, 0)
+ Name(RPWR, 0)
+ Name(LIDS, 0)
+ Name(SLPC, 0)
+ Name(VPWR, 0)
+ Name(WTMS, 0)
+ Name(AWT2, 0)
+ Name(AWT1, 0)
+ Name(AWT0, 0)
+ Name(DLED, 0)
+ Name(IBT1, 0)
+ Name(ECAV, 1) // Support DPTF feature
+ Name(SPT2, 0)
+ Name(PB10, 0)
+ Name(IWCW, 0)
+ Name(IWCR, 0)
+ Name(BTEN, 0)
+ Mutex(ECMT, 0)
+
+ Method (_CRS, 0, Serialized)
+ {
+ Name (BFFR, ResourceTemplate()
+ {
+ IO (Decode16, 0x62, 0x62, 0x00, 0x01)
+ IO (Decode16, 0x66, 0x66, 0x00, 0x01)
+ })
+ Return (BFFR)
+ }
+
+ Method (_STA, 0, NotSerialized)
+ {
+ If ((ECON == 1))
+ {
+ Return (0x0F)
+ }
+
+ Return (0x00)
+ }
+
+ Name (ECOK, Zero)
+ Method(_REG, 2, NotSerialized)
+ {
+ If ((Arg0 == 0x03) && (Arg1 == 0x01))
+ {
+ ECOS = 1
+ ECAV = 1
+
+ // Unconditionally fix up the Battery and Power State.
+
+ // Initialize the Number of Present Batteries.
+ // 1 = Real Battery 1 is present
+ // 2 = Real Battery 2 is present
+ // 3 = Real Battery 1 and 2 are present
+ BNUM = 0
+ BNUM |= ((ECRD (RefOf (ECWR)) & 0x02) >> 1)
+
+ // Save the current Power State for later.
+ // Store (PWRS, Local0)
+
+ // Initialize the Power State.
+ // BNUM = 0 = Virtual Power State
+ // BNUM > 0 = Real Power State
+ If (BNUM == 0x00)
+ {
+ \PWRS = ECRD (RefOf (VPWR))
+ }
+ Else
+ {
+ \PWRS = (ECRD (RefOf (ECWR)) & 0x01)
+ }
+ PNOT()
+
+ /* Initialize LID switch state */
+ \LIDS = LIDS
+ }
+
+ // Flag that the OS supports ACPI.
+ \_SB.PCI0.LPCB.H_EC.ECOS = 1
+ }
+
+ Name (S3OS, Zero)
+ Method (PTS, 1, Serialized)
+ {
+ Debug = Concatenate("EC: PTS: ", ToHexString(Arg0))
+ If (ECOK) {
+ S3OS = ECOS
+ }
+ \_SB.PCI0.LPCB.H_EC.ECOS = 0
+ }
+
+ Method (WAK, 1, Serialized)
+ {
+ Debug = Concatenate("EC: WAK: ", ToHexString(Arg0))
+ If (ECOK) {
+ ECOS = S3OS
+ }
+ \_SB.PCI0.LPCB.H_EC.ECOS = 1
+ }
+
+ OperationRegion (SIPR, SystemIO, 0xB2, 0x1)
+ Field (SIPR, ByteAcc, Lock, Preserve)
+ {
+ SMB2, 8
+ }
+
+ // EC RAM fields
+ OperationRegion(ECF2, EmbeddedControl, 0, 0xFF)
+ Field (ECF2, ByteAcc, Lock, Preserve)
+ {
+ XXX0, 8, // EC Firmware main- version number.
+ XXX1, 8, // EC Firmware sub- version number.
+ XXX2, 8, // EC Firmware test- version number.
+
+ Offset(0x06),
+ SKID, 8, // SKU ID
+
+ Offset(0x11),
+ KBCD, 8, // Key / Touch Pad disable/enable bit
+ ECOS, 8, // Enter OS flag
+ HDAO, 8,
+ ECHK, 8, // Hot keys flag
+
+ Offset(0x18),
+ KLBS, 8, // Keyboard backlight begin.
+ KLBE, 8, // Keyboard backlight status.
+
+ Offset(0x1A),
+ KBLT, 8, // Keyboard Backlight Timeout
+ PWPF, 8, // Power Profile
+
+ Offset(0x1E),
+ BTHP,8, // Health Battery Percentage
+
+ Offset(0x20),
+ RCMD, 8, // Same function as IO 66 port to send EC command
+ RCST, 8, // Report status for the result of command execution
+
+ Offset(0x2C),
+ FNST, 8, // FN LOCK key status.
+
+ Offset(0x3F),
+ SFAN, 8, // Set Fan Speed.
+ BTMP, 16, // Battery Temperature.
+ BCNT, 16, // Battery Cycle Count.
+ FRMP, 16, // Fan Current Speed.
+
+ Offset(0x60),
+ TSR1, 8, // Thermal Sensor Register 1 [CPU VR (IMVP) Temp on RVP]
+ TSR2, 8, // Thermal Sensor Register 2 [Heat exchanger fan temp on RVP]
+ TER4, 8, // Thermal Sensor Register 3 (skin temperature)
+
+ Offset(0x63),
+ TSI,4, // [0..3] 0 = SEN1 - CPU VR temperature sensor
+ // 1 = SEN2 - Heat Exchanger temperature sensor
+ // 2 = SEN3 - Skin temperature sensor
+ // 3 = SEN4 - Ambient temperature sensor
+ // 4 = SEN5 - DIMM temperature sensor [IR sensor 1 on WSB]
+ // 5 = SEN6 - not used on RVP
+ HYST, 4, // [4..7] - Hysteresis in degC.
+ TSHT, 8, // Thermal Sensor (N) high trip point(set default value =70)
+ TSLT, 8, // Thermal Sensor (N) low trip point (set default value =70)
+ TSSR, 8, // TSSR- thermal sensor status register (set bit2 =1)
+ // BIT0:SEN1 - CPU VR Temp Sensor Trip Flag
+ // BIT1:SEN2 - Fan Temp Sensor Trip Flag
+ // BIT2:SEN3 - Skin Temp Sensor Trip Flag
+ // BIT3:SEN4 - Ambient Temp Sensor Trip Flag
+ // BIT4:Reserved
+ // BIT5:Reserved
+ // BIT6:Reserved
+ // BIT7:Reserved
+ CHGR, 16, // Charge Rate
+
+ Offset(0x70),
+ CPTM, 8, // CPU Temperature
+
+ Offset(0x72),
+ TER2, 8, // Charger Temperature, Charger thermistor support
+
+ Offset(0x7F),
+ LSTE, 1, // Lid feature
+ // BIT0LID GPI
+ , 7, // Reserved
+
+ Offset(0x80),
+ ECWR, 8, // AC & Battery status
+ XX10, 8, // Battery#1 Model Number Code
+ XX11, 16, // Battery#1 Serial Number
+ B1DC, 16, // Battery#1 Design Capacity
+ B1FV, 16, // Battery#1 Design Voltage
+ B1FC, 16, // Battery#1 Last Full Charge Capacity
+ XX15, 16, // Battery#1 Trip Point
+ B1ST, 8, // Battery#1 State
+ B1CR, 16, // Battery#1 Present Rate
+ B1RC, 16, // Battery#1 Remaining Capacity
+ B1VT, 16, // Battery#1 Present Voltage
+ BPCN, 8, // Battery#1 Remaining percentage
+
+ // USB Type C Mailbox Interface// PPM->OPM Message In
+ Offset(0xc0),
+ MGI0, 8,
+ MGI1, 8,
+ MGI2, 8,
+ MGI3, 8,
+ MGI4, 8,
+ MGI5, 8,
+ MGI6, 8,
+ MGI7, 8,
+ MGI8, 8,
+ MGI9, 8,
+ MGIA, 8,
+ MGIB, 8,
+ MGIC, 8,
+ MGID, 8,
+ MGIE, 8,
+ MGIF, 8,
+
+ // USB Type C Mailbox Interface// OPM->PPM Message Out
+ MGO0, 8,
+ MGO1, 8,
+ MGO2, 8,
+ MGO3, 8,
+ MGO4, 8,
+ MGO5, 8,
+ MGO6, 8,
+ MGO7, 8,
+ MGO8, 8,
+ MGO9, 8,
+ MGOA, 8,
+ MGOB, 8,
+ MGOC, 8,
+ MGOD, 8,
+ MGOE, 8,
+ MGOF, 8,
+
+ // USB Type C UCSI DATA Structure.
+ VER1, 8,
+ VER2, 8,
+ RSV1, 8,
+ RSV2, 8,
+
+ // PPM->OPM CCI indicator
+ CCI0, 8,
+ CCI1, 8,
+ CCI2, 8,
+ CCI3, 8,
+
+ // OPM->PPM Control message
+ CTL0, 8,
+ CTL1, 8,
+ CTL2, 8,
+ CTL3, 8,
+ CTL4, 8,
+ CTL5, 8,
+ CTL6, 8,
+ CTL7, 8,
+
+ Offset(0xF0),
+ , 3,// BIT0 .. BIT2 Reserved
+ TPCC, 1,// BIT3 TypeC connection bit
+ , 2,// BIT4 .. BIT5 Reserved
+ DRMD, 1,// Bit6 Dual Role Mode. 0->DFP: Host mode; 1->UFP: Device Mode.
+ , 1,// BIT7 Reserved
+ }
+
+ Method (ECMD, 0, Serialized)
+ {
+ }
+
+ Method (ECWT, 2, Serialized,,, {IntObj, FieldUnitObj})
+ {
+ Local0 = Acquire (ECMT, 1000)
+ If (Local0 == 0x00)
+ {
+ If (ECAV)
+ {
+ // Execute write to Embedded Controller
+ Arg1 = Arg0
+ }
+ Release (ECMT)
+ }
+ }
+
+ Method (ECRD, 1, Serialized, 0, IntObj, FieldUnitObj)
+ {
+ Local0 = Acquire (ECMT, 1000)
+ If (Local0 == 0)
+ {
+ If (ECAV)
+ {
+ // Execute read from Embedded Controller
+ Local1 = DerefOf (Arg0)
+ Release (ECMT)
+ Return (Local1)
+ }
+ Else
+ {
+ Release (ECMT)
+ }
+ }
+ Return (Local1)
+ }
+
+ // Include the other parts of the Embedded Controller ASL.
+ #include "keyboard.asl"
+ #include "battery.asl"
+ #include "ac.asl"
+ #include "lid.asl"
+
+ // Method(_Q45) // SMM Mode - Not used in coreboot
+ // {
+ // SMB2 = 0xC1
+ // }
+ }
+}
diff --git a/src/ec/starlabs/it8987/acpi/hid.asl b/src/ec/starlabs/it8987/acpi/hid.asl
new file mode 100644
index 0000000000..25e3cd2ec9
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/hid.asl
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Device (HIDD)
+{
+ Name (_HID, "INT33D5")
+ Name (HBSY, Zero)
+ Name (HIDX, Zero)
+ Name (HMDE, Zero)
+ Name (HRDY, Zero)
+ Name (BTLD, Zero)
+ Name (BTS1, Zero)
+ Name (HEB1, 0x3003)
+
+ Method (_STA, 0, Serialized) // _STA: Status
+ {
+ If ((OSYS >= 0x07DD))
+ {
+ Return (0x0F)
+ }
+ Else
+ {
+ Return (Zero)
+ }
+ }
+
+ Method (HDDM, 0, Serialized)
+ {
+ Store ("-----> HDDM", Debug)
+ Name (DPKG, Package (0x04)
+ {
+ 0x11111111,
+ 0x22222222,
+ 0x33333333,
+ 0x44444444
+ })
+ Return (DPKG)
+ }
+
+ Method (HDEM, 0, Serialized)
+ {
+ Store ("-----> HDEM", Debug)
+ HBSY = Zero
+ If ((HMDE == Zero))
+ {
+ Return (HIDX)
+ }
+ Return (HMDE)
+ }
+
+ Method (HDMM, 0, Serialized)
+ {
+ Store ("-----> HDMM", Debug)
+ Return (HMDE)
+ }
+
+ Method (HDSM, 1, Serialized)
+ {
+ Store ("-----> HDSM", Debug)
+ HRDY = Arg0
+ }
+
+ Method (HPEM, 1, Serialized)
+ {
+ Store ("-----> HPEM", Debug)
+ HBSY = One
+ HIDX = Arg0
+
+ Notify (HIDD, 0xC0)
+ Local0 = Zero
+ While ((Local0 < 0xFA) && HBSY)
+ {
+ Sleep (0x04)
+ Local0++
+ }
+
+ If (HBSY == One)
+ {
+ HBSY = Zero
+ HIDX = Zero
+ Return (One)
+ }
+ Else
+ {
+ Return (Zero)
+ }
+ }
+
+ Method (BTNL, 0, Serialized)
+ {
+ Store ("-----> BTNL", Debug)
+ If (CondRefOf (\_SB.PWRB.PBST))
+ {
+ \_SB.PWRB.PBST = Zero
+ Notify (PWRB, One) // Device Check
+ }
+
+ BTLD = One
+// If ((AEAB == One))
+// {
+ BTS1 = 0x1F
+ \_SB.PCI0.LPCB.H_EC.ECWT (BTS1, RefOf (\_SB.PCI0.LPCB.H_EC.BTEN))
+// }
+// Else
+// {
+// BTS1 = Zero
+// }
+ }
+
+ Method (BTNE, 1, Serialized)
+ {
+ Store ("-----> BTNE", Debug)
+// If ((AEAB == One))
+// {
+ BTS1 = ((Arg0 & 0x1E) | One)
+ \_SB.PCI0.LPCB.H_EC.ECWT (BTS1, RefOf (\_SB.PCI0.LPCB.H_EC.BTEN))
+// }
+ }
+
+ Method (BTNS, 0, Serialized)
+ {
+ Store ("-----> BTNS", Debug)
+// If ((AEAB == One))
+// {
+ BTS1 = \_SB.PCI0.LPCB.H_EC.ECRD (RefOf (\_SB.PCI0.LPCB.H_EC.BTEN))
+// }
+ Return (BTS1)
+ }
+
+ Method (BTNC, 0, Serialized)
+ {
+ Store ("-----> BTNC", Debug)
+// If ((AEAB == One))
+// {
+ Return (0x1F)
+// }
+// Else
+// {
+// Return (Zero)
+// }
+ }
+
+ Name (HEB2, Zero)
+ Method (HEBC, 0, Serialized)
+ {
+ Store ("-----> HEBC", Debug)
+// If ((AHDB == One))
+// {
+// Return (\HEB1)
+// }
+// Else
+// {
+ Return (Zero)
+// }
+ }
+
+ Method (H2BC, 0, Serialized)
+ {
+ Store ("-----> H2BC", Debug)
+// If ((AHDB == One))
+// {
+// Return (\HEB1)
+// }
+// Else
+// {
+ Return (Zero)
+// }
+ }
+
+ Method (HEEC, 0, Serialized)
+ {
+ Store ("-----> HEEC", Debug)
+// If ((AHDB == One))
+// {
+ Return (HEB2) /* \_SB_.HIDD.HEB2 */
+// }
+// Else
+// {
+// Return (Zero)
+// }
+ }
+
+ Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method
+ {
+ If ((Arg0 == ToUUID ("eeec56b3-4442-408f-a792-4edd4d758054")))
+ {
+ If ((One == ToInteger (Arg1)))
+ {
+ Switch (ToInteger (Arg2))
+ {
+ Case (Zero)
+ {
+ Return (Buffer (0x02)
+ {
+ 0xFF, 0x03
+ })
+ }
+ Case (One)
+ {
+ BTNL ()
+ }
+ Case (0x02)
+ {
+ Return (HDMM ())
+ }
+ Case (0x03)
+ {
+ HDSM (DerefOf (Arg3 [Zero]))
+ }
+ Case (0x04)
+ {
+ Return (HDEM ())
+ }
+ Case (0x05)
+ {
+ Return (BTNS ())
+ }
+ Case (0x06)
+ {
+ BTNE (DerefOf (Arg3 [Zero]))
+ }
+ Case (0x07)
+ {
+ Return (HEBC ())
+ }
+ Case (0x08)
+ {
+ }
+ Case (0x09)
+ {
+ Return (H2BC ())
+ }
+ }
+ }
+ }
+
+ Return (Buffer (One)
+ {
+ 0x00
+ })
+ }
+}
+
+Method (PWPR, 0, Serialized)
+{
+ Notify (HIDD, 0xCE)
+}
+
+Method (PWRR, 0, Serialized)
+{
+ Notify (HIDD, 0xCF)
+}
diff --git a/src/ec/starlabs/it8987/acpi/keyboard.asl b/src/ec/starlabs/it8987/acpi/keyboard.asl
new file mode 100644
index 0000000000..f5b1d52631
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/keyboard.asl
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Method(_Q80) // Volume up
+{
+ Store ("-----> _Q80", Debug)
+ Notify (\_SB.HIDD, 0xC4)
+ Notify (\_SB.HIDD, 0xC5)
+ Store ("<----- _Q80", Debug)
+}
+
+Method(_Q81) // Volume down
+{
+ Store ("-----> _Q81", Debug)
+ Notify (\_SB.HIDD, 0xC6)
+ Notify (\_SB.HIDD, 0xC7)
+ Store ("<----- _Q81", Debug)
+}
+
+Method(_Q99) // Wireless mode
+{
+ Store ("-----> _Q99", Debug)
+ \_SB.HIDD.HPEM(8)
+ Store ("<----- _Q80", Debug)
+}
+
+Method(_Q06) // Brightness decrease
+{
+ \_SB.PCI0.GFX0.DECB()
+}
+
+Method(_Q07) // Brightness increase
+{
+ \_SB.PCI0.GFX0.INCB()
+}
+
+Method(_Q08) // FN lock QEvent
+{
+ FNLC = FNST
+}
+
+Method(_Q54) // Power Button Event
+{
+ Store ("-----> _Q54", Debug)
+ If (CondRefOf (\_SB.PWRB))
+ {
+ Notify(\_SB.PWRB, 0x80)
+ }
+ Store ("<----- _Q54", Debug)
+}
+
+Method(_QD5) // 10 second power button press
+{
+ Store ("-----> _QD5", Debug)
+ \_SB.PWPR()
+ Store ("<----- _QD5", Debug)
+}
+
+Method(_QD6) // 10 second power button de-press
+{
+ Store ("-----> _QD6", Debug)
+ \_SB.PWRR()
+ Store ("<----- _QD6", Debug)
+}
diff --git a/src/ec/starlabs/it8987/acpi/lid.asl b/src/ec/starlabs/it8987/acpi/lid.asl
new file mode 100644
index 0000000000..22e8eeb818
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/lid.asl
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Device (LID0)
+{
+ Name (_HID, EisaId ("PNP0C0D"))
+
+ Method (_STA, 0, NotSerialized)
+ {
+ DEBUG = "---> IT8987 LID: _STA"
+ Return (0x0F)
+ }
+
+ Method (_PSW, 1, NotSerialized)
+ {
+ DEBUG = Concatenate ("---> IT8987 LID: _PSW", ToHexString(Arg0))
+ }
+
+ Method (_LID, 0, NotSerialized)
+ {
+ DEBUG = "---> IT8987 LID: _LID"
+ If (\_SB.PCI0.LPCB.H_EC.ECRD (RefOf (\_SB.PCI0.LPCB.H_EC.LSTE)) == 0x01)
+ {
+ Local0 = 1
+ }
+ else
+ {
+ Local0 = 0
+ }
+ Return (Local0)
+ }
+}
+
+Method (_Q0C, 0, NotSerialized) // Lid close event
+{
+ DEBUG = "---> IT8987 LID: Q0C (close event)"
+ LIDS = 0
+ \LIDS = LIDS
+ Notify (LID0, 0x80)
+}
+
+Method (_Q0D, 0, NotSerialized) // Lid open event
+{
+ DEBUG = "---> IT8987 LID: Q0D (open event)"
+ LIDS = 1
+ \LIDS = LIDS
+ Notify (LID0, 0x80)
+}
diff --git a/src/ec/starlabs/it8987/acpi/thermal.asl b/src/ec/starlabs/it8987/acpi/thermal.asl
new file mode 100644
index 0000000000..6bf25bf7b6
--- /dev/null
+++ b/src/ec/starlabs/it8987/acpi/thermal.asl
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Method(_QF0) // Thermal event.
+{
+ If (LEqual (DBGS, 0x00))
+ {
+ /* Only handle the numerous thermal events if we are */
+ /* NOT doing ACPI Debugging. */
+ If (CondRefOf (\_TZ.TZ01))
+ {
+ Notify (\_TZ.TZ01, 0x80)
+ }
+ }
+}
diff --git a/src/ec/starlabs/it8987/chip.h b/src/ec/starlabs/it8987/chip.h
new file mode 100644
index 0000000000..a940a46acb
--- /dev/null
+++ b/src/ec/starlabs/it8987/chip.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _EC_STARLABS_IT8987_CHIP_H
+#define _EC_STARLABS_IT8987_CHIP_H
+
+struct ec_starlabs_it8987_config {
+ u8 cpuhot_limit; /* temperature in °C which asserts PROCHOT# */
+};
+
+#endif /* _EC_STARLABS_IT8987_CHIP_H */
diff --git a/src/ec/starlabs/it8987/ec.c b/src/ec/starlabs/it8987/ec.c
new file mode 100644
index 0000000000..b555d28b84
--- /dev/null
+++ b/src/ec/starlabs/it8987/ec.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pnp.h>
+#include <pc80/keyboard.h>
+#include <ec/acpi/ec.h>
+#include <delay.h>
+#include <option.h>
+
+#include "ec.h"
+#include "chip.h"
+
+u16 it8987_get_version(void)
+{
+ return (ec_read(0x00) << 8) | ec_read(0x01);
+}
+
+static void it8987_init(struct device *dev)
+{
+ if (!dev->enabled)
+ return;
+
+ /*
+ * The address/data IO port pair for the IT8987 EC are configurable
+ * through the EC domain and are fixed by the EC's firmware blob. If
+ * the value(s) passed through the "dev" structure don't match the
+ * expected values then output severe warnings.
+ */
+ if (dev->path.pnp.port != IT8987E_FIXED_ADDR) {
+ printk(BIOS_ERR, "IT8987: Incorrect ports defined in devicetree.cb.\n");
+ printk(BIOS_ERR, "IT8987: Serious operational issues will arise.\n");
+ return;
+ }
+
+ u8 chipid1 = pnp_read_index(dev->path.pnp.port, IT8987_CHIPID1);
+ u8 chipid2 = pnp_read_index(dev->path.pnp.port, IT8987_CHIPID2);
+ if (chipid1 != IT8987_CHIPID1_VAL || chipid2 != IT8987_CHIPID2_VAL) {
+ printk(BIOS_DEBUG, "IT8987: Device not found.\n");
+ return;
+ }
+
+ printk(BIOS_DEBUG, "IT8987: Initializing keyboard.\n");
+ pc_keyboard_init(NO_AUX_DEVICE);
+
+ /* Enable the keyboard backlight support. */
+ ec_write(0x18, 0xaa);
+ ec_write(0x19, 0xdd);
+
+ /* Set the timeout for the keyboard backlight. */
+ ec_write(ECRAM_KBL_TIMEOUT, get_uint_option("kbl_timeout", 0));
+
+ /*
+ * Set the correct state for the Ctrl Fn Reverse option. This
+ * swaps the Ctrl and Fn keys to make it like an Apple keyboard.
+ */
+ ec_write(ECRAM_FN_CTRL_REVERSE, get_uint_option("fn_ctrl_swap", 0));
+ /*
+ * Copy the stored state of the fn_lock_state CMOS variable to the
+ * corresponding location within the EC RAM.
+ */
+ ec_write(ECRAM_FN_LOCK_STATE, get_uint_option("fn_lock_state", 0));
+}
+
+static struct device_operations ops = {
+ .init = it8987_init,
+ .read_resources = noop_read_resources,
+ .set_resources = noop_set_resources,
+};
+
+static struct pnp_info pnp_dev_info[] = {
+ { NULL, 0, 0, 0, }
+};
+
+static void enable_dev(struct device *dev)
+{
+ pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
+}
+
+struct chip_operations ec_starlabs_it8987_ops = {
+ CHIP_NAME("ITE IT8987 EC")
+ .enable_dev = enable_dev
+};
diff --git a/src/ec/starlabs/it8987/ec.h b/src/ec/starlabs/it8987/ec.h
new file mode 100644
index 0000000000..c6d5a7a28e
--- /dev/null
+++ b/src/ec/starlabs/it8987/ec.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * EC communication interface for ITE IT8987 Embedded Controller.
+ */
+
+#ifndef _EC_STARLABS_IT8987_H
+#define _EC_STARLABS_IT8987_H
+
+/*
+ * Define the expected value of the PNP base address that is fixed through
+ * the BADRSEL register controlled within the EC domain by the binary blob.
+ */
+#define IT8987E_FIXED_ADDR 0x4e
+
+/* Logical device number (LDN) assignments. */
+#define IT8987E_SP1 0x01 /* Com1 */
+#define IT8987E_SP2 0x02 /* Com2 */
+#define IT8987E_SWUC 0x04 /* System Wake-Up */
+#define IT8987E_KBCM 0x05 /* PS/2 mouse */
+#define IT8987E_KBCK 0x06 /* PS/2 keyboard */
+#define IT8987E_IR 0x0a /* Consumer IR */
+#define IT8987E_SMFI 0x0f /* Shared Memory/Flash Interface */
+#define IT8987E_RTCT 0x10 /* RTC-like Timer */
+#define IT8987E_PMC1 0x11 /* Power Management Channel 1 */
+#define IT8987E_PMC2 0x12 /* Power Management Channel 2 */
+#define IT8987E_SSPI 0x13 /* Serial Peripheral Interface */
+#define IT8987E_PECI 0x14 /* Platform EC Interface */
+#define IT8987E_PMC3 0x17 /* Power Management Channel 3 */
+#define IT8987E_PMC4 0x18 /* Power Management Channel 4 */
+#define IT8987E_PMC5 0x19 /* Power Management Channel 5 */
+
+/* Host domain registers. */
+#define IT8987_CHIPID1 0x20 /* Device ID register 1 */
+#define IT8987_CHIPID2 0x21 /* Device ID register 2 */
+
+/* IT8987 chip ID byte values. */
+#define IT8987_CHIPID1_VAL 0x89
+#define IT8987_CHIPID2_VAL 0x87
+
+/* EC RAM offsets. */
+#define ECRAM_KBL_TIMEOUT 0x07
+#define ECRAM_FN_CTRL_REVERSE 0x08
+#define ECRAM_FN_LOCK_STATE 0x2C
+
+u16 it8987_get_version(void);
+
+#endif