1/* SPDX-License-Identifier: LGPL-2.1-only */ 2/* 3 * ssdt_pm.asl 4 * 5 * Copyright (c) 2008 Kamala Narasimhan 6 * Copyright (c) 2008 Citrix Systems, Inc. 7 */ 8 9/* 10 * SSDT for extended power management within HVM guest. Power management beyond 11 * S3, S4, S5 is handled by this vACPI layer. 12 * 13 * Battery Management Implementation - 14 * Xen vACPI layer exposes battery information to guest using CMBattery 15 * interface. This virtual firmware CMBattery implementation is very similar to 16 * the actual firmware CMBattery implementation. In fact, a good part of the 17 * below is heavily borrowed from the underlying firmware to support 18 * pass-through and non-pass-through battery management approaches using the 19 * same CMBattery interface implementation. When pass-through approach is used, 20 * the battery ports are directly mapped using xc_domain_ioport_mapping thus 21 * not relying on qemu battery port handling to intercept port reads/writes to 22 * feed relevant battery information to the guest. 23 * 24 * Following are the battery ports read/written to in order to implement 25 * battery support: 26 * Battery command port - 0xb2 27 * Batter data port - 0x86 28 * Battery commands (written to port 0xb2) - 29 * 0x7b - Battery operation init 30 * 0x7c - Type of battery operation 31 * 0x79 - Get battery data length 32 * 0x7d - Get battery data 33 * 34 * Also the following ports are used for debugging/logging: 35 * 0xB040, 0xB044, 0xB046, 0xB048 36 */ 37 38DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) 39{ 40 Scope (\_SB) 41 { 42 OperationRegion (DBGA, SystemIO, 0xB040, 0x01) 43 Field (DBGA, ByteAcc, NoLock, Preserve) 44 { 45 DBG1, 8, 46 } 47 48 OperationRegion (DBGB, SystemIO, 0xB044, 0x01) 49 Field (DBGB, ByteAcc, NoLock, Preserve) 50 { 51 DBG2, 8, 52 } 53 54 OperationRegion (DBGC, SystemIO, 0xB046, 0x01) 55 Field (DBGC, ByteAcc, NoLock, Preserve) 56 { 57 DBG3, 8, 58 } 59 60 OperationRegion (DBGD, SystemIO, 0xB048, 0x01) 61 Field (DBGD, ByteAcc, NoLock, Preserve) 62 { 63 DBG4, 8, 64 } 65 66 OperationRegion (PRT1, SystemIO, 0xB2, 0x02) 67 Field (PRT1, ByteAcc, NoLock, Preserve) 68 { 69 PB2, 8, 70 PB2A, 8 71 } 72 73 OperationRegion (PRT2, SystemIO, 0x86, 0x01) 74 Field (PRT2, ByteAcc, NoLock, Preserve) 75 { 76 P86, 8 77 } 78 79 OperationRegion (PRT3, SystemIO, 0x88, 0x01) 80 Field (PRT3, ByteAcc, NoLock, Preserve) 81 { 82 P88, 8 83 } 84 85 86 Mutex (SYNC, 0x01) 87 Name (BUF0, Buffer (0x0100) {}) 88 Name (BUF1, Buffer (0x08) {}) 89 CreateWordField (BUF1, 0x00, BUFA) 90 CreateWordField (BUF1, 0x04, BUFB) 91 Method (ACQR, 0, NotSerialized) 92 { 93 Acquire (SYNC, 0xFFFF) 94 Store (0x00, BUFA) 95 } 96 97 /* 98 * Initialize relevant buffer to indicate what type of 99 * information is being queried and by what object (e.g. 100 * by battery device 0 or 1). 101 */ 102 Method (INIT, 1, NotSerialized) 103 { 104 Store (BUFA, Local0) 105 Increment (Local0) 106 If (LLessEqual (Local0, SizeOf (BUF0))) 107 { 108 CreateByteField (BUF0, BUFA, TMP1) 109 Store (Arg0, TMP1) 110 Store (Local0, BUFA) 111 } 112 } 113 114 /* 115 * Write to battery port 0xb2 indicating the type of information 116 * to request, initialize battery data port 0x86 and then return 117 * value provided through data port 0x86. 118 */ 119 Method (WPRT, 2, NotSerialized) 120 { 121 Store (Arg1, \_SB.P86) 122 Store (Arg0, \_SB.PB2) 123 Store (Arg0, \_SB.DBG2) 124 Store (Arg1, \_SB.DBG4) 125 Store (\_SB.PB2, Local0) 126 While (LNotEqual (Local0, 0x00)) 127 { 128 Store (\_SB.PB2, Local0) 129 } 130 131 Store (\_SB.P86, Local1) 132 Store (Local1, \_SB.DBG3) 133 Return (\_SB.P86) 134 } 135 136 /* 137 * Helper method 1 to write to battery command and data port. 138 * 0x7c written to port 0xb2 indicating battery info type command. 139 * Value 1 or 2 written to port 0x86. 1 for BIF (batterry info) and 2 140 * for BST (battery status). 141 */ 142 Method (HLP1, 2, NotSerialized) 143 { 144 If (LLess (Arg1, SizeOf (Arg0))) 145 { 146 CreateByteField (Arg0, Arg1, TMP1) 147 WPRT (0x7C, TMP1) 148 } 149 } 150 151 /* 152 * Helper method 2. Value 0x7b written to battery command port 0xb2 153 * indicating battery info initialization request. First thing written 154 * to battery port before querying for further information pertaining 155 * to the battery. 156 */ 157 Method (HLP2, 0, NotSerialized) 158 { 159 WPRT (0x7B, 0x00) 160 Store (0x00, Local0) 161 While (LLess (Local0, BUFA)) 162 { 163 HLP1 (BUF0, Local0) 164 Increment (Local0) 165 } 166 } 167 168 /* 169 * Helper method 3. 0x7d written to battery command port 0xb2 170 * indicating request of battery data returned through battery data 171 * port 0x86. 172 */ 173 Method (HLP3, 2, NotSerialized) 174 { 175 If (LLess (Arg1, SizeOf (Arg0))) 176 { 177 CreateByteField (Arg0, Arg1, TMP1) 178 Store (WPRT (0x7D, 0x00), TMP1) 179 } 180 } 181 182 /* 183 * Helper method 4 to indirectly get battery data and store it in a 184 * local buffer. 185 */ 186 Method (HLP4, 0, NotSerialized) 187 { 188 Store (0x00, Local0) 189 While (LLess (Local0, BUFB)) 190 { 191 Add (BUFA, Local0, Local1) 192 HLP3 (BUF0, Local1) 193 Increment (Local0) 194 } 195 } 196 197 /* 198 * Helper method 5 to indirectly initialize battery port and get 199 * battery data. Also get battery data length by writing 0x79 to 200 * battery command port and receiving battery data length in port 0x86. 201 */ 202 Method (HLP5, 0, NotSerialized) 203 { 204 HLP2 () 205 Store (WPRT (0x79, 0x00), BUFB) 206 Add (BUFA, BUFB, Local0) 207 If (LLess (SizeOf (BUF0), Local0)) 208 { 209 Store (SizeOf (BUF0), Local0) 210 Subtract (Local0, BUFA, Local0) 211 Store (Local0, BUFB) 212 } 213 214 HLP4 () 215 } 216 217 /* Helper method for local buffer housekeeping... */ 218 Method (HLP6, 0, NotSerialized) 219 { 220 Store (BUFA, Local0) 221 Increment (Local0) 222 If (LLessEqual (Local0, SizeOf (BUF0))) 223 { 224 CreateByteField (BUF0, BUFA, TMP1) 225 Store (Local0, BUFA) 226 Return (TMP1) 227 } 228 229 Return (0x00) 230 } 231 232 /* Helper methods to help store battery data retrieved through 233 * battery data port 0x86. */ 234 235 Method (HLP7, 0, NotSerialized) 236 { 237 Store (BUFA, Local0) 238 Add (Local0, 0x04, Local0) 239 If (LLessEqual (Local0, SizeOf (BUF0))) 240 { 241 CreateDWordField (BUF0, BUFA, SX22) 242 Store (Local0, BUFA) 243 Return (SX22) 244 } 245 246 Return (0x00) 247 } 248 249 Method (HLP8, 2, NotSerialized) 250 { 251 If (LLess (Arg1, SizeOf (Arg0))) 252 { 253 CreateByteField (Arg0, Arg1, TMP1) 254 Store (HLP6 (), TMP1) 255 } 256 } 257 258 Method (HLP9, 2, NotSerialized) 259 { 260 Store (0x00, Local0) 261 While (LLess (Local0, Arg1)) 262 { 263 HLP8 (Arg0, Local0) 264 Increment (Local0) 265 } 266 Return (Arg0) 267 } 268 269 Method (HLPA, 0, NotSerialized) 270 { 271 Store (HLP6 (), Local0) 272 Return (HLP9 (Buffer (Local0) {}, Local0)) 273 } 274 275 Method (REL, 0, NotSerialized) 276 { 277 Release (SYNC) 278 } 279 280 /* Future patches will extend AC object to better account for 281 * AC to DC transition and more. */ 282 Device (AC) 283 { 284 Name (_HID, "ACPI0003") 285 Name (_PCL, Package (0x03) 286 { 287 \_SB, 288 BAT0, 289 BAT1 290 }) 291 Method (_PSR, 0, NotSerialized) 292 { 293 Return (0x0) 294 } 295 296 Method (_STA, 0, NotSerialized) 297 { 298 Return (0x0F) 299 } 300 } 301 302 /* Main battery information helper method. */ 303 Name (BIFP, Package (0x0D) {}) 304 Method (BIF, 1, NotSerialized) 305 { 306 ACQR () 307 INIT (0x01) 308 INIT (Arg0) 309 HLP5 () 310 Store (HLP7 (), Index (BIFP, 0x00)) 311 Store (HLP7 (), Index (BIFP, 0x01)) 312 Store (HLP7 (), Index (BIFP, 0x02)) 313 Store (HLP7 (), Index (BIFP, 0x03)) 314 Store (HLP7 (), Index (BIFP, 0x04)) 315 Store (HLP7 (), Index (BIFP, 0x05)) 316 Store (HLP7 (), Index (BIFP, 0x06)) 317 Store (HLP7 (), Index (BIFP, 0x07)) 318 Store (HLP7 (), Index (BIFP, 0x08)) 319 Store (HLPA (), Index (BIFP, 0x09)) 320 Store (HLPA (), Index (BIFP, 0x0A)) 321 Store (HLPA (), Index (BIFP, 0x0B)) 322 Store (HLPA (), Index (BIFP, 0x0C)) 323 REL () 324 Return (BIFP) 325 } 326 327 /* Battery object 0 - Always exposed as present. */ 328 Device (BAT0) 329 { 330 Name (_HID, EisaId ("PNP0C0A")) 331 Name (_UID, 0x01) 332 Name (_PCL, Package (0x01) 333 { 334 \_SB 335 }) 336 337 /* Always returns 0x1f indicating battery present. */ 338 Method (_STA, 0, NotSerialized) 339 { 340 Store (\_SB.P88, Local0) 341 Return ( Local0 ) 342 } 343 344 /* Battery generic info: design capacity, voltage, model # etc. */ 345 Method (_BIF, 0, NotSerialized) 346 { 347 //Store (1, \_SB.DBG1) 348 Store(BIF ( 0x01 ), Local0) 349 //Store (2, \_SB.DBG1) 350 Return( Local0 ) 351 } 352 353 /* Battery status including battery charging/discharging rate. */ 354 Method (_BST, 0, NotSerialized) 355 { 356 Store (1, \_SB.DBG1) 357 ACQR () 358 INIT (0x02) 359 INIT (0x01) 360 HLP5 () 361 Store (Package (0x04) {}, Local0) 362 Store (HLP7 (), Index (Local0, 0x00)) 363 Store (HLP7 (), Index (Local0, 0x01)) 364 Store (HLP7 (), Index (Local0, 0x02)) 365 Store (HLP7 (), Index (Local0, 0x03)) 366 REL () 367 Store (2, \_SB.DBG1) 368 Return (Local0) 369 } 370 } 371 372 /* Battery object 1 - Always exposed as not present. */ 373 Device (BAT1) 374 { 375 Name (_HID, EisaId ("PNP0C0A")) 376 Name (_UID, 0x02) 377 Name (_PCL, Package (0x01) 378 { 379 \_SB 380 }) 381 Method (_STA, 0, NotSerialized) 382 { 383 Return (0x0F) 384 } 385 386 Method (_BIF, 0, NotSerialized) 387 { 388 Store (\_SB.PB2, Local0) 389 Return (BIF (0x02)) 390 } 391 392 Method (_BST, 0, NotSerialized) 393 { 394 ACQR () 395 INIT (0x02) 396 INIT (0x02) 397 HLP5 () 398 Store (Package (0x04) {}, Local0) 399 Store (HLP7 (), Index (Local0, 0x00)) 400 Store (HLP7 (), Index (Local0, 0x01)) 401 Store (HLP7 (), Index (Local0, 0x02)) 402 Store (HLP7 (), Index (Local0, 0x03)) 403 REL () 404 Return (Local0) 405 } 406 } 407 } 408} 409 410