diff options
author | Michał Kopeć <michal.kopec@3mdeb.com> | 2024-05-20 17:21:38 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-06-03 16:45:20 +0000 |
commit | a79af4c7fd360119ec5b738491493fcf58e5dc37 (patch) | |
tree | ac0e2942cd7fcab9ede88eb17f9708d47e3e6f7c | |
parent | 377157c7fba0c68e2b5d273066713caa5af95f80 (diff) |
ec/dasharo/ec: Add initial copy of ec/system76/ec
Initial commit is a copy of ec/system76/ec from tag v24.02.1 (commit
0a280ff7) with string changes. Dasharo-specific features will be added
in subsequent commits, similar to how Librem EC support was added in
changes 52390 and 52391.
Change-Id: Ic7c3d9413488026548514963eb78accc28e41e06
Signed-off-by: Michał Kopeć <michal.kopec@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/82671
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Singer <service+coreboot-gerrit@felixsinger.de>
-rw-r--r-- | src/ec/dasharo/ec/Kconfig | 21 | ||||
-rw-r--r-- | src/ec/dasharo/ec/Makefile.mk | 10 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/ac.asl | 22 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/battery.asl | 248 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/battery_thresholds.asl | 46 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/buttons.asl | 13 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/ec.asl | 241 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/ec_ram.asl | 55 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/hid.asl | 50 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/lid.asl | 23 | ||||
-rw-r--r-- | src/ec/dasharo/ec/acpi/s76.asl | 178 | ||||
-rw-r--r-- | src/ec/dasharo/ec/dasharo_ec.c | 112 | ||||
-rw-r--r-- | src/ec/dasharo/ec/dasharo_ec.h | 17 | ||||
-rw-r--r-- | src/ec/dasharo/ec/smbios.c | 9 |
14 files changed, 1045 insertions, 0 deletions
diff --git a/src/ec/dasharo/ec/Kconfig b/src/ec/dasharo/ec/Kconfig new file mode 100644 index 0000000000..1a007fa163 --- /dev/null +++ b/src/ec/dasharo/ec/Kconfig @@ -0,0 +1,21 @@ +## SPDX-License-Identifier: GPL-2.0-only + +config EC_DASHARO_EC + bool + help + Dasharo EC + +config EC_DASHARO_EC_BAT_THRESHOLDS + depends on EC_DASHARO_EC + bool + default y + +config EC_DASHARO_EC_DGPU + depends on EC_DASHARO_EC + bool + default n + +config EC_DASHARO_EC_OLED + depends on EC_DASHARO_EC + bool + default n diff --git a/src/ec/dasharo/ec/Makefile.mk b/src/ec/dasharo/ec/Makefile.mk new file mode 100644 index 0000000000..247bcd40ee --- /dev/null +++ b/src/ec/dasharo/ec/Makefile.mk @@ -0,0 +1,10 @@ +## SPDX-License-Identifier: GPL-2.0-only +ifeq ($(CONFIG_EC_DASHARO_EC),y) + +all-y += dasharo_ec.c + +ramstage-y += smbios.c + +smm-$(CONFIG_DEBUG_SMI) += dasharo_ec.c + +endif diff --git a/src/ec/dasharo/ec/acpi/ac.asl b/src/ec/dasharo/ec/acpi/ac.asl new file mode 100644 index 0000000000..66cf742dec --- /dev/null +++ b/src/ec/dasharo/ec/acpi/ac.asl @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Device (AC) +{ + Name (_HID, "ACPI0003" /* Power Source Device */) + Name (_PCL, Package (0x01) // _PCL: Power Consumer List + { + _SB + }) + + Name (ACFG, 1) + + Method (_PSR, 0, NotSerialized) // _PSR: Power Source + { + Return (ACFG) + } + + Method (_STA, 0, NotSerialized) + { + Return (0x0F) + } +} diff --git a/src/ec/dasharo/ec/acpi/battery.asl b/src/ec/dasharo/ec/acpi/battery.asl new file mode 100644 index 0000000000..106f3d1be0 --- /dev/null +++ b/src/ec/dasharo/ec/acpi/battery.asl @@ -0,0 +1,248 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Device (BAT0) +{ + Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */) + Name (_UID, 0) + Name (_PCL, Package (0x01) // _PCL: Power Consumer List + { + _SB + }) + Name (BFCC, 0) + Method (_STA, 0, NotSerialized) + { + If (^^PCI0.LPCB.EC0.ECOK) + { + If (^^PCI0.LPCB.EC0.BAT0) + { + Return (0x1F) + } + Else + { + Return (0x0F) + } + } + Else + { + Return (0x0F) + } + } + + Name (PBIF, Package (0x0D) + { + 1, // 0 - Power Unit + 0xFFFFFFFF, // 1 - Design Capacity + 0xFFFFFFFF, // 2 - Last Full Charge Capacity + 1, // 3 - Battery Technology + 0xFFFFFFFF, // 4 - Design Voltage + 0, // 5 - Design Capacity of Warning + 0, // 6 - Design Capacity of Low + 0x40, // 7 - Battery Capacity Granularity 1 + 0x40, // 8 - Battery Capacity Granularity 2 + " ", // 9 - Model Number + " ", // 10 - Serial Number + " ", // 11 - Battery Type + " " // 12 - OEM Information + }) + Method (IVBI, 0, NotSerialized) + { + PBIF [1] = 0xFFFFFFFF + PBIF [2] = 0xFFFFFFFF + PBIF [4] = 0xFFFFFFFF + PBIF [9] = " " + PBIF [10] = " " + PBIF [11] = " " + PBIF [12] = " " + BFCC = 0 + } + + Method (UPBI, 0, NotSerialized) + { + If (^^PCI0.LPCB.EC0.BAT0) + { + Local0 = (^^PCI0.LPCB.EC0.BDC0 & 0xFFFF) + PBIF [1] = Local0 + Local0 = (^^PCI0.LPCB.EC0.BFC0 & 0xFFFF) + PBIF [2] = Local0 + BFCC = Local0 + Local0 = (^^PCI0.LPCB.EC0.BDV0 & 0xFFFF) + PBIF [4] = Local0 + Local0 = (^^PCI0.LPCB.EC0.BCW0 & 0xFFFF) + PBIF [5] = Local0 + Local0 = (^^PCI0.LPCB.EC0.BCL0 & 0xFFFF) + PBIF [6] = Local0 + PBIF [9] = "BAT" + PBIF [10] = "0001" + PBIF [11] = "LION" + PBIF [12] = "Notebook" + } + Else + { + IVBI () + } + } + + Method (_BIF, 0, NotSerialized) // _BIF: Battery Information + { + If (^^PCI0.LPCB.EC0.ECOK) + { + UPBI () + } + Else + { + IVBI () + } + + Return (PBIF) /* \_SB_.BAT0.PBIF */ + } + + Name (PBIX, Package () + { + 0, // 0 - Revision + 1, // 1 - Power Unit: mAh + 0xFFFFFFFF, // 2 - Design Capacity + 0xFFFFFFFF, // 3 - Last Full Charge Capacity + 1, // 4 - Battery Technology: Rechargeable + 0xFFFFFFFF, // 5 - Design Voltage + 0, // 6 - Design Capacity of Warning + 0, // 7 - Design Capacity of Low + 0, // 8 - Cycle Count + 98000, // 9 - Measurement Accuracy + 0xFFFFFFFF, // 10 - Max Sampling Time + 0xFFFFFFFF, // 11 - Min Sampling Time + 0xFFFFFFFF, // 12 - Max Averaging Interval + 0xFFFFFFFF, // 13 - Min Averaging Interval + 0x40, // 14 - Battery Capacity Granularity 1 + 0x40, // 15 - Battery Capacity Granularity 2 + " ", // 16 - Model Number + " ", // 17 - Serial Number + " ", // 18 - Battery Type + " " // 19 - OEM Information + }) + + Method (IVBX, 0, NotSerialized) + { + PBIX [2] = 0xFFFFFFFF + PBIX [3] = 0xFFFFFFFF + PBIX [5] = 0xFFFFFFFF + PBIX [16] = " " + PBIX [17] = " " + PBIX [18] = " " + PBIX [19] = " " + BFCC = 0 + } + + Method (UPBX, 0, NotSerialized) + { + If (^^PCI0.LPCB.EC0.BAT0) + { + Local0 = (^^PCI0.LPCB.EC0.BDC0 & 0xFFFF) + PBIX [2] = Local0 + Local0 = (^^PCI0.LPCB.EC0.BFC0 & 0xFFFF) + PBIX [3] = Local0 + BFCC = Local0 + Local0 = (^^PCI0.LPCB.EC0.BDV0 & 0xFFFF) + PBIX [5] = Local0 + Local0 = (^^PCI0.LPCB.EC0.BCW0 & 0xFFFF) + PBIX [6] = Local0 + Local0 = (^^PCI0.LPCB.EC0.BCL0 & 0xFFFF) + PBIX [7] = Local0 + LOCAL0 = ^^PCI0.LPCB.EC0.CYC0 + PBIX [8] = LOCAL0 + PBIX [16] = "BAT" + PBIX [17] = "0001" + PBIX [18] = "LION" + PBIX [19] = "Notebook" + } + Else + { + IVBX () + } + } + + // _BIX: Battery Information Extended + Method (_BIX, 0, NotSerialized) + { + If (^^PCI0.LPCB.EC0.ECOK) + { + UPBX () + } + Else + { + IVBX () + } + Return (PBIX) /* \_SB_.BAT0.PBIX */ + } + + Name (PBST, Package (0x04) + { + 0, // 0 - Battery state + 0xFFFFFFFF, // 1 - Battery present rate + 0xFFFFFFFF, // 2 - Battery remaining capacity + 0xFFFFFFFF // 3 - Battery present voltage + }) + Method (IVBS, 0, NotSerialized) + { + PBST [0] = 0 + PBST [1] = 0xFFFFFFFF + PBST [2] = 0xFFFFFFFF + PBST [3] = 0xFFFFFFFF + } + + Method (UPBS, 0, NotSerialized) + { + If (^^PCI0.LPCB.EC0.BAT0) + { + Local0 = 0 + Local1 = 0 + If (^^AC.ACFG) + { + If (((^^PCI0.LPCB.EC0.BST0 & 0x02) == 0x02)) + { + Local0 |= 0x02 + Local1 = (^^PCI0.LPCB.EC0.BPR0 & 0xFFFF) + } + } + Else + { + Local0 |= 1 + Local1 = (^^PCI0.LPCB.EC0.BPR0 & 0xFFFF) + } + + Local7 = (Local1 & 0x8000) + If ((Local7 == 0x8000)) + { + Local1 ^= 0xFFFF + } + + Local2 = (^^PCI0.LPCB.EC0.BRC0 & 0xFFFF) + Local3 = (^^PCI0.LPCB.EC0.BPV0 & 0xFFFF) + PBST [0] = Local0 + PBST [1] = Local1 + PBST [2] = Local2 + PBST [3] = Local3 + If ((BFCC != ^^PCI0.LPCB.EC0.BFC0)) + { + Notify (BAT0, 0x81) // Information Change + } + } + Else + { + IVBS () + } + } + + Method (_BST, 0, NotSerialized) // _BST: Battery Status + { + If (^^PCI0.LPCB.EC0.ECOK) + { + UPBS () + } + Else + { + IVBS () + } + + Return (PBST) /* \_SB_.BAT0.PBST */ + } +} diff --git a/src/ec/dasharo/ec/acpi/battery_thresholds.asl b/src/ec/dasharo/ec/acpi/battery_thresholds.asl new file mode 100644 index 0000000000..3bb1330fbf --- /dev/null +++ b/src/ec/dasharo/ec/acpi/battery_thresholds.asl @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Field (ERAM, ByteAcc, Lock, Preserve) +{ + Offset (0xBC), + BTL0, 8, /* BAT0 charging start threshold */ + BTH0, 8, /* BAT0 charging end threshold */ +} + +/* + * Get battery charging threshold + * + * Arg0: 0: Start threshold + * 1: Stop threshold + */ +Method (GBCT, 1, NotSerialized) +{ + If (Arg0 == 0) { + Return (BTL0) + } + + If (Arg0 == 1) { + Return (BTH0) + } + + Return (0xFF) +} + +/* + * Set battery charging threshold + * + * Arg0: 0: Start threshold + * 1: Stop threshold + * Arg1: Percentage + */ +Method (SBCT, 2, NotSerialized) +{ + If (Arg1 <= 100) { + If (Arg0 == 0) { + BTL0 = Arg1 + } + If (Arg0 == 1) { + BTH0 = Arg1 + } + } +} diff --git a/src/ec/dasharo/ec/acpi/buttons.asl b/src/ec/dasharo/ec/acpi/buttons.asl new file mode 100644 index 0000000000..ae85c67ccc --- /dev/null +++ b/src/ec/dasharo/ec/acpi/buttons.asl @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Device (PWRB) +{ + Name (_HID, EisaId ("PNP0C0C")) + Name (_PRW, Package () { EC_GPE_SWI, 3 }) +} + +Device (SLPB) +{ + Name (_HID, EisaId ("PNP0C0E")) + Name (_PRW, Package () { EC_GPE_SWI, 3 }) +} diff --git a/src/ec/dasharo/ec/acpi/ec.asl b/src/ec/dasharo/ec/acpi/ec.asl new file mode 100644 index 0000000000..e4fcdebf09 --- /dev/null +++ b/src/ec/dasharo/ec/acpi/ec.asl @@ -0,0 +1,241 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Scope (\_SB) { + #include "ac.asl" + #include "battery.asl" + #include "buttons.asl" + #include "hid.asl" + #include "lid.asl" + #include "s76.asl" +} + +Device (\_SB.PCI0.LPCB.EC0) +{ + Name (_HID, EisaId ("PNP0C09") /* Embedded Controller Device */) + Name (_GPE, EC_GPE_SCI) // _GPE: General Purpose Events + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x0062, // Range Minimum + 0x0062, // Range Maximum + 0x00, // Alignment + 0x01, // Length + ) + IO (Decode16, + 0x0066, // Range Minimum + 0x0066, // Range Maximum + 0x00, // Alignment + 0x01, // Length + ) + }) + + #include "ec_ram.asl" + + Name (ECOK, 0) + Method (_REG, 2, Serialized) // _REG: Region Availability + { + Printf ("EC: _REG %o %o", ToHexString(Arg0), ToHexString(Arg1)) + If ((Arg0 == 0x03) && (Arg1 == 1)) { + // Enable hardware touchpad lock, airplane mode, and keyboard backlight keys + ECOS = 1 + + // Enable software display brightness keys + WINF = 1 + + // Set current AC state + ^^^^AC.ACFG = ADP + // Update battery information and status + ^^^^BAT0.UPBI() + ^^^^BAT0.UPBS() + + // Notify of changes + Notify(^^^^AC, 0) + Notify(^^^^BAT0, 0) + + PNOT () + + // EC is now available + ECOK = Arg1 + + // Reset Dasharo Device + ^^^^S76D.RSET() + } + } + + Name (S3OS, 0) + Method (PTS, 1, Serialized) { + Printf ("EC: PTS: %o", ToHexString(Arg0)) + If (ECOK) { + // Save ECOS during sleep + S3OS = ECOS + + // Clear wake cause + WFNO = 0 + } + } + + Method (WAK, 1, Serialized) { + Printf ("EC: WAK: %o", ToHexString(Arg0)) + If (ECOK) { + // Restore ECOS after sleep + ECOS = S3OS + + // Set current AC state + ^^^^AC.ACFG = ADP + + // Update battery information and status + ^^^^BAT0.UPBI() + ^^^^BAT0.UPBS() + + // Notify of changes + Notify(^^^^AC, 0) + Notify(^^^^BAT0, 0) + } + } + + Method (_Q0A, 0, NotSerialized) // Touchpad Toggle + { + Printf ("EC: Touchpad Toggle") + } + + Method (_Q0B, 0, NotSerialized) // Screen Toggle + { + Printf ("EC: Screen Toggle") +#if CONFIG(EC_DASHARO_EC_OLED) + Notify (^^^^S76D, 0x85) +#endif // CONFIG(EC_DASHARO_EC_OLED) + } + + Method (_Q0C, 0, NotSerialized) // Mute + { + Printf ("EC: Mute") + } + + Method (_Q0D, 0, NotSerialized) // Keyboard Backlight + { + Printf ("EC: Keyboard Backlight") + } + + Method (_Q0E, 0, NotSerialized) // Volume Down + { + Printf ("EC: Volume Down") + } + + Method (_Q0F, 0, NotSerialized) // Volume Up + { + Printf ("EC: Volume Up") + } + + Method (_Q10, 0, NotSerialized) // Switch Video Mode + { + Printf ("EC: Switch Video Mode") + } + + Method (_Q11, 0, NotSerialized) // Brightness Down + { + Printf ("EC: Brightness Down") + if (^^^^HIDD.HRDY) { + ^^^^HIDD.HPEM (20) + } + } + + Method (_Q12, 0, NotSerialized) // Brightness Up + { + Printf ("EC: Brightness Up") + if (^^^^HIDD.HRDY) { + ^^^^HIDD.HPEM (19) + } + } + + Method (_Q13, 0, NotSerialized) // Camera Toggle + { + Printf ("EC: Camera Toggle") + } + + Method (_Q14, 0, NotSerialized) // Airplane Mode + { + Printf ("EC: Airplane Mode") + if (^^^^HIDD.HRDY) { + ^^^^HIDD.HPEM (8) + } + // TODO: hardware airplane mode + } + + Method (_Q15, 0, NotSerialized) // Suspend Button + { + Printf ("EC: Suspend Button") + Notify (SLPB, 0x80) + } + + Method (_Q16, 0, NotSerialized) // AC Detect + { + Printf ("EC: AC Detect") + ^^^^AC.ACFG = ADP + Notify (AC, 0x80) // Status Change + If (BAT0) + { + Notify (^^^^BAT0, 0x81) // Information Change + Notify (^^^^BAT0, 0x80) // Status Change + } + } + + Method (_Q17, 0, NotSerialized) // BAT0 Update + { + Printf ("EC: BAT0 Update (17)") + Notify (^^^^BAT0, 0x81) // Information Change + } + + Method (_Q19, 0, NotSerialized) // BAT0 Update + { + Printf ("EC: BAT0 Update (19)") + Notify (^^^^BAT0, 0x81) // Information Change + } + + Method (_Q1B, 0, NotSerialized) // Lid Close + { + Printf ("EC: Lid Close") + Notify (LID0, 0x80) + } + + Method (_Q1C, 0, NotSerialized) // Thermal Trip + { + Printf ("EC: Thermal Trip") + /* TODO + Notify (\_TZ.TZ0, 0x81) // Thermal Trip Point Change + Notify (\_TZ.TZ0, 0x80) // Thermal Status Change + */ + } + + Method (_Q1D, 0, NotSerialized) // Power Button + { + Printf ("EC: Power Button") + Notify (PWRB, 0x80) + } + + Method (_Q50, 0, NotSerialized) // Other Events + { + Local0 = OEM4 + If (Local0 == 0x8A) { + Printf ("EC: White Keyboard Backlight") + Notify (^^^^S76D, 0x80) + } ElseIf (Local0 == 0x9F) { + Printf ("EC: Color Keyboard Toggle") + Notify (^^^^S76D, 0x81) + } ElseIf (Local0 == 0x81) { + Printf ("EC: Color Keyboard Down") + Notify (^^^^S76D, 0x82) + } ElseIf (Local0 == 0x82) { + Printf ("EC: Color Keyboard Up") + Notify (^^^^S76D, 0x83) + } ElseIf (Local0 == 0x80) { + Printf ("EC: Color Keyboard Color Change") + Notify (^^^^S76D, 0x84) + } Else { + Printf ("EC: Other: %o", ToHexString(Local0)) + } + } + + #if CONFIG(EC_DASHARO_EC_BAT_THRESHOLDS) + #include "battery_thresholds.asl" + #endif +} diff --git a/src/ec/dasharo/ec/acpi/ec_ram.asl b/src/ec/dasharo/ec/acpi/ec_ram.asl new file mode 100644 index 0000000000..cb5bcf1444 --- /dev/null +++ b/src/ec/dasharo/ec/acpi/ec_ram.asl @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +OperationRegion (ERAM, EmbeddedControl, 0, 0xFF) +Field (ERAM, ByteAcc, Lock, Preserve) +{ + Offset (0x03), + LSTE, 1, // Lid is open + , 1, + LWKE, 1, // Lid wake + , 5, + Offset (0x07), + TMP1, 8, // CPU temperature + Offset (0x10), + ADP, 1, // AC adapter connected + , 1, + BAT0, 1, // Battery connected + , 5, + WFNO, 8, // Wake cause (not implemented) + Offset (0x16), + BDC0, 32, // Battery design capacity + BFC0, 32, // Battery full capacity + Offset (0x22), + BDV0, 32, // Battery design voltage + BST0, 32, // Battery status + BPR0, 32, // Battery current + BRC0, 32, // Battery remaining capacity + BPV0, 32, // Battery voltage + Offset (0x3A), + BCW0, 32, + BCL0, 32, + CYC0, 16, // Battery cycle count + Offset (0x68), + ECOS, 8, // Detected OS, 0 = no ACPI, 1 = ACPI but no driver, 2 = ACPI with driver + Offset (0xC8), + OEM1, 8, + OEM2, 8, + OEM3, 16, + OEM4, 8, // Extra SCI data + Offset (0xCD), + TMP2, 8, // GPU temperature + DUT1, 8, // Fan 1 duty + DUT2, 8, // Fan 2 duty + RPM1, 16, // Fan 1 RPM + RPM2, 16, // Fan 2 RPM + Offset (0xD9), + AIRP, 8, // Airplane mode LED + WINF, 8, // Enable ACPI brightness controls + Offset (0xF8), + FCMD, 8, + FDAT, 8, + FBUF, 8, + FBF1, 8, + FBF2, 8, + FBF3, 8, +} diff --git a/src/ec/dasharo/ec/acpi/hid.asl b/src/ec/dasharo/ec/acpi/hid.asl new file mode 100644 index 0000000000..eb5f420cce --- /dev/null +++ b/src/ec/dasharo/ec/acpi/hid.asl @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Device (HIDD) +{ + Name (_HID, "INT33D5") + Name (HBSY, 0) + Name (HIDX, 0) + Name (HRDY, 0) + + Method (HDEM, 0, Serialized) + { + HBSY = 0 + Return (HIDX) + } + + Method (HDMM, 0, Serialized) + { + Return (0) + } + + Method (HDSM, 1, Serialized) + { + HRDY = Arg0 + } + + Method (HPEM, 1, Serialized) + { + HBSY = 1 + HIDX = Arg0 + + Notify (HIDD, 0xC0) + Local0 = 0 + While ((Local0 < 0xFA) && HBSY) + { + Sleep (0x04) + Local0++ + } + + If (HBSY == 1) + { + HBSY = 0 + HIDX = 0 + Return (1) + } + Else + { + Return (0) + } + } +} diff --git a/src/ec/dasharo/ec/acpi/lid.asl b/src/ec/dasharo/ec/acpi/lid.asl new file mode 100644 index 0000000000..0a643416e3 --- /dev/null +++ b/src/ec/dasharo/ec/acpi/lid.asl @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +Device (LID0) +{ + Name (_HID, EisaId ("PNP0C0D")) + Name (_PRW, Package () { EC_GPE_SWI, 3 }) + + Method (_LID, 0, NotSerialized) { + Printf ("LID: _LID") + If (^^PCI0.LPCB.EC0.ECOK) { + Return (^^PCI0.LPCB.EC0.LSTE) + } Else { + Return (1) + } + } + + Method (_PSW, 1, NotSerialized) { + Printf ("LID: _PSW: %o", ToHexString(Arg0)) + If (^^PCI0.LPCB.EC0.ECOK) { + ^^PCI0.LPCB.EC0.LWKE = Arg0 + } + } +} diff --git a/src/ec/dasharo/ec/acpi/s76.asl b/src/ec/dasharo/ec/acpi/s76.asl new file mode 100644 index 0000000000..f23f85709f --- /dev/null +++ b/src/ec/dasharo/ec/acpi/s76.asl @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +// Notifications: +// 0x80 - hardware backlight toggle +// 0x81 - backlight toggle +// 0x82 - backlight down +// 0x83 - backlight up +// 0x84 - backlight color change +// 0x85 - OLED screen toggle +Device (S76D) { + Name (_HID, "17761776") + Name (_UID, 0) + // Hide the device so that Windows does not warn about a missing driver. + Name (_STA, 0xB) + + Method (RSET, 0, Serialized) { + Printf ("S76D: RSET") + SAPL(0) + SKBB(0) + SKBC(0xFFFFFF) + } + + Method (INIT, 0, Serialized) { + Printf ("S76D: INIT") + RSET() + If (^^PCI0.LPCB.EC0.ECOK) { + // Set flags to use software control + ^^PCI0.LPCB.EC0.ECOS = 2 + Return (0) + } Else { + Return (1) + } + } + + Method (FINI, 0, Serialized) { + Printf ("S76D: FINI") + RSET() + If (^^PCI0.LPCB.EC0.ECOK) { + // Set flags to use hardware control + ^^PCI0.LPCB.EC0.ECOS = 1 + Return (0) + } Else { + Return (1) + } + } + + // Get Airplane LED + Method (GAPL, 0, Serialized) { + If (^^PCI0.LPCB.EC0.ECOK) { + If (^^PCI0.LPCB.EC0.AIRP & 0x40) { + Return (1) + } + } + Return (0) + } + + // Set Airplane LED + Method (SAPL, 1, Serialized) { + If (^^PCI0.LPCB.EC0.ECOK) { + If (Arg0) { + ^^PCI0.LPCB.EC0.AIRP |= 0x40 + } Else { + ^^PCI0.LPCB.EC0.AIRP &= 0xBF + } + } + } + + // Get Keyboard Backlight Kind + // 0 - No backlight + // 1 - White backlight + // 2 - RGB backlight + Method (GKBK, 0, Serialized) { + Local0 = 0 + If (^^PCI0.LPCB.EC0.ECOK) { + ^^PCI0.LPCB.EC0.FDAT = 2 + ^^PCI0.LPCB.EC0.FCMD = 0xCA + Local0 = ^^PCI0.LPCB.EC0.FBUF + } + Return (Local0) + } + + // Get Keyboard Brightness + Method (GKBB, 0, Serialized) { + Local0 = 0 + If (^^PCI0.LPCB.EC0.ECOK) { + ^^PCI0.LPCB.EC0.FDAT = 1 + ^^PCI0.LPCB.EC0.FCMD = 0xCA + Local0 = ^^PCI0.LPCB.EC0.FBUF + } + Return (Local0) + } + + // Set Keyboard Brightness + Method (SKBB, 1, Serialized) { + If (^^PCI0.LPCB.EC0.ECOK) { + ^^PCI0.LPCB.EC0.FDAT = 0 + ^^PCI0.LPCB.EC0.FBUF = Arg0 + ^^PCI0.LPCB.EC0.FCMD = 0xCA + } + } + + // Get Keyboard Color + Method (GKBC, 0, Serialized) { + Local0 = 0 + If (^^PCI0.LPCB.EC0.ECOK) { + ^^PCI0.LPCB.EC0.FDAT = 4 + ^^PCI0.LPCB.EC0.FCMD = 0xCA + Local0 = ^^PCI0.LPCB.EC0.FBUF + Local0 |= (^^PCI0.LPCB.EC0.FBF1) << 16 + Local0 |= (^^PCI0.LPCB.EC0.FBF2) << 8 + } + Return (Local0) + } + + // Set Keyboard Color + Method (SKBC, 1, Serialized) { + If (^^PCI0.LPCB.EC0.ECOK) { + ^^PCI0.LPCB.EC0.FDAT = 3 + ^^PCI0.LPCB.EC0.FBUF = (Arg0 & 0xFF) + ^^PCI0.LPCB.EC0.FBF1 = ((Arg0 >> 16) & 0xFF) + ^^PCI0.LPCB.EC0.FBF2 = ((Arg0 >> 8) & 0xFF) + ^^PCI0.LPCB.EC0.FCMD = 0xCA + } + } + + // Fan names + Method (NFAN, 0, Serialized) { + Return (Package() { + "CPU fan", +#if CONFIG(EC_DASHARO_EC_DGPU) + "GPU fan", +#endif + }) + } + + // Get fan duty cycle and RPM as a single value + Method (GFAN, 1, Serialized) { + Local0 = 0 + Local1 = 0 + If (^^PCI0.LPCB.EC0.ECOK) { + If (Arg0 == 0) { + Local0 = ^^PCI0.LPCB.EC0.DUT1 + Local1 = ^^PCI0.LPCB.EC0.RPM1 + } ElseIf (Arg0 == 1) { + Local0 = ^^PCI0.LPCB.EC0.DUT2 + Local1 = ^^PCI0.LPCB.EC0.RPM2 + } + } + If (Local1 != 0) { + // 60 * (EC frequency / 120) / 2 + Local1 = 2156250 / Local1 + } + Return ((Local1 << 8) | Local0) + } + + // Temperature names + Method (NTMP, 0, Serialized) { + Return (Package() { + "CPU temp", +#if CONFIG(EC_DASHARO_EC_DGPU) + "GPU temp", +#endif + }) + } + + // Get temperature + Method (GTMP, 1, Serialized) { + Local0 = 0; + If (^^PCI0.LPCB.EC0.ECOK) { + If (Arg0 == 0) { + Local0 = ^^PCI0.LPCB.EC0.TMP1 + } ElseIf (Arg0 == 1) { + Local0 = ^^PCI0.LPCB.EC0.TMP2 + } + } + Return (Local0) + } +} diff --git a/src/ec/dasharo/ec/dasharo_ec.c b/src/ec/dasharo/ec/dasharo_ec.c new file mode 100644 index 0000000000..97c9613f82 --- /dev/null +++ b/src/ec/dasharo/ec/dasharo_ec.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "dasharo_ec.h" +#include <arch/io.h> +#include <console/dasharo_ec.h> +#include <console/console.h> +#include <timer.h> + +// This is the command region for Dasharo EC firmware. It must be +// enabled for LPC in the mainboard. +#define DASHARO_EC_BASE 0x0E00 +#define DASHARO_EC_SIZE 256 + +#define REG_CMD 0 +#define REG_RESULT 1 +#define REG_DATA 2 // Start of command data + +// When command register is 0, command is complete +#define CMD_FINISHED 0 + +#define RESULT_OK 0 + +// Print command. Registers are unique for each command +#define CMD_PRINT 4 +#define CMD_PRINT_REG_FLAGS 2 +#define CMD_PRINT_REG_LEN 3 +#define CMD_PRINT_REG_DATA 4 + +static inline uint8_t dasharo_ec_read(uint8_t addr) +{ + return inb(DASHARO_EC_BASE + (uint16_t)addr); +} + +static inline void dasharo_ec_write(uint8_t addr, uint8_t data) +{ + outb(data, DASHARO_EC_BASE + (uint16_t)addr); +} + +void dasharo_ec_init(void) +{ + // Clear entire command region + for (int i = 0; i < DASHARO_EC_SIZE; i++) + dasharo_ec_write((uint8_t)i, 0); +} + +void dasharo_ec_flush(void) +{ + dasharo_ec_write(REG_CMD, CMD_PRINT); + + // Wait for command completion, for up to 10 milliseconds, with a + // test period of 1 microsecond + wait_us(10000, dasharo_ec_read(REG_CMD) == CMD_FINISHED); + + dasharo_ec_write(CMD_PRINT_REG_LEN, 0); +} + +void dasharo_ec_print(uint8_t byte) +{ + uint8_t len = dasharo_ec_read(CMD_PRINT_REG_LEN); + dasharo_ec_write(CMD_PRINT_REG_DATA + len, byte); + dasharo_ec_write(CMD_PRINT_REG_LEN, len + 1); + + // If we hit the end of the buffer, or were given a newline, flush + if (byte == '\n' || len >= (DASHARO_EC_SIZE - CMD_PRINT_REG_DATA)) + dasharo_ec_flush(); +} + +bool dasharo_ec_cmd(uint8_t cmd, const uint8_t *request_data, + uint8_t request_size, uint8_t *reply_data, uint8_t reply_size) +{ + if (request_size > DASHARO_EC_SIZE - REG_DATA || + reply_size > DASHARO_EC_SIZE - REG_DATA) { + printk(BIOS_ERR, "EC command %d too long - request size %u, reply size %u\n", + cmd, request_size, reply_size); + return false; + } + + /* If any data were buffered by dasharo_ec_print(), flush it first */ + uint8_t buffered_len = dasharo_ec_read(CMD_PRINT_REG_LEN); + if (buffered_len > 0) + dasharo_ec_flush(); + + /* Write the data */ + uint8_t i; + for (i = 0; i < request_size; ++i) + dasharo_ec_write(REG_DATA + i, request_data[i]); + + /* Write the command */ + dasharo_ec_write(REG_CMD, cmd); + + /* Wait for the command to complete */ + bool ret = true; + int elapsed = wait_ms(1000, dasharo_ec_read(REG_CMD) == CMD_FINISHED); + if (elapsed == 0) { + /* Timed out: fail the command, don't attempt to read a reply. */ + printk(BIOS_WARNING, "EC command %d timed out - request size %d, reply size %d\n", + cmd, request_size, reply_size); + ret = false; + } else { + /* Read the reply */ + for (i = 0; i < reply_size; ++i) + reply_data[i] = dasharo_ec_read(REG_DATA+i); + /* Check the reply status */ + ret = (dasharo_ec_read(REG_RESULT) == RESULT_OK); + } + + /* Reset the flags and length so we can buffer console prints again */ + dasharo_ec_write(CMD_PRINT_REG_FLAGS, 0); + dasharo_ec_write(CMD_PRINT_REG_LEN, 0); + + return ret; +} diff --git a/src/ec/dasharo/ec/dasharo_ec.h b/src/ec/dasharo/ec/dasharo_ec.h new file mode 100644 index 0000000000..f313b0d0f5 --- /dev/null +++ b/src/ec/dasharo/ec/dasharo_ec.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef DASHARO_EC_H +#define DASHARO_EC_H + +#include <stdbool.h> +#include <stdint.h> + +/* + * Send a command to the EC. request_data/request_size are the request payload, + * request_data can be NULL if request_size is 0. reply_data/reply_size are + * the reply payload, reply_data can be NULL if reply_size is 0. + */ +bool dasharo_ec_cmd(uint8_t cmd, const uint8_t *request_data, + uint8_t request_size, uint8_t *reply_data, uint8_t reply_size); + +#endif diff --git a/src/ec/dasharo/ec/smbios.c b/src/ec/dasharo/ec/smbios.c new file mode 100644 index 0000000000..e55d5f0965 --- /dev/null +++ b/src/ec/dasharo/ec/smbios.c @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <smbios.h> + +smbios_wakeup_type smbios_system_wakeup_type(void) +{ + // TODO: Read wake source from EC. + return SMBIOS_WAKEUP_TYPE_POWER_SWITCH; +} |