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>
This commit is contained in:
Sean Rhodes 2021-04-30 16:32:23 +01:00 committed by Tim Wawrzynczak
parent cbd2abf9b4
commit 2d89789337
13 changed files with 1083 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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