From 07fe6184bc1d834377a91bfbe7e796d8027f1f24 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Fri, 26 Jan 2018 14:37:16 +0800 Subject: chromeec: Add support for reading second battery info We share the same shared memory fields for both batteries. When the host wants to switch battery to read out, it will: - Set BTID (EC_ACPI_MEM_BATTERY_INDEX) to the required index - Wait for BITX (EC_MEMMAP_BATT_INDEX) to have the required value - Then fetch the data BRANCH=none BUG=b:65697620 TEST=Boot lux, both /sys/class/power_supply/BAT0 and BAT1 are present, data is valid. Change-Id: Ib06176e6ab4c45a899259f0917e6292121865ed6 Signed-off-by: Nicolas Boichat Reviewed-on: https://review.coreboot.org/23598 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie --- src/ec/google/chromeec/acpi/battery.asl | 417 +++++++++++++++++++++++--------- src/ec/google/chromeec/acpi/ec.asl | 14 +- src/ec/google/chromeec/acpi/emem.asl | 5 + 3 files changed, 324 insertions(+), 112 deletions(-) diff --git a/src/ec/google/chromeec/acpi/battery.asl b/src/ec/google/chromeec/acpi/battery.asl index 2ed4468999..18b612db2a 100644 --- a/src/ec/google/chromeec/acpi/battery.asl +++ b/src/ec/google/chromeec/acpi/battery.asl @@ -16,6 +16,227 @@ // Scope (EC0) +/* Mutex for EC battery index interface */ +Mutex (BATM, 1) + +// Wait for desired battery index to be presented in shared memory +// Arg0 = battery index +// Returns Zero on success, One on error. +Method (BTSW, 1) +{ +#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE + If (LEqual (BTIX, Arg0)) { + Return (Zero) + } + If (LGreaterEqual (Arg0, BTCN)) { + Return (One) + } + Store (Arg0, \_SB.PCI0.LPCB.EC0.BTID) + Store (5, Local0) // Timeout 5 msec + While (LNotEqual (BTIX, Arg0)) + { + Sleep (1) + Decrement (Local0) + If (LEqual (Local0, Zero)) + { + Return (One) + } + } +#endif + Return (Zero) +} + +// _STA implementation. +// Arg0 = battery index +Method (BSTA, 1, Serialized) +{ + If (Acquire (^BATM, 1000)) { + Return (Zero) + } + + If (And(Not(BTSW (Arg0)), BTEX)) { + Store (0x1F, Local0) + } Else { + Store (0x0F, Local0) + } + + Release (^BATM) + Return (Local0) +} + +// _BIF implementation. +// Arg0 = battery index +// Arg1 = PBIF +Method (BBIF, 2, Serialized) +{ + If (Acquire (^BATM, 1000)) { + Return (Arg1) + } + + If (BTSW (Arg0)) { + Release (^BATM) + Return (Arg1) + } + // Last Full Charge Capacity + Store (BTDF, Index (Arg1, 2)) + + // Design Voltage + Store (BTDV, Index (Arg1, 4)) + + // Design Capacity + Store (BTDA, Local0) + Store (Local0, Index (Arg1, 1)) + + // Design Capacity of Warning + Divide (Multiply (Local0, DWRN), 100, , Local2) + Store (Local2, Index (Arg1, 5)) + + // Design Capacity of Low + Divide (Multiply (Local0, DLOW), 100, , Local2) + Store (Local2, Index (Arg1, 6)) + + // Get battery info from mainboard + Store (ToString(Concatenate(BMOD, 0x00)), Index (Arg1, 9)) + Store (ToString(Concatenate(BSER, 0x00)), Index (Arg1, 10)) + Store (ToString(Concatenate(BMFG, 0x00)), Index (Arg1, 12)) + + Release (^BATM) + Return (Arg1) +} + +// _BIX implementation. +// Arg0 = battery index +// Arg1 = PBIX +Method (BBIX, 2, Serialized) +{ + If (Acquire (^BATM, 1000)) { + Return (Arg1) + } + + If (BTSW (Arg0)) { + Release (^BATM) + Return (Arg1) + } + // Last Full Charge Capacity + Store (BTDF, Index (Arg1, 3)) + + // Design Voltage + Store (BTDV, Index (Arg1, 5)) + + // Design Capacity + Store (BTDA, Local0) + Store (Local0, Index (Arg1, 2)) + + // Design Capacity of Warning + Divide (Multiply (Local0, DWRN), 100, , Local2) + Store (Local2, Index (Arg1, 6)) + + // Design Capacity of Low + Divide (Multiply (Local0, DLOW), 100, , Local2) + Store (Local2, Index (Arg1, 7)) + + // Cycle Count + Store (BTCC, Index (Arg1, 8)) + + // Get battery info from mainboard + Store (ToString(Concatenate(BMOD, 0x00)), Index (Arg1, 16)) + Store (ToString(Concatenate(BSER, 0x00)), Index (Arg1, 17)) + Store (ToString(Concatenate(BMFG, 0x00)), Index (Arg1, 19)) + + Release (^BATM) + Return (Arg1) +} + +// _BST implementation. +// Arg0 = battery index +// Arg1 = PBST +// Arg2 = BSTP +// Arg3 = BFWK +Method (BBST, 4, Serialized) +{ + If (Acquire (^BATM, 1000)) { + Return (Arg1) + } + + If (BTSW (Arg0)) { + Release (^BATM) + Return (Arg1) + } + // + // 0: BATTERY STATE + // + // bit 0 = discharging + // bit 1 = charging + // bit 2 = critical level + // + Store (Zero, Local1) + + // Check if AC is present + If (ACEX) { + If (BFCG) { + Store (0x02, Local1) + } ElseIf (BFDC) { + Store (0x01, Local1) + } + } Else { + // Always discharging when on battery power + Store (0x01, Local1) + } + + // Check for critical battery level + If (BFCR) { + Or (Local1, 0x04, Local1) + } + Store (Local1, Index (Arg1, 0)) + + // Notify if battery state has changed since last time + If (LNotEqual (Local1, Arg2)) { + Store (Local1, Arg2) + If (LEqual(Arg0, 0)) { + Notify (BAT0, 0x80) + } +#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE + Else { + Notify (BAT1, 0x80) + } +#endif + } + + // + // 1: BATTERY PRESENT RATE + // + Store (BTPR, Index (Arg1, 1)) + + // + // 2: BATTERY REMAINING CAPACITY + // + Store (BTRA, Local1) + If (LAnd (Arg3, LAnd (ACEX, LNot (LAnd (BFDC, BFCG))))) { + // On AC power and battery is neither charging + // nor discharging. Linux expects a full battery + // to report same capacity as last full charge. + // https://bugzilla.kernel.org/show_bug.cgi?id=12632 + Store (BTDF, Local2) + + // See if within ~6% of full + ShiftRight (Local2, 4, Local3) + If (LAnd (LGreater (Local1, Subtract (Local2, Local3)), + LLess (Local1, Add (Local2, Local3)))) + { + Store (Local2, Local1) + } + } + Store (Local1, Index (Arg1, 2)) + + // + // 3: BATTERY PRESENT VOLTAGE + // + Store (BTVO, Index (Arg1, 3)) + + Release (^BATM) + Return (Arg1) +} + Device (BAT0) { Name (_HID, EISAID ("PNP0C0A")) @@ -86,138 +307,112 @@ Device (BAT0) Method (_STA, 0, Serialized) { - If (BTEX) { - Return (0x1F) - } Else { - Return (0x0F) - } + Return (BSTA (0)) } Method (_BIF, 0, Serialized) { - // Last Full Charge Capacity - Store (BTDF, Index (PBIF, 2)) - - // Design Voltage - Store (BTDV, Index (PBIF, 4)) - - // Design Capacity - Store (BTDA, Local0) - Store (Local0, Index (PBIF, 1)) - - // Design Capacity of Warning - Divide (Multiply (Local0, DWRN), 100, , Local2) - Store (Local2, Index (PBIF, 5)) - - // Design Capacity of Low - Divide (Multiply (Local0, DLOW), 100, , Local2) - Store (Local2, Index (PBIF, 6)) - - // Get battery info from mainboard - Store (ToString(Concatenate(BMOD, 0x00)), Index (PBIF, 9)) - Store (ToString(Concatenate(BSER, 0x00)), Index (PBIF, 10)) - Store (ToString(Concatenate(BMFG, 0x00)), Index (PBIF, 12)) - - Return (PBIF) + Return (BBIF (0, PBIF)) } Method (_BIX, 0, Serialized) { - // Last Full Charge Capacity - Store (BTDF, Index (PBIX, 3)) + Return (BBIX (0, PBIX)) + } - // Design Voltage - Store (BTDV, Index (PBIX, 5)) + Method (_BST, 0, Serialized) + { + Return (BBST (0, PBST, BSTP, BFWK)) + } +} - // Design Capacity - Store (BTDA, Local0) - Store (Local0, Index (PBIX, 2)) +#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE +Device (BAT1) +{ + Name (_HID, EISAID ("PNP0C0A")) + Name (_UID, 1) + Name (_PCL, Package () { \_SB }) - // Design Capacity of Warning - Divide (Multiply (Local0, DWRN), 100, , Local2) - Store (Local2, Index (PBIX, 6)) + Name (PBIF, Package () { + 0x00000001, // 0x00: Power Unit: mAh + 0xFFFFFFFF, // 0x01: Design Capacity + 0xFFFFFFFF, // 0x02: Last Full Charge Capacity + 0x00000001, // 0x03: Battery Technology: Rechargeable + 0xFFFFFFFF, // 0x04: Design Voltage + 0x00000003, // 0x05: Design Capacity of Warning + 0xFFFFFFFF, // 0x06: Design Capacity of Low + 0x00000001, // 0x07: Capacity Granularity 1 + 0x00000001, // 0x08: Capacity Granularity 2 + "", // 0x09: Model Number + "", // 0x0a: Serial Number + "LION", // 0x0b: Battery Type + "" // 0x0c: OEM Information + }) - // Design Capacity of Low - Divide (Multiply (Local0, DLOW), 100, , Local2) - Store (Local2, Index (PBIX, 7)) + Name (PBIX, Package () { + 0x00000000, // 0x00: Revision + 0x00000001, // 0x01: Power Unit: mAh + 0xFFFFFFFF, // 0x02: Design Capacity + 0xFFFFFFFF, // 0x03: Last Full Charge Capacity + 0x00000001, // 0x04: Battery Technology: Rechargeable + 0xFFFFFFFF, // 0x05: Design Voltage + 0x00000003, // 0x06: Design Capacity of Warning + 0xFFFFFFFF, // 0x07: Design Capacity of Low + 0x00000000, // 0x08: Cycle Count + 0x00018000, // 0x09: Measurement Accuracy (98.3%?) + 0x000001F4, // 0x0a: Max Sampling Time (500ms) + 0x0000000a, // 0x0b: Min Sampling Time (10ms) + 0xFFFFFFFF, // 0x0c: Max Averaging Interval + 0xFFFFFFFF, // 0x0d: Min Averaging Interval + 0x00000001, // 0x0e: Capacity Granularity 1 + 0x00000001, // 0x0f: Capacity Granularity 2 + "", // 0x10 Model Number + "", // 0x11: Serial Number + "LION", // 0x12: Battery Type + "" // 0x13: OEM Information + }) - // Cycle Count - Store (BTCC, Index (PBIX, 8)) + Name (PBST, Package () { + 0x00000000, // 0x00: Battery State + 0xFFFFFFFF, // 0x01: Battery Present Rate + 0xFFFFFFFF, // 0x02: Battery Remaining Capacity + 0xFFFFFFFF, // 0x03: Battery Present Voltage + }) + Name (BSTP, Zero) - // Get battery info from mainboard - Store (ToString(Concatenate(BMOD, 0x00)), Index (PBIX, 16)) - Store (ToString(Concatenate(BSER, 0x00)), Index (PBIX, 17)) - Store (ToString(Concatenate(BMFG, 0x00)), Index (PBIX, 19)) + // Workaround for full battery status, enabled by default + Name (BFWK, One) - Return (PBIX) + // Method to enable full battery workaround + Method (BFWE) + { + Store (One, BFWK) } - Method (_BST, 0, Serialized) + // Method to disable full battery workaround + Method (BFWD) { - // - // 0: BATTERY STATE - // - // bit 0 = discharging - // bit 1 = charging - // bit 2 = critical level - // - Store (Zero, Local1) - - // Check if AC is present - If (ACEX) { - If (BFCG) { - Store (0x02, Local1) - } ElseIf (BFDC) { - Store (0x01, Local1) - } - } Else { - // Always discharging when on battery power - Store (0x01, Local1) - } - - // Check for critical battery level - If (BFCR) { - Or (Local1, 0x04, Local1) - } - Store (Local1, Index (PBST, 0)) + Store (Zero, BFWK) + } - // Notify if battery state has changed since last time - If (LNotEqual (Local1, BSTP)) { - Store (Local1, BSTP) - Notify (BAT0, 0x80) - } + Method (_STA, 0, Serialized) + { + Return (BSTA (1)) + } - // - // 1: BATTERY PRESENT RATE - // - Store (BTPR, Index (PBST, 1)) - - // - // 2: BATTERY REMAINING CAPACITY - // - Store (BTRA, Local1) - If (LAnd (BFWK, LAnd (ACEX, LNot (LAnd (BFDC, BFCG))))) { - // On AC power and battery is neither charging - // nor discharging. Linux expects a full battery - // to report same capacity as last full charge. - // https://bugzilla.kernel.org/show_bug.cgi?id=12632 - Store (BTDF, Local2) - - // See if within ~6% of full - ShiftRight (Local2, 4, Local3) - If (LAnd (LGreater (Local1, Subtract (Local2, Local3)), - LLess (Local1, Add (Local2, Local3)))) - { - Store (Local2, Local1) - } - } - Store (Local1, Index (PBST, 2)) + Method (_BIF, 0, Serialized) + { + Return (BBIF (1, PBIF)) + } - // - // 3: BATTERY PRESENT VOLTAGE - // - Store (BTVO, Index (PBST, 3)) + Method (_BIX, 0, Serialized) + { + Return (BBIX (1, PBIX)) + } - Return (PBST) + Method (_BST, 0, Serialized) + { + Return (BBST (1, PBST, BSTP, BFWK)) } } +#endif diff --git a/src/ec/google/chromeec/acpi/ec.asl b/src/ec/google/chromeec/acpi/ec.asl index 618b00a79e..62f9acda4c 100644 --- a/src/ec/google/chromeec/acpi/ec.asl +++ b/src/ec/google/chromeec/acpi/ec.asl @@ -90,7 +90,9 @@ Device (EC0) DEVE, 1, // EC supports device events // make sure we're within our space envelope Offset (0x0e), - } + Offset (0x12), + BTID, 8, // Battery index that host wants to read +} #if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_ACPI_MEMMAP) OperationRegion (EMEM, EmbeddedControl, @@ -272,6 +274,11 @@ Device (EC0) { Store ("EC: BATTERY INFO", Debug) Notify (BAT0, 0x81) +#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE + If (CondRefOf (BAT1)) { + Notify (BAT1, 0x81) + } +#endif } // Thermal Overload Event @@ -347,6 +354,11 @@ Device (EC0) { Store ("EC: BATTERY STATUS", Debug) Notify (BAT0, 0x80) +#ifdef EC_ENABLE_SECOND_BATTERY_DEVICE + If (CondRefOf (BAT1)) { + Notify (BAT1, 0x80) + } +#endif } // MKBP interrupt. diff --git a/src/ec/google/chromeec/acpi/emem.asl b/src/ec/google/chromeec/acpi/emem.asl index ba98831b73..982ec5bf89 100644 --- a/src/ec/google/chromeec/acpi/emem.asl +++ b/src/ec/google/chromeec/acpi/emem.asl @@ -30,6 +30,8 @@ TIN8, 8, // Temperature 8 TIN9, 8, // Temperature 9 Offset (0x10), FAN0, 16, // Fan Speed 0 +Offset (0x24), +BTVR, 8, // Battery structure version Offset (0x30), LIDS, 1, // Lid Switch State PBTN, 1, // Power Button Pressed @@ -45,6 +47,9 @@ BTEX, 1, // Battery Present BFDC, 1, // Battery Discharging BFCG, 1, // Battery Charging BFCR, 1, // Battery Level Critical +Offset (0x4d), +BTCN, 8, // Battery Count +BTIX, 8, // Battery index Offset (0x50), BTDA, 32, // Battery Design Capacity BTDV, 32, // Battery Design Voltage -- cgit v1.2.3