/** @file Copyright (c) 2021, Baruch Binyamin Doron SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef LGMR_ENABLED // TODO: Consider actually enforcing mutex? Mutex (BMTX, 0) #endif Name (B0ST, 0) /* Battery 0 status */ /* * EC Registers * * "EBID" is the battery page selector. * * * Data on the 128 bits following offset * 0xE0 is accessed in the following order: * * Information: * Page 0: EBCM # start on page 0 # * Page 0: EBFC * Page 1: EBDC # switch to page 1 # * Page 1: EBDV * Page 1: EBSN * Page 3: EBDN # switch to page 3 # * Page 4: EBCH # switch to page 4 # * Page 2: EBMN # switch to page 2 # * * Status: * Page 0: EBAC # start on page 0 # * Page 0: EBRC * Page 0: EBFC * Page 0: EBVO */ /* Page 0 */ Field (RAM, ByteAcc, Lock, Preserve) { Offset (0xE0), EBRC, 16, /* Battery remaining capacity */ EBFC, 16, /* Battery full charge capacity */ EBPE, 16, EBAC, 16, /* Battery present rate */ EBVO, 16, /* Battery voltage */ , 15, EBCM, 1, /* Battery charging */ EBCU, 16, EBTV, 16, } /* Page 1 */ Field (RAM, ByteAcc, Lock, Preserve) { Offset (0xE0), EBDC, 16, /* Battery design capacity */ EBDV, 16, /* Battery design voltage */ EBSN, 16, /* Battery serial number */ } /* Page 2 */ Field (RAM, ByteAcc, NoLock, Preserve) { Offset (0xE0), EBMN, 128, /* Battery manufacturer */ } /* Page 3 */ Field (RAM, ByteAcc, NoLock, Preserve) { Offset (0xE0), EBDN, 128, /* Battery model */ } /* Page 4 */ Field (RAM, ByteAcc, NoLock, Preserve) { Offset (0xE0), EBCH, 128, /* Battery type */ } #ifdef LGMR_ENABLED OperationRegion (MBB0, SystemMemory, (LGMR + 0x80), 0xFF) Field (MBB0, ByteAcc, Lock, Preserve) { MBRC, 16, MBFC, 16, MBPE, 16, MBAC, 16, MBVO, 16, , 15, MBCM, 1, MBCU, 16, MBTV, 16, } Field (MBB0, ByteAcc, Lock, Preserve) { Offset (0x10), MBDC, 16, MBDV, 16, MBSN, 16, } Field (MBB0, ByteAcc, Lock, Preserve) { Offset (0x40), MBMN, 128, } Field (MBB0, ByteAcc, Lock, Preserve) { Offset (0x50), MBDN, 256, } Field (MBB0, ByteAcc, Lock, Preserve) { Offset (0x70), MBCH, 128, } #endif /* * Arg0: Battery number * Arg1: Battery Information Package * Arg2: Status */ #ifndef LGMR_ENABLED Method (GBIF, 3, Serialized) { Acquire (BMTX, 0xFFFF) // Due to EC paging, don't run this with another function #else Method (GBIF, 3, NotSerialized) { #endif If (Arg2) { Arg1[1] = 0xFFFFFFFF Arg1[2] = 0xFFFFFFFF Arg1[4] = 0xFFFFFFFF Arg1[5] = 0 Arg1[6] = 0 } Else { #ifdef LGMR_ENABLED Local0 = MBCM #else EBID = 0 // We don't know which page was active Local0 = EBCM #endif Arg1[0] = (Local0 ^ 1) #ifdef LGMR_ENABLED Local2 = MBFC Local1 = MBDC #else Local2 = EBFC EBID = 1 Local1 = EBDC #endif If (Local0) { Local2 *= 10 Local1 *= 10 } Arg1[1] = Local1 // Design capacity Arg1[2] = Local2 // Last full charge capacity #ifdef LGMR_ENABLED Arg1[4] = MBDV // Design voltage #else Arg1[4] = EBDV // Design voltage #endif Local6 = (Local2 / 100) // Warning capacities; Remainders ignored Arg1[5] = (Local6 * 7) /* Low: 7% */ Arg1[6] = ((Local6 * 11) / 2) /* Very low: 5.5% */ #ifdef LGMR_ENABLED Local7 = MBSN #else Local7 = EBSN #endif Name (SERN, Buffer (0x06) { " " }) Local6 = 4 While (Local7) { Divide (Local7, 10, Local5, Local7) SERN[Local6] = (Local5 + 0x30) // Add ASCII 0x30 to get character Local6-- } Arg1[10] = SERN // Serial number #ifdef LGMR_ENABLED Arg1[9] = MBDN // Model number Arg1[11] = MBCH // Battery type Arg1[12] = MBMN // OEM information #else EBID = 3 Arg1[9] = EBDN // Model number EBID = 4 Arg1[11] = EBCH // Battery type EBID = 2 Arg1[12] = EBMN // OEM information #endif } #ifndef LGMR_ENABLED Release (BMTX) #endif Return (Arg1) } /* * Arg0: Battery number * Arg1: State information * Arg2: Power units * Arg3: Battery Status Package */ Method (GBST, 4, NotSerialized) // All on one page { #ifndef LGMR_ENABLED Acquire (BMTX, 0xFFFF) // Due to EC paging, don't run this with another function #endif If (Arg1 & 0x02) // BIT1 in "MB0S/EB0S" { Local0 = 2 If (Arg1 & 0x20) // "EB0F" { Local0 = 0 } } ElseIf (Arg1 & 0x04) // BIT2 in "MB0S/EB0S" { Local0 = 1 } Else { Local0 = 0 } If (Arg1 & 0x10) // "EB0L" { Local0 |= 0x04 } If (Arg1 & 0x01) // "EB0A" { /* * Present rate is a 16bit signed int, positive while charging * and negative while discharging. */ #ifdef LGMR_ENABLED Local1 = MBAC Local2 = MBRC If (MACS) // Charging #else EBID = 0 // We don't know which page was active Local1 = EBAC Local2 = EBRC If (EACS) // Charging #endif { If (Arg1 & 0x20) // "EB0F" { #ifdef LGMR_ENABLED Local2 = MBFC #else Local2 = EBFC #endif } } If (Arg2) { Local2 *= 10 } #ifdef LGMR_ENABLED Local3 = MBVO #else Local3 = EBVO #endif /* * The present rate value should be positive unless discharging. If so, * negate present rate. */ If (Local1 >= 0x8000) { If (Local0 & 0x01) { Local1 = (0x00010000 - Local1) } Else { Local1 = 0 // Full battery, force to 0 } } /* * If that was not the case, we have an EC bug or inconsistency * and force the value to 0. */ ElseIf ((Local0 & 0x02) == 0) { Local1 = 0 } If (Arg2) { Local1 *= Local3 Local1 /= 1000 /* Remainder ignored */ } } Else { Local0 = 0 Local1 = 0xFFFFFFFF Local2 = 0xFFFFFFFF Local3 = 0xFFFFFFFF } Arg3[0] = Local0 Arg3[1] = Local1 Arg3[2] = Local2 Arg3[3] = Local3 #ifndef LGMR_ENABLED Release (BMTX) #endif Return (Arg3) } Device (BAT0) { Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */) // _HID: Hardware ID Name (_UID, 0) // _UID: Unique ID Name (_PCL, Package () { \_SB }) // _PCL: Power Consumer List Name (B0IP, Package (0x0D) { 1, /* 0x00: Power Unit: mAh */ 0xFFFFFFFF, /* 0x01: Design Capacity */ 0xFFFFFFFF, /* 0x02: Last Full Charge Capacity */ 1, /* 0x03: Battery Technology: Rechargeable */ 0xFFFFFFFF, /* 0x04: Design Voltage */ 0, /* 0x05: Design Capacity of Warning */ 0, /* 0x06: Design Capacity of Low */ 1, /* 0x07: Capacity Granularity 1 */ 1, /* 0x08: Capacity Granularity 2 */ "", /* 0x09: Model Number */ "100", /* 0x0a: Serial Number */ "Lion", /* 0x0b: Battery Type */ 0 /* 0x0c: OEM Information */ }) Name (B0SP, Package (0x04) { 0, /* 0x00: Battery State */ 0xFFFFFFFF, /* 0x01: Battery Present Rate */ 0xFFFFFFFF, /* 0x02: Battery Remaining Capacity */ 0xFFFFFFFF /* 0x03: Battery Present Voltage */ }) Method (_STA, 0, NotSerialized) // _STA: Status { Local1 = EB0A If (Local1 & 0x40) { Local1 = 0 } B0ST = Local1 If (Local1) { Return (0x1F) } Else { Return (0x0F) } } Method (_BIF, 0, NotSerialized) // _BIF: Battery Information { Local6 = B0ST Local7 = 20 While (Local6 && Local7) { If (EB0R) { Local6 = 0 } Else { Sleep (500) Local7-- } } Return (GBIF (0, B0IP, Local6)) } Method (_BST, 0, NotSerialized) // _BST: Battery Status { Local0 = (DerefOf (B0IP[0]) ^ 1) #ifdef LGMR_ENABLED Local5 = MB0S #else Local5 = EB0S #endif Return (GBST (0, Local5, Local0, B0SP)) } }