| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| config EC_LIBREM_EC | ||
| bool | ||
| help | ||
| Purism Librem EC |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| ifeq ($(CONFIG_EC_LIBREM_EC),y) | ||
|
|
||
| all-y += librem_ec.c | ||
| smm-$(CONFIG_DEBUG_SMI) += librem_ec.c | ||
|
|
||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| Device (AC) | ||
| { | ||
| Name (_HID, "ACPI0003" /* Power Source Device */) // _HID: Hardware ID | ||
| Name (_PCL, Package (0x01) // _PCL: Power Consumer List | ||
| { | ||
| _SB | ||
| }) | ||
|
|
||
| Name (ACFG, One) | ||
|
|
||
| Method (_PSR, 0, NotSerialized) // _PSR: Power Source | ||
| { | ||
| Return (ACFG) | ||
| } | ||
|
|
||
| Method (_STA, 0, NotSerialized) // _STA: Status | ||
| { | ||
| Return (0x0F) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #define BATTERY_DESIGN_VOLTAGE_MV 14800 | ||
|
|
||
| Device (BAT0) | ||
| { | ||
| Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */) // _HID: Hardware ID | ||
| Name (_UID, Zero) // _UID: Unique ID | ||
| Name (_PCL, Package (0x01) // _PCL: Power Consumer List | ||
| { | ||
| _SB | ||
| }) | ||
| Name (BFCC, Zero) | ||
| Method (_STA, 0, NotSerialized) // _STA: Status | ||
| { | ||
| If (^^PCI0.LPCB.EC0.ECOK) | ||
| { | ||
| If (^^PCI0.LPCB.EC0.BAT0) | ||
| { | ||
| Return (0x1F) | ||
| } | ||
| Else | ||
| { | ||
| Return (0x0F) | ||
| } | ||
| } | ||
| Else | ||
| { | ||
| Return (0x0F) | ||
| } | ||
| } | ||
|
|
||
| Name (PBIF, Package (0x0D) | ||
| { | ||
| One, // 0 - Power Unit | ||
| 0xFFFFFFFF, // 1 - Design Capacity | ||
| 0xFFFFFFFF, // 2 - Last Full Charge Capacity | ||
| One, // 3 - Battery Technology | ||
| BATTERY_DESIGN_VOLTAGE_MV, // 4 - Design Voltage | ||
| Zero, // 5 - Design Capacity of Warning | ||
| Zero, // 6 - Design Capacity of Low | ||
| 0x40, // 7 - Battery Capacity Granularity 1 | ||
| 0x40, // 8 - Battery Capacity Granularity 2 | ||
| "BAT", // 9 - Model Number | ||
| "0001", // 10 - Serial Number | ||
| "LION", // 11 - Battery Type | ||
| "Notebook" // 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 = Zero | ||
| } | ||
|
|
||
| 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 (PBST, Package (0x04) | ||
| { | ||
| Zero, // 0 - Battery state | ||
| 0xFFFFFFFF, // 1 - Battery present rate | ||
| 0xFFFFFFFF, // 2 - Battery remaining capacity | ||
| BATTERY_DESIGN_VOLTAGE_MV // 3 - Battery present voltage | ||
| }) | ||
| Method (IVBS, 0, NotSerialized) | ||
| { | ||
| PBST [0] = Zero | ||
| PBST [1] = 0xFFFFFFFF | ||
| PBST [2] = 0xFFFFFFFF | ||
| PBST [3] = 0x2710 | ||
| } | ||
|
|
||
| Method (UPBS, 0, NotSerialized) | ||
| { | ||
| If (^^PCI0.LPCB.EC0.BAT0) | ||
| { | ||
| Local0 = Zero | ||
| Local1 = Zero | ||
| If (^^AC.ACFG) | ||
| { | ||
| If (((^^PCI0.LPCB.EC0.BST0 & 0x02) == 0x02)) | ||
| { | ||
| Local0 |= 0x02 | ||
| Local1 = (^^PCI0.LPCB.EC0.BPR0 & 0xFFFF) | ||
| } | ||
| } | ||
| Else | ||
| { | ||
| Local0 |= One | ||
| 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 */ | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 }) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,232 @@ | ||
| /* 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 "librem-ec.asl" | ||
| } | ||
|
|
||
| Device (\_SB.PCI0.LPCB.EC0) | ||
| { | ||
| Name (_HID, EisaId ("PNP0C09") /* Embedded Controller Device */) // _HID: Hardware ID | ||
| 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, Zero) | ||
| Method (_REG, 2, Serialized) // _REG: Region Availability | ||
| { | ||
| Debug = Concatenate("EC: _REG", Concatenate(ToHexString(Arg0), Concatenate(" ", ToHexString(Arg1)))) | ||
| If ((Arg0 == 0x03) && (Arg1 == One)) { | ||
| // 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, Zero) | ||
| Notify(^^^^BAT0, Zero) | ||
|
|
||
| PNOT () | ||
|
|
||
| // EC is now available | ||
| ECOK = Arg1 | ||
|
|
||
| // Reset Librem EC Device | ||
| ^^^^LIEC.RSET() | ||
| } | ||
| } | ||
|
|
||
| Method (PTS, 1, Serialized) { | ||
| Debug = Concatenate("EC: PTS: ", ToHexString(Arg0)) | ||
| If (ECOK) { | ||
| // Clear wake cause | ||
| WFNO = Zero | ||
| } | ||
| } | ||
|
|
||
| Method (WAK, 1, Serialized) { | ||
| Debug = Concatenate("EC: WAK: ", ToHexString(Arg0)) | ||
| If (ECOK) { | ||
| // Set current AC state | ||
| ^^^^AC.ACFG = ADP | ||
|
|
||
| // Update battery information and status | ||
| ^^^^BAT0.UPBI() | ||
| ^^^^BAT0.UPBS() | ||
|
|
||
| // Notify of changes | ||
| Notify(^^^^AC, Zero) | ||
| Notify(^^^^BAT0, Zero) | ||
|
|
||
| // Reset Librem EC Device | ||
| ^^^^LIEC.RSET() | ||
| } | ||
| } | ||
|
|
||
| Method (_Q0A, 0, NotSerialized) // Touchpad Toggle | ||
| { | ||
| Debug = "EC: Touchpad Toggle" | ||
| } | ||
|
|
||
| Method (_Q0B, 0, NotSerialized) // Screen Toggle | ||
| { | ||
| Debug = "EC: Screen Toggle" | ||
| } | ||
|
|
||
| Method (_Q0C, 0, NotSerialized) // Mute | ||
| { | ||
| Debug = "EC: Mute" | ||
| } | ||
|
|
||
| Method (_Q0D, 0, NotSerialized) // Keyboard Backlight | ||
| { | ||
| Debug = "EC: Keyboard Backlight" | ||
| } | ||
|
|
||
| Method (_Q0E, 0, NotSerialized) // Volume Down | ||
| { | ||
| Debug = "EC: Volume Down" | ||
| } | ||
|
|
||
| Method (_Q0F, 0, NotSerialized) // Volume Up | ||
| { | ||
| Debug = "EC: Volume Up" | ||
| } | ||
|
|
||
| Method (_Q10, 0, NotSerialized) // Switch Video Mode | ||
| { | ||
| Debug = "EC: Switch Video Mode" | ||
| } | ||
|
|
||
| Method (_Q11, 0, NotSerialized) // Brightness Down | ||
| { | ||
| Debug = "EC: Brightness Down" | ||
| if (^^^^HIDD.HRDY) { | ||
| ^^^^HIDD.HPEM (20) | ||
| } | ||
| } | ||
|
|
||
| Method (_Q12, 0, NotSerialized) // Brightness Up | ||
| { | ||
| Debug = "EC: Brightness Up" | ||
| if (^^^^HIDD.HRDY) { | ||
| ^^^^HIDD.HPEM (19) | ||
| } | ||
| } | ||
|
|
||
| Method (_Q13, 0, NotSerialized) // Camera Toggle | ||
| { | ||
| Debug = "EC: Camera Toggle" | ||
| } | ||
|
|
||
| Method (_Q14, 0, NotSerialized) // Airplane Mode | ||
| { | ||
| Debug = "EC: Airplane Mode" | ||
| if (^^^^HIDD.HRDY) { | ||
| ^^^^HIDD.HPEM (8) | ||
| } | ||
| // TODO: hardware airplane mode | ||
| } | ||
|
|
||
| Method (_Q15, 0, NotSerialized) // Suspend Button | ||
| { | ||
| Debug = "EC: Suspend Button" | ||
| Notify (SLPB, 0x80) | ||
| } | ||
|
|
||
| Method (_Q16, 0, NotSerialized) // AC Detect | ||
| { | ||
| Debug = "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 | ||
| { | ||
| Debug = "EC: BAT0 Update (17)" | ||
| Notify (^^^^BAT0, 0x81) // Information Change | ||
| } | ||
|
|
||
| Method (_Q19, 0, NotSerialized) // BAT0 Update | ||
| { | ||
| Debug = "EC: BAT0 Update (19)" | ||
| Notify (^^^^BAT0, 0x81) // Information Change | ||
| } | ||
|
|
||
| Method (_Q1B, 0, NotSerialized) // Lid Close | ||
| { | ||
| Debug = "EC: Lid Close" | ||
| Notify (LID0, 0x80) | ||
| } | ||
|
|
||
| Method (_Q1C, 0, NotSerialized) // Thermal Trip | ||
| { | ||
| Debug = "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 | ||
| { | ||
| Debug = "EC: Power Button" | ||
| Notify (PWRB, 0x80) | ||
| } | ||
|
|
||
| Method (_Q50, 0, NotSerialized) // Other Events | ||
| { | ||
| Local0 = OEM4 | ||
| If (Local0 == 0x8A) { | ||
| Debug = "EC: White Keyboard Backlight" | ||
| Notify (^^^^LIEC, 0x80) | ||
| } ElseIf (Local0 == 0x9F) { | ||
| Debug = "EC: Color Keyboard Toggle" | ||
| Notify (^^^^LIEC, 0x81) | ||
| } ElseIf (Local0 == 0x81) { | ||
| Debug = "EC: Color Keyboard Down" | ||
| Notify (^^^^LIEC, 0x82) | ||
| } ElseIf (Local0 == 0x82) { | ||
| Debug = "EC: Color Keyboard Up" | ||
| Notify (^^^^LIEC, 0x83) | ||
| } ElseIf (Local0 == 0x80) { | ||
| Debug = "EC: Color Keyboard Color Change" | ||
| Notify (^^^^LIEC, 0x84) | ||
| } Else { | ||
| Debug = Concatenate("EC: Other: ", ToHexString(Local0)) | ||
| } | ||
| } | ||
|
|
||
| #include "battery_thresholds.asl" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| OperationRegion (ERAM, EmbeddedControl, Zero, 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, | ||
| 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), | ||
| WLED, 8, // WiFi LED | ||
| NOTR, 8, // notification LED R | ||
| NOTG, 8, // notification LED G | ||
| NOTB, 8, // notification LED B | ||
| WINF, 8, // Enable ACPI brightness controls | ||
| Offset (0xF8), | ||
| FCMD, 8, | ||
| FDAT, 8, | ||
| FBUF, 8, | ||
| FBF1, 8, | ||
| FBF2, 8, | ||
| FBF3, 8, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| Device (HIDD) | ||
| { | ||
| Name (_HID, "INT33D5") | ||
| Name (HBSY, Zero) | ||
| Name (HIDX, Zero) | ||
| Name (HRDY, Zero) | ||
|
|
||
| Method (HDEM, 0, Serialized) | ||
| { | ||
| HBSY = Zero | ||
| Return (HIDX) | ||
| } | ||
|
|
||
| Method (HDMM, 0, Serialized) | ||
| { | ||
| Return (Zero) | ||
| } | ||
|
|
||
| Method (HDSM, 1, Serialized) | ||
| { | ||
| HRDY = Arg0 | ||
| } | ||
|
|
||
| Method (HPEM, 1, Serialized) | ||
| { | ||
| 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) | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,176 @@ | ||
| /* 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 | ||
| Device (LIEC) { | ||
| Name (_HID, "PURI4543") | ||
| Name (_UID, 0) | ||
|
|
||
| Method (RSET, 0, Serialized) { | ||
| Debug = "LIEC: RSET" | ||
| SAPL(0) | ||
| SKBL(0) | ||
| } | ||
|
|
||
| Method (INIT, 0, Serialized) { | ||
| Debug = "LIEC: 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) { | ||
| Debug = "LIEC: 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.WLED & 0x40) { | ||
| Return (1) | ||
| } | ||
| } | ||
| Return (0) | ||
| } | ||
|
|
||
| // Set Airplane LED | ||
| Method (SAPL, 1, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| If (Arg0) { | ||
| ^^PCI0.LPCB.EC0.WLED |= 0x40 | ||
| } Else { | ||
| ^^PCI0.LPCB.EC0.WLED &= 0xBF | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Get notification red LED | ||
| Method (GNTR, 0, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| Return (^^PCI0.LPCB.EC0.NOTR) | ||
| } | ||
| Return (0) | ||
| } | ||
|
|
||
| // Set notification red LED | ||
| Method (SNTR, 1, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| ^^PCI0.LPCB.EC0.NOTR = Arg0 | ||
| } | ||
| } | ||
|
|
||
| // Get notification green LED | ||
| Method (GNTG, 0, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| Return (^^PCI0.LPCB.EC0.NOTG) | ||
| } | ||
| Return (0) | ||
| } | ||
|
|
||
| // Set notification green LED | ||
| Method (SNTG, 1, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| ^^PCI0.LPCB.EC0.NOTG = Arg0 | ||
| } | ||
| } | ||
|
|
||
| // Get notification blue LED | ||
| Method (GNTB, 0, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| Return (^^PCI0.LPCB.EC0.NOTB) | ||
| } | ||
| Return (0) | ||
| } | ||
|
|
||
| // Set notification blue LED | ||
| Method (SNTB, 1, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| ^^PCI0.LPCB.EC0.NOTB = Arg0 | ||
| } | ||
| } | ||
|
|
||
| // Get KB LED | ||
| Method (GKBL, 0, Serialized) { | ||
| Local0 = 0 | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| ^^PCI0.LPCB.EC0.FDAT = One | ||
| ^^PCI0.LPCB.EC0.FCMD = 0xCA | ||
| Local0 = ^^PCI0.LPCB.EC0.FBUF | ||
| ^^PCI0.LPCB.EC0.FCMD = Zero | ||
| } | ||
| Return (Local0) | ||
| } | ||
|
|
||
| // Set KB Led | ||
| Method (SKBL, 1, Serialized) { | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| ^^PCI0.LPCB.EC0.FDAT = Zero | ||
| ^^PCI0.LPCB.EC0.FBUF = Arg0 | ||
| ^^PCI0.LPCB.EC0.FCMD = 0xCA | ||
| } | ||
| } | ||
|
|
||
| // Fan names | ||
| Method (NFAN, 0, Serialized) { | ||
| Return (Package() { | ||
| "CPU fan", | ||
| }) | ||
| } | ||
|
|
||
| // 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", | ||
| }) | ||
| } | ||
|
|
||
| // 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) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) { | ||
| DEBUG = "LID: _LID" | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| Return (^^PCI0.LPCB.EC0.LSTE) | ||
| } Else { | ||
| Return (One) | ||
| } | ||
| } | ||
|
|
||
| Method (_PSW, 1, NotSerialized) { | ||
| DEBUG = Concatenate("LID: _PSW: ", ToHexString(Arg0)) | ||
| If (^^PCI0.LPCB.EC0.ECOK) { | ||
| ^^PCI0.LPCB.EC0.LWKE = Arg0 | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <arch/io.h> | ||
| #include <console/system76_ec.h> | ||
| #include <timer.h> | ||
|
|
||
| // This is the command region for Librem EC firmware. It must be | ||
| // enabled for LPC in the mainboard. | ||
| #define LIBREM_EC_BASE 0x0E00 | ||
| #define LIBREM_EC_SIZE 256 | ||
|
|
||
| #define REG_CMD 0 | ||
| #define REG_RESULT 1 | ||
|
|
||
| // When command register is 0, command is complete | ||
| #define CMD_FINISHED 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 system76_ec_read(uint8_t addr) | ||
| { | ||
| return inb(LIBREM_EC_BASE + (uint16_t)addr); | ||
| } | ||
|
|
||
| static inline void system76_ec_write(uint8_t addr, uint8_t data) | ||
| { | ||
| outb(data, LIBREM_EC_BASE + (uint16_t)addr); | ||
| } | ||
|
|
||
| void system76_ec_init(void) | ||
| { | ||
| // Clear entire command region | ||
| for (int i = 0; i < LIBREM_EC_SIZE; i++) | ||
| system76_ec_write((uint8_t)i, 0); | ||
| } | ||
|
|
||
| void system76_ec_flush(void) | ||
| { | ||
| system76_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, system76_ec_read(REG_CMD) == CMD_FINISHED); | ||
|
|
||
| system76_ec_write(CMD_PRINT_REG_LEN, 0); | ||
| } | ||
|
|
||
| void system76_ec_print(uint8_t byte) | ||
| { | ||
| uint8_t len = system76_ec_read(CMD_PRINT_REG_LEN); | ||
| system76_ec_write(CMD_PRINT_REG_DATA + len, byte); | ||
| system76_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 >= (LIBREM_EC_SIZE - CMD_PRINT_REG_DATA)) | ||
| system76_ec_flush(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __ACPI_ACPI_OSC_H__ | ||
| #define __ACPI_ACPI_OSC_H__ | ||
|
|
||
| /* _OSC (Operating System Capabilities) */ | ||
| #define OSC_CDW1_QUERY (1 << 0) | ||
| #define OSC_CDW1_UNKNOWN_FAILURE (1 << 1) | ||
| #define OSC_CDW1_UNRECOGNIZED_UUID (1 << 2) | ||
| #define OSC_CDW1_UNRECOGNIZED_REVISION (1 << 3) | ||
| #define OSC_CDW1_CAPABILITIES_MASKED (1 << 4) | ||
|
|
||
| /* Platform-Wide \_SB._OSC */ | ||
| #define OSC_SB_UUID "0811b06e-4a27-44f9-8d60-3cbbc22e7b48" | ||
|
|
||
| #endif /* __ACPI_ACPI_OSC_H__ */ |