1/* SPDX-License-Identifier: GPL-2.0-only */ 2 3/* 4 * The mainboard must define strings in the root scope to 5 * report device-specific battery information to the OS. 6 * 7 * BATM: Model 8 * BATS: Serial 9 * BATV: Vendor 10 */ 11 12// Scope (EC0) 13 14Device (BAT0) 15{ 16 Name (_HID, EISAID ("PNP0C0A")) 17 Name (_UID, 1) 18 Name (_PCL, Package () { \_SB }) 19 20 Name (PBIF, Package () { 21 0x00000001, // Power Unit: mAh 22 0xFFFFFFFF, // Design Capacity 23 0xFFFFFFFF, // Last Full Charge Capacity 24 0x00000001, // Battery Technology: Rechargeable 25 0xFFFFFFFF, // Design Voltage 26 0x00000003, // Design Capacity of Warning 27 0xFFFFFFFF, // Design Capacity of Low 28 0x00000001, // Capacity Granularity 1 29 0x00000001, // Capacity Granularity 2 30 "", // Model Number 31 "", // Serial Number 32 "LION", // Battery Type 33 "" // OEM Information 34 }) 35 36 Name (PBST, Package () { 37 0x00000000, // Battery State 38 0xFFFFFFFF, // Battery Present Rate 39 0xFFFFFFFF, // Battery Remaining Capacity 40 0xFFFFFFFF, // Battery Present Voltage 41 }) 42 Name (BSTP, 0) 43 44 // Workaround for full battery status, enabled by default 45 Name (BFWK, 1) 46 47 // Method to enable full battery workaround 48 Method (BFWE) 49 { 50 BFWK = 1 51 } 52 53 // Method to disable full battery workaround 54 Method (BFWD) 55 { 56 BFWK = 0 57 } 58 59 // Swap bytes in a word 60 Method (SWAB, 1, NotSerialized) 61 { 62 Local0 = Arg0 >> 8 63 Local1 = Arg0 << 8 64 Local1 &= 0xFF00 65 Local0 |= Local1 66 If (Local0 == 0xFFFF) { 67 Local0 = 0xFFFFFFFF 68 } 69 Return (Local0) 70 } 71 72 Method (_STA, 0, Serialized) 73 { 74 If (BTEX) { 75 Return (0x1F) 76 } Else { 77 Return (0x0F) 78 } 79 } 80 81 Method (_BIF, 0, Serialized) 82 { 83 // Update fields from EC 84 PBIF[1] = SWAB (BTDA) 85 PBIF[2] = SWAB (BTDF) 86 PBIF[4] = SWAB (BTDV) 87 PBIF[6] = SWAB (BTDL) 88 89 // Get battery info from mainboard 90 PBIF[9] = \BATM 91 PBIF[10] = \BATS 92 PBIF[12] = \BATV 93 94 Return (PBIF) 95 } 96 97 Method (_BST, 0, Serialized) 98 { 99 // 100 // 0: BATTERY STATE 101 // 102 // bit 0 = discharging 103 // bit 1 = charging 104 // bit 2 = critical level 105 // 106 107 // Get battery state from EC 108 Local0 = BTST 109 Local1 = 0 110 111 // Check if AC is present 112 If (ACEX) { 113 // Set only charging/discharging bits 114 Local1 = Local0 & 3 115 } Else { 116 // Always discharging when on battery power 117 Local1 = 0x01 118 } 119 120 // Flag if the battery level is critical 121 Local4 = Local0 & 4 122 Local1 |= Local4 123 PBST[0] = Local1 124 125 // Notify if battery state has changed since last time 126 If (Local1 != BSTP) { 127 BSTP = Local1 128 Notify (BAT0, 0x80) 129 } 130 131 // 132 // 1: BATTERY PRESENT RATE 133 // 134 135 Local1 = SWAB (BTPR) 136 If (Local1 != 0xFFFFFFFF && Local1 >= 0x8000) { 137 Local1 ^= 0xFFFF 138 Local1++ 139 } 140 PBST[1] = Local1 141 142 // 143 // 2: BATTERY REMAINING CAPACITY 144 // 145 Local1 = SWAB (BTRA) 146 If (Local1 != 0xFFFFFFFF && Local1 >= 0x8000) { 147 Local1 ^= 0xFFFF 148 Local1++ 149 } 150 151 If (BFWK && ACEX && !Local0) { 152 // On AC power and battery is neither charging 153 // nor discharging. Linux expects a full battery 154 // to report same capacity as last full charge. 155 // https://bugzilla.kernel.org/show_bug.cgi?id=12632 156 Local2 = SWAB (BTDF) 157 158 // See if within ~3% of full 159 Local3 = Local2 >> 5 160 If (Local1 > Local2 - Local3 && Local1 < Local2 + Local3) 161 { 162 Local1 = Local2 163 } 164 } 165 PBST[2] = Local1 166 167 // 168 // 3: BATTERY PRESENT VOLTAGE 169 // 170 PBST[3] = SWAB (BTVO) 171 172 Return (PBST) 173 } 174} 175