.. SPDX-License-Identifier: GPL-2.0-only =============================================================================================== Kernel driver yogafan =============================================================================================== Supported chips: * Lenovo Yoga, Legion, IdeaPad, Slim, Flex, and LOQ Embedded Controllers Prefix: 'yogafan' Addresses: ACPI handle (See Database Below) Author: Sergio Melas Description ----------- This driver provides fan speed monitoring for modern Lenovo consumer laptops. Most Lenovo laptops do not provide fan tachometer data through standard ISA/LPC hardware monitoring chips. Instead, the data is stored in the Embedded Controller (EC) and exposed via ACPI. The driver implements a **Rate-Limited Lag (RLLag)** filter to handle the low-resolution and jittery sampling found in Lenovo EC firmware. Hardware Identification and Multiplier Logic -------------------------------------------- The driver supports two distinct EC architectures. Differentiation is handled deterministically via a DMI Product Family quirk table during the probe phase, eliminating the need for runtime heuristics. 1. 8-bit EC Architecture (Multiplier: 100) - **Families:** Yoga, IdeaPad, Slim, Flex. - **Technical Detail:** These models allocate a single 8-bit register for tachometer data. Since 8-bit fields are limited to a value of 255, the BIOS stores fan speed in units of 100 RPM (e.g., 42 = 4200 RPM). 2. 16-bit EC Architecture (Multiplier: 1) - **Families:** Legion, LOQ. - **Technical Detail:** High-performance gaming models require greater precision for fans exceeding 6000 RPM. These use a 16-bit word (2 bytes) storing the raw RPM value directly. Filter Details: --------------- The RLLag filter is a passive discrete-time first-order lag model that ensures: - **Smoothing:** Low-resolution step increments are smoothed into 1-RPM increments. - **Slew-Rate Limiting:** Prevents unrealistic readings by capping the change to 1500 RPM/s, matching physical fan inertia. - **Polling Independence:** The filter math scales based on the time delta between userspace reads, ensuring a consistent physical curve regardless of polling frequency. Suspend and Resume ------------------ The driver utilizes the boottime clock (ktime_get_boottime()) to calculate the sampling delta. This ensures that time spent in system suspend is accounted for. If the delta exceeds 5 seconds (e.g., after waking the laptop), the filter automatically resets to the current hardware value to prevent reporting "ghost" RPM data from before the sleep state. Usage ----- The driver exposes standard hwmon sysfs attributes: Attribute Description fanX_input Filtered fan speed in RPM. Note: If the hardware reports 0 RPM, the filter is bypassed and 0 is reported immediately to ensure the user knows the fan has stopped. ==================================================================================================== LENOVO FAN CONTROLLER: MASTER REFERENCE DATABASE (2026) ==================================================================================================== MODEL (DMI PN) | FAMILY / SERIES | EC OFFSET | FULL ACPI OBJECT PATH | WIDTH | MULTiplier ---------------------------------------------------------------------------------------------------- 82N7 | Yoga 14cACN | 0x06 | \_SB.PCI0.LPC0.EC0.FANS | 8-bit | 100 80V2 / 81C3 | Yoga 710/720 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100 83E2 / 83DN | Yoga Pro 7/9 | 0xFE | \_SB.PCI0.LPC0.EC0.FANS | 8-bit | 100 82A2 / 82A3 | Yoga Slim 7 | 0x06 | \_SB.PCI0.LPC0.EC0.FANS | 8-bit | 100 81YM / 82FG | IdeaPad 5 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100 82JW / 82JU | Legion 5 (AMD) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FANS (Fan1) | 16-bit | 1 82JW / 82JU | Legion 5 (AMD) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FA2S (Fan2) | 16-bit | 1 82WQ | Legion 7i (Int) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FANS (Fan1) | 16-bit | 1 82WQ | Legion 7i (Int) | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FA2S (Fan2) | 16-bit | 1 82XV / 83DV | LOQ 15/16 | 0xFE/0xFF | \_SB.PCI0.LPC0.EC0.FANS /FA2S | 16-bit | 1 83AK | ThinkBook G6 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100 81X1 | Flex 5 | 0x06 | \_SB.PCI0.LPC0.EC0.FAN0 | 8-bit | 100 *Legacy* | Pre-2020 Models | 0x06 | \_SB.PCI0.LPC.EC.FAN0 | 8-bit | 100 ---------------------------------------------------------------------------------------------------- METHODOLOGY & IDENTIFICATION: 1. DSDT ANALYSIS (THE PATH): BIOS ACPI tables were analyzed using 'iasl' and cross-referenced with public dumps. Internal labels (FANS, FAN0, FA2S) are mapped to EmbeddedControl OperationRegion offsets. 2. EC MEMORY MAPPING (THE OFFSET): Validated by matching NBFC (NoteBook FanControl) XML logic with DSDT Field definitions found in BIOS firmware. 3. DATA-WIDTH ANALYSIS (THE MULTIPLIER): - 8-bit (Multiplier 100): Standard for Yoga/IdeaPad. Raw values (0-255). - 16-bit (Multiplier 1): Standard for Legion/LOQ. Two registers (0xFE/0xFF). References ---------- 1. **ACPI Specification (Field Objects):** Documentation on how 8-bit vs 16-bit fields are accessed in OperationRegions. https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#field-objects 2. **NBFC Projects:** Community-driven reverse engineering of Lenovo Legion/LOQ EC memory maps (16-bit raw registers). https://github.com/hirschmann/nbfc/tree/master/Configs 3. **Linux Kernel Timekeeping API:** Documentation for ktime_get_boottime() and handling deltas across suspend states. https://www.kernel.org/doc/html/latest/core-api/timekeeping.html 4. **Lenovo IdeaPad Laptop Driver:** Reference for DMI-based hardware feature gating in Lenovo laptops. https://github.com/torvalds/linux/blob/master/drivers/platform/x86/ideapad-laptop.c