diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/Kconfig | 1285 | ||||
-rw-r--r-- | drivers/platform/x86/Makefile | 198 | ||||
-rw-r--r-- | drivers/platform/x86/asus-wmi.c | 7 | ||||
-rw-r--r-- | drivers/platform/x86/dell_rbu.c | 173 | ||||
-rw-r--r-- | drivers/platform/x86/gpd-pocket-fan.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/i2c-multi-instantiate.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel-hid.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel-uncore-frequency.c | 51 | ||||
-rw-r--r-- | drivers/platform/x86/intel-vbtn.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel_pmc_core.c | 343 | ||||
-rw-r--r-- | drivers/platform/x86/intel_pmc_core.h | 29 | ||||
-rw-r--r-- | drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/pmc_atom.c | 8 | ||||
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 8 | ||||
-rw-r--r-- | drivers/platform/x86/surface3_power.c | 589 |
15 files changed, 1806 insertions, 895 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index cd9e2758c479..0ad7ad8cf8e1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -16,40 +16,103 @@ menuconfig X86_PLATFORM_DEVICES if X86_PLATFORM_DEVICES -config ACER_WMI - tristate "Acer WMI Laptop Extras" +config ACPI_WMI + tristate "WMI" + depends on ACPI + help + This driver adds support for the ACPI-WMI (Windows Management + Instrumentation) mapper device (PNP0C14) found on some systems. + + ACPI-WMI is a proprietary extension to ACPI to expose parts of the + ACPI firmware to userspace - this is done through various vendor + defined methods and data blocks in a PNP0C14 device, which are then + made available for userspace to call. + + The implementation of this in Linux currently only exposes this to + other kernel space drivers. + + This driver is a required dependency to build the firmware specific + drivers needed on many machines, including Acer and HP laptops. + + It is safe to enable this driver even if your DSDT doesn't define + any ACPI-WMI devices. + +config WMI_BMOF + tristate "WMI embedded Binary MOF driver" + depends on ACPI_WMI + default ACPI_WMI + ---help--- + Say Y here if you want to be able to read a firmware-embedded + WMI Binary MOF data. Using this requires userspace tools and may be + rather tedious. + + To compile this driver as a module, choose M here: the module will + be called wmi-bmof. + +config ALIENWARE_WMI + tristate "Alienware Special feature control" depends on ACPI + depends on LEDS_CLASS + depends on NEW_LEDS + depends on ACPI_WMI + ---help--- + This is a driver for controlling Alienware BIOS driven + features. It exposes an interface for controlling the AlienFX + zones on Alienware machines that don't contain a dedicated AlienFX + USB MCU such as the X51 and X51-R2. + +config HUAWEI_WMI + tristate "Huawei WMI laptop extras driver" + depends on ACPI_BATTERY + depends on ACPI_WMI + depends on INPUT + select INPUT_SPARSEKMAP select LEDS_CLASS + select LEDS_TRIGGERS + select LEDS_TRIGGER_AUDIO select NEW_LEDS - depends on BACKLIGHT_CLASS_DEVICE - depends on SERIO_I8042 - depends on INPUT - depends on RFKILL || RFKILL = n + help + This driver provides support for Huawei WMI hotkeys, battery charge + control, fn-lock, mic-mute LED, and other extra features. + + To compile this driver as a module, choose M here: the module + will be called huawei-wmi. + +config INTEL_WMI_THUNDERBOLT + tristate "Intel WMI thunderbolt force power driver" depends on ACPI_WMI - select INPUT_SPARSEKMAP - # Acer WMI depends on ACPI_VIDEO when ACPI is enabled - select ACPI_VIDEO if ACPI ---help--- - This is a driver for newer Acer (and Wistron) laptops. It adds - wireless radio and bluetooth control, and on some laptops, - exposes the mail LED and LCD backlight. + Say Y here if you want to be able to use the WMI interface on select + systems to force the power control of Intel Thunderbolt controllers. + This is useful for updating the firmware when devices are not plugged + into the controller. - If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M - here. + To compile this driver as a module, choose M here: the module will + be called intel-wmi-thunderbolt. -config ACER_WIRELESS - tristate "Acer Wireless Radio Control Driver" - depends on ACPI - depends on INPUT - ---help--- - The Acer Wireless Radio Control handles the airplane mode hotkey - present on new Acer laptops. +config MXM_WMI + tristate "WMI support for MXM Laptop Graphics" + depends on ACPI_WMI + ---help--- + MXM is a standard for laptop graphics cards, the WMI interface + is required for switchable nvidia graphics machines - Say Y or M here if you have an Acer notebook with an airplane mode - hotkey. +config PEAQ_WMI + tristate "PEAQ 2-in-1 WMI hotkey driver" + depends on ACPI_WMI + depends on INPUT + help + Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s. - If you choose to compile this driver as a module the module will be - called acer-wireless. +config XIAOMI_WMI + tristate "Xiaomi WMI key driver" + depends on ACPI_WMI + depends on INPUT + help + Say Y here if you want to support WMI-based keys on Xiaomi notebooks. + + To compile this driver as a module, choose M here: the module will + be called xiaomi-wmi. config ACERHDF tristate "Acer Aspire One temperature and fan driver" @@ -72,17 +135,53 @@ config ACERHDF If you have an Acer Aspire One netbook, say Y or M here. -config ALIENWARE_WMI - tristate "Alienware Special feature control" +config ACER_WIRELESS + tristate "Acer Wireless Radio Control Driver" + depends on ACPI + depends on INPUT + ---help--- + The Acer Wireless Radio Control handles the airplane mode hotkey + present on new Acer laptops. + + Say Y or M here if you have an Acer notebook with an airplane mode + hotkey. + + If you choose to compile this driver as a module the module will be + called acer-wireless. + +config ACER_WMI + tristate "Acer WMI Laptop Extras" depends on ACPI - depends on LEDS_CLASS - depends on NEW_LEDS + select LEDS_CLASS + select NEW_LEDS + depends on BACKLIGHT_CLASS_DEVICE + depends on SERIO_I8042 + depends on INPUT + depends on RFKILL || RFKILL = n depends on ACPI_WMI + select INPUT_SPARSEKMAP + # Acer WMI depends on ACPI_VIDEO when ACPI is enabled + select ACPI_VIDEO if ACPI ---help--- - This is a driver for controlling Alienware BIOS driven - features. It exposes an interface for controlling the AlienFX - zones on Alienware machines that don't contain a dedicated AlienFX - USB MCU such as the X51 and X51-R2. + This is a driver for newer Acer (and Wistron) laptops. It adds + wireless radio and bluetooth control, and on some laptops, + exposes the mail LED and LCD backlight. + + If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M + here. + +config APPLE_GMUX + tristate "Apple Gmux Driver" + depends on ACPI && PCI + depends on PNP + depends on BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE + depends on ACPI_VIDEO=n || ACPI_VIDEO + ---help--- + This driver provides support for the gmux device found on many + Apple laptops, which controls the display mux for the hybrid + graphics as well as the backlight. Currently only backlight + control is supported by the driver. config ASUS_LAPTOP tristate "Asus Laptop Extras" @@ -108,6 +207,91 @@ config ASUS_LAPTOP If you have an ACPI-compatible ASUS laptop, say Y or M here. +config ASUS_WIRELESS + tristate "Asus Wireless Radio Control Driver" + depends on ACPI + depends on INPUT + select NEW_LEDS + select LEDS_CLASS + ---help--- + The Asus Wireless Radio Control handles the airplane mode hotkey + present on some Asus laptops. + + Say Y or M here if you have an ASUS notebook with an airplane mode + hotkey. + + If you choose to compile this driver as a module the module will be + called asus-wireless. + +config ASUS_WMI + tristate "ASUS WMI Driver" + depends on ACPI_WMI + depends on ACPI_BATTERY + depends on INPUT + depends on HWMON + depends on BACKLIGHT_CLASS_DEVICE + depends on RFKILL || RFKILL = n + depends on HOTPLUG_PCI + depends on ACPI_VIDEO || ACPI_VIDEO = n + select INPUT_SPARSEKMAP + select LEDS_CLASS + select NEW_LEDS + ---help--- + Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new + Asus Notebooks). + + To compile this driver as a module, choose M here: the module will + be called asus-wmi. + +config ASUS_NB_WMI + tristate "Asus Notebook WMI Driver" + depends on ASUS_WMI + depends on SERIO_I8042 || SERIO_I8042 = n + ---help--- + This is a driver for newer Asus notebooks. It adds extra features + like wireless radio and bluetooth control, leds, hotkeys, backlight... + + For more information, see + <file:Documentation/ABI/testing/sysfs-platform-asus-wmi> + + If you have an ACPI-WMI compatible Asus Notebook, say Y or M + here. + +config EEEPC_LAPTOP + tristate "Eee PC Hotkey Driver" + depends on ACPI + depends on INPUT + depends on RFKILL || RFKILL = n + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on HOTPLUG_PCI + depends on BACKLIGHT_CLASS_DEVICE + select HWMON + select LEDS_CLASS + select NEW_LEDS + select INPUT_SPARSEKMAP + ---help--- + This driver supports the Fn-Fx keys on Eee PC laptops. + + It also gives access to some extra laptop functionalities like + Bluetooth, backlight and allows powering on/off some other + devices. + + If you have an Eee PC laptop, say Y or M here. If this driver + doesn't work on your Eee PC, try eeepc-wmi instead. + +config EEEPC_WMI + tristate "Eee PC WMI Driver" + depends on ASUS_WMI + ---help--- + This is a driver for newer Eee PC laptops. It adds extra features + like wireless radio and bluetooth control, leds, hotkeys, backlight... + + For more information, see + <file:Documentation/ABI/testing/sysfs-platform-asus-wmi> + + If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M + here. + config DCDBAS tristate "Dell Systems Management Base Driver" depends on X86 @@ -183,6 +367,44 @@ config DELL_LAPTOP This driver adds support for rfkill and backlight control to Dell laptops (except for some models covered by the Compal driver). +config DELL_RBTN + tristate "Dell Airplane Mode Switch driver" + depends on ACPI + depends on INPUT + depends on RFKILL + ---help--- + Say Y here if you want to support Dell Airplane Mode Switch ACPI + device on Dell laptops. Sometimes it has names: DELLABCE or DELRBTN. + This driver register rfkill device or input hotkey device depending + on hardware type (hw switch slider or keyboard toggle button). For + rfkill devices it receive HW switch events and set correct hard + rfkill state. + + To compile this driver as a module, choose M here: the module will + be called dell-rbtn. + +config DELL_RBU + tristate "BIOS update support for DELL systems via sysfs" + depends on X86 + select FW_LOADER + select FW_LOADER_USER_HELPER + help + Say m if you want to have the option of updating the BIOS for your + DELL system. Note you need a Dell OpenManage or Dell Update package (DUP) + supporting application to communicate with the BIOS regarding the new + image for the image update to take effect. + See <file:Documentation/admin-guide/dell_rbu.rst> for more details on the driver. + +config DELL_SMO8800 + tristate "Dell Latitude freefall driver (ACPI SMO88XX)" + depends on ACPI + ---help--- + Say Y here if you want to support SMO88XX freefall devices + on Dell Latitude laptops. + + To compile this driver as a module, choose M here: the module will + be called dell-smo8800. + config DELL_WMI tristate "Dell WMI notifications" depends on ACPI_WMI @@ -222,44 +444,13 @@ config DELL_WMI_LED This adds support for the Latitude 2100 and similar notebooks that have an external LED. -config DELL_SMO8800 - tristate "Dell Latitude freefall driver (ACPI SMO88XX)" - depends on ACPI - ---help--- - Say Y here if you want to support SMO88XX freefall devices - on Dell Latitude laptops. - - To compile this driver as a module, choose M here: the module will - be called dell-smo8800. - -config DELL_RBTN - tristate "Dell Airplane Mode Switch driver" - depends on ACPI - depends on INPUT +config AMILO_RFKILL + tristate "Fujitsu-Siemens Amilo rfkill support" depends on RFKILL + depends on SERIO_I8042 ---help--- - Say Y here if you want to support Dell Airplane Mode Switch ACPI - device on Dell laptops. Sometimes it has names: DELLABCE or DELRBTN. - This driver register rfkill device or input hotkey device depending - on hardware type (hw switch slider or keyboard toggle button). For - rfkill devices it receive HW switch events and set correct hard - rfkill state. - - To compile this driver as a module, choose M here: the module will - be called dell-rbtn. - -config DELL_RBU - tristate "BIOS update support for DELL systems via sysfs" - depends on X86 - select FW_LOADER - select FW_LOADER_USER_HELPER - help - Say m if you want to have the option of updating the BIOS for your - DELL system. Note you need a Dell OpenManage or Dell Update package (DUP) - supporting application to communicate with the BIOS regarding the new - image for the image update to take effect. - See <file:Documentation/admin-guide/dell_rbu.rst> for more details on the driver. - + This is a driver for enabling wifi on some Fujitsu-Siemens Amilo + laptops. config FUJITSU_LAPTOP tristate "Fujitsu Laptop Extras" @@ -297,14 +488,6 @@ config FUJITSU_TABLET If you have a Fujitsu convertible or slate, say Y or M here. -config AMILO_RFKILL - tristate "Fujitsu-Siemens Amilo rfkill support" - depends on RFKILL - depends on SERIO_I8042 - ---help--- - This is a driver for enabling wifi on some Fujitsu-Siemens Amilo - laptops. - config GPD_POCKET_FAN tristate "GPD Pocket Fan Controller support" depends on ACPI @@ -317,15 +500,6 @@ config GPD_POCKET_FAN of the CPU temperature. Say Y or M if the kernel may be used on a GPD pocket. -config TC1100_WMI - tristate "HP Compaq TC1100 Tablet WMI Extras" - depends on !X86_64 - depends on ACPI - depends on ACPI_WMI - ---help--- - This is a driver for the WMI extensions (wireless and bluetooth power - control) of the HP Compaq TC1100 tablet. - config HP_ACCEL tristate "HP laptop accelerometer" depends on INPUT && ACPI @@ -369,91 +543,30 @@ config HP_WMI To compile this driver as a module, choose M here: the module will be called hp-wmi. -config LG_LAPTOP - tristate "LG Laptop Extras" +config TC1100_WMI + tristate "HP Compaq TC1100 Tablet WMI Extras" + depends on !X86_64 depends on ACPI depends on ACPI_WMI - depends on INPUT - select INPUT_SPARSEKMAP - select LEDS_CLASS - help - This driver adds support for hotkeys as well as control of keyboard - backlight, battery maximum charge level and various other ACPI - features. - - If you have an LG Gram laptop, say Y or M here. - -config MSI_LAPTOP - tristate "MSI Laptop Extras" - depends on ACPI - depends on BACKLIGHT_CLASS_DEVICE - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on RFKILL - depends on INPUT && SERIO_I8042 - select INPUT_SPARSEKMAP - ---help--- - This is a driver for laptops built by MSI (MICRO-STAR - INTERNATIONAL): - - MSI MegaBook S270 (MS-1013) - Cytron/TCM/Medion/Tchibo MD96100/SAM2000 - - It adds support for Bluetooth, WLAN and LCD brightness control. - - More information about this driver is available at - <http://0pointer.de/lennart/tchibo.html>. - - If you have an MSI S270 laptop, say Y or M here. - -config PANASONIC_LAPTOP - tristate "Panasonic Laptop Extras" - depends on INPUT && ACPI - depends on BACKLIGHT_CLASS_DEVICE - select INPUT_SPARSEKMAP ---help--- - This driver adds support for access to backlight control and hotkeys - on Panasonic Let's Note laptops. - - If you have a Panasonic Let's note laptop (such as the R1(N variant), - R2, R3, R5, T2, W2 and Y2 series), say Y. + This is a driver for the WMI extensions (wireless and bluetooth power + control) of the HP Compaq TC1100 tablet. -config COMPAL_LAPTOP - tristate "Compal (and others) Laptop Extras" - depends on ACPI - depends on BACKLIGHT_CLASS_DEVICE - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on RFKILL - depends on HWMON - depends on POWER_SUPPLY +config IBM_RTL + tristate "Device driver to enable PRTL support" + depends on PCI ---help--- - This is a driver for laptops built by Compal, and some models by - other brands (e.g. Dell, Toshiba). - - It adds support for rfkill, Bluetooth, WLAN, LCD brightness, hwmon - and battery charging level control. - -config SONY_LAPTOP - tristate "Sony Laptop Extras" - depends on ACPI - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on BACKLIGHT_CLASS_DEVICE - depends on INPUT - depends on RFKILL - ---help--- - This mini-driver drives the SNC and SPIC devices present in the ACPI - BIOS of the Sony Vaio laptops. - - It gives access to some extra laptop functionalities like Bluetooth, - screen brightness control, Fn keys and allows powering on/off some - devices. - - Read <file:Documentation/admin-guide/laptops/sony-laptop.rst> for more information. + Enable support for IBM Premium Real Time Mode (PRTM). + This module will allow you the enter and exit PRTM in the BIOS via + sysfs on platforms that support this feature. System in PRTM will + not receive CPU-generated SMIs for recoverable errors. Use of this + feature without proper support may void your hardware warranty. -config SONYPI_COMPAT - bool "Sonypi compatibility" - depends on SONY_LAPTOP - ---help--- - Build the sonypi driver compatibility code into the sony-laptop driver. + If the proper BIOS support is found the driver will load and create + /sys/devices/system/ibm_rtl/. The "state" variable will indicate + whether or not the BIOS is in PRTM. + state = 0 (BIOS SMIs on) + state = 1 (BIOS SMIs off) config IDEAPAD_LAPTOP tristate "Lenovo IdeaPad Laptop Extras" @@ -468,17 +581,23 @@ config IDEAPAD_LAPTOP This is a driver for Lenovo IdeaPad netbooks contains drivers for rfkill switch, hotkey, fan control and backlight control. -config SURFACE3_WMI - tristate "Surface 3 WMI Driver" - depends on ACPI_WMI - depends on DMI +config SENSORS_HDAPS + tristate "Thinkpad Hard Drive Active Protection System (hdaps)" depends on INPUT - depends on SPI - ---help--- - Say Y here if you have a Surface 3. + help + This driver provides support for the IBM Hard Drive Active Protection + System (hdaps), which provides an accelerometer and other misc. data. + ThinkPads starting with the R50, T41, and X40 are supported. The + accelerometer data is readable via sysfs. - To compile this driver as a module, choose M here: the module will - be called surface3-wmi. + This driver also provides an absolute input class device, allowing + the laptop to act as a pinball machine-esque joystick. + + If your ThinkPad is not recognized by the driver, please update to latest + BIOS. This is especially the case for some R52 ThinkPads. + + Say Y here if you have an applicable laptop and want to experience + the awesome power of hdaps. config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" @@ -619,23 +738,72 @@ config THINKPAD_ACPI_HOTKEY_POLL If you are not sure, say Y here. The driver enables polling only if it is strictly necessary to do so. -config SENSORS_HDAPS - tristate "Thinkpad Hard Drive Active Protection System (hdaps)" +config INTEL_ATOMISP2_PM + tristate "Intel AtomISP2 dummy / power-management driver" + depends on PCI && IOSF_MBI && PM + help + Power-management driver for Intel's Image Signal Processor found on + Bay Trail and Cherry Trail devices. This dummy driver's sole purpose + is to turn the ISP off (put it in D3) to save power and to allow + entering of S0ix modes. + + To compile this driver as a module, choose M here: the module + will be called intel_atomisp2_pm. + +config INTEL_CHT_INT33FE + tristate "Intel Cherry Trail ACPI INT33FE Driver" + depends on X86 && ACPI && I2C && REGULATOR + depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m) + depends on USB_ROLES_INTEL_XHCI=y || (USB_ROLES_INTEL_XHCI=m && m) + depends on TYPEC_MUX_PI3USB30532=y || (TYPEC_MUX_PI3USB30532=m && m) + ---help--- + This driver add support for the INT33FE ACPI device found on + some Intel Cherry Trail devices. + + There are two kinds of INT33FE ACPI device possible: for hardware + with USB Type-C and Micro-B connectors. This driver supports both. + + The INT33FE ACPI device has a CRS table with I2cSerialBusV2 + resources for Fuel Gauge Controller and (in the Type-C variant) + FUSB302 USB Type-C Controller and PI3USB30532 USB switch. + This driver instantiates i2c-clients for these, so that standard + i2c drivers for these chips can bind to the them. + + If you enable this driver it is advised to also select + CONFIG_BATTERY_BQ27XXX=m or CONFIG_BATTERY_BQ27XXX_I2C=m for Micro-B + device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m + for Type-C device. + +config INTEL_HID_EVENT + tristate "INTEL HID Event" + depends on ACPI depends on INPUT + select INPUT_SPARSEKMAP help - This driver provides support for the IBM Hard Drive Active Protection - System (hdaps), which provides an accelerometer and other misc. data. - ThinkPads starting with the R50, T41, and X40 are supported. The - accelerometer data is readable via sysfs. + This driver provides support for the Intel HID Event hotkey interface. + Some laptops require this driver for hotkey support. - This driver also provides an absolute input class device, allowing - the laptop to act as a pinball machine-esque joystick. + To compile this driver as a module, choose M here: the module will + be called intel_hid. - If your ThinkPad is not recognized by the driver, please update to latest - BIOS. This is especially the case for some R52 ThinkPads. +config INTEL_INT0002_VGPIO + tristate "Intel ACPI INT0002 Virtual GPIO driver" + depends on GPIOLIB && ACPI + select GPIOLIB_IRQCHIP + ---help--- + Some peripherals on Bay Trail and Cherry Trail platforms signal a + Power Management Event (PME) to the Power Management Controller (PMC) + to wakeup the system. When this happens software needs to explicitly + clear the PME bus 0 status bit in the GPE0a_STS register to avoid an + IRQ storm on IRQ 9. - Say Y here if you have an applicable laptop and want to experience - the awesome power of hdaps. + This is modelled in ACPI through the INT0002 ACPI device, which is + called a "Virtual GPIO controller" in ACPI because it defines the + event handler to call when the PME triggers through _AEI and _L02 + methods as would be done for a real GPIO interrupt in ACPI. + + To compile this driver as a module, choose M here: the module will + be called intel_int0002_vgpio. config INTEL_MENLOW tristate "Thermal Management driver for Intel menlow platform" @@ -647,145 +815,80 @@ config INTEL_MENLOW If unsure, say N. -config EEEPC_LAPTOP - tristate "Eee PC Hotkey Driver" +config INTEL_OAKTRAIL + tristate "Intel Oaktrail Platform Extras" depends on ACPI - depends on INPUT - depends on RFKILL || RFKILL = n depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on HOTPLUG_PCI - depends on BACKLIGHT_CLASS_DEVICE - select HWMON - select LEDS_CLASS - select NEW_LEDS - select INPUT_SPARSEKMAP + depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI ---help--- - This driver supports the Fn-Fx keys on Eee PC laptops. - - It also gives access to some extra laptop functionalities like - Bluetooth, backlight and allows powering on/off some other - devices. - - If you have an Eee PC laptop, say Y or M here. If this driver - doesn't work on your Eee PC, try eeepc-wmi instead. + Intel Oaktrail platform need this driver to provide interfaces to + enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y + here; it will only load on supported platforms. -config ASUS_WMI - tristate "ASUS WMI Driver" - depends on ACPI_WMI - depends on ACPI_BATTERY +config INTEL_VBTN + tristate "INTEL VIRTUAL BUTTON" + depends on ACPI depends on INPUT - depends on HWMON - depends on BACKLIGHT_CLASS_DEVICE - depends on RFKILL || RFKILL = n - depends on HOTPLUG_PCI - depends on ACPI_VIDEO || ACPI_VIDEO = n select INPUT_SPARSEKMAP - select LEDS_CLASS - select NEW_LEDS - ---help--- - Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new - Asus Notebooks). + help + This driver provides support for the Intel Virtual Button interface. + Some laptops require this driver for power button support. To compile this driver as a module, choose M here: the module will - be called asus-wmi. + be called intel_vbtn. -config ASUS_NB_WMI - tristate "Asus Notebook WMI Driver" - depends on ASUS_WMI - depends on SERIO_I8042 || SERIO_I8042 = n +config SURFACE3_WMI + tristate "Surface 3 WMI Driver" + depends on ACPI_WMI + depends on DMI + depends on INPUT + depends on SPI ---help--- - This is a driver for newer Asus notebooks. It adds extra features - like wireless radio and bluetooth control, leds, hotkeys, backlight... - - For more information, see - <file:Documentation/ABI/testing/sysfs-platform-asus-wmi> + Say Y here if you have a Surface 3. - If you have an ACPI-WMI compatible Asus Notebook, say Y or M - here. + To compile this driver as a module, choose M here: the module will + be called surface3-wmi. -config EEEPC_WMI - tristate "Eee PC WMI Driver" - depends on ASUS_WMI +config SURFACE_3_BUTTON + tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet" + depends on ACPI && KEYBOARD_GPIO && I2C ---help--- - This is a driver for newer Eee PC laptops. It adds extra features - like wireless radio and bluetooth control, leds, hotkeys, backlight... - - For more information, see - <file:Documentation/ABI/testing/sysfs-platform-asus-wmi> + This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet. - If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M - here. +config SURFACE_3_POWER_OPREGION + tristate "Surface 3 battery platform operation region support" + depends on ACPI && I2C + help + This driver provides support for ACPI operation + region of the Surface 3 battery platform driver. -config ASUS_WIRELESS - tristate "Asus Wireless Radio Control Driver" - depends on ACPI - depends on INPUT - select NEW_LEDS - select LEDS_CLASS +config SURFACE_PRO3_BUTTON + tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet" + depends on ACPI && INPUT ---help--- - The Asus Wireless Radio Control handles the airplane mode hotkey - present on some Asus laptops. - - Say Y or M here if you have an ASUS notebook with an airplane mode - hotkey. - - If you choose to compile this driver as a module the module will be - called asus-wireless. + This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet. -config ACPI_WMI - tristate "WMI" +config MSI_LAPTOP + tristate "MSI Laptop Extras" depends on ACPI - help - This driver adds support for the ACPI-WMI (Windows Management - Instrumentation) mapper device (PNP0C14) found on some systems. - - ACPI-WMI is a proprietary extension to ACPI to expose parts of the - ACPI firmware to userspace - this is done through various vendor - defined methods and data blocks in a PNP0C14 device, which are then - made available for userspace to call. - - The implementation of this in Linux currently only exposes this to - other kernel space drivers. - - This driver is a required dependency to build the firmware specific - drivers needed on many machines, including Acer and HP laptops. - - It is safe to enable this driver even if your DSDT doesn't define - any ACPI-WMI devices. - -config WMI_BMOF - tristate "WMI embedded Binary MOF driver" - depends on ACPI_WMI - default ACPI_WMI + depends on BACKLIGHT_CLASS_DEVICE + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on RFKILL + depends on INPUT && SERIO_I8042 + select INPUT_SPARSEKMAP ---help--- - Say Y here if you want to be able to read a firmware-embedded - WMI Binary MOF data. Using this requires userspace tools and may be - rather tedious. - - To compile this driver as a module, choose M here: the module will - be called wmi-bmof. + This is a driver for laptops built by MSI (MICRO-STAR + INTERNATIONAL): -config INTEL_WMI_THUNDERBOLT - tristate "Intel WMI thunderbolt force power driver" - depends on ACPI_WMI - ---help--- - Say Y here if you want to be able to use the WMI interface on select - systems to force the power control of Intel Thunderbolt controllers. - This is useful for updating the firmware when devices are not plugged - into the controller. + MSI MegaBook S270 (MS-1013) + Cytron/TCM/Medion/Tchibo MD96100/SAM2000 - To compile this driver as a module, choose M here: the module will - be called intel-wmi-thunderbolt. + It adds support for Bluetooth, WLAN and LCD brightness control. -config XIAOMI_WMI - tristate "Xiaomi WMI key driver" - depends on ACPI_WMI - depends on INPUT - help - Say Y here if you want to support WMI-based keys on Xiaomi notebooks. + More information about this driver is available at + <http://0pointer.de/lennart/tchibo.html>. - To compile this driver as a module, choose M here: the module will - be called xiaomi-wmi. + If you have an MSI S270 laptop, say Y or M here. config MSI_WMI tristate "MSI WMI extras" @@ -800,24 +903,63 @@ config MSI_WMI To compile this driver as a module, choose M here: the module will be called msi-wmi. -config PEAQ_WMI - tristate "PEAQ 2-in-1 WMI hotkey driver" - depends on ACPI_WMI - depends on INPUT +config XO15_EBOOK + tristate "OLPC XO-1.5 ebook switch" + depends on OLPC || COMPILE_TEST + depends on ACPI && INPUT + ---help--- + Support for the ebook switch on the OLPC XO-1.5 laptop. + + This switch is triggered as the screen is rotated and folded down to + convert the device into ebook form. + +config XO1_RFKILL + tristate "OLPC XO-1 software RF kill switch" + depends on OLPC || COMPILE_TEST + depends on RFKILL + ---help--- + Support for enabling/disabling the WLAN interface on the OLPC XO-1 + laptop. + +config PCENGINES_APU2 + tristate "PC Engines APUv2/3 front button and LEDs driver" + depends on INPUT && INPUT_KEYBOARD && GPIOLIB + depends on LEDS_CLASS + select GPIO_AMD_FCH + select KEYBOARD_GPIO_POLLED + select LEDS_GPIO help - Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s. + This driver provides support for the front button and LEDs on + PC Engines APUv2/APUv3 board. -config TOPSTAR_LAPTOP - tristate "Topstar Laptop Extras" - depends on ACPI - depends on INPUT - select INPUT_SPARSEKMAP + To compile this driver as a module, choose M here: the module + will be called pcengines-apuv2. + +config SAMSUNG_LAPTOP + tristate "Samsung Laptop driver" + depends on RFKILL || RFKILL = n + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on BACKLIGHT_CLASS_DEVICE select LEDS_CLASS select NEW_LEDS ---help--- - This driver adds support for hotkeys found on Topstar laptops. + This module implements a driver for a wide range of different + Samsung laptops. It offers control over the different + function keys, wireless LED, LCD backlight level. - If you have a Topstar laptop, say Y or M here. + It may also provide some sysfs files described in + <file:Documentation/ABI/testing/sysfs-driver-samsung-laptop> + + To compile this driver as a module, choose M here: the module + will be called samsung-laptop. + +config SAMSUNG_Q10 + tristate "Samsung Q10 Extras" + depends on ACPI + select BACKLIGHT_CLASS_DEVICE + ---help--- + This driver provides support for backlight control on Samsung Q10 + and related laptops, including Dell Latitude X200. config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" @@ -917,115 +1059,129 @@ config ACPI_CMPC keys as input device, backlight device, tablet and accelerometer devices. -config INTEL_CHT_INT33FE - tristate "Intel Cherry Trail ACPI INT33FE Driver" - depends on X86 && ACPI && I2C && REGULATOR - depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m) - depends on USB_ROLES_INTEL_XHCI=y || (USB_ROLES_INTEL_XHCI=m && m) - depends on TYPEC_MUX_PI3USB30532=y || (TYPEC_MUX_PI3USB30532=m && m) +config COMPAL_LAPTOP + tristate "Compal (and others) Laptop Extras" + depends on ACPI + depends on BACKLIGHT_CLASS_DEVICE + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on RFKILL + depends on HWMON + depends on POWER_SUPPLY ---help--- - This driver add support for the INT33FE ACPI device found on - some Intel Cherry Trail devices. + This is a driver for laptops built by Compal, and some models by + other brands (e.g. Dell, Toshiba). - There are two kinds of INT33FE ACPI device possible: for hardware - with USB Type-C and Micro-B connectors. This driver supports both. + It adds support for rfkill, Bluetooth, WLAN, LCD brightness, hwmon + and battery charging level control. - The INT33FE ACPI device has a CRS table with I2cSerialBusV2 - resources for Fuel Gauge Controller and (in the Type-C variant) - FUSB302 USB Type-C Controller and PI3USB30532 USB switch. - This driver instantiates i2c-clients for these, so that standard - i2c drivers for these chips can bind to the them. +config LG_LAPTOP + tristate "LG Laptop Extras" + depends on ACPI + depends on ACPI_WMI + depends on INPUT + select INPUT_SPARSEKMAP + select LEDS_CLASS + help + This driver adds support for hotkeys as well as control of keyboard + backlight, battery maximum charge level and various other ACPI + features. - If you enable this driver it is advised to also select - CONFIG_BATTERY_BQ27XXX=m or CONFIG_BATTERY_BQ27XXX_I2C=m for Micro-B - device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m - for Type-C device. + If you have an LG Gram laptop, say Y or M here. +config PANASONIC_LAPTOP + tristate "Panasonic Laptop Extras" + depends on INPUT && ACPI + depends on BACKLIGHT_CLASS_DEVICE + select INPUT_SPARSEKMAP + ---help--- + This driver adds support for access to backlight control and hotkeys + on Panasonic Let's Note laptops. -config INTEL_INT0002_VGPIO - tristate "Intel ACPI INT0002 Virtual GPIO driver" - depends on GPIOLIB && ACPI - select GPIOLIB_IRQCHIP + If you have a Panasonic Let's note laptop (such as the R1(N variant), + R2, R3, R5, T2, W2 and Y2 series), say Y. + +config SONY_LAPTOP + tristate "Sony Laptop Extras" + depends on ACPI + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on BACKLIGHT_CLASS_DEVICE + depends on INPUT + depends on RFKILL ---help--- - Some peripherals on Bay Trail and Cherry Trail platforms signal a - Power Management Event (PME) to the Power Management Controller (PMC) - to wakeup the system. When this happens software needs to explicitly - clear the PME bus 0 status bit in the GPE0a_STS register to avoid an - IRQ storm on IRQ 9. + This mini-driver drives the SNC and SPIC devices present in the ACPI + BIOS of the Sony Vaio laptops. - This is modelled in ACPI through the INT0002 ACPI device, which is - called a "Virtual GPIO controller" in ACPI because it defines the - event handler to call when the PME triggers through _AEI and _L02 - methods as would be done for a real GPIO interrupt in ACPI. + It gives access to some extra laptop functionalities like Bluetooth, + screen brightness control, Fn keys and allows powering on/off some + devices. - To compile this driver as a module, choose M here: the module will - be called intel_int0002_vgpio. + Read <file:Documentation/admin-guide/laptops/sony-laptop.rst> for more information. -config INTEL_HID_EVENT - tristate "INTEL HID Event" +config SONYPI_COMPAT + bool "Sonypi compatibility" + depends on SONY_LAPTOP + ---help--- + Build the sonypi driver compatibility code into the sony-laptop driver. + +config SYSTEM76_ACPI + tristate "System76 ACPI Driver" depends on ACPI - depends on INPUT - select INPUT_SPARSEKMAP + select NEW_LEDS + select LEDS_CLASS + select LEDS_TRIGGERS help - This driver provides support for the Intel HID Event hotkey interface. - Some laptops require this driver for hotkey support. + This is a driver for System76 laptops running open firmware. It adds + support for Fn-Fx key combinations, keyboard backlight, and airplane mode + LEDs. - To compile this driver as a module, choose M here: the module will - be called intel_hid. + If you have a System76 laptop running open firmware, say Y or M here. -config INTEL_VBTN - tristate "INTEL VIRTUAL BUTTON" +config TOPSTAR_LAPTOP + tristate "Topstar Laptop Extras" depends on ACPI depends on INPUT select INPUT_SPARSEKMAP - help - This driver provides support for the Intel Virtual Button interface. - Some laptops require this driver for power button support. - - To compile this driver as a module, choose M here: the module will - be called intel_vbtn. - -config INTEL_SCU_IPC - bool "Intel SCU IPC Support" - depends on X86_INTEL_MID - default y + select LEDS_CLASS + select NEW_LEDS ---help--- - IPC is used to bridge the communications between kernel and SCU on - some embedded Intel x86 platforms. This is not needed for PC-type - machines. + This driver adds support for hotkeys found on Topstar laptops. -config INTEL_SCU_IPC_UTIL - tristate "Intel SCU IPC utility driver" - depends on INTEL_SCU_IPC - ---help--- - The IPC Util driver provides an interface with the SCU enabling - low level access for debug work and updating the firmware. Say - N unless you will be doing this on an Intel MID platform. + If you have a Topstar laptop, say Y or M here. -config INTEL_MID_POWER_BUTTON - tristate "power button driver for Intel MID platforms" - depends on INTEL_SCU_IPC && INPUT +config I2C_MULTI_INSTANTIATE + tristate "I2C multi instantiate pseudo device driver" + depends on I2C && ACPI help - This driver handles the power button on the Intel MID platforms. + Some ACPI-based systems list multiple i2c-devices in a single ACPI + firmware-node. This driver will instantiate separate i2c-clients + for each device in the firmware-node. - If unsure, say N. + To compile this driver as a module, choose M here: the module + will be called i2c-multi-instantiate. -config INTEL_MFLD_THERMAL - tristate "Thermal driver for Intel Medfield platform" - depends on MFD_INTEL_MSIC && THERMAL - help - Say Y here to enable thermal driver support for the Intel Medfield - platform. +config MLX_PLATFORM + tristate "Mellanox Technologies platform support" + depends on I2C && REGMAP + ---help--- + This option enables system support for the Mellanox Technologies + platform. The Mellanox systems provide data center networking + solutions based on Virtual Protocol Interconnect (VPI) technology + enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE + connection. -config INTEL_IPS - tristate "Intel Intelligent Power Sharing" - depends on ACPI && PCI + If you have a Mellanox system, say Y or M here. + +config TOUCHSCREEN_DMI + bool "DMI based touchscreen configuration info" + depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD + select EFI_EMBEDDED_FIRMWARE if EFI ---help--- - Intel Calpella platforms support dynamic power sharing between the - CPU and GPU, maximizing performance in a given TDP. This driver, - along with the CPU frequency and i915 drivers, provides that - functionality. If in doubt, say Y here; it will only load on - supported platforms. + Certain ACPI based tablets with e.g. Silead or Chipone touchscreens + do not have enough data in ACPI tables for the touchscreen driver to + handle the touchscreen properly, as OEMs expect the data to be baked + into the tablet model specific version of the driver shipped with the + the OS-image for the device. This option supplies the missing info. + Enable this for x86 tablets with Silead or Chipone touchscreens. config INTEL_IMR bool "Intel Isolated Memory Region support" @@ -1051,116 +1207,21 @@ config INTEL_IMR If you are running on a Galileo/Quark say Y here. -config INTEL_PMC_CORE - tristate "Intel PMC Core driver" - depends on PCI - ---help--- - The Intel Platform Controller Hub for Intel Core SoCs provides access - to Power Management Controller registers via a PCI interface. This - driver can utilize debugging capabilities and supported features as - exposed by the Power Management Controller. - - Supported features: - - SLP_S0_RESIDENCY counter - - PCH IP Power Gating status - - LTR Ignore - - MPHY/PLL gating status (Sunrisepoint PCH only) - -config IBM_RTL - tristate "Device driver to enable PRTL support" - depends on PCI - ---help--- - Enable support for IBM Premium Real Time Mode (PRTM). - This module will allow you the enter and exit PRTM in the BIOS via - sysfs on platforms that support this feature. System in PRTM will - not receive CPU-generated SMIs for recoverable errors. Use of this - feature without proper support may void your hardware warranty. - - If the proper BIOS support is found the driver will load and create - /sys/devices/system/ibm_rtl/. The "state" variable will indicate - whether or not the BIOS is in PRTM. - state = 0 (BIOS SMIs on) - state = 1 (BIOS SMIs off) - -config XO1_RFKILL - tristate "OLPC XO-1 software RF kill switch" - depends on OLPC || COMPILE_TEST - depends on RFKILL - ---help--- - Support for enabling/disabling the WLAN interface on the OLPC XO-1 - laptop. - -config XO15_EBOOK - tristate "OLPC XO-1.5 ebook switch" - depends on OLPC || COMPILE_TEST - depends on ACPI && INPUT - ---help--- - Support for the ebook switch on the OLPC XO-1.5 laptop. - - This switch is triggered as the screen is rotated and folded down to - convert the device into ebook form. - -config SAMSUNG_LAPTOP - tristate "Samsung Laptop driver" - depends on RFKILL || RFKILL = n - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on BACKLIGHT_CLASS_DEVICE - select LEDS_CLASS - select NEW_LEDS - ---help--- - This module implements a driver for a wide range of different - Samsung laptops. It offers control over the different - function keys, wireless LED, LCD backlight level. - - It may also provide some sysfs files described in - <file:Documentation/ABI/testing/sysfs-driver-samsung-laptop> - - To compile this driver as a module, choose M here: the module - will be called samsung-laptop. - -config MXM_WMI - tristate "WMI support for MXM Laptop Graphics" - depends on ACPI_WMI - ---help--- - MXM is a standard for laptop graphics cards, the WMI interface - is required for switchable nvidia graphics machines - -config INTEL_OAKTRAIL - tristate "Intel Oaktrail Platform Extras" - depends on ACPI - depends on ACPI_VIDEO || ACPI_VIDEO = n - depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI - ---help--- - Intel Oaktrail platform need this driver to provide interfaces to - enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y - here; it will only load on supported platforms. - -config SAMSUNG_Q10 - tristate "Samsung Q10 Extras" - depends on ACPI - select BACKLIGHT_CLASS_DEVICE - ---help--- - This driver provides support for backlight control on Samsung Q10 - and related laptops, including Dell Latitude X200. - -config APPLE_GMUX - tristate "Apple Gmux Driver" +config INTEL_IPS + tristate "Intel Intelligent Power Sharing" depends on ACPI && PCI - depends on PNP - depends on BACKLIGHT_CLASS_DEVICE - depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE - depends on ACPI_VIDEO=n || ACPI_VIDEO ---help--- - This driver provides support for the gmux device found on many - Apple laptops, which controls the display mux for the hybrid - graphics as well as the backlight. Currently only backlight - control is supported by the driver. + Intel Calpella platforms support dynamic power sharing between the + CPU and GPU, maximizing performance in a given TDP. This driver, + along with the CPU frequency and i915 drivers, provides that + functionality. If in doubt, say Y here; it will only load on + supported platforms. config INTEL_RST tristate "Intel Rapid Start Technology Driver" depends on ACPI ---help--- - This driver provides support for modifying paramaters on systems + This driver provides support for modifying parameters on systems equipped with Intel's Rapid Start Technology. When put in an ACPI sleep state, these devices will wake after either a configured timeout or when the system battery reaches a critical state, @@ -1182,62 +1243,7 @@ config INTEL_SMARTCONNECT This driver checks to determine whether the device has Intel Smart Connect enabled, and if so disables it. -config INTEL_PMC_IPC - tristate "Intel PMC IPC Driver" - depends on ACPI && PCI - ---help--- - This driver provides support for PMC control on some Intel platforms. - The PMC is an ARC processor which defines IPC commands for communication - with other entities in the CPU. - -config INTEL_BXTWC_PMIC_TMU - tristate "Intel BXT Whiskey Cove TMU Driver" - depends on REGMAP - depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC - ---help--- - Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature. - This driver enables the alarm wakeup functionality in the TMU unit - of Whiskey Cove PMIC. - -config SURFACE_PRO3_BUTTON - tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet" - depends on ACPI && INPUT - ---help--- - This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet. - -config SURFACE_3_BUTTON - tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet" - depends on ACPI && KEYBOARD_GPIO && I2C - ---help--- - This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet. - -config INTEL_PUNIT_IPC - tristate "Intel P-Unit IPC Driver" - ---help--- - This driver provides support for Intel P-Unit Mailbox IPC mechanism, - which is used to bridge the communications between kernel and P-Unit. - -config INTEL_TELEMETRY - tristate "Intel SoC Telemetry Driver" - depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64 - ---help--- - This driver provides interfaces to configure and use - telemetry for INTEL SoC from APL onwards. It is also - used to get various SoC events and parameters - directly via debugfs files. Various tools may use - this interface for SoC state monitoring. - -config MLX_PLATFORM - tristate "Mellanox Technologies platform support" - depends on I2C && REGMAP - ---help--- - This option enables system support for the Mellanox Technologies - platform. The Mellanox systems provide data center networking - solutions based on Virtual Protocol Interconnect (VPI) technology - enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE - connection. - - If you have a Mellanox system, say Y or M here. +source "drivers/platform/x86/intel_speed_select_if/Kconfig" config INTEL_TURBO_MAX_3 bool "Intel Turbo Boost Max Technology 3.0 enumeration driver" @@ -1249,17 +1255,25 @@ config INTEL_TURBO_MAX_3 This driver is only required when the system is not using Hardware P-States (HWP). In HWP mode, priority can be read from ACPI tables. -config TOUCHSCREEN_DMI - bool "DMI based touchscreen configuration info" - depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD - select EFI_EMBEDDED_FIRMWARE if EFI +config INTEL_UNCORE_FREQ_CONTROL + tristate "Intel Uncore frequency control driver" + depends on X86_64 + help + This driver allows control of uncore frequency limits on + supported server platforms. + Uncore frequency controls RING/LLC (last-level cache) clocks. + + To compile this driver as a module, choose M here: the module + will be called intel-uncore-frequency. + +config INTEL_BXTWC_PMIC_TMU + tristate "Intel BXT Whiskey Cove TMU Driver" + depends on REGMAP + depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC ---help--- - Certain ACPI based tablets with e.g. Silead or Chipone touchscreens - do not have enough data in ACPI tables for the touchscreen driver to - handle the touchscreen properly, as OEMs expect the data to be baked - into the tablet model specific version of the driver shipped with the - the OS-image for the device. This option supplies the missing info. - Enable this for x86 tablets with Silead or Chipone touchscreens. + Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature. + This driver enables the alarm wakeup functionality in the TMU unit + of Whiskey Cove PMIC. config INTEL_CHTDC_TI_PWRBTN tristate "Intel Cherry Trail Dollar Cove TI power button driver" @@ -1272,6 +1286,21 @@ config INTEL_CHTDC_TI_PWRBTN To compile this driver as a module, choose M here: the module will be called intel_chtdc_ti_pwrbtn. +config INTEL_MFLD_THERMAL + tristate "Thermal driver for Intel Medfield platform" + depends on MFD_INTEL_MSIC && THERMAL + help + Say Y here to enable thermal driver support for the Intel Medfield + platform. + +config INTEL_MID_POWER_BUTTON + tristate "power button driver for Intel MID platforms" + depends on INTEL_SCU_IPC && INPUT + help + This driver handles the power button on the Intel MID platforms. + + If unsure, say N. + config INTEL_MRFLD_PWRBTN tristate "Intel Merrifield Basin Cove power button driver" depends on INTEL_SOC_PMIC_MRFLD @@ -1283,85 +1312,61 @@ config INTEL_MRFLD_PWRBTN To compile this driver as a module, choose M here: the module will be called intel_mrfld_pwrbtn. -config I2C_MULTI_INSTANTIATE - tristate "I2C multi instantiate pseudo device driver" - depends on I2C && ACPI - help - Some ACPI-based systems list multiple i2c-devices in a single ACPI - firmware-node. This driver will instantiate separate i2c-clients - for each device in the firmware-node. - - To compile this driver as a module, choose M here: the module - will be called i2c-multi-instantiate. - -config INTEL_ATOMISP2_PM - tristate "Intel AtomISP2 dummy / power-management driver" - depends on PCI && IOSF_MBI && PM - help - Power-management driver for Intel's Image Signal Processor found on - Bay Trail and Cherry Trail devices. This dummy driver's sole purpose - is to turn the ISP off (put it in D3) to save power and to allow - entering of S0ix modes. - - To compile this driver as a module, choose M here: the module - will be called intel_atomisp2_pm. - -config HUAWEI_WMI - tristate "Huawei WMI laptop extras driver" - depends on ACPI_BATTERY - depends on ACPI_WMI - depends on INPUT - select INPUT_SPARSEKMAP - select LEDS_CLASS - select LEDS_TRIGGERS - select LEDS_TRIGGER_AUDIO - select NEW_LEDS - help - This driver provides support for Huawei WMI hotkeys, battery charge - control, fn-lock, mic-mute LED, and other extra features. - - To compile this driver as a module, choose M here: the module - will be called huawei-wmi. - -config PCENGINES_APU2 - tristate "PC Engines APUv2/3 front button and LEDs driver" - depends on INPUT && INPUT_KEYBOARD && GPIOLIB - depends on LEDS_CLASS - select GPIO_AMD_FCH - select KEYBOARD_GPIO_POLLED - select LEDS_GPIO - help - This driver provides support for the front button and LEDs on - PC Engines APUv2/APUv3 board. +config INTEL_PMC_CORE + tristate "Intel PMC Core driver" + depends on PCI + ---help--- + The Intel Platform Controller Hub for Intel Core SoCs provides access + to Power Management Controller registers via a PCI interface. This + driver can utilize debugging capabilities and supported features as + exposed by the Power Management Controller. - To compile this driver as a module, choose M here: the module - will be called pcengines-apuv2. + Supported features: + - SLP_S0_RESIDENCY counter + - PCH IP Power Gating status + - LTR Ignore + - MPHY/PLL gating status (Sunrisepoint PCH only) -config INTEL_UNCORE_FREQ_CONTROL - tristate "Intel Uncore frequency control driver" - depends on X86_64 - help - This driver allows control of uncore frequency limits on - supported server platforms. - Uncore frequency controls RING/LLC (last-level cache) clocks. +config INTEL_PMC_IPC + tristate "Intel PMC IPC Driver" + depends on ACPI && PCI + ---help--- + This driver provides support for PMC control on some Intel platforms. + The PMC is an ARC processor which defines IPC commands for communication + with other entities in the CPU. - To compile this driver as a module, choose M here: the module - will be called intel-uncore-frequency. +config INTEL_PUNIT_IPC + tristate "Intel P-Unit IPC Driver" + ---help--- + This driver provides support for Intel P-Unit Mailbox IPC mechanism, + which is used to bridge the communications between kernel and P-Unit. -source "drivers/platform/x86/intel_speed_select_if/Kconfig" +config INTEL_SCU_IPC + bool "Intel SCU IPC Support" + depends on X86_INTEL_MID + default y + ---help--- + IPC is used to bridge the communications between kernel and SCU on + some embedded Intel x86 platforms. This is not needed for PC-type + machines. -config SYSTEM76_ACPI - tristate "System76 ACPI Driver" - depends on ACPI - select NEW_LEDS - select LEDS_CLASS - select LEDS_TRIGGERS - help - This is a driver for System76 laptops running open firmware. It adds - support for Fn-Fx key combinations, keyboard backlight, and airplane mode - LEDs. +config INTEL_SCU_IPC_UTIL + tristate "Intel SCU IPC utility driver" + depends on INTEL_SCU_IPC + ---help--- + The IPC Util driver provides an interface with the SCU enabling + low level access for debug work and updating the firmware. Say + N unless you will be doing this on an Intel MID platform. - If you have a System76 laptop running open firmware, say Y or M here. +config INTEL_TELEMETRY + tristate "Intel SoC Telemetry Driver" + depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64 + ---help--- + This driver provides interfaces to configure and use + telemetry for INTEL SoC from APL onwards. It is also + used to get various SoC events and parameters + directly via debugfs files. Various tools may use + this interface for SoC state monitoring. endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 3747b1f07cf1..53408d965874 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -3,106 +3,146 @@ # Makefile for linux/drivers/platform/x86 # x86 Platform-Specific Drivers # + +# Windows Management Interface +obj-$(CONFIG_ACPI_WMI) += wmi.o +obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o + +# WMI drivers +obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o +obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o +obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o +obj-$(CONFIG_MXM_WMI) += mxm-wmi.o +obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o +obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o + +# Acer +obj-$(CONFIG_ACERHDF) += acerhdf.o +obj-$(CONFIG_ACER_WIRELESS) += acer-wireless.o +obj-$(CONFIG_ACER_WMI) += acer-wmi.o + +# Apple +obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o + +# ASUS obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o +obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o obj-$(CONFIG_ASUS_WMI) += asus-wmi.o obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o -obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o -obj-$(CONFIG_LG_LAPTOP) += lg-laptop.o -obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o -obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o -obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o -obj-$(CONFIG_DCDBAS) += dcdbas.o -obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o -dell-smbios-objs := dell-smbios-base.o + +# Dell +obj-$(CONFIG_DCDBAS) += dcdbas.o +obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o +dell-smbios-objs := dell-smbios-base.o dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o -obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o -obj-$(CONFIG_DELL_WMI) += dell-wmi.o +obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o +obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o +obj-$(CONFIG_DELL_RBU) += dell_rbu.o +obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o +obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o -obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o -obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o -obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o -obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o -obj-$(CONFIG_DELL_RBU) += dell_rbu.o -obj-$(CONFIG_ACER_WMI) += acer-wmi.o -obj-$(CONFIG_ACER_WIRELESS) += acer-wireless.o -obj-$(CONFIG_ACERHDF) += acerhdf.o +obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o +obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o + +# Fujitsu +obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o +obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o +obj-$(CONFIG_FUJITSU_TABLET) += fujitsu-tablet.o + +# GPD +obj-$(CONFIG_GPD_POCKET_FAN) += gpd-pocket-fan.o + +# Hewlett Packard obj-$(CONFIG_HP_ACCEL) += hp_accel.o obj-$(CONFIG_HP_WIRELESS) += hp-wireless.o obj-$(CONFIG_HP_WMI) += hp-wmi.o -obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o -obj-$(CONFIG_AMILO_RFKILL) += amilo-rfkill.o -obj-$(CONFIG_GPD_POCKET_FAN) += gpd-pocket-fan.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o -obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o + +# IBM Thinkpad and Lenovo +obj-$(CONFIG_IBM_RTL) += ibm_rtl.o obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o -obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o -obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o -obj-$(CONFIG_FUJITSU_TABLET) += fujitsu-tablet.o -obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o -obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o -obj-$(CONFIG_ACPI_WMI) += wmi.o +obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o + +# Intel +obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o +obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o +intel_cht_int33fe-objs := intel_cht_int33fe_common.o \ + intel_cht_int33fe_typec.o \ + intel_cht_int33fe_microb.o +obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o +obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o +obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o +obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o +obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o + +# Microsoft +obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o +obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o +obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o +obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o + +# MSI +obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_MSI_WMI) += msi-wmi.o -obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o -obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o -obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o -obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o -obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o -obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o -# toshiba_acpi must link after wmi to ensure that wmi devices are found -# before toshiba_acpi initializes -obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o +# OLPC +obj-$(CONFIG_XO15_EBOOK) += xo15-ebook.o +obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o +# PC Engines +obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o + +# Samsung +obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o +obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o + +# Toshiba obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o -obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o -intel_cht_int33fe-objs := intel_cht_int33fe_common.o \ - intel_cht_int33fe_typec.o \ - intel_cht_int33fe_microb.o - -obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o -obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o -obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o -obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o -obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o -obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o -obj-$(CONFIG_INTEL_IPS) += intel_ips.o -obj-$(CONFIG_XO1_RFKILL) += xo1-rfkill.o -obj-$(CONFIG_XO15_EBOOK) += xo15-ebook.o -obj-$(CONFIG_IBM_RTL) += ibm_rtl.o -obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o -obj-$(CONFIG_MXM_WMI) += mxm-wmi.o -obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o -obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o -obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o -obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o -obj-$(CONFIG_INTEL_RST) += intel-rst.o -obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o -obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o -obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o -obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o -obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o -obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o -obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o +# toshiba_acpi must link after wmi to ensure that wmi devices are found +# before toshiba_acpi initializes +obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o + +# Laptop drivers +obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o +obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o +obj-$(CONFIG_LG_LAPTOP) += lg-laptop.o +obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o +obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o +obj-$(CONFIG_SYSTEM76_ACPI) += system76_acpi.o +obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o + +# Platform drivers +obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o +obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o +obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o + +# Intel uncore drivers +obj-$(CONFIG_INTEL_IPS) += intel_ips.o +obj-$(CONFIG_INTEL_RST) += intel-rst.o +obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o +obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/ +obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o +obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o + +# Intel PMIC / PMC / P-Unit devices obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o -obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ - intel_telemetry_pltdrv.o \ - intel_telemetry_debugfs.o -obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o -obj-$(CONFIG_PMC_ATOM) += pmc_atom.o -obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o -obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o +obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o +obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o -obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o -obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o -obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o -obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/ -obj-$(CONFIG_SYSTEM76_ACPI) += system76_acpi.o -obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o +obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o +obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o +obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o +obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o +obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o +obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ + intel_telemetry_pltdrv.o \ + intel_telemetry_debugfs.o +obj-$(CONFIG_PMC_ATOM) += pmc_atom.o diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 612ef5526226..bb7c529d7d16 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -426,8 +426,11 @@ static int asus_wmi_battery_add(struct power_supply *battery) { /* The WMI method does not provide a way to specific a battery, so we * just assume it is the first battery. + * Note: On some newer ASUS laptops (Zenbook UM431DA), the primary/first + * battery is named BATT. */ - if (strcmp(battery->desc->name, "BAT0") != 0) + if (strcmp(battery->desc->name, "BAT0") != 0 && + strcmp(battery->desc->name, "BATT") != 0) return -ENODEV; if (device_create_file(&battery->dev, @@ -1719,7 +1722,7 @@ static ssize_t fan_boost_mode_store(struct device *dev, asus->fan_boost_mode = new_mode; fan_boost_mode_write(asus); - return result; + return count; } // Fan boost mode: 0 - normal, 1 - overboost, 2 - silent diff --git a/drivers/platform/x86/dell_rbu.c b/drivers/platform/x86/dell_rbu.c index 7d5453326b43..03c3ff34bcf5 100644 --- a/drivers/platform/x86/dell_rbu.c +++ b/drivers/platform/x86/dell_rbu.c @@ -26,6 +26,9 @@ * * See Documentation/admin-guide/dell_rbu.rst for more info. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> @@ -61,13 +64,11 @@ static struct _rbu_data { static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; module_param_string(image_type, image_type, sizeof (image_type), 0); -MODULE_PARM_DESC(image_type, - "BIOS image type. choose- mono or packet or init"); +MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet or init"); static unsigned long allocation_floor = 0x100000; module_param(allocation_floor, ulong, 0644); -MODULE_PARM_DESC(allocation_floor, - "Minimum address for allocations when using Packet mode"); +MODULE_PARM_DESC(allocation_floor, "Minimum address for allocations when using Packet mode"); struct packet_data { struct list_head list; @@ -100,10 +101,10 @@ static int create_packet(void *data, size_t length) void *packet_data_temp_buf = NULL; unsigned int idx = 0; - pr_debug("create_packet: entry \n"); + pr_debug("entry\n"); if (!rbu_data.packetsize) { - pr_debug("create_packet: packetsize not specified\n"); + pr_debug("packetsize not specified\n"); retval = -EINVAL; goto out_noalloc; } @@ -113,9 +114,7 @@ static int create_packet(void *data, size_t length) newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL); if (!newpacket) { - printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __func__); + pr_warn("failed to allocate new packet\n"); retval = -ENOMEM; spin_lock(&rbu_data.lock); goto out_noalloc; @@ -134,17 +133,12 @@ static int create_packet(void *data, size_t length) * due to BIOS errata. This shouldn't be used for higher floors * or you will run out of mem trying to allocate the array. */ - packet_array_size = max( - (unsigned int)(allocation_floor / rbu_data.packetsize), - (unsigned int)1); + packet_array_size = max_t(unsigned int, allocation_floor / rbu_data.packetsize, 1); invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *), GFP_KERNEL); if (!invalid_addr_packet_array) { - printk(KERN_WARNING - "dell_rbu:%s: failed to allocate " - "invalid_addr_packet_array \n", - __func__); + pr_warn("failed to allocate invalid_addr_packet_array\n"); retval = -ENOMEM; spin_lock(&rbu_data.lock); goto out_alloc_packet; @@ -154,9 +148,7 @@ static int create_packet(void *data, size_t length) packet_data_temp_buf = (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); if (!packet_data_temp_buf) { - printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __func__); + pr_warn("failed to allocate new packet\n"); retval = -ENOMEM; spin_lock(&rbu_data.lock); goto out_alloc_packet_array; @@ -164,7 +156,7 @@ static int create_packet(void *data, size_t length) if ((unsigned long)virt_to_phys(packet_data_temp_buf) < allocation_floor) { - pr_debug("packet 0x%lx below floor at 0x%lx.\n", + pr_debug("packet 0x%lx below floor at 0x%lx\n", (unsigned long)virt_to_phys( packet_data_temp_buf), allocation_floor); @@ -181,7 +173,7 @@ static int create_packet(void *data, size_t length) newpacket->data = packet_data_temp_buf; - pr_debug("create_packet: newpacket at physical addr %lx\n", + pr_debug("newpacket at physical addr %lx\n", (unsigned long)virt_to_phys(newpacket->data)); /* packets may not have fixed size */ @@ -195,16 +187,14 @@ static int create_packet(void *data, size_t length) memcpy(newpacket->data, data, length); - pr_debug("create_packet: exit \n"); + pr_debug("exit\n"); out_alloc_packet_array: /* always free packet array */ - for (;idx>0;idx--) { - pr_debug("freeing unused packet below floor 0x%lx.\n", - (unsigned long)virt_to_phys( - invalid_addr_packet_array[idx-1])); - free_pages((unsigned long)invalid_addr_packet_array[idx-1], - ordernum); + while (idx--) { + pr_debug("freeing unused packet below floor 0x%lx\n", + (unsigned long)virt_to_phys(invalid_addr_packet_array[idx])); + free_pages((unsigned long)invalid_addr_packet_array[idx], ordernum); } kfree(invalid_addr_packet_array); @@ -224,10 +214,9 @@ static int packetize_data(const u8 *data, size_t length) int packet_length; u8 *temp; u8 *end = (u8 *) data + length; - pr_debug("packetize_data: data length %zd\n", length); + pr_debug("data length %zd\n", length); if (!rbu_data.packetsize) { - printk(KERN_WARNING - "dell_rbu: packetsize not specified\n"); + pr_warn("packetsize not specified\n"); return -EIO; } @@ -255,15 +244,13 @@ static int packetize_data(const u8 *data, size_t length) return rc; } -static int do_packet_read(char *data, struct list_head *ptemp_list, +static int do_packet_read(char *data, struct packet_data *newpacket, int length, int bytes_read, int *list_read_count) { void *ptemp_buf; - struct packet_data *newpacket = NULL; int bytes_copied = 0; int j = 0; - newpacket = list_entry(ptemp_list, struct packet_data, list); *list_read_count += newpacket->length; if (*list_read_count > bytes_read) { @@ -291,7 +278,7 @@ static int do_packet_read(char *data, struct list_head *ptemp_list, static int packet_read_list(char *data, size_t * pread_length) { - struct list_head *ptemp_list; + struct packet_data *newpacket; int temp_count = 0; int bytes_copied = 0; int bytes_read = 0; @@ -305,9 +292,8 @@ static int packet_read_list(char *data, size_t * pread_length) remaining_bytes = *pread_length; bytes_read = rbu_data.packet_read_count; - ptemp_list = (&packet_data_head.list)->next; - while (!list_empty(ptemp_list)) { - bytes_copied = do_packet_read(pdest, ptemp_list, + list_for_each_entry(newpacket, (&packet_data_head.list)->next, list) { + bytes_copied = do_packet_read(pdest, newpacket, remaining_bytes, bytes_read, &temp_count); remaining_bytes -= bytes_copied; bytes_read += bytes_copied; @@ -318,8 +304,6 @@ static int packet_read_list(char *data, size_t * pread_length) */ if (remaining_bytes == 0) break; - - ptemp_list = ptemp_list->next; } /*finally set the bytes read */ *pread_length = bytes_read - rbu_data.packet_read_count; @@ -329,17 +313,11 @@ static int packet_read_list(char *data, size_t * pread_length) static void packet_empty_list(void) { - struct list_head *ptemp_list; - struct list_head *pnext_list; - struct packet_data *newpacket; + struct packet_data *newpacket, *tmp; + + list_for_each_entry_safe(newpacket, tmp, (&packet_data_head.list)->next, list) { + list_del(&newpacket->list); - ptemp_list = (&packet_data_head.list)->next; - while (!list_empty(ptemp_list)) { - newpacket = - list_entry(ptemp_list, struct packet_data, list); - pnext_list = ptemp_list->next; - list_del(ptemp_list); - ptemp_list = pnext_list; /* * zero out the RBU packet memory before freeing * to make sure there are no stale RBU packets left in memory @@ -407,8 +385,7 @@ static int img_update_realloc(unsigned long size) * check for corruption */ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { - printk(KERN_ERR "dell_rbu:%s: corruption " - "check failed\n", __func__); + pr_err("corruption check failed\n"); return -EINVAL; } /* @@ -430,8 +407,7 @@ static int img_update_realloc(unsigned long size) (unsigned char *)__get_free_pages(GFP_DMA32, ordernum); spin_lock(&rbu_data.lock); if (!image_update_buffer) { - pr_debug("Not enough memory for image update:" - "size = %ld\n", size); + pr_debug("Not enough memory for image update: size = %ld\n", size); return -ENOMEM; } @@ -455,15 +431,14 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) /* check to see if we have something to return */ if (rbu_data.num_packets == 0) { - pr_debug("read_packet_data: no packets written\n"); + pr_debug("no packets written\n"); retval = -ENOMEM; goto read_rbu_data_exit; } if (pos > rbu_data.imagesize) { retval = 0; - printk(KERN_WARNING "dell_rbu:read_packet_data: " - "data underrun\n"); + pr_warn("data underrun\n"); goto read_rbu_data_exit; } @@ -489,8 +464,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) /* check to see if we have something to return */ if ((rbu_data.image_update_buffer == NULL) || (rbu_data.bios_image_size == 0)) { - pr_debug("read_rbu_data_mono: image_update_buffer %p ," - "bios_image_size %lu\n", + pr_debug("image_update_buffer %p, bios_image_size %lu\n", rbu_data.image_update_buffer, rbu_data.bios_image_size); return -ENOMEM; @@ -500,9 +474,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) rbu_data.image_update_buffer, rbu_data.bios_image_size); } -static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { ssize_t ret_count = 0; @@ -513,11 +487,12 @@ static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj, else if (!strcmp(image_type, "packet")) ret_count = read_packet_data(buffer, pos, count); else - pr_debug("read_rbu_data: invalid image type specified\n"); + pr_debug("invalid image type specified\n"); spin_unlock(&rbu_data.lock); return ret_count; } +static BIN_ATTR_RO(data, 0); static void callbackfn_rbu(const struct firmware *fw, void *context) { @@ -548,15 +523,15 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) */ packet_empty_list(); } else - pr_debug("invalid image type specified.\n"); + pr_debug("invalid image type specified\n"); spin_unlock(&rbu_data.lock); out: release_firmware(fw); } -static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t image_type_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int size = 0; if (!pos) @@ -564,9 +539,9 @@ static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj, return size; } -static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t image_type_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int rc = count; int req_firm_rc = 0; @@ -602,9 +577,7 @@ static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, &rbu_device->dev, GFP_KERNEL, &context, callbackfn_rbu); if (req_firm_rc) { - printk(KERN_ERR - "dell_rbu:%s request_firmware_nowait" - " failed %d\n", __func__, rc); + pr_err("request_firmware_nowait failed %d\n", rc); rc = -EIO; } else rbu_data.entry_created = 1; @@ -612,7 +585,7 @@ static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, spin_lock(&rbu_data.lock); } } else { - printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); + pr_warn("image_type is invalid\n"); spin_unlock(&rbu_data.lock); return -EINVAL; } @@ -624,10 +597,11 @@ static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, return rc; } +static BIN_ATTR_RW(image_type, 0); -static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t packet_size_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { int size = 0; if (!pos) { @@ -638,9 +612,9 @@ static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj, return size; } -static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) +static ssize_t packet_size_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) { unsigned long temp; spin_lock(&rbu_data.lock); @@ -652,22 +626,17 @@ static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj, spin_unlock(&rbu_data.lock); return count; } +static BIN_ATTR_RW(packet_size, 0); -static struct bin_attribute rbu_data_attr = { - .attr = {.name = "data", .mode = 0444}, - .read = read_rbu_data, -}; - -static struct bin_attribute rbu_image_type_attr = { - .attr = {.name = "image_type", .mode = 0644}, - .read = read_rbu_image_type, - .write = write_rbu_image_type, +static struct bin_attribute *rbu_bin_attrs[] = { + &bin_attr_data, + &bin_attr_image_type, + &bin_attr_packet_size, + NULL }; -static struct bin_attribute rbu_packet_size_attr = { - .attr = {.name = "packet_size", .mode = 0644}, - .read = read_rbu_packet_size, - .write = write_rbu_packet_size, +static const struct attribute_group rbu_group = { + .bin_attrs = rbu_bin_attrs, }; static int __init dcdrbu_init(void) @@ -678,30 +647,17 @@ static int __init dcdrbu_init(void) init_packet_head(); rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0); if (IS_ERR(rbu_device)) { - printk(KERN_ERR - "dell_rbu:%s:platform_device_register_simple " - "failed\n", __func__); + pr_err("platform_device_register_simple failed\n"); return PTR_ERR(rbu_device); } - rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); + rc = sysfs_create_group(&rbu_device->dev.kobj, &rbu_group); if (rc) goto out_devreg; - rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); - if (rc) - goto out_data; - rc = sysfs_create_bin_file(&rbu_device->dev.kobj, - &rbu_packet_size_attr); - if (rc) - goto out_imtype; rbu_data.entry_created = 0; return 0; -out_imtype: - sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); -out_data: - sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); out_devreg: platform_device_unregister(rbu_device); return rc; @@ -713,6 +669,7 @@ static __exit void dcdrbu_exit(void) packet_empty_list(); img_update_free(); spin_unlock(&rbu_data.lock); + sysfs_remove_group(&rbu_device->dev.kobj, &rbu_group); platform_device_unregister(rbu_device); } diff --git a/drivers/platform/x86/gpd-pocket-fan.c b/drivers/platform/x86/gpd-pocket-fan.c index b471b86c28fe..5b516e4c2bfb 100644 --- a/drivers/platform/x86/gpd-pocket-fan.c +++ b/drivers/platform/x86/gpd-pocket-fan.c @@ -128,7 +128,7 @@ static int gpd_pocket_fan_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(temp_limits); i++) { if (temp_limits[i] < 20000 || temp_limits[i] > 90000) { - dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 40000 and 70000)\n", + dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 20000 and 90000)\n", temp_limits[i]); temp_limits[0] = TEMP_LIMIT0_DEFAULT; temp_limits[1] = TEMP_LIMIT1_DEFAULT; diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index ffb8d5d1eb5f..6acc8457866e 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -28,7 +28,7 @@ struct i2c_inst_data { struct i2c_multi_inst_data { int num_clients; - struct i2c_client *clients[0]; + struct i2c_client *clients[]; }; static int i2c_multi_inst_count(struct acpi_resource *ares, void *data) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 43d590250228..5f4f5716c893 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -23,6 +23,7 @@ static const struct acpi_device_id intel_hid_ids[] = { {"INT33D5", 0}, {"", 0}, }; +MODULE_DEVICE_TABLE(acpi, intel_hid_ids); /* In theory, these are HID usages. */ static const struct key_entry intel_hid_keymap[] = { @@ -541,7 +542,6 @@ static struct platform_driver intel_hid_pl_driver = { .probe = intel_hid_probe, .remove = intel_hid_remove, }; -MODULE_DEVICE_TABLE(acpi, intel_hid_ids); /* * Unfortunately, some laptops provide a _HID="INT33D5" device with diff --git a/drivers/platform/x86/intel-uncore-frequency.c b/drivers/platform/x86/intel-uncore-frequency.c index 859272075a8f..b96d172eb2c1 100644 --- a/drivers/platform/x86/intel-uncore-frequency.c +++ b/drivers/platform/x86/intel-uncore-frequency.c @@ -38,6 +38,7 @@ */ struct uncore_data { struct kobject kobj; + struct completion kobj_unregister; u64 stored_uncore_data; u32 initial_min_freq_khz; u32 initial_max_freq_khz; @@ -52,7 +53,7 @@ static int uncore_max_entries __read_mostly; /* Storage for uncore data for all instances */ static struct uncore_data *uncore_instances; /* Root of the all uncore sysfs kobjs */ -struct kobject uncore_root_kobj; +struct kobject *uncore_root_kobj; /* Stores the CPU mask of the target CPUs to use during uncore read/write */ static cpumask_t uncore_cpu_mask; /* CPU online callback register instance */ @@ -97,6 +98,9 @@ static int uncore_read_ratio(struct uncore_data *data, unsigned int *min, u64 cap; int ret; + if (data->control_cpu < 0) + return -ENXIO; + ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap); if (ret) return ret; @@ -116,6 +120,11 @@ static int uncore_write_ratio(struct uncore_data *data, unsigned int input, mutex_lock(&uncore_lock); + if (data->control_cpu < 0) { + ret = -ENXIO; + goto finish_write; + } + input /= UNCORE_FREQ_KHZ_MULTIPLIER; if (!input || input > 0x7F) { ret = -EINVAL; @@ -217,15 +226,19 @@ static struct attribute *uncore_attrs[] = { NULL }; +static void uncore_sysfs_entry_release(struct kobject *kobj) +{ + struct uncore_data *data = to_uncore_data(kobj); + + complete(&data->kobj_unregister); +} + static struct kobj_type uncore_ktype = { + .release = uncore_sysfs_entry_release, .sysfs_ops = &kobj_sysfs_ops, .default_attrs = uncore_attrs, }; -static struct kobj_type uncore_root_ktype = { - .sysfs_ops = &kobj_sysfs_ops, -}; - /* Caller provides protection */ static struct uncore_data *uncore_get_instance(unsigned int cpu) { @@ -263,8 +276,10 @@ static void uncore_add_die_entry(int cpu) uncore_read_ratio(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz); + init_completion(&data->kobj_unregister); + ret = kobject_init_and_add(&data->kobj, &uncore_ktype, - &uncore_root_kobj, str); + uncore_root_kobj, str); if (!ret) { data->control_cpu = cpu; data->valid = true; @@ -273,18 +288,15 @@ static void uncore_add_die_entry(int cpu) mutex_unlock(&uncore_lock); } -/* Last CPU in this die is offline, so remove sysfs entries */ +/* Last CPU in this die is offline, make control cpu invalid */ static void uncore_remove_die_entry(int cpu) { struct uncore_data *data; mutex_lock(&uncore_lock); data = uncore_get_instance(cpu); - if (data) { - kobject_put(&data->kobj); + if (data) data->control_cpu = -1; - data->valid = false; - } mutex_unlock(&uncore_lock); } @@ -384,11 +396,12 @@ static int __init intel_uncore_init(void) if (!uncore_instances) return -ENOMEM; - ret = kobject_init_and_add(&uncore_root_kobj, &uncore_root_ktype, - &cpu_subsys.dev_root->kobj, - "intel_uncore_frequency"); - if (ret) + uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency", + &cpu_subsys.dev_root->kobj); + if (!uncore_root_kobj) { + ret = -ENOMEM; goto err_free; + } ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "platform/x86/uncore-freq:online", @@ -408,7 +421,7 @@ static int __init intel_uncore_init(void) err_rem_state: cpuhp_remove_state(uncore_hp_state); err_rem_kobj: - kobject_put(&uncore_root_kobj); + kobject_put(uncore_root_kobj); err_free: kfree(uncore_instances); @@ -423,10 +436,12 @@ static void __exit intel_uncore_exit(void) unregister_pm_notifier(&uncore_pm_nb); cpuhp_remove_state(uncore_hp_state); for (i = 0; i < uncore_max_entries; ++i) { - if (uncore_instances[i].valid) + if (uncore_instances[i].valid) { kobject_put(&uncore_instances[i].kobj); + wait_for_completion(&uncore_instances[i].kobj_unregister); + } } - kobject_put(&uncore_root_kobj); + kobject_put(uncore_root_kobj); kfree(uncore_instances); } module_exit(intel_uncore_exit) diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index b74932307d69..b5880936d785 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -26,6 +26,7 @@ static const struct acpi_device_id intel_vbtn_ids[] = { {"INT33D6", 0}, {"", 0}, }; +MODULE_DEVICE_TABLE(acpi, intel_vbtn_ids); /* In theory, these are HID usages. */ static const struct key_entry intel_vbtn_keymap[] = { @@ -239,7 +240,6 @@ static struct platform_driver intel_vbtn_pl_driver = { .probe = intel_vbtn_probe, .remove = intel_vbtn_remove, }; -MODULE_DEVICE_TABLE(acpi, intel_vbtn_ids); static acpi_status __init check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 3df33ff50faa..d2a5d4c36715 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <linux/suspend.h> #include <linux/uaccess.h> @@ -193,7 +194,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"Fuse", BIT(6)}, /* * Reserved for Cannon Lake but valid for Ice Lake, Comet Lake, - * Tiger Lake and Elkhart Lake. + * Tiger Lake, Elkhart Lake and Jasper Lake. */ {"SBR8", BIT(7)}, @@ -240,7 +241,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"HDA_PGD6", BIT(4)}, /* * Reserved for Cannon Lake but valid for Ice Lake, Comet Lake, - * Tiger Lake and ELkhart Lake. + * Tiger Lake, ELkhart Lake and Jasper Lake. */ {"PSF6", BIT(5)}, {"PSF7", BIT(6)}, @@ -273,7 +274,7 @@ static const struct pmc_bit_map *ext_icl_pfear_map[] = { }; static const struct pmc_bit_map tgl_pfear_map[] = { - /* Tiger Lake and Elkhart Lake generation onwards only */ + /* Tiger Lake, Elkhart Lake and Jasper Lake generation onwards only */ {"PSF9", BIT(0)}, {"RES_66", BIT(1)}, {"RES_67", BIT(2)}, @@ -408,13 +409,157 @@ static const struct pmc_reg_map icl_reg_map = { .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, }; +static const struct pmc_bit_map tgl_lpm0_map[] = { + {"USB2PLL_OFF_STS", BIT(18)}, + {"PCIe/USB3.1_Gen2PLL_OFF_STS", BIT(19)}, + {"PCIe_Gen3PLL_OFF_STS", BIT(20)}, + {"OPIOPLL_OFF_STS", BIT(21)}, + {"OCPLL_OFF_STS", BIT(22)}, + {"AudioPLL_OFF_STS", BIT(23)}, + {"MIPIPLL_OFF_STS", BIT(24)}, + {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, + {"AC_Ring_Osc_OFF_STS", BIT(26)}, + {"MC_Ring_Osc_OFF_STS", BIT(27)}, + {"SATAPLL_OFF_STS", BIT(29)}, + {"XTAL_USB2PLL_OFF_STS", BIT(31)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm1_map[] = { + {"SPI_PG_STS", BIT(2)}, + {"xHCI_PG_STS", BIT(3)}, + {"PCIe_Ctrller_A_PG_STS", BIT(4)}, + {"PCIe_Ctrller_B_PG_STS", BIT(5)}, + {"PCIe_Ctrller_C_PG_STS", BIT(6)}, + {"GBE_PG_STS", BIT(7)}, + {"SATA_PG_STS", BIT(8)}, + {"HDA0_PG_STS", BIT(9)}, + {"HDA1_PG_STS", BIT(10)}, + {"HDA2_PG_STS", BIT(11)}, + {"HDA3_PG_STS", BIT(12)}, + {"PCIe_Ctrller_D_PG_STS", BIT(13)}, + {"ISIO_PG_STS", BIT(14)}, + {"SMB_PG_STS", BIT(16)}, + {"ISH_PG_STS", BIT(17)}, + {"ITH_PG_STS", BIT(19)}, + {"SDX_PG_STS", BIT(20)}, + {"xDCI_PG_STS", BIT(25)}, + {"DCI_PG_STS", BIT(26)}, + {"CSME0_PG_STS", BIT(27)}, + {"CSME_KVM_PG_STS", BIT(28)}, + {"CSME1_PG_STS", BIT(29)}, + {"CSME_CLINK_PG_STS", BIT(30)}, + {"CSME2_PG_STS", BIT(31)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm2_map[] = { + {"ADSP_D3_STS", BIT(0)}, + {"SATA_D3_STS", BIT(1)}, + {"xHCI0_D3_STS", BIT(2)}, + {"xDCI1_D3_STS", BIT(5)}, + {"SDX_D3_STS", BIT(6)}, + {"EMMC_D3_STS", BIT(7)}, + {"IS_D3_STS", BIT(8)}, + {"THC0_D3_STS", BIT(9)}, + {"THC1_D3_STS", BIT(10)}, + {"GBE_D3_STS", BIT(11)}, + {"GBE_TSN_D3_STS", BIT(12)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm3_map[] = { + {"GPIO_COM0_VNN_REQ_STS", BIT(1)}, + {"GPIO_COM1_VNN_REQ_STS", BIT(2)}, + {"GPIO_COM2_VNN_REQ_STS", BIT(3)}, + {"GPIO_COM3_VNN_REQ_STS", BIT(4)}, + {"GPIO_COM4_VNN_REQ_STS", BIT(5)}, + {"GPIO_COM5_VNN_REQ_STS", BIT(6)}, + {"Audio_VNN_REQ_STS", BIT(7)}, + {"ISH_VNN_REQ_STS", BIT(8)}, + {"CNVI_VNN_REQ_STS", BIT(9)}, + {"eSPI_VNN_REQ_STS", BIT(10)}, + {"Display_VNN_REQ_STS", BIT(11)}, + {"DTS_VNN_REQ_STS", BIT(12)}, + {"SMBUS_VNN_REQ_STS", BIT(14)}, + {"CSME_VNN_REQ_STS", BIT(15)}, + {"SMLINK0_VNN_REQ_STS", BIT(16)}, + {"SMLINK1_VNN_REQ_STS", BIT(17)}, + {"CLINK_VNN_REQ_STS", BIT(20)}, + {"DCI_VNN_REQ_STS", BIT(21)}, + {"ITH_VNN_REQ_STS", BIT(22)}, + {"CSME_VNN_REQ_STS", BIT(24)}, + {"GBE_VNN_REQ_STS", BIT(25)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm4_map[] = { + {"CPU_C10_REQ_STS_0", BIT(0)}, + {"PCIe_LPM_En_REQ_STS_3", BIT(3)}, + {"ITH_REQ_STS_5", BIT(5)}, + {"CNVI_REQ_STS_6", BIT(6)}, + {"ISH_REQ_STS_7", BIT(7)}, + {"USB2_SUS_PG_Sys_REQ_STS_10", BIT(10)}, + {"PCIe_Clk_REQ_STS_12", BIT(12)}, + {"MPHY_Core_DL_REQ_STS_16", BIT(16)}, + {"Break-even_En_REQ_STS_17", BIT(17)}, + {"Auto-demo_En_REQ_STS_18", BIT(18)}, + {"MPHY_SUS_REQ_STS_22", BIT(22)}, + {"xDCI_attached_REQ_STS_24", BIT(24)}, + {} +}; + +static const struct pmc_bit_map tgl_lpm5_map[] = { + {"LSX_Wake0_En_STS", BIT(0)}, + {"LSX_Wake0_Pol_STS", BIT(1)}, + {"LSX_Wake1_En_STS", BIT(2)}, + {"LSX_Wake1_Pol_STS", BIT(3)}, + {"LSX_Wake2_En_STS", BIT(4)}, + {"LSX_Wake2_Pol_STS", BIT(5)}, + {"LSX_Wake3_En_STS", BIT(6)}, + {"LSX_Wake3_Pol_STS", BIT(7)}, + {"LSX_Wake4_En_STS", BIT(8)}, + {"LSX_Wake4_Pol_STS", BIT(9)}, + {"LSX_Wake5_En_STS", BIT(10)}, + {"LSX_Wake5_Pol_STS", BIT(11)}, + {"LSX_Wake6_En_STS", BIT(12)}, + {"LSX_Wake6_Pol_STS", BIT(13)}, + {"LSX_Wake7_En_STS", BIT(14)}, + {"LSX_Wake7_Pol_STS", BIT(15)}, + {"Intel_Se_IO_Wake0_En_STS", BIT(16)}, + {"Intel_Se_IO_Wake0_Pol_STS", BIT(17)}, + {"Intel_Se_IO_Wake1_En_STS", BIT(18)}, + {"Intel_Se_IO_Wake1_Pol_STS", BIT(19)}, + {"Int_Timer_SS_Wake0_En_STS", BIT(20)}, + {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)}, + {"Int_Timer_SS_Wake1_En_STS", BIT(22)}, + {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)}, + {"Int_Timer_SS_Wake2_En_STS", BIT(24)}, + {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)}, + {"Int_Timer_SS_Wake3_En_STS", BIT(26)}, + {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)}, + {"Int_Timer_SS_Wake4_En_STS", BIT(28)}, + {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)}, + {"Int_Timer_SS_Wake5_En_STS", BIT(30)}, + {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)}, + {} +}; + +static const struct pmc_bit_map *tgl_lpm_maps[] = { + tgl_lpm0_map, + tgl_lpm1_map, + tgl_lpm2_map, + tgl_lpm3_map, + tgl_lpm4_map, + tgl_lpm5_map, + NULL +}; + static const struct pmc_reg_map tgl_reg_map = { .pfear_sts = ext_tgl_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slps0_dbg_maps = cnp_slps0_dbg_maps, .ltr_show_sts = cnp_ltr_show_map, .msr_sts = msr_map, - .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, .regmap_length = CNP_PMC_MMIO_REG_LEN, .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, @@ -422,6 +567,12 @@ static const struct pmc_reg_map tgl_reg_map = { .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, + .lpm_modes = tgl_lpm_modes, + .lpm_en_offset = TGL_LPM_EN_OFFSET, + .lpm_residency_offset = TGL_LPM_RESIDENCY_OFFSET, + .lpm_sts = tgl_lpm_maps, + .lpm_status_offset = TGL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET, }; static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) @@ -463,6 +614,84 @@ static int pmc_core_check_read_lock_bit(void) return value & BIT(pmcdev->map->pm_read_disable_bit); } +static void pmc_core_slps0_display(struct pmc_dev *pmcdev, struct device *dev, + struct seq_file *s) +{ + const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; + const struct pmc_bit_map *map; + int offset = pmcdev->map->slps0_dbg_offset; + u32 data; + + while (*maps) { + map = *maps; + data = pmc_core_reg_read(pmcdev, offset); + offset += 4; + while (map->name) { + if (dev) + dev_dbg(dev, "SLP_S0_DBG: %-32s\tState: %s\n", + map->name, + data & map->bit_mask ? "Yes" : "No"); + if (s) + seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", + map->name, + data & map->bit_mask ? "Yes" : "No"); + ++map; + } + ++maps; + } +} + +static int pmc_core_lpm_get_arr_size(const struct pmc_bit_map **maps) +{ + int idx; + + for (idx = 0; maps[idx]; idx++) + ;/* Nothing */ + + return idx; +} + +static void pmc_core_lpm_display(struct pmc_dev *pmcdev, struct device *dev, + struct seq_file *s, u32 offset, + const char *str, + const struct pmc_bit_map **maps) +{ + int index, idx, len = 32, bit_mask, arr_size; + u32 *lpm_regs; + + arr_size = pmc_core_lpm_get_arr_size(maps); + lpm_regs = kmalloc_array(arr_size, sizeof(*lpm_regs), GFP_KERNEL); + if (!lpm_regs) + return; + + for (index = 0; index < arr_size; index++) { + lpm_regs[index] = pmc_core_reg_read(pmcdev, offset); + offset += 4; + } + + for (idx = 0; idx < arr_size; idx++) { + if (dev) + dev_dbg(dev, "\nLPM_%s_%d:\t0x%x\n", str, idx, + lpm_regs[idx]); + if (s) + seq_printf(s, "\nLPM_%s_%d:\t0x%x\n", str, idx, + lpm_regs[idx]); + for (index = 0; maps[idx][index].name && index < len; index++) { + bit_mask = maps[idx][index].bit_mask; + if (dev) + dev_dbg(dev, "%-30s %-30d\n", + maps[idx][index].name, + lpm_regs[idx] & bit_mask ? 1 : 0); + if (s) + seq_printf(s, "%-30s %-30d\n", + maps[idx][index].name, + lpm_regs[idx] & bit_mask ? 1 : 0); + } + } + + kfree(lpm_regs); +} + #if IS_ENABLED(CONFIG_DEBUG_FS) static bool slps0_dbg_latch; @@ -698,27 +927,11 @@ out_unlock: static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; - const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; - const struct pmc_bit_map *map; - int offset; - u32 data; pmc_core_slps0_dbg_latch(pmcdev, false); - offset = pmcdev->map->slps0_dbg_offset; - while (*maps) { - map = *maps; - data = pmc_core_reg_read(pmcdev, offset); - offset += 4; - while (map->name) { - seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", - map->name, - data & map->bit_mask ? - "Yes" : "No"); - ++map; - } - ++maps; - } + pmc_core_slps0_display(pmcdev, NULL, s); pmc_core_slps0_dbg_latch(pmcdev, true); + return 0; } DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); @@ -794,6 +1007,51 @@ static int pmc_core_ltr_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); +static int pmc_core_substate_res_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const char **lpm_modes = pmcdev->map->lpm_modes; + u32 offset = pmcdev->map->lpm_residency_offset; + u32 lpm_en; + int index; + + lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset); + seq_printf(s, "status substate residency\n"); + for (index = 0; lpm_modes[index]; index++) { + seq_printf(s, "%7s %7s %-15u\n", + BIT(index) & lpm_en ? "Enabled" : " ", + lpm_modes[index], pmc_core_reg_read(pmcdev, offset)); + offset += 4; + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_res); + +static int pmc_core_substate_sts_regs_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + u32 offset = pmcdev->map->lpm_status_offset; + + pmc_core_lpm_display(pmcdev, NULL, s, offset, "STATUS", maps); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_sts_regs); + +static int pmc_core_substate_l_sts_regs_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + u32 offset = pmcdev->map->lpm_live_status_offset; + + pmc_core_lpm_display(pmcdev, NULL, s, offset, "LIVE_STATUS", maps); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_l_sts_regs); + static int pmc_core_pkgc_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; @@ -859,6 +1117,21 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) debugfs_create_bool("slp_s0_dbg_latch", 0644, dir, &slps0_dbg_latch); } + + if (pmcdev->map->lpm_en_offset) { + debugfs_create_file("substate_residencies", 0444, + pmcdev->dbgfs_dir, pmcdev, + &pmc_core_substate_res_fops); + } + + if (pmcdev->map->lpm_status_offset) { + debugfs_create_file("substate_status_registers", 0444, + pmcdev->dbgfs_dir, pmcdev, + &pmc_core_substate_sts_regs_fops); + debugfs_create_file("substate_live_status_registers", 0444, + pmcdev->dbgfs_dir, pmcdev, + &pmc_core_substate_l_sts_regs_fops); + } } #else static inline void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) @@ -883,6 +1156,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &tgl_reg_map), X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &tgl_reg_map), X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, &tgl_reg_map), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &tgl_reg_map), {} }; @@ -1047,10 +1321,8 @@ static inline bool pmc_core_is_s0ix_failed(struct pmc_dev *pmcdev) static int pmc_core_resume(struct device *dev) { struct pmc_dev *pmcdev = dev_get_drvdata(dev); - const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; - int offset = pmcdev->map->slps0_dbg_offset; - const struct pmc_bit_map *map; - u32 data; + const struct pmc_bit_map **maps = pmcdev->map->lpm_sts; + int offset = pmcdev->map->lpm_status_offset; if (!pmcdev->check_counters) return 0; @@ -1068,18 +1340,11 @@ static int pmc_core_resume(struct device *dev) /* The real interesting case - S0ix failed - lets ask PMC why. */ dev_warn(dev, "CPU did not enter SLP_S0!!! (S0ix cnt=%llu)\n", pmcdev->s0ix_counter); - while (*maps) { - map = *maps; - data = pmc_core_reg_read(pmcdev, offset); - offset += 4; - while (map->name) { - dev_dbg(dev, "SLP_S0_DBG: %-32s\tState: %s\n", - map->name, - data & map->bit_mask ? "Yes" : "No"); - map++; - } - maps++; - } + if (pmcdev->map->slps0_dbg_maps) + pmc_core_slps0_display(pmcdev, dev, NULL); + if (pmcdev->map->lpm_sts) + pmc_core_lpm_display(pmcdev, dev, NULL, offset, "STATUS", maps); + return 0; } diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index f1a0792b3f91..0d50b2402abe 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -188,6 +188,28 @@ enum ppfear_regs { #define TGL_NUM_IP_IGN_ALLOWED 22 +/* + * Tigerlake Power Management Controller register offsets + */ +#define TGL_LPM_EN_OFFSET 0x1C78 +#define TGL_LPM_RESIDENCY_OFFSET 0x1C80 + +/* Tigerlake Low Power Mode debug registers */ +#define TGL_LPM_STATUS_OFFSET 0x1C3C +#define TGL_LPM_LIVE_STATUS_OFFSET 0x1C5C + +const char *tgl_lpm_modes[] = { + "S0i2.0", + "S0i2.1", + "S0i2.2", + "S0i3.0", + "S0i3.1", + "S0i3.2", + "S0i3.3", + "S0i3.4", + NULL +}; + struct pmc_bit_map { const char *name; u32 bit_mask; @@ -221,6 +243,7 @@ struct pmc_reg_map { const struct pmc_bit_map **slps0_dbg_maps; const struct pmc_bit_map *ltr_show_sts; const struct pmc_bit_map *msr_sts; + const struct pmc_bit_map **lpm_sts; const u32 slp_s0_offset; const u32 ltr_ignore_offset; const int regmap_length; @@ -231,6 +254,12 @@ struct pmc_reg_map { const u32 slps0_dbg_offset; const u32 ltr_ignore_max; const u32 pm_vric1_offset; + /* Low Power Mode registers */ + const char **lpm_modes; + const u32 lpm_en_offset; + const u32 lpm_residency_offset; + const u32 lpm_status_offset; + const u32 lpm_live_status_offset; }; /** diff --git a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c index ad8c7c0df4d9..3584859fcc42 100644 --- a/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c +++ b/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c @@ -126,7 +126,7 @@ static void isst_if_remove(struct pci_dev *pdev) struct isst_if_device *punit_dev; punit_dev = pci_get_drvdata(pdev); - isst_if_cdev_unregister(ISST_IF_DEV_MBOX); + isst_if_cdev_unregister(ISST_IF_DEV_MMIO); mutex_destroy(&punit_dev->mutex); } diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c index 3e3c66dfec2e..ca684ed760d1 100644 --- a/drivers/platform/x86/pmc_atom.c +++ b/drivers/platform/x86/pmc_atom.c @@ -385,6 +385,14 @@ static const struct dmi_system_id critclk_systems[] = { }, { /* pmc_plt_clk* - are used for ethernet controllers */ + .ident = "Lex 2I385SW", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Lex BayTrail"), + DMI_MATCH(DMI_PRODUCT_NAME, "2I385SW"), + }, + }, + { + /* pmc_plt_clk* - are used for ethernet controllers */ .ident = "Beckhoff CB3163", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Beckhoff Automation"), diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index fb088dd8529e..51309f7ceede 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -827,10 +827,10 @@ static ssize_t sony_nc_handles_show(struct device *dev, int i; for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ", + len += scnprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ", handles->cap[i]); } - len += snprintf(buffer + len, PAGE_SIZE - len, "\n"); + len += scnprintf(buffer + len, PAGE_SIZE - len, "\n"); return len; } @@ -2187,10 +2187,10 @@ static ssize_t sony_nc_thermal_profiles_show(struct device *dev, for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) { if (!cnt || (th_handle->profiles & cnt)) - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ", + idx += scnprintf(buffer + idx, PAGE_SIZE - idx, "%s ", snc_thermal_profiles[cnt]); } - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n"); + idx += scnprintf(buffer + idx, PAGE_SIZE - idx, "\n"); return idx; } diff --git a/drivers/platform/x86/surface3_power.c b/drivers/platform/x86/surface3_power.c new file mode 100644 index 000000000000..946ac2dc08ae --- /dev/null +++ b/drivers/platform/x86/surface3_power.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Supports for the power IC on the Surface 3 tablet. + * + * (C) Copyright 2016-2018 Red Hat, Inc + * (C) Copyright 2016-2018 Benjamin Tissoires <benjamin.tissoires@gmail.com> + * (C) Copyright 2016 Stephen Just <stephenjust@gmail.com> + * + * This driver has been reverse-engineered by parsing the DSDT of the Surface 3 + * and looking at the registers of the chips. + * + * The DSDT allowed to find out that: + * - the driver is required for the ACPI BAT0 device to communicate to the chip + * through an operation region. + * - the various defines for the operation region functions to communicate with + * this driver + * - the DSM 3f99e367-6220-4955-8b0f-06ef2ae79412 allows to trigger ACPI + * events to BAT0 (the code is all available in the DSDT). + * + * Further findings regarding the 2 chips declared in the MSHW0011 are: + * - there are 2 chips declared: + * . 0x22 seems to control the ADP1 line status (and probably the charger) + * . 0x55 controls the battery directly + * - the battery chip uses a SMBus protocol (using plain SMBus allows non + * destructive commands): + * . the commands/registers used are in the range 0x00..0x7F + * . if bit 8 (0x80) is set in the SMBus command, the returned value is the + * same as when it is not set. There is a high chance this bit is the + * read/write + * . the various registers semantic as been deduced by observing the register + * dumps. + */ + +#include <linux/acpi.h> +#include <linux/bits.h> +#include <linux/freezer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/kthread.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/uuid.h> +#include <asm/unaligned.h> + +#define SURFACE_3_POLL_INTERVAL (2 * HZ) +#define SURFACE_3_STRLEN 10 + +struct mshw0011_data { + struct i2c_client *adp1; + struct i2c_client *bat0; + unsigned short notify_mask; + struct task_struct *poll_task; + bool kthread_running; + + bool charging; + bool bat_charging; + u8 trip_point; + s32 full_capacity; +}; + +struct mshw0011_handler_data { + struct acpi_connection_info info; + struct i2c_client *client; +}; + +struct bix { + u32 revision; + u32 power_unit; + u32 design_capacity; + u32 last_full_charg_capacity; + u32 battery_technology; + u32 design_voltage; + u32 design_capacity_of_warning; + u32 design_capacity_of_low; + u32 cycle_count; + u32 measurement_accuracy; + u32 max_sampling_time; + u32 min_sampling_time; + u32 max_average_interval; + u32 min_average_interval; + u32 battery_capacity_granularity_1; + u32 battery_capacity_granularity_2; + char model[SURFACE_3_STRLEN]; + char serial[SURFACE_3_STRLEN]; + char type[SURFACE_3_STRLEN]; + char OEM[SURFACE_3_STRLEN]; +} __packed; + +struct bst { + u32 battery_state; + s32 battery_present_rate; + u32 battery_remaining_capacity; + u32 battery_present_voltage; +} __packed; + +struct gsb_command { + u8 arg0; + u8 arg1; + u8 arg2; +} __packed; + +struct gsb_buffer { + u8 status; + u8 len; + u8 ret; + union { + struct gsb_command cmd; + struct bst bst; + struct bix bix; + } __packed; +} __packed; + +#define ACPI_BATTERY_STATE_DISCHARGING BIT(0) +#define ACPI_BATTERY_STATE_CHARGING BIT(1) +#define ACPI_BATTERY_STATE_CRITICAL BIT(2) + +#define MSHW0011_CMD_DEST_BAT0 0x01 +#define MSHW0011_CMD_DEST_ADP1 0x03 + +#define MSHW0011_CMD_BAT0_STA 0x01 +#define MSHW0011_CMD_BAT0_BIX 0x02 +#define MSHW0011_CMD_BAT0_BCT 0x03 +#define MSHW0011_CMD_BAT0_BTM 0x04 +#define MSHW0011_CMD_BAT0_BST 0x05 +#define MSHW0011_CMD_BAT0_BTP 0x06 +#define MSHW0011_CMD_ADP1_PSR 0x07 +#define MSHW0011_CMD_BAT0_PSOC 0x09 +#define MSHW0011_CMD_BAT0_PMAX 0x0a +#define MSHW0011_CMD_BAT0_PSRC 0x0b +#define MSHW0011_CMD_BAT0_CHGI 0x0c +#define MSHW0011_CMD_BAT0_ARTG 0x0d + +#define MSHW0011_NOTIFY_GET_VERSION 0x00 +#define MSHW0011_NOTIFY_ADP1 0x01 +#define MSHW0011_NOTIFY_BAT0_BST 0x02 +#define MSHW0011_NOTIFY_BAT0_BIX 0x05 + +#define MSHW0011_ADP1_REG_PSR 0x04 + +#define MSHW0011_BAT0_REG_CAPACITY 0x0c +#define MSHW0011_BAT0_REG_FULL_CHG_CAPACITY 0x0e +#define MSHW0011_BAT0_REG_DESIGN_CAPACITY 0x40 +#define MSHW0011_BAT0_REG_VOLTAGE 0x08 +#define MSHW0011_BAT0_REG_RATE 0x14 +#define MSHW0011_BAT0_REG_OEM 0x45 +#define MSHW0011_BAT0_REG_TYPE 0x4e +#define MSHW0011_BAT0_REG_SERIAL_NO 0x56 +#define MSHW0011_BAT0_REG_CYCLE_CNT 0x6e + +#define MSHW0011_EV_2_5_MASK GENMASK(8, 0) + +/* 3f99e367-6220-4955-8b0f-06ef2ae79412 */ +static const guid_t mshw0011_guid = + GUID_INIT(0x3F99E367, 0x6220, 0x4955, 0x8B, 0x0F, 0x06, 0xEF, + 0x2A, 0xE7, 0x94, 0x12); + +static int +mshw0011_notify(struct mshw0011_data *cdata, u8 arg1, u8 arg2, + unsigned int *ret_value) +{ + union acpi_object *obj; + struct acpi_device *adev; + acpi_handle handle; + unsigned int i; + + handle = ACPI_HANDLE(&cdata->adp1->dev); + if (!handle || acpi_bus_get_device(handle, &adev)) + return -ENODEV; + + obj = acpi_evaluate_dsm_typed(handle, &mshw0011_guid, arg1, arg2, NULL, + ACPI_TYPE_BUFFER); + if (!obj) { + dev_err(&cdata->adp1->dev, "device _DSM execution failed\n"); + return -ENODEV; + } + + *ret_value = 0; + for (i = 0; i < obj->buffer.length; i++) + *ret_value |= obj->buffer.pointer[i] << (i * 8); + + ACPI_FREE(obj); + return 0; +} + +static const struct bix default_bix = { + .revision = 0x00, + .power_unit = 0x01, + .design_capacity = 0x1dca, + .last_full_charg_capacity = 0x1dca, + .battery_technology = 0x01, + .design_voltage = 0x10df, + .design_capacity_of_warning = 0x8f, + .design_capacity_of_low = 0x47, + .cycle_count = 0xffffffff, + .measurement_accuracy = 0x00015f90, + .max_sampling_time = 0x03e8, + .min_sampling_time = 0x03e8, + .max_average_interval = 0x03e8, + .min_average_interval = 0x03e8, + .battery_capacity_granularity_1 = 0x45, + .battery_capacity_granularity_2 = 0x11, + .model = "P11G8M", + .serial = "", + .type = "LION", + .OEM = "", +}; + +static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix) +{ + struct i2c_client *client = cdata->bat0; + char buf[SURFACE_3_STRLEN]; + int ret; + + *bix = default_bix; + + /* get design capacity */ + ret = i2c_smbus_read_word_data(client, + MSHW0011_BAT0_REG_DESIGN_CAPACITY); + if (ret < 0) { + dev_err(&client->dev, "Error reading design capacity: %d\n", + ret); + return ret; + } + bix->design_capacity = ret; + + /* get last full charge capacity */ + ret = i2c_smbus_read_word_data(client, + MSHW0011_BAT0_REG_FULL_CHG_CAPACITY); + if (ret < 0) { + dev_err(&client->dev, + "Error reading last full charge capacity: %d\n", ret); + return ret; + } + bix->last_full_charg_capacity = ret; + + /* get serial number */ + ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_SERIAL_NO, + sizeof(buf), buf); + if (ret != sizeof(buf)) { + dev_err(&client->dev, "Error reading serial no: %d\n", ret); + return ret; + } + snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf); + + /* get cycle count */ + ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CYCLE_CNT); + if (ret < 0) { + dev_err(&client->dev, "Error reading cycle count: %d\n", ret); + return ret; + } + bix->cycle_count = ret; + + /* get OEM name */ + ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_OEM, + 4, buf); + if (ret != 4) { + dev_err(&client->dev, "Error reading cycle count: %d\n", ret); + return ret; + } + snprintf(bix->OEM, ARRAY_SIZE(bix->OEM), "%3pE", buf); + + return 0; +} + +static int mshw0011_bst(struct mshw0011_data *cdata, struct bst *bst) +{ + struct i2c_client *client = cdata->bat0; + int rate, capacity, voltage, state; + s16 tmp; + + rate = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_RATE); + if (rate < 0) + return rate; + + capacity = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CAPACITY); + if (capacity < 0) + return capacity; + + voltage = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_VOLTAGE); + if (voltage < 0) + return voltage; + + tmp = rate; + bst->battery_present_rate = abs((s32)tmp); + + state = 0; + if ((s32) tmp > 0) + state |= ACPI_BATTERY_STATE_CHARGING; + else if ((s32) tmp < 0) + state |= ACPI_BATTERY_STATE_DISCHARGING; + bst->battery_state = state; + + bst->battery_remaining_capacity = capacity; + bst->battery_present_voltage = voltage; + + return 0; +} + +static int mshw0011_adp_psr(struct mshw0011_data *cdata) +{ + return i2c_smbus_read_byte_data(cdata->adp1, MSHW0011_ADP1_REG_PSR); +} + +static int mshw0011_isr(struct mshw0011_data *cdata) +{ + struct bst bst; + struct bix bix; + int ret; + bool status, bat_status; + + ret = mshw0011_adp_psr(cdata); + if (ret < 0) + return ret; + + status = ret; + if (status != cdata->charging) + mshw0011_notify(cdata, cdata->notify_mask, + MSHW0011_NOTIFY_ADP1, &ret); + + cdata->charging = status; + + ret = mshw0011_bst(cdata, &bst); + if (ret < 0) + return ret; + + bat_status = bst.battery_state; + if (bat_status != cdata->bat_charging) + mshw0011_notify(cdata, cdata->notify_mask, + MSHW0011_NOTIFY_BAT0_BST, &ret); + + cdata->bat_charging = bat_status; + + ret = mshw0011_bix(cdata, &bix); + if (ret < 0) + return ret; + + if (bix.last_full_charg_capacity != cdata->full_capacity) + mshw0011_notify(cdata, cdata->notify_mask, + MSHW0011_NOTIFY_BAT0_BIX, &ret); + + cdata->full_capacity = bix.last_full_charg_capacity; + + return 0; +} + +static int mshw0011_poll_task(void *data) +{ + struct mshw0011_data *cdata = data; + int ret = 0; + + cdata->kthread_running = true; + + set_freezable(); + + while (!kthread_should_stop()) { + schedule_timeout_interruptible(SURFACE_3_POLL_INTERVAL); + try_to_freeze(); + ret = mshw0011_isr(data); + if (ret) + break; + } + + cdata->kthread_running = false; + return ret; +} + +static acpi_status +mshw0011_space_handler(u32 function, acpi_physical_address command, + u32 bits, u64 *value64, + void *handler_context, void *region_context) +{ + struct gsb_buffer *gsb = (struct gsb_buffer *)value64; + struct mshw0011_handler_data *data = handler_context; + struct acpi_connection_info *info = &data->info; + struct acpi_resource_i2c_serialbus *sb; + struct i2c_client *client = data->client; + struct mshw0011_data *cdata = i2c_get_clientdata(client); + struct acpi_resource *ares; + u32 accessor_type = function >> 16; + acpi_status ret; + int status = 1; + + ret = acpi_buffer_to_resource(info->connection, info->length, &ares); + if (ACPI_FAILURE(ret)) + return ret; + + if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { + ret = AE_BAD_PARAMETER; + goto err; + } + + sb = &ares->data.i2c_serial_bus; + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { + ret = AE_BAD_PARAMETER; + goto err; + } + + if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) { + ret = AE_BAD_PARAMETER; + goto err; + } + + if (gsb->cmd.arg0 == MSHW0011_CMD_DEST_ADP1 && + gsb->cmd.arg1 == MSHW0011_CMD_ADP1_PSR) { + status = mshw0011_adp_psr(cdata); + if (status >= 0) { + ret = AE_OK; + goto out; + } else { + ret = AE_ERROR; + goto err; + } + } + + if (gsb->cmd.arg0 != MSHW0011_CMD_DEST_BAT0) { + ret = AE_BAD_PARAMETER; + goto err; + } + + switch (gsb->cmd.arg1) { + case MSHW0011_CMD_BAT0_STA: + break; + case MSHW0011_CMD_BAT0_BIX: + ret = mshw0011_bix(cdata, &gsb->bix); + break; + case MSHW0011_CMD_BAT0_BTP: + cdata->trip_point = gsb->cmd.arg2; + break; + case MSHW0011_CMD_BAT0_BST: + ret = mshw0011_bst(cdata, &gsb->bst); + break; + default: + dev_info(&cdata->bat0->dev, "command(0x%02x) is not supported.\n", gsb->cmd.arg1); + ret = AE_BAD_PARAMETER; + goto err; + } + + out: + gsb->ret = status; + gsb->status = 0; + + err: + ACPI_FREE(ares); + return ret; +} + +static int mshw0011_install_space_handler(struct i2c_client *client) +{ + acpi_handle handle; + struct mshw0011_handler_data *data; + acpi_status status; + + handle = ACPI_HANDLE(&client->dev); + if (!handle) + return -ENODEV; + + data = kzalloc(sizeof(struct mshw0011_handler_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + status = acpi_bus_attach_private_data(handle, (void *)data); + if (ACPI_FAILURE(status)) { + kfree(data); + return -ENOMEM; + } + + status = acpi_install_address_space_handler(handle, + ACPI_ADR_SPACE_GSBUS, + &mshw0011_space_handler, + NULL, + data); + if (ACPI_FAILURE(status)) { + dev_err(&client->dev, "Error installing i2c space handler\n"); + acpi_bus_detach_private_data(handle); + kfree(data); + return -ENOMEM; + } + + acpi_walk_dep_device_list(handle); + return 0; +} + +static void mshw0011_remove_space_handler(struct i2c_client *client) +{ + struct mshw0011_handler_data *data; + acpi_handle handle; + acpi_status status; + + handle = ACPI_HANDLE(&client->dev); + if (!handle) + return; + + acpi_remove_address_space_handler(handle, + ACPI_ADR_SPACE_GSBUS, + &mshw0011_space_handler); + + status = acpi_bus_get_private_data(handle, (void **)&data); + if (ACPI_SUCCESS(status)) + kfree(data); + + acpi_bus_detach_private_data(handle); +} + +static int mshw0011_probe(struct i2c_client *client) +{ + struct i2c_board_info board_info; + struct device *dev = &client->dev; + struct i2c_client *bat0; + struct mshw0011_data *data; + int error, mask; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->adp1 = client; + i2c_set_clientdata(client, data); + + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "MSHW0011-bat0", I2C_NAME_SIZE); + + bat0 = i2c_acpi_new_device(dev, 1, &board_info); + if (!bat0) + return -ENOMEM; + + data->bat0 = bat0; + i2c_set_clientdata(bat0, data); + + error = mshw0011_notify(data, 1, MSHW0011_NOTIFY_GET_VERSION, &mask); + if (error) + goto out_err; + + data->notify_mask = mask == MSHW0011_EV_2_5_MASK; + + data->poll_task = kthread_run(mshw0011_poll_task, data, "mshw0011_adp"); + if (IS_ERR(data->poll_task)) { + error = PTR_ERR(data->poll_task); + dev_err(&client->dev, "Unable to run kthread err %d\n", error); + goto out_err; + } + + error = mshw0011_install_space_handler(client); + if (error) + goto out_err; + + return 0; + +out_err: + if (data->kthread_running) + kthread_stop(data->poll_task); + i2c_unregister_device(data->bat0); + return error; +} + +static int mshw0011_remove(struct i2c_client *client) +{ + struct mshw0011_data *cdata = i2c_get_clientdata(client); + + mshw0011_remove_space_handler(client); + + if (cdata->kthread_running) + kthread_stop(cdata->poll_task); + + i2c_unregister_device(cdata->bat0); + + return 0; +} + +static const struct acpi_device_id mshw0011_acpi_match[] = { + { "MSHW0011", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match); + +static struct i2c_driver mshw0011_driver = { + .probe_new = mshw0011_probe, + .remove = mshw0011_remove, + .driver = { + .name = "mshw0011", + .acpi_match_table = mshw0011_acpi_match, + }, +}; +module_i2c_driver(mshw0011_driver); + +MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); +MODULE_DESCRIPTION("mshw0011 driver"); +MODULE_LICENSE("GPL v2"); |