Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'platform-drivers-x86-v6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform drivers updates from Hans de Goede:

- asus-wmi: Add support for vivobook fan profiles

- dell-laptop: Add knobs to change battery charge settings

- lg-laptop: Add operation region support

- intel-uncore-freq: Add support for efficiency latency control

- intel/ifs: Add SBAF test support

- intel/pmc: Ignore all LTRs during suspend

- platform/surface: Support for arm64 based Surface devices

- wmi: Pass event data directly to legacy notify handlers

- x86/platform/geode: switch GPIO buttons and LEDs to software
properties

- bunch of small cleanups, fixes, hw-id additions, etc.

* tag 'platform-drivers-x86-v6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (65 commits)
MAINTAINERS: adjust file entry in INTEL MID PLATFORM
platform/x86: x86-android-tablets: Adjust Xiaomi Pad 2 bottom bezel touch buttons LED
platform/mellanox: mlxbf-pmc: fix lockdep warning
platform/x86/amd: pmf: Add quirk for TUF Gaming A14
platform/x86: touchscreen_dmi: add nanote-next quirk
platform/x86: asus-wmi: don't fail if platform_profile already registered
platform/x86: asus-wmi: add debug print in more key places
platform/x86: intel_scu_wdt: Move intel_scu_wdt.h to x86 subfolder
platform/x86: intel_scu_ipc: Move intel_scu_ipc.h out of arch/x86/include/asm
MAINTAINERS: Add Intel MID section
platform/x86: panasonic-laptop: Add support for programmable buttons
platform/olpc: Remove redundant null pointer checks in olpc_ec_setup_debugfs()
platform/x86: intel/pmc: Ignore all LTRs during suspend
platform/x86: wmi: Call both legacy and WMI driver notify handlers
platform/x86: wmi: Merge get_event_data() with wmi_get_notify_data()
platform/x86: wmi: Remove wmi_get_event_data()
platform/x86: wmi: Pass event data directly to legacy notify handlers
platform/x86: thinkpad_acpi: Fix uninitialized symbol 's' warning
platform/x86: x86-android-tablets: Fix spelling in the comments
platform/x86: ideapad-laptop: Make the scope_guard() clear of its scope
...

+2723 -1060
+59
Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst
··· 113 113 114 114 Support for "current_freq_khz" is available only at each fabric cluster 115 115 level (i.e., in uncore* directory). 116 + 117 + Efficiency vs. Latency Tradeoff 118 + ------------------------------- 119 + 120 + The Efficiency Latency Control (ELC) feature improves performance 121 + per watt. With this feature hardware power management algorithms 122 + optimize trade-off between latency and power consumption. For some 123 + latency sensitive workloads further tuning can be done by SW to 124 + get desired performance. 125 + 126 + The hardware monitors the average CPU utilization across all cores 127 + in a power domain at regular intervals and decides an uncore frequency. 128 + While this may result in the best performance per watt, workload may be 129 + expecting higher performance at the expense of power. Consider an 130 + application that intermittently wakes up to perform memory reads on an 131 + otherwise idle system. In such cases, if hardware lowers uncore 132 + frequency, then there may be delay in ramp up of frequency to meet 133 + target performance. 134 + 135 + The ELC control defines some parameters which can be changed from SW. 136 + If the average CPU utilization is below a user-defined threshold 137 + (elc_low_threshold_percent attribute below), the user-defined uncore 138 + floor frequency will be used (elc_floor_freq_khz attribute below) 139 + instead of hardware calculated minimum. 140 + 141 + Similarly in high load scenario where the CPU utilization goes above 142 + the high threshold value (elc_high_threshold_percent attribute below) 143 + instead of jumping to maximum uncore frequency, frequency is increased 144 + in 100MHz steps. This avoids consuming unnecessarily high power 145 + immediately with CPU utilization spikes. 146 + 147 + Attributes for efficiency latency control: 148 + 149 + ``elc_floor_freq_khz`` 150 + This attribute is used to get/set the efficiency latency floor frequency. 151 + If this variable is lower than the 'min_freq_khz', it is ignored by 152 + the firmware. 153 + 154 + ``elc_low_threshold_percent`` 155 + This attribute is used to get/set the efficiency latency control low 156 + threshold. This attribute is in percentages of CPU utilization. 157 + 158 + ``elc_high_threshold_percent`` 159 + This attribute is used to get/set the efficiency latency control high 160 + threshold. This attribute is in percentages of CPU utilization. 161 + 162 + ``elc_high_threshold_enable`` 163 + This attribute is used to enable/disable the efficiency latency control 164 + high threshold. Write '1' to enable, '0' to disable. 165 + 166 + Example system configuration below, which does following: 167 + * when CPU utilization is less than 10%: sets uncore frequency to 800MHz 168 + * when CPU utilization is higher than 95%: increases uncore frequency in 169 + 100MHz steps, until power limit is reached 170 + 171 + elc_floor_freq_khz:800000 172 + elc_high_threshold_percent:95 173 + elc_high_threshold_enable:1 174 + elc_low_threshold_percent:10
+47
Documentation/devicetree/bindings/platform/microsoft,surface-sam.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/platform/microsoft,surface-sam.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Surface System Aggregator Module (SAM, SSAM) 8 + 9 + maintainers: 10 + - Konrad Dybcio <konradybcio@kernel.org> 11 + 12 + description: | 13 + Surface devices use a standardized embedded controller to let the 14 + operating system interface with various hardware functions. The 15 + specific functionalities are modeled as subdevices and matched on 16 + five levels: domain, category, target, instance and function. 17 + 18 + properties: 19 + compatible: 20 + const: microsoft,surface-sam 21 + 22 + interrupts: 23 + maxItems: 1 24 + 25 + current-speed: true 26 + 27 + required: 28 + - compatible 29 + - interrupts 30 + 31 + additionalProperties: false 32 + 33 + examples: 34 + - | 35 + #include <dt-bindings/interrupt-controller/irq.h> 36 + uart { 37 + embedded-controller { 38 + compatible = "microsoft,surface-sam"; 39 + 40 + interrupts-extended = <&tlmm 91 IRQ_TYPE_EDGE_RISING>; 41 + 42 + pinctrl-0 = <&ssam_state>; 43 + pinctrl-names = "default"; 44 + 45 + current-speed = <4000000>; 46 + }; 47 + };
+1 -1
Documentation/devicetree/bindings/serial/serial.yaml
··· 88 88 TX FIFO threshold configuration (in bytes). 89 89 90 90 patternProperties: 91 - "^(bluetooth|bluetooth-gnss|gnss|gps|mcu|onewire)$": 91 + "^(bluetooth|bluetooth-gnss|embedded-controller|gnss|gps|mcu|onewire)$": 92 92 if: 93 93 type: object 94 94 then:
+21 -2
MAINTAINERS
··· 11552 11552 F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update 11553 11553 F: drivers/fpga/intel-m10-bmc-sec-update.c 11554 11554 11555 + INTEL MID (Mobile Internet Device) PLATFORM 11556 + M: Andy Shevchenko <andy@kernel.org> 11557 + L: linux-kernel@vger.kernel.org 11558 + S: Supported 11559 + F: arch/x86/include/asm/intel-mid.h 11560 + F: arch/x86/pci/intel_mid_pci.c 11561 + F: arch/x86/platform/intel-mid/ 11562 + F: drivers/extcon/extcon-intel-mrfld.c 11563 + F: drivers/iio/adc/intel_mrfld_adc.c 11564 + F: drivers/mfd/intel_soc_pmic_mrfld.c 11565 + F: drivers/platform/x86/intel/mrfld_pwrbtn.c 11566 + F: drivers/platform/x86/intel_scu_* 11567 + F: drivers/staging/media/atomisp/ 11568 + F: drivers/watchdog/intel-mid_wdt.c 11569 + F: include/linux/mfd/intel_soc_pmic_mrfld.h 11570 + F: include/linux/platform_data/x86/intel-mid_wdt.h 11571 + F: include/linux/platform_data/x86/intel_scu_ipc.h 11572 + 11555 11573 INTEL P-Unit IPC DRIVER 11556 11574 M: Zha Qipeng <qipeng.zha@intel.com> 11557 11575 L: platform-driver-x86@vger.kernel.org ··· 11632 11614 INTEL SCU DRIVERS 11633 11615 M: Mika Westerberg <mika.westerberg@linux.intel.com> 11634 11616 S: Maintained 11635 - F: arch/x86/include/asm/intel_scu_ipc.h 11636 11617 F: drivers/platform/x86/intel_scu_* 11618 + F: include/linux/platform_data/x86/intel_scu_ipc.h 11637 11619 11638 11620 INTEL SDSI DRIVER 11639 11621 M: David E. Box <david.e.box@linux.intel.com> ··· 11708 11690 INTEL VENDOR SPECIFIC EXTENDED CAPABILITIES DRIVER 11709 11691 M: David E. Box <david.e.box@linux.intel.com> 11710 11692 S: Supported 11711 - F: drivers/platform/x86/intel/vsec.* 11693 + F: drivers/platform/x86/intel/vsec.c 11694 + F: include/linux/intel_vsec.h 11712 11695 11713 11696 INTEL VIRTUAL BUTTON DRIVER 11714 11697 M: AceLan Kao <acelan.kao@canonical.com>
+6
arch/x86/Kconfig
··· 3076 3076 - AC adapter status updates 3077 3077 - Battery status updates 3078 3078 3079 + config GEODE_COMMON 3080 + bool 3081 + 3079 3082 config ALIX 3080 3083 bool "PCEngines ALIX System Support (LED setup)" 3081 3084 select GPIOLIB 3085 + select GEODE_COMMON 3082 3086 help 3083 3087 This option enables system support for the PCEngines ALIX. 3084 3088 At present this just sets up LEDs for GPIO control on ··· 3097 3093 config NET5501 3098 3094 bool "Soekris Engineering net5501 System Support (LEDS, GPIO, etc)" 3099 3095 select GPIOLIB 3096 + select GEODE_COMMON 3100 3097 help 3101 3098 This option enables system support for the Soekris Engineering net5501. 3102 3099 3103 3100 config GEOS 3104 3101 bool "Traverse Technologies GEOS System Support (LEDS, GPIO, etc)" 3105 3102 select GPIOLIB 3103 + select GEODE_COMMON 3106 3104 depends on DMI 3107 3105 help 3108 3106 This option enables system support for the Traverse Technologies GEOS.
+2 -2
arch/x86/include/asm/intel_scu_ipc.h include/linux/platform_data/x86/intel_scu_ipc.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _ASM_X86_INTEL_SCU_IPC_H_ 3 - #define _ASM_X86_INTEL_SCU_IPC_H_ 2 + #ifndef __PLATFORM_X86_INTEL_SCU_IPC_H_ 3 + #define __PLATFORM_X86_INTEL_SCU_IPC_H_ 4 4 5 5 #include <linux/ioport.h> 6 6
+1 -1
arch/x86/include/asm/intel_telemetry.h
··· 10 10 #define TELEM_MAX_EVENTS_SRAM 28 11 11 #define TELEM_MAX_OS_ALLOCATED_EVENTS 20 12 12 13 - #include <asm/intel_scu_ipc.h> 13 + #include <linux/platform_data/x86/intel_scu_ipc.h> 14 14 15 15 enum telemetry_unit { 16 16 TELEM_PSS = 0,
+2
arch/x86/include/asm/msr-index.h
··· 247 247 #define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT) 248 248 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4 249 249 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) 250 + #define MSR_INTEGRITY_CAPS_SBAF_BIT 8 251 + #define MSR_INTEGRITY_CAPS_SBAF BIT(MSR_INTEGRITY_CAPS_SBAF_BIT) 250 252 #define MSR_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9) 251 253 252 254 #define MSR_LBR_NHM_FROM 0x00000680
+1
arch/x86/platform/geode/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 + obj-$(CONFIG_GEODE_COMMON) += geode-common.o 2 3 obj-$(CONFIG_ALIX) += alix.o 3 4 obj-$(CONFIG_NET5501) += net5501.o 4 5 obj-$(CONFIG_GEOS) += geos.o
+8 -74
arch/x86/platform/geode/alix.c
··· 18 18 #include <linux/io.h> 19 19 #include <linux/string.h> 20 20 #include <linux/moduleparam.h> 21 - #include <linux/leds.h> 22 - #include <linux/platform_device.h> 23 - #include <linux/input.h> 24 - #include <linux/gpio_keys.h> 25 - #include <linux/gpio/machine.h> 26 21 #include <linux/dmi.h> 27 22 28 23 #include <asm/geode.h> 24 + 25 + #include "geode-common.h" 29 26 30 27 #define BIOS_SIGNATURE_TINYBIOS 0xf0000 31 28 #define BIOS_SIGNATURE_COREBOOT 0x500 ··· 38 41 /* FIXME: Award bios is not automatically detected as Alix platform */ 39 42 MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); 40 43 41 - static struct gpio_keys_button alix_gpio_buttons[] = { 42 - { 43 - .code = KEY_RESTART, 44 - .gpio = 24, 45 - .active_low = 1, 46 - .desc = "Reset button", 47 - .type = EV_KEY, 48 - .wakeup = 0, 49 - .debounce_interval = 100, 50 - .can_disable = 0, 51 - } 52 - }; 53 - static struct gpio_keys_platform_data alix_buttons_data = { 54 - .buttons = alix_gpio_buttons, 55 - .nbuttons = ARRAY_SIZE(alix_gpio_buttons), 56 - .poll_interval = 20, 57 - }; 58 - 59 - static struct platform_device alix_buttons_dev = { 60 - .name = "gpio-keys-polled", 61 - .id = 1, 62 - .dev = { 63 - .platform_data = &alix_buttons_data, 64 - } 65 - }; 66 - 67 - static struct gpio_led alix_leds[] = { 68 - { 69 - .name = "alix:1", 70 - .default_trigger = "default-on", 71 - }, 72 - { 73 - .name = "alix:2", 74 - .default_trigger = "default-off", 75 - }, 76 - { 77 - .name = "alix:3", 78 - .default_trigger = "default-off", 79 - }, 80 - }; 81 - 82 - static struct gpio_led_platform_data alix_leds_data = { 83 - .num_leds = ARRAY_SIZE(alix_leds), 84 - .leds = alix_leds, 85 - }; 86 - 87 - static struct gpiod_lookup_table alix_leds_gpio_table = { 88 - .dev_id = "leds-gpio", 89 - .table = { 90 - /* The Geode GPIOs should be on the CS5535 companion chip */ 91 - GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_LOW), 92 - GPIO_LOOKUP_IDX("cs5535-gpio", 25, NULL, 1, GPIO_ACTIVE_LOW), 93 - GPIO_LOOKUP_IDX("cs5535-gpio", 27, NULL, 2, GPIO_ACTIVE_LOW), 94 - { } 95 - }, 96 - }; 97 - 98 - static struct platform_device alix_leds_dev = { 99 - .name = "leds-gpio", 100 - .id = -1, 101 - .dev.platform_data = &alix_leds_data, 102 - }; 103 - 104 - static struct platform_device *alix_devs[] __initdata = { 105 - &alix_buttons_dev, 106 - &alix_leds_dev, 44 + static const struct geode_led alix_leds[] __initconst = { 45 + { 6, true }, 46 + { 25, false }, 47 + { 27, false }, 107 48 }; 108 49 109 50 static void __init register_alix(void) 110 51 { 111 - /* Setup LED control through leds-gpio driver */ 112 - gpiod_add_lookup_table(&alix_leds_gpio_table); 113 - platform_add_devices(alix_devs, ARRAY_SIZE(alix_devs)); 52 + geode_create_restart_key(24); 53 + geode_create_leds("alix", alix_leds, ARRAY_SIZE(alix_leds)); 114 54 } 115 55 116 56 static bool __init alix_present(unsigned long bios_phys,
+178
arch/x86/platform/geode/geode-common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Shared helpers to register GPIO-connected buttons and LEDs 4 + * on AMD Geode boards. 5 + */ 6 + 7 + #include <linux/err.h> 8 + #include <linux/gpio/machine.h> 9 + #include <linux/gpio/property.h> 10 + #include <linux/input.h> 11 + #include <linux/leds.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/slab.h> 14 + 15 + #include "geode-common.h" 16 + 17 + static const struct software_node geode_gpiochip_node = { 18 + .name = "cs5535-gpio", 19 + }; 20 + 21 + static const struct property_entry geode_gpio_keys_props[] = { 22 + PROPERTY_ENTRY_U32("poll-interval", 20), 23 + { } 24 + }; 25 + 26 + static const struct software_node geode_gpio_keys_node = { 27 + .name = "geode-gpio-keys", 28 + .properties = geode_gpio_keys_props, 29 + }; 30 + 31 + static struct property_entry geode_restart_key_props[] = { 32 + { /* Placeholder for GPIO property */ }, 33 + PROPERTY_ENTRY_U32("linux,code", KEY_RESTART), 34 + PROPERTY_ENTRY_STRING("label", "Reset button"), 35 + PROPERTY_ENTRY_U32("debounce-interval", 100), 36 + { } 37 + }; 38 + 39 + static const struct software_node geode_restart_key_node = { 40 + .parent = &geode_gpio_keys_node, 41 + .properties = geode_restart_key_props, 42 + }; 43 + 44 + static const struct software_node *geode_gpio_keys_swnodes[] __initconst = { 45 + &geode_gpiochip_node, 46 + &geode_gpio_keys_node, 47 + &geode_restart_key_node, 48 + NULL 49 + }; 50 + 51 + /* 52 + * Creates gpio-keys-polled device for the restart key. 53 + * 54 + * Note that it needs to be called first, before geode_create_leds(), 55 + * because it registers gpiochip software node used by both gpio-keys and 56 + * leds-gpio devices. 57 + */ 58 + int __init geode_create_restart_key(unsigned int pin) 59 + { 60 + struct platform_device_info keys_info = { 61 + .name = "gpio-keys-polled", 62 + .id = 1, 63 + }; 64 + struct platform_device *pd; 65 + int err; 66 + 67 + geode_restart_key_props[0] = PROPERTY_ENTRY_GPIO("gpios", 68 + &geode_gpiochip_node, 69 + pin, GPIO_ACTIVE_LOW); 70 + 71 + err = software_node_register_node_group(geode_gpio_keys_swnodes); 72 + if (err) { 73 + pr_err("failed to register gpio-keys software nodes: %d\n", err); 74 + return err; 75 + } 76 + 77 + keys_info.fwnode = software_node_fwnode(&geode_gpio_keys_node); 78 + 79 + pd = platform_device_register_full(&keys_info); 80 + err = PTR_ERR_OR_ZERO(pd); 81 + if (err) { 82 + pr_err("failed to create gpio-keys device: %d\n", err); 83 + software_node_unregister_node_group(geode_gpio_keys_swnodes); 84 + return err; 85 + } 86 + 87 + return 0; 88 + } 89 + 90 + static const struct software_node geode_gpio_leds_node = { 91 + .name = "geode-leds", 92 + }; 93 + 94 + #define MAX_LEDS 3 95 + 96 + int __init geode_create_leds(const char *label, const struct geode_led *leds, 97 + unsigned int n_leds) 98 + { 99 + const struct software_node *group[MAX_LEDS + 2] = { 0 }; 100 + struct software_node *swnodes; 101 + struct property_entry *props; 102 + struct platform_device_info led_info = { 103 + .name = "leds-gpio", 104 + .id = PLATFORM_DEVID_NONE, 105 + }; 106 + struct platform_device *led_dev; 107 + const char *node_name; 108 + int err; 109 + int i; 110 + 111 + if (n_leds > MAX_LEDS) { 112 + pr_err("%s: too many LEDs\n", __func__); 113 + return -EINVAL; 114 + } 115 + 116 + swnodes = kcalloc(n_leds, sizeof(*swnodes), GFP_KERNEL); 117 + if (!swnodes) 118 + return -ENOMEM; 119 + 120 + /* 121 + * Each LED is represented by 3 properties: "gpios", 122 + * "linux,default-trigger", and am empty terminator. 123 + */ 124 + props = kcalloc(n_leds * 3, sizeof(*props), GFP_KERNEL); 125 + if (!props) { 126 + err = -ENOMEM; 127 + goto err_free_swnodes; 128 + } 129 + 130 + group[0] = &geode_gpio_leds_node; 131 + for (i = 0; i < n_leds; i++) { 132 + node_name = kasprintf(GFP_KERNEL, "%s:%d", label, i); 133 + if (!node_name) { 134 + err = -ENOMEM; 135 + goto err_free_names; 136 + } 137 + 138 + props[i * 3 + 0] = 139 + PROPERTY_ENTRY_GPIO("gpios", &geode_gpiochip_node, 140 + leds[i].pin, GPIO_ACTIVE_LOW); 141 + props[i * 3 + 1] = 142 + PROPERTY_ENTRY_STRING("linux,default-trigger", 143 + leds[i].default_on ? 144 + "default-on" : "default-off"); 145 + /* props[i * 3 + 2] is an empty terminator */ 146 + 147 + swnodes[i] = SOFTWARE_NODE(node_name, &props[i * 3], 148 + &geode_gpio_leds_node); 149 + group[i + 1] = &swnodes[i]; 150 + } 151 + 152 + err = software_node_register_node_group(group); 153 + if (err) { 154 + pr_err("failed to register LED software nodes: %d\n", err); 155 + goto err_free_names; 156 + } 157 + 158 + led_info.fwnode = software_node_fwnode(&geode_gpio_leds_node); 159 + 160 + led_dev = platform_device_register_full(&led_info); 161 + err = PTR_ERR_OR_ZERO(led_dev); 162 + if (err) { 163 + pr_err("failed to create LED device: %d\n", err); 164 + goto err_unregister_group; 165 + } 166 + 167 + return 0; 168 + 169 + err_unregister_group: 170 + software_node_unregister_node_group(group); 171 + err_free_names: 172 + while (--i >= 0) 173 + kfree(swnodes[i].name); 174 + kfree(props); 175 + err_free_swnodes: 176 + kfree(swnodes); 177 + return err; 178 + }
+21
arch/x86/platform/geode/geode-common.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Shared helpers to register GPIO-connected buttons and LEDs 4 + * on AMD Geode boards. 5 + */ 6 + 7 + #ifndef __PLATFORM_GEODE_COMMON_H 8 + #define __PLATFORM_GEODE_COMMON_H 9 + 10 + #include <linux/property.h> 11 + 12 + struct geode_led { 13 + unsigned int pin; 14 + bool default_on; 15 + }; 16 + 17 + int geode_create_restart_key(unsigned int pin); 18 + int geode_create_leds(const char *label, const struct geode_led *leds, 19 + unsigned int n_leds); 20 + 21 + #endif /* __PLATFORM_GEODE_COMMON_H */
+7 -73
arch/x86/platform/geode/geos.c
··· 16 16 #include <linux/init.h> 17 17 #include <linux/io.h> 18 18 #include <linux/string.h> 19 - #include <linux/leds.h> 20 - #include <linux/platform_device.h> 21 - #include <linux/input.h> 22 - #include <linux/gpio_keys.h> 23 - #include <linux/gpio/machine.h> 24 19 #include <linux/dmi.h> 25 20 26 21 #include <asm/geode.h> 27 22 28 - static struct gpio_keys_button geos_gpio_buttons[] = { 29 - { 30 - .code = KEY_RESTART, 31 - .gpio = 3, 32 - .active_low = 1, 33 - .desc = "Reset button", 34 - .type = EV_KEY, 35 - .wakeup = 0, 36 - .debounce_interval = 100, 37 - .can_disable = 0, 38 - } 39 - }; 40 - static struct gpio_keys_platform_data geos_buttons_data = { 41 - .buttons = geos_gpio_buttons, 42 - .nbuttons = ARRAY_SIZE(geos_gpio_buttons), 43 - .poll_interval = 20, 44 - }; 23 + #include "geode-common.h" 45 24 46 - static struct platform_device geos_buttons_dev = { 47 - .name = "gpio-keys-polled", 48 - .id = 1, 49 - .dev = { 50 - .platform_data = &geos_buttons_data, 51 - } 52 - }; 53 - 54 - static struct gpio_led geos_leds[] = { 55 - { 56 - .name = "geos:1", 57 - .default_trigger = "default-on", 58 - }, 59 - { 60 - .name = "geos:2", 61 - .default_trigger = "default-off", 62 - }, 63 - { 64 - .name = "geos:3", 65 - .default_trigger = "default-off", 66 - }, 67 - }; 68 - 69 - static struct gpio_led_platform_data geos_leds_data = { 70 - .num_leds = ARRAY_SIZE(geos_leds), 71 - .leds = geos_leds, 72 - }; 73 - 74 - static struct gpiod_lookup_table geos_leds_gpio_table = { 75 - .dev_id = "leds-gpio", 76 - .table = { 77 - /* The Geode GPIOs should be on the CS5535 companion chip */ 78 - GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_LOW), 79 - GPIO_LOOKUP_IDX("cs5535-gpio", 25, NULL, 1, GPIO_ACTIVE_LOW), 80 - GPIO_LOOKUP_IDX("cs5535-gpio", 27, NULL, 2, GPIO_ACTIVE_LOW), 81 - { } 82 - }, 83 - }; 84 - 85 - static struct platform_device geos_leds_dev = { 86 - .name = "leds-gpio", 87 - .id = -1, 88 - .dev.platform_data = &geos_leds_data, 89 - }; 90 - 91 - static struct platform_device *geos_devs[] __initdata = { 92 - &geos_buttons_dev, 93 - &geos_leds_dev, 25 + static const struct geode_led geos_leds[] __initconst = { 26 + { 6, true }, 27 + { 25, false }, 28 + { 27, false }, 94 29 }; 95 30 96 31 static void __init register_geos(void) 97 32 { 98 - /* Setup LED control through leds-gpio driver */ 99 - gpiod_add_lookup_table(&geos_leds_gpio_table); 100 - platform_add_devices(geos_devs, ARRAY_SIZE(geos_devs)); 33 + geode_create_restart_key(3); 34 + geode_create_leds("geos", geos_leds, ARRAY_SIZE(geos_leds)); 101 35 } 102 36 103 37 static int __init geos_init(void)
+7 -62
arch/x86/platform/geode/net5501.c
··· 16 16 #include <linux/init.h> 17 17 #include <linux/io.h> 18 18 #include <linux/string.h> 19 - #include <linux/leds.h> 20 - #include <linux/platform_device.h> 21 19 #include <linux/input.h> 22 - #include <linux/gpio_keys.h> 23 20 #include <linux/gpio/machine.h> 21 + #include <linux/gpio/property.h> 24 22 25 23 #include <asm/geode.h> 24 + 25 + #include "geode-common.h" 26 26 27 27 #define BIOS_REGION_BASE 0xffff0000 28 28 #define BIOS_REGION_SIZE 0x00010000 29 29 30 - static struct gpio_keys_button net5501_gpio_buttons[] = { 31 - { 32 - .code = KEY_RESTART, 33 - .gpio = 24, 34 - .active_low = 1, 35 - .desc = "Reset button", 36 - .type = EV_KEY, 37 - .wakeup = 0, 38 - .debounce_interval = 100, 39 - .can_disable = 0, 40 - } 41 - }; 42 - static struct gpio_keys_platform_data net5501_buttons_data = { 43 - .buttons = net5501_gpio_buttons, 44 - .nbuttons = ARRAY_SIZE(net5501_gpio_buttons), 45 - .poll_interval = 20, 46 - }; 47 - 48 - static struct platform_device net5501_buttons_dev = { 49 - .name = "gpio-keys-polled", 50 - .id = 1, 51 - .dev = { 52 - .platform_data = &net5501_buttons_data, 53 - } 54 - }; 55 - 56 - static struct gpio_led net5501_leds[] = { 57 - { 58 - .name = "net5501:1", 59 - .default_trigger = "default-on", 60 - }, 61 - }; 62 - 63 - static struct gpio_led_platform_data net5501_leds_data = { 64 - .num_leds = ARRAY_SIZE(net5501_leds), 65 - .leds = net5501_leds, 66 - }; 67 - 68 - static struct gpiod_lookup_table net5501_leds_gpio_table = { 69 - .dev_id = "leds-gpio", 70 - .table = { 71 - /* The Geode GPIOs should be on the CS5535 companion chip */ 72 - GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_HIGH), 73 - { } 74 - }, 75 - }; 76 - 77 - static struct platform_device net5501_leds_dev = { 78 - .name = "leds-gpio", 79 - .id = -1, 80 - .dev.platform_data = &net5501_leds_data, 81 - }; 82 - 83 - static struct platform_device *net5501_devs[] __initdata = { 84 - &net5501_buttons_dev, 85 - &net5501_leds_dev, 30 + static const struct geode_led net5501_leds[] __initconst = { 31 + { 6, true }, 86 32 }; 87 33 88 34 static void __init register_net5501(void) 89 35 { 90 - /* Setup LED control through leds-gpio driver */ 91 - gpiod_add_lookup_table(&net5501_leds_gpio_table); 92 - platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs)); 36 + geode_create_restart_key(24); 37 + geode_create_leds("net5501", net5501_leds, ARRAY_SIZE(net5501_leds)); 93 38 } 94 39 95 40 struct net5501_board {
+2 -1
arch/x86/platform/intel-mid/intel-mid.c
··· 27 27 #include <asm/intel-mid.h> 28 28 #include <asm/io.h> 29 29 #include <asm/i8259.h> 30 - #include <asm/intel_scu_ipc.h> 31 30 #include <asm/reboot.h> 31 + 32 + #include <linux/platform_data/x86/intel_scu_ipc.h> 32 33 33 34 #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ 34 35 #define IPCMSG_COLD_RESET 0xF1
+7
drivers/hid/hid-asus.c
··· 492 492 */ 493 493 static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev) 494 494 { 495 + struct asus_drvdata *drvdata = hid_get_drvdata(hdev); 495 496 u32 value; 496 497 int ret; 497 498 498 499 if (!IS_ENABLED(CONFIG_ASUS_WMI)) 499 500 return false; 501 + 502 + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && 503 + dmi_check_system(asus_use_hid_led_dmi_ids)) { 504 + hid_info(hdev, "using HID for asus::kbd_backlight\n"); 505 + return false; 506 + } 500 507 501 508 ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 502 509 ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
+6 -16
drivers/hwmon/hp-wmi-sensors.c
··· 1597 1597 } 1598 1598 1599 1599 /* hp_wmi_notify - WMI event notification handler */ 1600 - static void hp_wmi_notify(u32 value, void *context) 1600 + static void hp_wmi_notify(union acpi_object *wobj, void *context) 1601 1601 { 1602 1602 struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {}; 1603 - struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 1604 1603 struct hp_wmi_sensors *state = context; 1605 1604 struct device *dev = &state->wdev->dev; 1606 1605 struct hp_wmi_event event = {}; 1607 1606 struct hp_wmi_info *fan_info; 1608 - union acpi_object *wobj; 1609 1607 acpi_status err; 1610 1608 int event_type; 1611 1609 u8 count; ··· 1628 1630 * HPBIOS_BIOSEvent instance. 1629 1631 */ 1630 1632 1631 - mutex_lock(&state->lock); 1632 - 1633 - err = wmi_get_event_data(value, &out); 1634 - if (ACPI_FAILURE(err)) 1635 - goto out_unlock; 1636 - 1637 - wobj = out.pointer; 1638 1633 if (!wobj) 1639 - goto out_unlock; 1634 + return; 1635 + 1636 + mutex_lock(&state->lock); 1640 1637 1641 1638 err = populate_event_from_wobj(dev, &event, wobj); 1642 1639 if (err) { 1643 1640 dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type); 1644 - goto out_free_wobj; 1641 + goto out_free; 1645 1642 } 1646 1643 1647 1644 event_type = classify_event(event.name, event.category); ··· 1661 1668 break; 1662 1669 } 1663 1670 1664 - out_free_wobj: 1665 - kfree(wobj); 1666 - 1671 + out_free: 1667 1672 devm_kfree(dev, event.name); 1668 1673 devm_kfree(dev, event.description); 1669 1674 1670 - out_unlock: 1671 1675 mutex_unlock(&state->lock); 1672 1676 } 1673 1677
+1 -2
drivers/mfd/intel_pmc_bxt.c
··· 23 23 #include <linux/module.h> 24 24 #include <linux/platform_device.h> 25 25 #include <linux/platform_data/itco_wdt.h> 26 - 27 - #include <asm/intel_scu_ipc.h> 26 + #include <linux/platform_data/x86/intel_scu_ipc.h> 28 27 29 28 /* Residency with clock rate at 19.2MHz to usecs */ 30 29 #define S0IX_RESIDENCY_IN_USECS(d, s) \
+1 -2
drivers/mfd/intel_soc_pmic_bxtwc.c
··· 15 15 #include <linux/mfd/intel_soc_pmic.h> 16 16 #include <linux/mfd/intel_soc_pmic_bxtwc.h> 17 17 #include <linux/module.h> 18 - 19 - #include <asm/intel_scu_ipc.h> 18 + #include <linux/platform_data/x86/intel_scu_ipc.h> 20 19 21 20 /* PMIC device registers */ 22 21 #define REG_ADDR_MASK GENMASK(15, 8)
+1 -2
drivers/mfd/intel_soc_pmic_mrfld.c
··· 12 12 #include <linux/mfd/intel_soc_pmic.h> 13 13 #include <linux/mfd/intel_soc_pmic_mrfld.h> 14 14 #include <linux/module.h> 15 + #include <linux/platform_data/x86/intel_scu_ipc.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/regmap.h> 17 - 18 - #include <asm/intel_scu_ipc.h> 19 18 20 19 /* 21 20 * Level 2 IRQs
+5
drivers/platform/mellanox/mlxbf-pmc.c
··· 1774 1774 1775 1775 /* "event_list" sysfs to list events supported by the block */ 1776 1776 attr = &pmc->block[blk_num].attr_event_list; 1777 + sysfs_attr_init(&attr->dev_attr.attr); 1777 1778 attr->dev_attr.attr.mode = 0444; 1778 1779 attr->dev_attr.show = mlxbf_pmc_event_list_show; 1779 1780 attr->nr = blk_num; ··· 1788 1787 if (strstr(pmc->block_name[blk_num], "l3cache") || 1789 1788 ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))) { 1790 1789 attr = &pmc->block[blk_num].attr_enable; 1790 + sysfs_attr_init(&attr->dev_attr.attr); 1791 1791 attr->dev_attr.attr.mode = 0644; 1792 1792 attr->dev_attr.show = mlxbf_pmc_enable_show; 1793 1793 attr->dev_attr.store = mlxbf_pmc_enable_store; ··· 1816 1814 /* "eventX" and "counterX" sysfs to program and read counter values */ 1817 1815 for (j = 0; j < pmc->block[blk_num].counters; ++j) { 1818 1816 attr = &pmc->block[blk_num].attr_counter[j]; 1817 + sysfs_attr_init(&attr->dev_attr.attr); 1819 1818 attr->dev_attr.attr.mode = 0644; 1820 1819 attr->dev_attr.show = mlxbf_pmc_counter_show; 1821 1820 attr->dev_attr.store = mlxbf_pmc_counter_store; ··· 1829 1826 attr = NULL; 1830 1827 1831 1828 attr = &pmc->block[blk_num].attr_event[j]; 1829 + sysfs_attr_init(&attr->dev_attr.attr); 1832 1830 attr->dev_attr.attr.mode = 0644; 1833 1831 attr->dev_attr.show = mlxbf_pmc_event_show; 1834 1832 attr->dev_attr.store = mlxbf_pmc_event_store; ··· 1865 1861 while (count > 0) { 1866 1862 --count; 1867 1863 attr = &pmc->block[blk_num].attr_event[count]; 1864 + sysfs_attr_init(&attr->dev_attr.attr); 1868 1865 attr->dev_attr.attr.mode = 0644; 1869 1866 attr->dev_attr.show = mlxbf_pmc_counter_show; 1870 1867 attr->dev_attr.store = mlxbf_pmc_counter_store;
-3
drivers/platform/olpc/olpc-ec.c
··· 332 332 struct dentry *dbgfs_dir; 333 333 334 334 dbgfs_dir = debugfs_create_dir("olpc-ec", NULL); 335 - if (IS_ERR_OR_NULL(dbgfs_dir)) 336 - return NULL; 337 - 338 335 debugfs_create_file("cmd", 0600, dbgfs_dir, NULL, &ec_dbgfs_ops); 339 336 340 337 return dbgfs_dir;
+2
drivers/platform/surface/aggregator/bus.c
··· 6 6 */ 7 7 8 8 #include <linux/device.h> 9 + #include <linux/of.h> 9 10 #include <linux/property.h> 10 11 #include <linux/slab.h> 11 12 ··· 442 441 443 442 sdev->dev.parent = parent; 444 443 sdev->dev.fwnode = fwnode_handle_get(node); 444 + sdev->dev.of_node = to_of_node(node); 445 445 446 446 status = ssam_device_add(sdev); 447 447 if (status)
+53 -14
drivers/platform/surface/aggregator/controller.c
··· 1104 1104 u64 funcs; 1105 1105 int status; 1106 1106 1107 - /* Set defaults. */ 1108 - caps->ssh_power_profile = U32_MAX; 1109 - caps->screen_on_sleep_idle_timeout = U32_MAX; 1110 - caps->screen_off_sleep_idle_timeout = U32_MAX; 1111 - caps->d3_closes_handle = false; 1112 - caps->ssh_buffer_size = U32_MAX; 1113 - 1114 1107 /* Pre-load supported DSM functions. */ 1115 1108 status = ssam_dsm_get_functions(handle, &funcs); 1116 1109 if (status) ··· 1143 1150 } 1144 1151 1145 1152 /** 1153 + * ssam_controller_caps_load_from_of() - Load controller capabilities from OF/DT. 1154 + * @dev: A pointer to the controller device 1155 + * @caps: Where to store the capabilities in. 1156 + * 1157 + * Return: Returns zero on success, a negative error code on failure. 1158 + */ 1159 + static int ssam_controller_caps_load_from_of(struct device *dev, struct ssam_controller_caps *caps) 1160 + { 1161 + /* 1162 + * Every device starting with Surface Pro X through Laptop 7 uses these 1163 + * identical values, which makes them good defaults. 1164 + */ 1165 + caps->d3_closes_handle = true; 1166 + caps->screen_on_sleep_idle_timeout = 5000; 1167 + caps->screen_off_sleep_idle_timeout = 30; 1168 + caps->ssh_buffer_size = 48; 1169 + /* TODO: figure out power profile */ 1170 + 1171 + return 0; 1172 + } 1173 + 1174 + /** 1175 + * ssam_controller_caps_load() - Load controller capabilities 1176 + * @dev: A pointer to the controller device 1177 + * @caps: Where to store the capabilities in. 1178 + * 1179 + * Return: Returns zero on success, a negative error code on failure. 1180 + */ 1181 + static int ssam_controller_caps_load(struct device *dev, struct ssam_controller_caps *caps) 1182 + { 1183 + acpi_handle handle = ACPI_HANDLE(dev); 1184 + 1185 + /* Set defaults. */ 1186 + caps->ssh_power_profile = U32_MAX; 1187 + caps->screen_on_sleep_idle_timeout = U32_MAX; 1188 + caps->screen_off_sleep_idle_timeout = U32_MAX; 1189 + caps->d3_closes_handle = false; 1190 + caps->ssh_buffer_size = U32_MAX; 1191 + 1192 + if (handle) 1193 + return ssam_controller_caps_load_from_acpi(handle, caps); 1194 + else 1195 + return ssam_controller_caps_load_from_of(dev, caps); 1196 + } 1197 + 1198 + /** 1146 1199 * ssam_controller_init() - Initialize SSAM controller. 1147 1200 * @ctrl: The controller to initialize. 1148 1201 * @serdev: The serial device representing the underlying data transport. ··· 1204 1165 int ssam_controller_init(struct ssam_controller *ctrl, 1205 1166 struct serdev_device *serdev) 1206 1167 { 1207 - acpi_handle handle = ACPI_HANDLE(&serdev->dev); 1208 1168 int status; 1209 1169 1210 1170 init_rwsem(&ctrl->lock); 1211 1171 kref_init(&ctrl->kref); 1212 1172 1213 - status = ssam_controller_caps_load_from_acpi(handle, &ctrl->caps); 1173 + status = ssam_controller_caps_load(&serdev->dev, &ctrl->caps); 1214 1174 if (status) 1215 1175 return status; 1216 1176 ··· 2754 2716 const int irqf = IRQF_ONESHOT | IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN; 2755 2717 2756 2718 gpiod = gpiod_get(dev, "ssam_wakeup-int", GPIOD_ASIS); 2757 - if (IS_ERR(gpiod)) 2758 - return PTR_ERR(gpiod); 2759 - 2760 - irq = gpiod_to_irq(gpiod); 2761 - gpiod_put(gpiod); 2719 + if (IS_ERR(gpiod)) { 2720 + irq = fwnode_irq_get(dev_fwnode(dev), 0); 2721 + } else { 2722 + irq = gpiod_to_irq(gpiod); 2723 + gpiod_put(gpiod); 2724 + } 2762 2725 2763 2726 if (irq < 0) 2764 2727 return irq;
+63 -19
drivers/platform/surface/aggregator/core.c
··· 17 17 #include <linux/kernel.h> 18 18 #include <linux/kref.h> 19 19 #include <linux/module.h> 20 + #include <linux/of.h> 21 + #include <linux/platform_device.h> 20 22 #include <linux/pm.h> 21 23 #include <linux/serdev.h> 22 24 #include <linux/sysfs.h> 25 + #include <linux/units.h> 23 26 24 27 #include <linux/surface_aggregator/controller.h> 25 28 #include <linux/surface_aggregator/device.h> ··· 302 299 }; 303 300 304 301 305 - /* -- ACPI based device setup. ---------------------------------------------- */ 302 + /* -- Serial device setup. -------------------------------------------------- */ 306 303 307 304 static acpi_status ssam_serdev_setup_via_acpi_crs(struct acpi_resource *rsc, 308 305 void *ctx) ··· 355 352 return AE_CTRL_TERMINATE; 356 353 } 357 354 358 - static acpi_status ssam_serdev_setup_via_acpi(acpi_handle handle, 359 - struct serdev_device *serdev) 355 + static int ssam_serdev_setup_via_acpi(struct serdev_device *serdev, acpi_handle handle) 360 356 { 361 - return acpi_walk_resources(handle, METHOD_NAME__CRS, 362 - ssam_serdev_setup_via_acpi_crs, serdev); 357 + acpi_status status; 358 + 359 + status = acpi_walk_resources(handle, METHOD_NAME__CRS, 360 + ssam_serdev_setup_via_acpi_crs, serdev); 361 + 362 + return status ? -ENXIO : 0; 363 363 } 364 364 365 + static int ssam_serdev_setup(struct acpi_device *ssh, struct serdev_device *serdev) 366 + { 367 + if (ssh) 368 + return ssam_serdev_setup_via_acpi(serdev, ssh->handle); 369 + 370 + /* TODO: these values may differ per board/implementation */ 371 + serdev_device_set_baudrate(serdev, 4 * HZ_PER_MHZ); 372 + serdev_device_set_flow_control(serdev, true); 373 + serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); 374 + 375 + return 0; 376 + } 365 377 366 378 /* -- Power management. ----------------------------------------------------- */ 367 379 ··· 639 621 struct device *dev = &serdev->dev; 640 622 struct acpi_device *ssh = ACPI_COMPANION(dev); 641 623 struct ssam_controller *ctrl; 642 - acpi_status astatus; 643 624 int status; 644 625 645 - status = gpiod_count(dev, NULL); 646 - if (status < 0) 647 - return dev_err_probe(dev, status, "no GPIO found\n"); 626 + if (ssh) { 627 + status = gpiod_count(dev, NULL); 628 + if (status < 0) 629 + return dev_err_probe(dev, status, "no GPIO found\n"); 648 630 649 - status = devm_acpi_dev_add_driver_gpios(dev, ssam_acpi_gpios); 650 - if (status) 651 - return status; 631 + status = devm_acpi_dev_add_driver_gpios(dev, ssam_acpi_gpios); 632 + if (status) 633 + return status; 634 + } 652 635 653 636 /* Allocate controller. */ 654 637 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); ··· 674 655 goto err_devopen; 675 656 } 676 657 677 - astatus = ssam_serdev_setup_via_acpi(ssh->handle, serdev); 678 - if (ACPI_FAILURE(astatus)) { 679 - status = dev_err_probe(dev, -ENXIO, "failed to setup serdev\n"); 658 + status = ssam_serdev_setup(ssh, serdev); 659 + if (status) { 660 + status = dev_err_probe(dev, status, "failed to setup serdev\n"); 680 661 goto err_devinit; 681 662 } 682 663 ··· 736 717 * For now let's thus default power/wakeup to false. 737 718 */ 738 719 device_set_wakeup_capable(dev, true); 739 - acpi_dev_clear_dependencies(ssh); 720 + 721 + /* 722 + * When using DT, we have to register the platform hub driver manually, 723 + * as it can't be matched based on top-level board compatible (like it 724 + * does the ACPI case). 725 + */ 726 + if (!ssh) { 727 + struct platform_device *ph_pdev = 728 + platform_device_register_simple("surface_aggregator_platform_hub", 729 + 0, NULL, 0); 730 + if (IS_ERR(ph_pdev)) 731 + return dev_err_probe(dev, PTR_ERR(ph_pdev), 732 + "Failed to register the platform hub driver\n"); 733 + } 734 + 735 + if (ssh) 736 + acpi_dev_clear_dependencies(ssh); 740 737 741 738 return 0; 742 739 ··· 817 782 device_set_wakeup_capable(&serdev->dev, false); 818 783 } 819 784 820 - static const struct acpi_device_id ssam_serial_hub_match[] = { 785 + static const struct acpi_device_id ssam_serial_hub_acpi_match[] = { 821 786 { "MSHW0084", 0 }, 822 787 { }, 823 788 }; 824 - MODULE_DEVICE_TABLE(acpi, ssam_serial_hub_match); 789 + MODULE_DEVICE_TABLE(acpi, ssam_serial_hub_acpi_match); 790 + 791 + #ifdef CONFIG_OF 792 + static const struct of_device_id ssam_serial_hub_of_match[] = { 793 + { .compatible = "microsoft,surface-sam", }, 794 + { }, 795 + }; 796 + MODULE_DEVICE_TABLE(of, ssam_serial_hub_of_match); 797 + #endif 825 798 826 799 static struct serdev_device_driver ssam_serial_hub = { 827 800 .probe = ssam_serial_hub_probe, 828 801 .remove = ssam_serial_hub_remove, 829 802 .driver = { 830 803 .name = "surface_serial_hub", 831 - .acpi_match_table = ssam_serial_hub_match, 804 + .acpi_match_table = ACPI_PTR(ssam_serial_hub_acpi_match), 805 + .of_match_table = of_match_ptr(ssam_serial_hub_of_match), 832 806 .pm = &ssam_serial_hub_pm_ops, 833 807 .shutdown = ssam_serial_hub_shutdown, 834 808 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+40 -5
drivers/platform/surface/surface_aggregator_registry.c
··· 12 12 #include <linux/acpi.h> 13 13 #include <linux/kernel.h> 14 14 #include <linux/module.h> 15 + #include <linux/of.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/property.h> 17 18 #include <linux/types.h> ··· 292 291 NULL, 293 292 }; 294 293 294 + /* Devices for Surface Laptop 7. */ 295 + static const struct software_node *ssam_node_group_sl7[] = { 296 + &ssam_node_root, 297 + &ssam_node_bat_ac, 298 + &ssam_node_bat_main, 299 + &ssam_node_tmp_perf_profile_with_fan, 300 + &ssam_node_fan_speed, 301 + &ssam_node_hid_sam_keyboard, 302 + /* TODO: evaluate thermal sensors devices when we get a driver for that */ 303 + NULL, 304 + }; 305 + 295 306 /* Devices for Surface Laptop Studio 1. */ 296 307 static const struct software_node *ssam_node_group_sls1[] = { 297 308 &ssam_node_root, ··· 393 380 394 381 /* -- SSAM platform/meta-hub driver. ---------------------------------------- */ 395 382 396 - static const struct acpi_device_id ssam_platform_hub_match[] = { 383 + static const struct acpi_device_id ssam_platform_hub_acpi_match[] = { 397 384 /* Surface Pro 4, 5, and 6 (OMBR < 0x10) */ 398 385 { "MSHW0081", (unsigned long)ssam_node_group_gen5 }, 399 386 ··· 459 446 460 447 { }, 461 448 }; 462 - MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_match); 449 + MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_acpi_match); 450 + 451 + static const struct of_device_id ssam_platform_hub_of_match[] __maybe_unused = { 452 + /* Surface Laptop 7 */ 453 + { .compatible = "microsoft,romulus13", (void *)ssam_node_group_sl7 }, 454 + { .compatible = "microsoft,romulus15", (void *)ssam_node_group_sl7 }, 455 + { }, 456 + }; 463 457 464 458 static int ssam_platform_hub_probe(struct platform_device *pdev) 465 459 { 466 460 const struct software_node **nodes; 461 + const struct of_device_id *match; 462 + struct device_node *fdt_root; 467 463 struct ssam_controller *ctrl; 468 464 struct fwnode_handle *root; 469 465 int status; 470 466 471 467 nodes = (const struct software_node **)acpi_device_get_match_data(&pdev->dev); 472 - if (!nodes) 473 - return -ENODEV; 468 + if (!nodes) { 469 + fdt_root = of_find_node_by_path("/"); 470 + if (!fdt_root) 471 + return -ENODEV; 472 + 473 + match = of_match_node(ssam_platform_hub_of_match, fdt_root); 474 + of_node_put(fdt_root); 475 + if (!match) 476 + return -ENODEV; 477 + 478 + nodes = (const struct software_node **)match->data; 479 + if (!nodes) 480 + return -ENODEV; 481 + } 474 482 475 483 /* 476 484 * As we're adding the SSAM client devices as children under this device ··· 540 506 .remove_new = ssam_platform_hub_remove, 541 507 .driver = { 542 508 .name = "surface_aggregator_platform_hub", 543 - .acpi_match_table = ssam_platform_hub_match, 509 + .acpi_match_table = ssam_platform_hub_acpi_match, 544 510 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 545 511 }, 546 512 }; 547 513 module_platform_driver(ssam_platform_hub_driver); 548 514 515 + MODULE_ALIAS("platform:surface_aggregator_platform_hub"); 549 516 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 550 517 MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module"); 551 518 MODULE_LICENSE("GPL");
+2 -1
drivers/platform/x86/Kconfig
··· 1000 1000 1001 1001 config SERIAL_MULTI_INSTANTIATE 1002 1002 tristate "Serial bus multi instantiate pseudo device driver" 1003 - depends on I2C && SPI && ACPI 1003 + depends on ACPI 1004 + depends on (I2C && !SPI) || (!I2C && SPI) || (I2C && SPI) 1004 1005 help 1005 1006 Some ACPI-based systems list multiple devices in a single ACPI 1006 1007 firmware-node. This driver will instantiate separate clients
+2 -17
drivers/platform/x86/acer-wmi.c
··· 16 16 #include <linux/init.h> 17 17 #include <linux/types.h> 18 18 #include <linux/dmi.h> 19 - #include <linux/fb.h> 20 19 #include <linux/backlight.h> 21 20 #include <linux/leds.h> 22 21 #include <linux/platform_device.h> ··· 1684 1685 1685 1686 acer_backlight_device = bd; 1686 1687 1687 - bd->props.power = FB_BLANK_UNBLANK; 1688 + bd->props.power = BACKLIGHT_POWER_ON; 1688 1689 bd->props.brightness = read_brightness(bd); 1689 1690 backlight_update_status(bd); 1690 1691 return 0; ··· 2223 2224 } 2224 2225 } 2225 2226 2226 - static void acer_wmi_notify(u32 value, void *context) 2227 + static void acer_wmi_notify(union acpi_object *obj, void *context) 2227 2228 { 2228 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 2229 - union acpi_object *obj; 2230 2229 struct event_return_value return_value; 2231 - acpi_status status; 2232 2230 u16 device_state; 2233 2231 const struct key_entry *key; 2234 2232 u32 scancode; 2235 - 2236 - status = wmi_get_event_data(value, &response); 2237 - if (status != AE_OK) { 2238 - pr_warn("bad event status 0x%x\n", status); 2239 - return; 2240 - } 2241 - 2242 - obj = (union acpi_object *)response.pointer; 2243 2233 2244 2234 if (!obj) 2245 2235 return; 2246 2236 if (obj->type != ACPI_TYPE_BUFFER) { 2247 2237 pr_warn("Unknown response received %d\n", obj->type); 2248 - kfree(obj); 2249 2238 return; 2250 2239 } 2251 2240 if (obj->buffer.length != 8) { 2252 2241 pr_warn("Unknown buffer length %d\n", obj->buffer.length); 2253 - kfree(obj); 2254 2242 return; 2255 2243 } 2256 2244 2257 2245 return_value = *((struct event_return_value *)obj->buffer.pointer); 2258 - kfree(obj); 2259 2246 2260 2247 switch (return_value.function) { 2261 2248 case WMID_HOTKEY_EVENT:
+31
drivers/platform/x86/amd/pmf/acpi.c
··· 282 282 return 0; 283 283 } 284 284 285 + static int apmf_notify_smart_pc_update(struct amd_pmf_dev *pdev, u32 val, u32 preq, u32 index) 286 + { 287 + struct amd_pmf_notify_smart_pc_update args; 288 + struct acpi_buffer params; 289 + union acpi_object *info; 290 + 291 + args.size = sizeof(args); 292 + args.pending_req = preq; 293 + args.custom_bios[index] = val; 294 + 295 + params.length = sizeof(args); 296 + params.pointer = &args; 297 + 298 + info = apmf_if_call(pdev, APMF_FUNC_NOTIFY_SMART_PC_UPDATES, &params); 299 + if (!info) 300 + return -EIO; 301 + 302 + kfree(info); 303 + dev_dbg(pdev->dev, "Notify smart pc update, val: %u\n", val); 304 + 305 + return 0; 306 + } 307 + 285 308 int apmf_get_auto_mode_def(struct amd_pmf_dev *pdev, struct apmf_auto_mode *data) 286 309 { 287 310 return apmf_if_call_store_buffer(pdev, APMF_FUNC_AUTO_MODE, data, sizeof(*data)); ··· 468 445 } 469 446 470 447 return 0; 448 + } 449 + 450 + int amd_pmf_smartpc_apply_bios_output(struct amd_pmf_dev *dev, u32 val, u32 preq, u32 idx) 451 + { 452 + if (!is_apmf_func_supported(dev, APMF_FUNC_NOTIFY_SMART_PC_UPDATES)) 453 + return -EINVAL; 454 + 455 + return apmf_notify_smart_pc_update(dev, val, preq, idx); 471 456 } 472 457 473 458 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
+13 -7
drivers/platform/x86/amd/pmf/core.c
··· 37 37 #define AMD_PMF_RESULT_CMD_UNKNOWN 0xFE 38 38 #define AMD_PMF_RESULT_FAILED 0xFF 39 39 40 - /* List of supported CPU ids */ 41 - #define AMD_CPU_ID_RMB 0x14b5 42 - #define AMD_CPU_ID_PS 0x14e8 43 - #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 44 - #define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 45 - 46 40 #define PMF_MSG_DELAY_MIN_US 50 47 41 #define RESPONSE_REGISTER_LOOP_MAX 20000 48 42 ··· 255 261 256 262 /* Get Metrics Table Address */ 257 263 if (alloc_buffer) { 258 - dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL); 264 + switch (dev->cpu_id) { 265 + case AMD_CPU_ID_PS: 266 + case AMD_CPU_ID_RMB: 267 + dev->mtable_size = sizeof(dev->m_table); 268 + break; 269 + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: 270 + dev->mtable_size = sizeof(dev->m_table_v2); 271 + break; 272 + default: 273 + dev_err(dev->dev, "Invalid CPU id: 0x%x", dev->cpu_id); 274 + } 275 + 276 + dev->buf = kzalloc(dev->mtable_size, GFP_KERNEL); 259 277 if (!dev->buf) 260 278 return -ENOMEM; 261 279 }
+8
drivers/platform/x86/amd/pmf/pmf-quirks.c
··· 37 37 }, 38 38 .driver_data = &quirk_no_sps_bug, 39 39 }, 40 + { 41 + .ident = "ASUS TUF Gaming A14", 42 + .matches = { 43 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 44 + DMI_MATCH(DMI_PRODUCT_NAME, "FA401W"), 45 + }, 46 + .driver_data = &quirk_no_sps_bug, 47 + }, 40 48 {} 41 49 }; 42 50
+73
drivers/platform/x86/amd/pmf/pmf.h
··· 19 19 #define POLICY_SIGN_COOKIE 0x31535024 20 20 #define POLICY_COOKIE_OFFSET 0x10 21 21 22 + /* List of supported CPU ids */ 23 + #define AMD_CPU_ID_RMB 0x14b5 24 + #define AMD_CPU_ID_PS 0x14e8 25 + #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 26 + #define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 27 + 22 28 struct cookie_header { 23 29 u32 sign; 24 30 u32 length; ··· 41 35 #define APMF_FUNC_STATIC_SLIDER_GRANULAR 9 42 36 #define APMF_FUNC_DYN_SLIDER_AC 11 43 37 #define APMF_FUNC_DYN_SLIDER_DC 12 38 + #define APMF_FUNC_NOTIFY_SMART_PC_UPDATES 14 44 39 #define APMF_FUNC_SBIOS_HEARTBEAT_V2 16 45 40 46 41 /* Message Definitions */ ··· 89 82 #define PMF_POLICY_STT_SKINTEMP_APU 7 90 83 #define PMF_POLICY_STT_SKINTEMP_HS2 8 91 84 #define PMF_POLICY_SYSTEM_STATE 9 85 + #define PMF_POLICY_BIOS_OUTPUT_1 10 86 + #define PMF_POLICY_BIOS_OUTPUT_2 11 92 87 #define PMF_POLICY_P3T 38 88 + #define PMF_POLICY_BIOS_OUTPUT_3 57 89 + #define PMF_POLICY_BIOS_OUTPUT_4 58 90 + #define PMF_POLICY_BIOS_OUTPUT_5 59 91 + #define PMF_POLICY_BIOS_OUTPUT_6 60 92 + #define PMF_POLICY_BIOS_OUTPUT_7 61 93 + #define PMF_POLICY_BIOS_OUTPUT_8 62 94 + #define PMF_POLICY_BIOS_OUTPUT_9 63 95 + #define PMF_POLICY_BIOS_OUTPUT_10 64 93 96 94 97 /* TA macros */ 95 98 #define PMF_TA_IF_VERSION_MAJOR 1 ··· 196 179 u16 size; 197 180 u8 fan_ctl_mode; 198 181 u32 fan_ctl_idx; 182 + } __packed; 183 + 184 + struct smu_pmf_metrics_v2 { 185 + u16 core_frequency[16]; /* MHz */ 186 + u16 core_power[16]; /* mW */ 187 + u16 core_temp[16]; /* centi-C */ 188 + u16 gfx_temp; /* centi-C */ 189 + u16 soc_temp; /* centi-C */ 190 + u16 stapm_opn_limit; /* mW */ 191 + u16 stapm_cur_limit; /* mW */ 192 + u16 infra_cpu_maxfreq; /* MHz */ 193 + u16 infra_gfx_maxfreq; /* MHz */ 194 + u16 skin_temp; /* centi-C */ 195 + u16 gfxclk_freq; /* MHz */ 196 + u16 fclk_freq; /* MHz */ 197 + u16 gfx_activity; /* GFX busy % [0-100] */ 198 + u16 socclk_freq; /* MHz */ 199 + u16 vclk_freq; /* MHz */ 200 + u16 vcn_activity; /* VCN busy % [0-100] */ 201 + u16 vpeclk_freq; /* MHz */ 202 + u16 ipuclk_freq; /* MHz */ 203 + u16 ipu_busy[8]; /* NPU busy % [0-100] */ 204 + u16 dram_reads; /* MB/sec */ 205 + u16 dram_writes; /* MB/sec */ 206 + u16 core_c0residency[16]; /* C0 residency % [0-100] */ 207 + u16 ipu_power; /* mW */ 208 + u32 apu_power; /* mW */ 209 + u32 gfx_power; /* mW */ 210 + u32 dgpu_power; /* mW */ 211 + u32 socket_power; /* mW */ 212 + u32 all_core_power; /* mW */ 213 + u32 filter_alpha_value; /* time constant [us] */ 214 + u32 metrics_counter; 215 + u16 memclk_freq; /* MHz */ 216 + u16 mpipuclk_freq; /* MHz */ 217 + u16 ipu_reads; /* MB/sec */ 218 + u16 ipu_writes; /* MB/sec */ 219 + u32 throttle_residency_prochot; 220 + u32 throttle_residency_spl; 221 + u32 throttle_residency_fppt; 222 + u32 throttle_residency_sppt; 223 + u32 throttle_residency_thm_core; 224 + u32 throttle_residency_thm_gfx; 225 + u32 throttle_residency_thm_soc; 226 + u16 psys; 227 + u16 spare1; 228 + u32 spare[6]; 199 229 } __packed; 200 230 201 231 struct smu_pmf_metrics { ··· 342 278 int hb_interval; /* SBIOS heartbeat interval */ 343 279 struct delayed_work heart_beat; 344 280 struct smu_pmf_metrics m_table; 281 + struct smu_pmf_metrics_v2 m_table_v2; 345 282 struct delayed_work work_buffer; 346 283 ktime_t start_time; 347 284 int socket_power_history[AVG_SAMPLE_SIZE]; ··· 367 302 bool smart_pc_enabled; 368 303 u16 pmf_if_version; 369 304 struct input_dev *pmf_idev; 305 + size_t mtable_size; 370 306 }; 371 307 372 308 struct apmf_sps_prop_granular_v2 { ··· 408 342 struct os_power_slider { 409 343 u16 size; 410 344 u8 slider_event; 345 + } __packed; 346 + 347 + struct amd_pmf_notify_smart_pc_update { 348 + u16 size; 349 + u32 pending_req; 350 + u32 custom_bios[10]; 411 351 } __packed; 412 352 413 353 struct fan_table_control { ··· 789 717 int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev); 790 718 void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev); 791 719 int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev); 720 + int amd_pmf_smartpc_apply_bios_output(struct amd_pmf_dev *dev, u32 val, u32 preq, u32 idx); 792 721 793 722 /* Smart PC - TA interfaces */ 794 723 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
+35 -16
drivers/platform/x86/amd/pmf/spc.c
··· 53 53 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {} 54 54 #endif 55 55 56 - static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) 56 + static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in) 57 57 { 58 58 u16 max, avg = 0; 59 59 int i; 60 60 61 - memset(dev->buf, 0, sizeof(dev->m_table)); 62 - amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL); 63 - memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table)); 64 - 65 - in->ev_info.socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power; 66 - in->ev_info.skin_temperature = dev->m_table.skin_temp; 67 - 68 61 /* Get the avg and max C0 residency of all the cores */ 69 - max = dev->m_table.avg_core_c0residency[0]; 70 - for (i = 0; i < ARRAY_SIZE(dev->m_table.avg_core_c0residency); i++) { 71 - avg += dev->m_table.avg_core_c0residency[i]; 72 - if (dev->m_table.avg_core_c0residency[i] > max) 73 - max = dev->m_table.avg_core_c0residency[i]; 62 + max = *core_res; 63 + for (i = 0; i < size; i++) { 64 + avg += core_res[i]; 65 + if (core_res[i] > max) 66 + max = core_res[i]; 74 67 } 75 - 76 - avg = DIV_ROUND_CLOSEST(avg, ARRAY_SIZE(dev->m_table.avg_core_c0residency)); 68 + avg = DIV_ROUND_CLOSEST(avg, size); 77 69 in->ev_info.avg_c0residency = avg; 78 70 in->ev_info.max_c0residency = max; 79 - in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity; 71 + } 72 + 73 + static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) 74 + { 75 + /* Get the updated metrics table data */ 76 + memset(dev->buf, 0, dev->mtable_size); 77 + amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL); 78 + 79 + switch (dev->cpu_id) { 80 + case AMD_CPU_ID_PS: 81 + memcpy(&dev->m_table, dev->buf, dev->mtable_size); 82 + in->ev_info.socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power; 83 + in->ev_info.skin_temperature = dev->m_table.skin_temp; 84 + in->ev_info.gfx_busy = dev->m_table.avg_gfx_activity; 85 + amd_pmf_get_c0_residency(dev->m_table.avg_core_c0residency, 86 + ARRAY_SIZE(dev->m_table.avg_core_c0residency), in); 87 + break; 88 + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: 89 + memcpy(&dev->m_table_v2, dev->buf, dev->mtable_size); 90 + in->ev_info.socket_power = dev->m_table_v2.apu_power + dev->m_table_v2.dgpu_power; 91 + in->ev_info.skin_temperature = dev->m_table_v2.skin_temp; 92 + in->ev_info.gfx_busy = dev->m_table_v2.gfx_activity; 93 + amd_pmf_get_c0_residency(dev->m_table_v2.core_c0residency, 94 + ARRAY_SIZE(dev->m_table_v2.core_c0residency), in); 95 + break; 96 + default: 97 + dev_err(dev->dev, "Unsupported CPU id: 0x%x", dev->cpu_id); 98 + } 80 99 } 81 100 82 101 static const char * const pmf_battery_supply_name[] = {
+40
drivers/platform/x86/amd/pmf/tee-if.c
··· 160 160 dev_dbg(dev->dev, "update SYSTEM_STATE: %s\n", 161 161 amd_pmf_uevent_as_str(val)); 162 162 break; 163 + 164 + case PMF_POLICY_BIOS_OUTPUT_1: 165 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(0), 0); 166 + break; 167 + 168 + case PMF_POLICY_BIOS_OUTPUT_2: 169 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(1), 1); 170 + break; 171 + 172 + case PMF_POLICY_BIOS_OUTPUT_3: 173 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(2), 2); 174 + break; 175 + 176 + case PMF_POLICY_BIOS_OUTPUT_4: 177 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(3), 3); 178 + break; 179 + 180 + case PMF_POLICY_BIOS_OUTPUT_5: 181 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(4), 4); 182 + break; 183 + 184 + case PMF_POLICY_BIOS_OUTPUT_6: 185 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(5), 5); 186 + break; 187 + 188 + case PMF_POLICY_BIOS_OUTPUT_7: 189 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(6), 6); 190 + break; 191 + 192 + case PMF_POLICY_BIOS_OUTPUT_8: 193 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(7), 7); 194 + break; 195 + 196 + case PMF_POLICY_BIOS_OUTPUT_9: 197 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(8), 8); 198 + break; 199 + 200 + case PMF_POLICY_BIOS_OUTPUT_10: 201 + amd_pmf_smartpc_apply_bios_output(dev, val, BIT(9), 9); 202 + break; 163 203 } 164 204 } 165 205 }
+1 -2
drivers/platform/x86/asus-laptop.c
··· 28 28 #include <linux/err.h> 29 29 #include <linux/proc_fs.h> 30 30 #include <linux/backlight.h> 31 - #include <linux/fb.h> 32 31 #include <linux/leds.h> 33 32 #include <linux/platform_device.h> 34 33 #include <linux/uaccess.h> ··· 817 818 818 819 asus->backlight_device = bd; 819 820 bd->props.brightness = asus_read_brightness(bd); 820 - bd->props.power = FB_BLANK_UNBLANK; 821 + bd->props.power = BACKLIGHT_POWER_ON; 821 822 backlight_update_status(bd); 822 823 return 0; 823 824 }
+2 -2
drivers/platform/x86/asus-nb-wmi.c
··· 7 7 8 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 9 10 + #include <linux/backlight.h> 10 11 #include <linux/kernel.h> 11 12 #include <linux/module.h> 12 13 #include <linux/init.h> 13 14 #include <linux/input.h> 14 15 #include <linux/input/sparse-keymap.h> 15 - #include <linux/fb.h> 16 16 #include <linux/dmi.h> 17 17 #include <linux/i8042.h> 18 18 ··· 538 538 dmi_check_system(asus_quirks); 539 539 540 540 driver->quirks = quirks; 541 - driver->panel_power = FB_BLANK_UNBLANK; 541 + driver->panel_power = BACKLIGHT_POWER_ON; 542 542 543 543 /* overwrite the wapf setting if the wapf paramater is specified */ 544 544 if (wapf != -1)
+137 -87
drivers/platform/x86/asus-wmi.c
··· 18 18 #include <linux/debugfs.h> 19 19 #include <linux/delay.h> 20 20 #include <linux/dmi.h> 21 - #include <linux/fb.h> 22 21 #include <linux/hwmon.h> 23 22 #include <linux/hwmon-sysfs.h> 24 23 #include <linux/init.h> ··· 95 96 #define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT 0 96 97 #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 1 97 98 #define ASUS_THROTTLE_THERMAL_POLICY_SILENT 2 99 + 100 + #define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO 0 101 + #define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1 102 + #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO 2 103 + 104 + #define PLATFORM_PROFILE_MAX 2 98 105 99 106 #define USB_INTEL_XUSB2PR 0xD0 100 107 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 ··· 305 300 u32 kbd_rgb_dev; 306 301 bool kbd_rgb_state_available; 307 302 308 - bool throttle_thermal_policy_available; 309 303 u8 throttle_thermal_policy_mode; 304 + u32 throttle_thermal_policy_dev; 310 305 311 306 bool cpu_fan_curve_available; 312 307 bool gpu_fan_curve_available; ··· 354 349 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, 355 350 &input, &output); 356 351 357 - if (ACPI_FAILURE(status)) 352 + pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x\n", 353 + __func__, method_id, arg0, arg1, arg2); 354 + if (ACPI_FAILURE(status)) { 355 + pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", 356 + __func__, method_id, arg0, -EIO); 358 357 return -EIO; 358 + } 359 359 360 360 obj = (union acpi_object *)output.pointer; 361 361 if (obj && obj->type == ACPI_TYPE_INTEGER) 362 362 tmp = (u32) obj->integer.value; 363 363 364 + pr_debug("Result: 0x%08x\n", tmp); 364 365 if (retval) 365 366 *retval = tmp; 366 367 367 368 kfree(obj); 368 369 369 - if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) 370 + if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) { 371 + pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", 372 + __func__, method_id, arg0, -ENODEV); 370 373 return -ENODEV; 374 + } 371 375 372 376 return 0; 373 377 } ··· 406 392 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, 407 393 &input, &output); 408 394 409 - if (ACPI_FAILURE(status)) 395 + pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", 396 + __func__, method_id, arg0, arg1, arg2, arg3, arg4); 397 + if (ACPI_FAILURE(status)) { 398 + pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", 399 + __func__, method_id, arg0, -EIO); 410 400 return -EIO; 401 + } 411 402 412 403 obj = (union acpi_object *)output.pointer; 413 404 if (obj && obj->type == ACPI_TYPE_INTEGER) 414 405 tmp = (u32) obj->integer.value; 415 406 407 + pr_debug("Result: %x\n", tmp); 416 408 if (retval) 417 409 *retval = tmp; 418 410 419 411 kfree(obj); 420 412 421 - if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) 413 + if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) { 414 + pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", 415 + __func__, method_id, arg0, -ENODEV); 422 416 return -ENODEV; 417 + } 423 418 424 419 return 0; 425 420 } ··· 454 431 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, 455 432 &input, &output); 456 433 457 - if (ACPI_FAILURE(status)) 434 + pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x\n", 435 + __func__, method_id, arg0, arg1); 436 + if (ACPI_FAILURE(status)) { 437 + pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", 438 + __func__, method_id, arg0, -EIO); 458 439 return -EIO; 440 + } 459 441 460 442 obj = (union acpi_object *)output.pointer; 461 443 ··· 496 468 497 469 kfree(obj); 498 470 499 - if (err) 471 + if (err) { 472 + pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", 473 + __func__, method_id, arg0, err); 500 474 return err; 475 + } 501 476 502 477 return 0; 503 478 } ··· 588 557 { 589 558 u32 retval; 590 559 int status = asus_wmi_get_devstate(asus, dev_id, &retval); 560 + pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval); 591 561 592 562 return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); 593 563 } ··· 1754 1722 goto error; 1755 1723 } 1756 1724 1757 - if (!kbd_led_read(asus, &led_val, NULL)) { 1725 + if (!kbd_led_read(asus, &led_val, NULL) && !dmi_check_system(asus_use_hid_led_dmi_ids)) { 1726 + pr_info("using asus-wmi for asus::kbd_backlight\n"); 1758 1727 asus->kbd_led_wk = led_val; 1759 1728 asus->kbd_led.name = "asus::kbd_backlight"; 1760 1729 asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED; ··· 3219 3186 int err, fan_idx; 3220 3187 u8 mode = 0; 3221 3188 3222 - if (asus->throttle_thermal_policy_available) 3189 + if (asus->throttle_thermal_policy_dev) 3223 3190 mode = asus->throttle_thermal_policy_mode; 3224 3191 /* DEVID_<C/G>PU_FAN_CURVE is switched for OVERBOOST vs SILENT */ 3225 3192 if (mode == 2) ··· 3426 3393 * For machines with throttle this is the only way to reset fans 3427 3394 * to default mode of operation (does not erase curve data). 3428 3395 */ 3429 - if (asus->throttle_thermal_policy_available) { 3396 + if (asus->throttle_thermal_policy_dev) { 3430 3397 err = throttle_thermal_policy_write(asus); 3431 3398 if (err) 3432 3399 return err; ··· 3643 3610 __ATTRIBUTE_GROUPS(asus_fan_curve_attr); 3644 3611 3645 3612 /* 3646 - * Must be initialised after throttle_thermal_policy_check_present() as 3647 - * we check the status of throttle_thermal_policy_available during init. 3613 + * Must be initialised after throttle_thermal_policy_dev is set as 3614 + * we check the status of throttle_thermal_policy_dev during init. 3648 3615 */ 3649 3616 static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) 3650 3617 { ··· 3654 3621 3655 3622 err = fan_curve_check_present(asus, &asus->cpu_fan_curve_available, 3656 3623 ASUS_WMI_DEVID_CPU_FAN_CURVE); 3657 - if (err) 3624 + if (err) { 3625 + pr_debug("%s, checked 0x%08x, failed: %d\n", 3626 + __func__, ASUS_WMI_DEVID_CPU_FAN_CURVE, err); 3658 3627 return err; 3628 + } 3659 3629 3660 3630 err = fan_curve_check_present(asus, &asus->gpu_fan_curve_available, 3661 3631 ASUS_WMI_DEVID_GPU_FAN_CURVE); 3662 - if (err) 3632 + if (err) { 3633 + pr_debug("%s, checked 0x%08x, failed: %d\n", 3634 + __func__, ASUS_WMI_DEVID_GPU_FAN_CURVE, err); 3663 3635 return err; 3636 + } 3664 3637 3665 3638 err = fan_curve_check_present(asus, &asus->mid_fan_curve_available, 3666 3639 ASUS_WMI_DEVID_MID_FAN_CURVE); 3667 - if (err) 3640 + if (err) { 3641 + pr_debug("%s, checked 0x%08x, failed: %d\n", 3642 + __func__, ASUS_WMI_DEVID_MID_FAN_CURVE, err); 3668 3643 return err; 3644 + } 3669 3645 3670 3646 if (!asus->cpu_fan_curve_available 3671 3647 && !asus->gpu_fan_curve_available ··· 3694 3652 } 3695 3653 3696 3654 /* Throttle thermal policy ****************************************************/ 3697 - 3698 - static int throttle_thermal_policy_check_present(struct asus_wmi *asus) 3699 - { 3700 - u32 result; 3701 - int err; 3702 - 3703 - asus->throttle_thermal_policy_available = false; 3704 - 3705 - err = asus_wmi_get_devstate(asus, 3706 - ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 3707 - &result); 3708 - if (err) { 3709 - if (err == -ENODEV) 3710 - return 0; 3711 - return err; 3712 - } 3713 - 3714 - if (result & ASUS_WMI_DSTS_PRESENCE_BIT) 3715 - asus->throttle_thermal_policy_available = true; 3716 - 3717 - return 0; 3718 - } 3719 - 3720 3655 static int throttle_thermal_policy_write(struct asus_wmi *asus) 3721 3656 { 3722 - int err; 3723 - u8 value; 3657 + u8 value = asus->throttle_thermal_policy_mode; 3724 3658 u32 retval; 3659 + int err; 3725 3660 3726 - value = asus->throttle_thermal_policy_mode; 3727 - 3728 - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 3661 + err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, 3729 3662 value, &retval); 3730 3663 3731 3664 sysfs_notify(&asus->platform_device->dev.kobj, NULL, ··· 3730 3713 3731 3714 static int throttle_thermal_policy_set_default(struct asus_wmi *asus) 3732 3715 { 3733 - if (!asus->throttle_thermal_policy_available) 3716 + if (!asus->throttle_thermal_policy_dev) 3734 3717 return 0; 3735 3718 3736 3719 asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; ··· 3742 3725 u8 new_mode = asus->throttle_thermal_policy_mode + 1; 3743 3726 int err; 3744 3727 3745 - if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) 3728 + if (new_mode > PLATFORM_PROFILE_MAX) 3746 3729 new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; 3747 3730 3748 3731 asus->throttle_thermal_policy_mode = new_mode; ··· 3781 3764 if (result < 0) 3782 3765 return result; 3783 3766 3784 - if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) 3767 + if (new_mode > PLATFORM_PROFILE_MAX) 3785 3768 return -EINVAL; 3786 3769 3787 3770 asus->throttle_thermal_policy_mode = new_mode; ··· 3798 3781 return count; 3799 3782 } 3800 3783 3801 - // Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent 3784 + /* 3785 + * Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent 3786 + */ 3802 3787 static DEVICE_ATTR_RW(throttle_thermal_policy); 3803 3788 3804 3789 /* Platform profile ***********************************************************/ 3790 + static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode) 3791 + { 3792 + bool vivo; 3793 + 3794 + vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; 3795 + 3796 + if (vivo) { 3797 + switch (mode) { 3798 + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: 3799 + return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; 3800 + case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: 3801 + return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; 3802 + case ASUS_THROTTLE_THERMAL_POLICY_SILENT: 3803 + return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; 3804 + } 3805 + } 3806 + 3807 + return mode; 3808 + } 3809 + 3810 + static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int mode) 3811 + { 3812 + bool vivo; 3813 + 3814 + vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; 3815 + 3816 + if (vivo) { 3817 + switch (mode) { 3818 + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO: 3819 + return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; 3820 + case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO: 3821 + return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST; 3822 + case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO: 3823 + return ASUS_THROTTLE_THERMAL_POLICY_SILENT; 3824 + } 3825 + } 3826 + 3827 + return mode; 3828 + } 3829 + 3805 3830 static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, 3806 3831 enum platform_profile_option *profile) 3807 3832 { ··· 3851 3792 int tp; 3852 3793 3853 3794 asus = container_of(pprof, struct asus_wmi, platform_profile_handler); 3854 - 3855 3795 tp = asus->throttle_thermal_policy_mode; 3856 3796 3857 - switch (tp) { 3797 + switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) { 3858 3798 case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: 3859 3799 *profile = PLATFORM_PROFILE_BALANCED; 3860 3800 break; ··· 3892 3834 return -EOPNOTSUPP; 3893 3835 } 3894 3836 3895 - asus->throttle_thermal_policy_mode = tp; 3837 + asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp); 3896 3838 return throttle_thermal_policy_write(asus); 3897 3839 } 3898 3840 ··· 3905 3847 * Not an error if a component platform_profile relies on is unavailable 3906 3848 * so early return, skipping the setup of platform_profile. 3907 3849 */ 3908 - if (!asus->throttle_thermal_policy_available) 3850 + if (!asus->throttle_thermal_policy_dev) 3909 3851 return 0; 3910 3852 3911 3853 dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n"); ··· 3920 3862 asus->platform_profile_handler.choices); 3921 3863 3922 3864 err = platform_profile_register(&asus->platform_profile_handler); 3923 - if (err) 3865 + if (err == -EEXIST) { 3866 + pr_warn("%s, a platform_profile handler is already registered\n", __func__); 3867 + return 0; 3868 + } else if (err) { 3869 + pr_err("%s, failed at platform_profile_register: %d\n", __func__, err); 3924 3870 return err; 3871 + } 3925 3872 3926 3873 asus->platform_profile_support = true; 3927 3874 return 0; ··· 3947 3884 if (ret < 0) 3948 3885 return ret; 3949 3886 3950 - return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 3887 + return ret ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF; 3951 3888 } 3952 3889 3953 3890 static int read_brightness_max(struct asus_wmi *asus) ··· 4006 3943 4007 3944 power = read_backlight_power(asus); 4008 3945 if (power != -ENODEV && bd->props.power != power) { 4009 - ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK); 3946 + ctrl_param = !!(bd->props.power == BACKLIGHT_POWER_ON); 4010 3947 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 4011 3948 ctrl_param, NULL); 4012 3949 if (asus->driver->quirks->store_backlight_power) ··· 4065 4002 4066 4003 power = read_backlight_power(asus); 4067 4004 if (power == -ENODEV) 4068 - power = FB_BLANK_UNBLANK; 4005 + power = BACKLIGHT_POWER_ON; 4069 4006 else if (power < 0) 4070 4007 return power; 4071 4008 ··· 4123 4060 if (ret < 0) 4124 4061 return ret; 4125 4062 /* 1 == powered */ 4126 - return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 4063 + return ret ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF; 4127 4064 } 4128 4065 4129 4066 static int read_screenpad_brightness(struct backlight_device *bd) ··· 4136 4073 if (err < 0) 4137 4074 return err; 4138 4075 /* The device brightness can only be read if powered, so return stored */ 4139 - if (err == FB_BLANK_POWERDOWN) 4076 + if (err == BACKLIGHT_POWER_OFF) 4140 4077 return asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN; 4141 4078 4142 4079 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); ··· 4157 4094 return power; 4158 4095 4159 4096 if (bd->props.power != power) { 4160 - if (power != FB_BLANK_UNBLANK) { 4097 + if (power != BACKLIGHT_POWER_ON) { 4161 4098 /* Only brightness > 0 can power it back on */ 4162 4099 ctrl_param = asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN; 4163 4100 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ··· 4165 4102 } else { 4166 4103 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL); 4167 4104 } 4168 - } else if (power == FB_BLANK_UNBLANK) { 4105 + } else if (power == BACKLIGHT_POWER_ON) { 4169 4106 /* Only set brightness if powered on or we get invalid/unsync state */ 4170 4107 ctrl_param = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN; 4171 4108 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL); ··· 4195 4132 if (power < 0) 4196 4133 return power; 4197 4134 4198 - if (power != FB_BLANK_POWERDOWN) { 4135 + if (power != BACKLIGHT_POWER_OFF) { 4199 4136 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness); 4200 4137 if (err < 0) 4201 4138 return err; ··· 4252 4189 4253 4190 /* WMI events *****************************************************************/ 4254 4191 4255 - static int asus_wmi_get_event_code(u32 value) 4192 + static int asus_wmi_get_event_code(union acpi_object *obj) 4256 4193 { 4257 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 4258 - union acpi_object *obj; 4259 - acpi_status status; 4260 4194 int code; 4261 - 4262 - status = wmi_get_event_data(value, &response); 4263 - if (ACPI_FAILURE(status)) { 4264 - pr_warn("Failed to get WMI notify code: %s\n", 4265 - acpi_format_exception(status)); 4266 - return -EIO; 4267 - } 4268 - 4269 - obj = (union acpi_object *)response.pointer; 4270 4195 4271 4196 if (obj && obj->type == ACPI_TYPE_INTEGER) 4272 4197 code = (int)(obj->integer.value & WMI_EVENT_MASK); 4273 4198 else 4274 4199 code = -EIO; 4275 4200 4276 - kfree(obj); 4277 4201 return code; 4278 4202 } 4279 4203 ··· 4312 4262 if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) { 4313 4263 if (asus->fan_boost_mode_available) 4314 4264 fan_boost_mode_switch_next(asus); 4315 - if (asus->throttle_thermal_policy_available) 4265 + if (asus->throttle_thermal_policy_dev) 4316 4266 throttle_thermal_policy_switch_next(asus); 4317 4267 return; 4318 4268 ··· 4326 4276 pr_info("Unknown key code 0x%x\n", code); 4327 4277 } 4328 4278 4329 - static void asus_wmi_notify(u32 value, void *context) 4279 + static void asus_wmi_notify(union acpi_object *obj, void *context) 4330 4280 { 4331 4281 struct asus_wmi *asus = context; 4332 - int code = asus_wmi_get_event_code(value); 4282 + int code = asus_wmi_get_event_code(obj); 4333 4283 4334 4284 if (code < 0) { 4335 4285 pr_warn("Failed to get notify code: %d\n", code); ··· 4484 4434 else if (attr == &dev_attr_fan_boost_mode.attr) 4485 4435 ok = asus->fan_boost_mode_available; 4486 4436 else if (attr == &dev_attr_throttle_thermal_policy.attr) 4487 - ok = asus->throttle_thermal_policy_available; 4437 + ok = asus->throttle_thermal_policy_dev != 0; 4488 4438 else if (attr == &dev_attr_ppt_pl2_sppt.attr) 4489 4439 devid = ASUS_WMI_DEVID_PPT_PL2_SPPT; 4490 4440 else if (attr == &dev_attr_ppt_pl1_spl.attr) ··· 4510 4460 else if (attr == &dev_attr_available_mini_led_mode.attr) 4511 4461 ok = asus->mini_led_dev_id != 0; 4512 4462 4513 - if (devid != -1) 4463 + if (devid != -1) { 4514 4464 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); 4465 + pr_debug("%s called 0x%08x, ok: %x\n", __func__, devid, ok); 4466 + } 4515 4467 4516 4468 return ok ? attr->mode : 0; 4517 4469 } ··· 4778 4726 else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2)) 4779 4727 asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2; 4780 4728 4729 + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) 4730 + asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY; 4731 + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO)) 4732 + asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; 4733 + 4781 4734 err = fan_boost_mode_check_present(asus); 4782 4735 if (err) 4783 4736 goto fail_fan_boost_mode; 4784 - 4785 - err = throttle_thermal_policy_check_present(asus); 4786 - if (err) 4787 - goto fail_throttle_thermal_policy; 4788 - else 4789 - throttle_thermal_policy_set_default(asus); 4790 4737 4791 4738 err = platform_profile_setup(asus); 4792 4739 if (err) ··· 4881 4830 fail_input: 4882 4831 asus_wmi_sysfs_exit(asus->platform_device); 4883 4832 fail_sysfs: 4884 - fail_throttle_thermal_policy: 4885 4833 fail_custom_fan_curve: 4886 4834 fail_platform_profile_setup: 4887 4835 if (asus->platform_profile_support)
+1
drivers/platform/x86/dell/Kconfig
··· 49 49 default m 50 50 depends on DMI 51 51 depends on BACKLIGHT_CLASS_DEVICE 52 + depends on ACPI_BATTERY 52 53 depends on ACPI_VIDEO || ACPI_VIDEO = n 53 54 depends on RFKILL || RFKILL = n 54 55 depends on DELL_WMI || DELL_WMI = n
+337 -82
drivers/platform/x86/dell/dell-laptop.c
··· 22 22 #include <linux/io.h> 23 23 #include <linux/rfkill.h> 24 24 #include <linux/power_supply.h> 25 + #include <linux/sysfs.h> 25 26 #include <linux/acpi.h> 26 27 #include <linux/mm.h> 27 28 #include <linux/i8042.h> 28 29 #include <linux/debugfs.h> 29 30 #include <linux/seq_file.h> 31 + #include <acpi/battery.h> 30 32 #include <acpi/video.h> 31 33 #include "dell-rbtn.h" 32 34 #include "dell-smbios.h" ··· 100 98 static bool force_rfkill; 101 99 static bool micmute_led_registered; 102 100 static bool mute_led_registered; 101 + 102 + struct battery_mode_info { 103 + int token; 104 + const char *label; 105 + }; 106 + 107 + static const struct battery_mode_info battery_modes[] = { 108 + { BAT_PRI_AC_MODE_TOKEN, "Trickle" }, 109 + { BAT_EXPRESS_MODE_TOKEN, "Fast" }, 110 + { BAT_STANDARD_MODE_TOKEN, "Standard" }, 111 + { BAT_ADAPTIVE_MODE_TOKEN, "Adaptive" }, 112 + { BAT_CUSTOM_MODE_TOKEN, "Custom" }, 113 + }; 114 + static u32 battery_supported_modes; 103 115 104 116 module_param(force_rfkill, bool, 0444); 105 117 MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models"); ··· 368 352 }, 369 353 { } 370 354 }; 355 + 356 + /* -1 is a sentinel value, telling us to use token->value */ 357 + #define USE_TVAL ((u32) -1) 358 + static int dell_send_request_for_tokenid(struct calling_interface_buffer *buffer, 359 + u16 class, u16 select, u16 tokenid, 360 + u32 val) 361 + { 362 + struct calling_interface_token *token; 363 + 364 + token = dell_smbios_find_token(tokenid); 365 + if (!token) 366 + return -ENODEV; 367 + 368 + if (val == USE_TVAL) 369 + val = token->value; 370 + 371 + dell_fill_request(buffer, token->location, val, 0, 0); 372 + return dell_send_request(buffer, class, select); 373 + } 374 + 375 + static inline int dell_set_std_token_value(struct calling_interface_buffer *buffer, 376 + u16 tokenid, u32 value) 377 + { 378 + return dell_send_request_for_tokenid(buffer, CLASS_TOKEN_WRITE, 379 + SELECT_TOKEN_STD, tokenid, value); 380 + } 371 381 372 382 /* 373 383 * Derived from information in smbios-wireless-ctl: ··· 937 895 static int dell_send_intensity(struct backlight_device *bd) 938 896 { 939 897 struct calling_interface_buffer buffer; 940 - struct calling_interface_token *token; 941 - int ret; 898 + u16 select; 942 899 943 - token = dell_smbios_find_token(BRIGHTNESS_TOKEN); 944 - if (!token) 945 - return -ENODEV; 946 - 947 - dell_fill_request(&buffer, 948 - token->location, bd->props.brightness, 0, 0); 949 - if (power_supply_is_system_supplied() > 0) 950 - ret = dell_send_request(&buffer, 951 - CLASS_TOKEN_WRITE, SELECT_TOKEN_AC); 952 - else 953 - ret = dell_send_request(&buffer, 954 - CLASS_TOKEN_WRITE, SELECT_TOKEN_BAT); 955 - 956 - return ret; 900 + select = power_supply_is_system_supplied() > 0 ? 901 + SELECT_TOKEN_AC : SELECT_TOKEN_BAT; 902 + return dell_send_request_for_tokenid(&buffer, CLASS_TOKEN_WRITE, 903 + select, BRIGHTNESS_TOKEN, bd->props.brightness); 957 904 } 958 905 959 906 static int dell_get_intensity(struct backlight_device *bd) 960 907 { 961 908 struct calling_interface_buffer buffer; 962 - struct calling_interface_token *token; 963 909 int ret; 910 + u16 select; 964 911 965 - token = dell_smbios_find_token(BRIGHTNESS_TOKEN); 966 - if (!token) 967 - return -ENODEV; 968 - 969 - dell_fill_request(&buffer, token->location, 0, 0, 0); 970 - if (power_supply_is_system_supplied() > 0) 971 - ret = dell_send_request(&buffer, 972 - CLASS_TOKEN_READ, SELECT_TOKEN_AC); 973 - else 974 - ret = dell_send_request(&buffer, 975 - CLASS_TOKEN_READ, SELECT_TOKEN_BAT); 976 - 912 + select = power_supply_is_system_supplied() > 0 ? 913 + SELECT_TOKEN_AC : SELECT_TOKEN_BAT; 914 + ret = dell_send_request_for_tokenid(&buffer, CLASS_TOKEN_READ, 915 + select, BRIGHTNESS_TOKEN, 0); 977 916 if (ret == 0) 978 917 ret = buffer.output[1]; 979 918 ··· 1378 1355 static int kbd_set_token_bit(u8 bit) 1379 1356 { 1380 1357 struct calling_interface_buffer buffer; 1381 - struct calling_interface_token *token; 1382 - int ret; 1383 1358 1384 1359 if (bit >= ARRAY_SIZE(kbd_tokens)) 1385 1360 return -EINVAL; 1386 1361 1387 - token = dell_smbios_find_token(kbd_tokens[bit]); 1388 - if (!token) 1389 - return -EINVAL; 1390 - 1391 - dell_fill_request(&buffer, token->location, token->value, 0, 0); 1392 - ret = dell_send_request(&buffer, CLASS_TOKEN_WRITE, SELECT_TOKEN_STD); 1393 - 1394 - return ret; 1362 + return dell_set_std_token_value(&buffer, kbd_tokens[bit], USE_TVAL); 1395 1363 } 1396 1364 1397 1365 static int kbd_get_token_bit(u8 bit) ··· 1401 1387 1402 1388 dell_fill_request(&buffer, token->location, 0, 0, 0); 1403 1389 ret = dell_send_request(&buffer, CLASS_TOKEN_READ, SELECT_TOKEN_STD); 1404 - val = buffer.output[1]; 1405 - 1406 1390 if (ret) 1407 1391 return ret; 1408 1392 1393 + val = buffer.output[1]; 1409 1394 return (val == token->value); 1410 1395 } 1411 1396 ··· 1510 1497 1511 1498 } 1512 1499 1513 - static inline void kbd_init_tokens(void) 1500 + static inline void __init kbd_init_tokens(void) 1514 1501 { 1515 1502 int i; 1516 1503 ··· 1519 1506 kbd_token_bits |= BIT(i); 1520 1507 } 1521 1508 1522 - static void kbd_init(void) 1509 + static void __init kbd_init(void) 1523 1510 { 1524 1511 int ret; 1525 1512 ··· 2144 2131 enum led_brightness brightness) 2145 2132 { 2146 2133 struct calling_interface_buffer buffer; 2147 - struct calling_interface_token *token; 2148 - int state = brightness != LED_OFF; 2134 + u32 tokenid; 2149 2135 2150 - if (state == 0) 2151 - token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE); 2152 - else 2153 - token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE); 2154 - 2155 - if (!token) 2156 - return -ENODEV; 2157 - 2158 - dell_fill_request(&buffer, token->location, token->value, 0, 0); 2159 - dell_send_request(&buffer, CLASS_TOKEN_WRITE, SELECT_TOKEN_STD); 2160 - 2161 - return 0; 2136 + tokenid = brightness == LED_OFF ? 2137 + GLOBAL_MIC_MUTE_DISABLE : GLOBAL_MIC_MUTE_ENABLE; 2138 + return dell_set_std_token_value(&buffer, tokenid, USE_TVAL); 2162 2139 } 2163 2140 2164 2141 static struct led_classdev micmute_led_cdev = { ··· 2162 2159 enum led_brightness brightness) 2163 2160 { 2164 2161 struct calling_interface_buffer buffer; 2165 - struct calling_interface_token *token; 2166 - int state = brightness != LED_OFF; 2162 + u32 tokenid; 2167 2163 2168 - if (state == 0) 2169 - token = dell_smbios_find_token(GLOBAL_MUTE_DISABLE); 2170 - else 2171 - token = dell_smbios_find_token(GLOBAL_MUTE_ENABLE); 2172 - 2173 - if (!token) 2174 - return -ENODEV; 2175 - 2176 - dell_fill_request(&buffer, token->location, token->value, 0, 0); 2177 - dell_send_request(&buffer, CLASS_TOKEN_WRITE, SELECT_TOKEN_STD); 2178 - 2179 - return 0; 2164 + tokenid = brightness == LED_OFF ? 2165 + GLOBAL_MUTE_DISABLE : GLOBAL_MUTE_ENABLE; 2166 + return dell_set_std_token_value(&buffer, tokenid, USE_TVAL); 2180 2167 } 2181 2168 2182 2169 static struct led_classdev mute_led_cdev = { ··· 2176 2183 .default_trigger = "audio-mute", 2177 2184 }; 2178 2185 2179 - static int __init dell_init(void) 2186 + static int dell_battery_set_mode(const u16 tokenid) 2187 + { 2188 + struct calling_interface_buffer buffer; 2189 + 2190 + return dell_set_std_token_value(&buffer, tokenid, USE_TVAL); 2191 + } 2192 + 2193 + static int dell_battery_read(const u16 tokenid) 2194 + { 2195 + struct calling_interface_buffer buffer; 2196 + int err; 2197 + 2198 + err = dell_send_request_for_tokenid(&buffer, CLASS_TOKEN_READ, 2199 + SELECT_TOKEN_STD, tokenid, 0); 2200 + if (err) 2201 + return err; 2202 + 2203 + if (buffer.output[1] > INT_MAX) 2204 + return -EIO; 2205 + 2206 + return buffer.output[1]; 2207 + } 2208 + 2209 + static bool dell_battery_mode_is_active(const u16 tokenid) 2180 2210 { 2181 2211 struct calling_interface_token *token; 2212 + int ret; 2213 + 2214 + ret = dell_battery_read(tokenid); 2215 + if (ret < 0) 2216 + return false; 2217 + 2218 + token = dell_smbios_find_token(tokenid); 2219 + /* token's already verified by dell_battery_read() */ 2220 + 2221 + return token->value == (u16) ret; 2222 + } 2223 + 2224 + /* 2225 + * The rules: the minimum start charging value is 50%. The maximum 2226 + * start charging value is 95%. The minimum end charging value is 2227 + * 55%. The maximum end charging value is 100%. And finally, there 2228 + * has to be at least a 5% difference between start & end values. 2229 + */ 2230 + #define CHARGE_START_MIN 50 2231 + #define CHARGE_START_MAX 95 2232 + #define CHARGE_END_MIN 55 2233 + #define CHARGE_END_MAX 100 2234 + #define CHARGE_MIN_DIFF 5 2235 + 2236 + static int dell_battery_set_custom_charge_start(int start) 2237 + { 2238 + struct calling_interface_buffer buffer; 2239 + int end; 2240 + 2241 + start = clamp(start, CHARGE_START_MIN, CHARGE_START_MAX); 2242 + end = dell_battery_read(BAT_CUSTOM_CHARGE_END); 2243 + if (end < 0) 2244 + return end; 2245 + if ((end - start) < CHARGE_MIN_DIFF) 2246 + start = end - CHARGE_MIN_DIFF; 2247 + 2248 + return dell_set_std_token_value(&buffer, BAT_CUSTOM_CHARGE_START, 2249 + start); 2250 + } 2251 + 2252 + static int dell_battery_set_custom_charge_end(int end) 2253 + { 2254 + struct calling_interface_buffer buffer; 2255 + int start; 2256 + 2257 + end = clamp(end, CHARGE_END_MIN, CHARGE_END_MAX); 2258 + start = dell_battery_read(BAT_CUSTOM_CHARGE_START); 2259 + if (start < 0) 2260 + return start; 2261 + if ((end - start) < CHARGE_MIN_DIFF) 2262 + end = start + CHARGE_MIN_DIFF; 2263 + 2264 + return dell_set_std_token_value(&buffer, BAT_CUSTOM_CHARGE_END, end); 2265 + } 2266 + 2267 + static ssize_t charge_types_show(struct device *dev, 2268 + struct device_attribute *attr, 2269 + char *buf) 2270 + { 2271 + ssize_t count = 0; 2272 + int i; 2273 + 2274 + for (i = 0; i < ARRAY_SIZE(battery_modes); i++) { 2275 + bool active; 2276 + 2277 + if (!(battery_supported_modes & BIT(i))) 2278 + continue; 2279 + 2280 + active = dell_battery_mode_is_active(battery_modes[i].token); 2281 + count += sysfs_emit_at(buf, count, active ? "[%s] " : "%s ", 2282 + battery_modes[i].label); 2283 + } 2284 + 2285 + /* convert the last space to a newline */ 2286 + if (count > 0) 2287 + count--; 2288 + count += sysfs_emit_at(buf, count, "\n"); 2289 + 2290 + return count; 2291 + } 2292 + 2293 + static ssize_t charge_types_store(struct device *dev, 2294 + struct device_attribute *attr, 2295 + const char *buf, size_t size) 2296 + { 2297 + bool matched = false; 2298 + int err, i; 2299 + 2300 + for (i = 0; i < ARRAY_SIZE(battery_modes); i++) { 2301 + if (!(battery_supported_modes & BIT(i))) 2302 + continue; 2303 + 2304 + if (sysfs_streq(battery_modes[i].label, buf)) { 2305 + matched = true; 2306 + break; 2307 + } 2308 + } 2309 + if (!matched) 2310 + return -EINVAL; 2311 + 2312 + err = dell_battery_set_mode(battery_modes[i].token); 2313 + if (err) 2314 + return err; 2315 + 2316 + return size; 2317 + } 2318 + 2319 + static ssize_t charge_control_start_threshold_show(struct device *dev, 2320 + struct device_attribute *attr, 2321 + char *buf) 2322 + { 2323 + int start; 2324 + 2325 + start = dell_battery_read(BAT_CUSTOM_CHARGE_START); 2326 + if (start < 0) 2327 + return start; 2328 + 2329 + if (start > CHARGE_START_MAX) 2330 + return -EIO; 2331 + 2332 + return sysfs_emit(buf, "%d\n", start); 2333 + } 2334 + 2335 + static ssize_t charge_control_start_threshold_store(struct device *dev, 2336 + struct device_attribute *attr, 2337 + const char *buf, size_t size) 2338 + { 2339 + int ret, start; 2340 + 2341 + ret = kstrtoint(buf, 10, &start); 2342 + if (ret) 2343 + return ret; 2344 + if (start < 0 || start > 100) 2345 + return -EINVAL; 2346 + 2347 + ret = dell_battery_set_custom_charge_start(start); 2348 + if (ret) 2349 + return ret; 2350 + 2351 + return size; 2352 + } 2353 + 2354 + static ssize_t charge_control_end_threshold_show(struct device *dev, 2355 + struct device_attribute *attr, 2356 + char *buf) 2357 + { 2358 + int end; 2359 + 2360 + end = dell_battery_read(BAT_CUSTOM_CHARGE_END); 2361 + if (end < 0) 2362 + return end; 2363 + 2364 + if (end > CHARGE_END_MAX) 2365 + return -EIO; 2366 + 2367 + return sysfs_emit(buf, "%d\n", end); 2368 + } 2369 + 2370 + static ssize_t charge_control_end_threshold_store(struct device *dev, 2371 + struct device_attribute *attr, 2372 + const char *buf, size_t size) 2373 + { 2374 + int ret, end; 2375 + 2376 + ret = kstrtouint(buf, 10, &end); 2377 + if (ret) 2378 + return ret; 2379 + if (end < 0 || end > 100) 2380 + return -EINVAL; 2381 + 2382 + ret = dell_battery_set_custom_charge_end(end); 2383 + if (ret) 2384 + return ret; 2385 + 2386 + return size; 2387 + } 2388 + 2389 + static DEVICE_ATTR_RW(charge_control_start_threshold); 2390 + static DEVICE_ATTR_RW(charge_control_end_threshold); 2391 + static DEVICE_ATTR_RW(charge_types); 2392 + 2393 + static struct attribute *dell_battery_attrs[] = { 2394 + &dev_attr_charge_control_start_threshold.attr, 2395 + &dev_attr_charge_control_end_threshold.attr, 2396 + &dev_attr_charge_types.attr, 2397 + NULL, 2398 + }; 2399 + ATTRIBUTE_GROUPS(dell_battery); 2400 + 2401 + static int dell_battery_add(struct power_supply *battery, 2402 + struct acpi_battery_hook *hook) 2403 + { 2404 + /* this currently only supports the primary battery */ 2405 + if (strcmp(battery->desc->name, "BAT0") != 0) 2406 + return -ENODEV; 2407 + 2408 + return device_add_groups(&battery->dev, dell_battery_groups); 2409 + } 2410 + 2411 + static int dell_battery_remove(struct power_supply *battery, 2412 + struct acpi_battery_hook *hook) 2413 + { 2414 + device_remove_groups(&battery->dev, dell_battery_groups); 2415 + return 0; 2416 + } 2417 + 2418 + static struct acpi_battery_hook dell_battery_hook = { 2419 + .add_battery = dell_battery_add, 2420 + .remove_battery = dell_battery_remove, 2421 + .name = "Dell Primary Battery Extension", 2422 + }; 2423 + 2424 + static u32 __init battery_get_supported_modes(void) 2425 + { 2426 + u32 modes = 0; 2427 + int i; 2428 + 2429 + for (i = 0; i < ARRAY_SIZE(battery_modes); i++) { 2430 + if (dell_smbios_find_token(battery_modes[i].token)) 2431 + modes |= BIT(i); 2432 + } 2433 + 2434 + return modes; 2435 + } 2436 + 2437 + static void __init dell_battery_init(struct device *dev) 2438 + { 2439 + battery_supported_modes = battery_get_supported_modes(); 2440 + 2441 + if (battery_supported_modes != 0) 2442 + battery_hook_register(&dell_battery_hook); 2443 + } 2444 + 2445 + static void dell_battery_exit(void) 2446 + { 2447 + if (battery_supported_modes != 0) 2448 + battery_hook_unregister(&dell_battery_hook); 2449 + } 2450 + 2451 + static int __init dell_init(void) 2452 + { 2453 + struct calling_interface_buffer buffer; 2182 2454 int max_intensity = 0; 2183 2455 int ret; 2184 2456 ··· 2477 2219 touchpad_led_init(&platform_device->dev); 2478 2220 2479 2221 kbd_led_init(&platform_device->dev); 2222 + dell_battery_init(&platform_device->dev); 2480 2223 2481 2224 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); 2482 2225 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, ··· 2505 2246 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2506 2247 return 0; 2507 2248 2508 - token = dell_smbios_find_token(BRIGHTNESS_TOKEN); 2509 - if (token) { 2510 - struct calling_interface_buffer buffer; 2511 - 2512 - dell_fill_request(&buffer, token->location, 0, 0, 0); 2513 - ret = dell_send_request(&buffer, 2514 - CLASS_TOKEN_READ, SELECT_TOKEN_AC); 2515 - if (ret == 0) 2516 - max_intensity = buffer.output[3]; 2517 - } 2249 + ret = dell_send_request_for_tokenid(&buffer, CLASS_TOKEN_READ, 2250 + SELECT_TOKEN_AC, BRIGHTNESS_TOKEN, 0); 2251 + if (ret == 0) 2252 + max_intensity = buffer.output[3]; 2518 2253 2519 2254 if (max_intensity) { 2520 2255 struct backlight_properties props; ··· 2546 2293 if (mute_led_registered) 2547 2294 led_classdev_unregister(&mute_led_cdev); 2548 2295 fail_led: 2296 + dell_battery_exit(); 2549 2297 dell_cleanup_rfkill(); 2550 2298 fail_rfkill: 2551 2299 platform_device_del(platform_device); ··· 2565 2311 if (quirks && quirks->touchpad_led) 2566 2312 touchpad_led_exit(); 2567 2313 kbd_led_exit(); 2314 + dell_battery_exit(); 2568 2315 backlight_device_unregister(dell_backlight_device); 2569 2316 if (micmute_led_registered) 2570 2317 led_classdev_unregister(&micmute_led_cdev);
+7
drivers/platform/x86/dell/dell-smbios.h
··· 33 33 #define KBD_LED_AUTO_50_TOKEN 0x02EB 34 34 #define KBD_LED_AUTO_75_TOKEN 0x02EC 35 35 #define KBD_LED_AUTO_100_TOKEN 0x02F6 36 + #define BAT_PRI_AC_MODE_TOKEN 0x0341 37 + #define BAT_ADAPTIVE_MODE_TOKEN 0x0342 38 + #define BAT_CUSTOM_MODE_TOKEN 0x0343 39 + #define BAT_STANDARD_MODE_TOKEN 0x0346 40 + #define BAT_EXPRESS_MODE_TOKEN 0x0347 41 + #define BAT_CUSTOM_CHARGE_START 0x0349 42 + #define BAT_CUSTOM_CHARGE_END 0x034A 36 43 #define GLOBAL_MIC_MUTE_ENABLE 0x0364 37 44 #define GLOBAL_MIC_MUTE_DISABLE 0x0365 38 45 #define GLOBAL_MUTE_ENABLE 0x058C
+1 -12
drivers/platform/x86/dell/dell-wmi-aio.c
··· 70 70 return false; 71 71 } 72 72 73 - static void dell_wmi_aio_notify(u32 value, void *context) 73 + static void dell_wmi_aio_notify(union acpi_object *obj, void *context) 74 74 { 75 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 76 - union acpi_object *obj; 77 75 struct dell_wmi_event *event; 78 - acpi_status status; 79 76 80 - status = wmi_get_event_data(value, &response); 81 - if (status != AE_OK) { 82 - pr_info("bad event status 0x%x\n", status); 83 - return; 84 - } 85 - 86 - obj = (union acpi_object *)response.pointer; 87 77 if (obj) { 88 78 unsigned int scancode = 0; 89 79 ··· 104 114 break; 105 115 } 106 116 } 107 - kfree(obj); 108 117 } 109 118 110 119 static int __init dell_wmi_aio_input_setup(void)
+1 -2
drivers/platform/x86/eeepc-laptop.c
··· 15 15 #include <linux/types.h> 16 16 #include <linux/platform_device.h> 17 17 #include <linux/backlight.h> 18 - #include <linux/fb.h> 19 18 #include <linux/hwmon.h> 20 19 #include <linux/hwmon-sysfs.h> 21 20 #include <linux/slab.h> ··· 1136 1137 } 1137 1138 eeepc->backlight_device = bd; 1138 1139 bd->props.brightness = read_brightness(bd); 1139 - bd->props.power = FB_BLANK_UNBLANK; 1140 + bd->props.power = BACKLIGHT_POWER_ON; 1140 1141 backlight_update_status(bd); 1141 1142 return 0; 1142 1143 }
+2 -2
drivers/platform/x86/eeepc-wmi.c
··· 13 13 14 14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 15 16 + #include <linux/backlight.h> 16 17 #include <linux/kernel.h> 17 18 #include <linux/module.h> 18 19 #include <linux/init.h> 19 20 #include <linux/input.h> 20 21 #include <linux/input/sparse-keymap.h> 21 22 #include <linux/dmi.h> 22 - #include <linux/fb.h> 23 23 #include <linux/acpi.h> 24 24 25 25 #include "asus-wmi.h" ··· 192 192 193 193 driver->quirks = quirks; 194 194 driver->quirks->wapf = -1; 195 - driver->panel_power = FB_BLANK_UNBLANK; 195 + driver->panel_power = BACKLIGHT_POWER_ON; 196 196 } 197 197 198 198 static struct asus_wmi_driver asus_wmi_driver = {
+4 -5
drivers/platform/x86/fujitsu-laptop.c
··· 43 43 #include <linux/bitops.h> 44 44 #include <linux/dmi.h> 45 45 #include <linux/backlight.h> 46 - #include <linux/fb.h> 47 46 #include <linux/input.h> 48 47 #include <linux/input/sparse-keymap.h> 49 48 #include <linux/kfifo.h> ··· 355 356 { 356 357 struct acpi_device *device = bl_get_data(b); 357 358 358 - return b->props.power == FB_BLANK_POWERDOWN ? 0 : get_lcd_level(device); 359 + return b->props.power == BACKLIGHT_POWER_OFF ? 0 : get_lcd_level(device); 359 360 } 360 361 361 362 static int bl_update_status(struct backlight_device *b) ··· 363 364 struct acpi_device *device = bl_get_data(b); 364 365 365 366 if (fext) { 366 - if (b->props.power == FB_BLANK_POWERDOWN) 367 + if (b->props.power == BACKLIGHT_POWER_OFF) 367 368 call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 368 369 BACKLIGHT_PARAM_POWER, BACKLIGHT_OFF); 369 370 else ··· 932 933 acpi_video_get_backlight_type() == acpi_backlight_vendor) { 933 934 if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2, 934 935 BACKLIGHT_PARAM_POWER, 0x0) == BACKLIGHT_OFF) 935 - fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN; 936 + fujitsu_bl->bl_device->props.power = BACKLIGHT_POWER_OFF; 936 937 else 937 - fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK; 938 + fujitsu_bl->bl_device->props.power = BACKLIGHT_POWER_ON; 938 939 } 939 940 940 941 ret = acpi_fujitsu_laptop_input_setup(device);
+1 -15
drivers/platform/x86/hp/hp-wmi.c
··· 834 834 }; 835 835 ATTRIBUTE_GROUPS(hp_wmi); 836 836 837 - static void hp_wmi_notify(u32 value, void *context) 837 + static void hp_wmi_notify(union acpi_object *obj, void *context) 838 838 { 839 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 840 839 u32 event_id, event_data; 841 - union acpi_object *obj; 842 - acpi_status status; 843 840 u32 *location; 844 841 int key_code; 845 - 846 - status = wmi_get_event_data(value, &response); 847 - if (status != AE_OK) { 848 - pr_info("bad event status 0x%x\n", status); 849 - return; 850 - } 851 - 852 - obj = (union acpi_object *)response.pointer; 853 842 854 843 if (!obj) 855 844 return; 856 845 if (obj->type != ACPI_TYPE_BUFFER) { 857 846 pr_info("Unknown response received %d\n", obj->type); 858 - kfree(obj); 859 847 return; 860 848 } 861 849 ··· 860 872 event_data = *(location + 2); 861 873 } else { 862 874 pr_info("Unknown buffer length %d\n", obj->buffer.length); 863 - kfree(obj); 864 875 return; 865 876 } 866 - kfree(obj); 867 877 868 878 switch (event_id) { 869 879 case HPWMI_DOCK_EVENT:
+1 -13
drivers/platform/x86/huawei-wmi.c
··· 734 734 sparse_keymap_report_entry(idev, key, 1, true); 735 735 } 736 736 737 - static void huawei_wmi_input_notify(u32 value, void *context) 737 + static void huawei_wmi_input_notify(union acpi_object *obj, void *context) 738 738 { 739 739 struct input_dev *idev = (struct input_dev *)context; 740 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 741 - union acpi_object *obj; 742 - acpi_status status; 743 740 744 - status = wmi_get_event_data(value, &response); 745 - if (ACPI_FAILURE(status)) { 746 - dev_err(&idev->dev, "Unable to get event data\n"); 747 - return; 748 - } 749 - 750 - obj = (union acpi_object *)response.pointer; 751 741 if (obj && obj->type == ACPI_TYPE_INTEGER) 752 742 huawei_wmi_process_key(idev, obj->integer.value); 753 743 else 754 744 dev_err(&idev->dev, "Bad response type\n"); 755 - 756 - kfree(response.pointer); 757 745 } 758 746 759 747 static int huawei_wmi_input_setup(struct device *dev, const char *guid)
+166 -25
drivers/platform/x86/ideapad-laptop.c
··· 17 17 #include <linux/debugfs.h> 18 18 #include <linux/device.h> 19 19 #include <linux/dmi.h> 20 - #include <linux/fb.h> 21 20 #include <linux/i8042.h> 22 21 #include <linux/init.h> 23 22 #include <linux/input.h> 24 23 #include <linux/input/sparse-keymap.h> 24 + #include <linux/jiffies.h> 25 25 #include <linux/kernel.h> 26 26 #include <linux/leds.h> 27 27 #include <linux/module.h> ··· 85 85 SALS_USB_CHARGING_OFF = 0xb, 86 86 SALS_FNLOCK_ON = 0xe, 87 87 SALS_FNLOCK_OFF = 0xf, 88 + }; 89 + 90 + enum { 91 + VPCCMD_R_VPC1 = 0x10, 92 + VPCCMD_R_BL_MAX, 93 + VPCCMD_R_BL, 94 + VPCCMD_W_BL, 95 + VPCCMD_R_WIFI, 96 + VPCCMD_W_WIFI, 97 + VPCCMD_R_BT, 98 + VPCCMD_W_BT, 99 + VPCCMD_R_BL_POWER, 100 + VPCCMD_R_NOVO, 101 + VPCCMD_R_VPC2, 102 + VPCCMD_R_TOUCHPAD, 103 + VPCCMD_W_TOUCHPAD, 104 + VPCCMD_R_CAMERA, 105 + VPCCMD_W_CAMERA, 106 + VPCCMD_R_3G, 107 + VPCCMD_W_3G, 108 + VPCCMD_R_ODD, /* 0x21 */ 109 + VPCCMD_W_FAN, 110 + VPCCMD_R_RF, 111 + VPCCMD_W_RF, 112 + VPCCMD_W_YMC = 0x2A, 113 + VPCCMD_R_FAN = 0x2B, 114 + VPCCMD_R_SPECIAL_BUTTONS = 0x31, 115 + VPCCMD_W_BL_POWER = 0x33, 88 116 }; 89 117 90 118 /* ··· 265 237 /* 266 238 * ACPI Helpers 267 239 */ 240 + #define IDEAPAD_EC_TIMEOUT 200 /* in ms */ 268 241 269 242 static int eval_int(acpi_handle handle, const char *name, unsigned long *res) 270 243 { ··· 277 248 return -EIO; 278 249 279 250 *res = result; 251 + 252 + return 0; 253 + } 254 + 255 + static int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg, 256 + unsigned long *res) 257 + { 258 + struct acpi_object_list params; 259 + unsigned long long result; 260 + union acpi_object in_obj; 261 + acpi_status status; 262 + 263 + params.count = 1; 264 + params.pointer = &in_obj; 265 + in_obj.type = ACPI_TYPE_INTEGER; 266 + in_obj.integer.value = arg; 267 + 268 + status = acpi_evaluate_integer(handle, (char *)name, &params, &result); 269 + if (ACPI_FAILURE(status)) 270 + return -EIO; 271 + 272 + if (res) 273 + *res = result; 280 274 281 275 return 0; 282 276 } ··· 344 292 static int eval_dytc(acpi_handle handle, unsigned long cmd, unsigned long *res) 345 293 { 346 294 return eval_int_with_arg(handle, "DYTC", cmd, res); 295 + } 296 + 297 + static int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res) 298 + { 299 + return eval_int_with_arg(handle, "VPCR", cmd, res); 300 + } 301 + 302 + static int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data) 303 + { 304 + struct acpi_object_list params; 305 + union acpi_object in_obj[2]; 306 + acpi_status status; 307 + 308 + params.count = 2; 309 + params.pointer = in_obj; 310 + in_obj[0].type = ACPI_TYPE_INTEGER; 311 + in_obj[0].integer.value = cmd; 312 + in_obj[1].type = ACPI_TYPE_INTEGER; 313 + in_obj[1].integer.value = data; 314 + 315 + status = acpi_evaluate_object(handle, "VPCW", &params, NULL); 316 + if (ACPI_FAILURE(status)) 317 + return -EIO; 318 + 319 + return 0; 320 + } 321 + 322 + static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data) 323 + { 324 + unsigned long end_jiffies, val; 325 + int err; 326 + 327 + err = eval_vpcw(handle, 1, cmd); 328 + if (err) 329 + return err; 330 + 331 + end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; 332 + 333 + while (time_before(jiffies, end_jiffies)) { 334 + schedule(); 335 + 336 + err = eval_vpcr(handle, 1, &val); 337 + if (err) 338 + return err; 339 + 340 + if (val == 0) 341 + return eval_vpcr(handle, 0, data); 342 + } 343 + 344 + acpi_handle_err(handle, "timeout in %s\n", __func__); 345 + 346 + return -ETIMEDOUT; 347 + } 348 + 349 + static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data) 350 + { 351 + unsigned long end_jiffies, val; 352 + int err; 353 + 354 + err = eval_vpcw(handle, 0, data); 355 + if (err) 356 + return err; 357 + 358 + err = eval_vpcw(handle, 1, cmd); 359 + if (err) 360 + return err; 361 + 362 + end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; 363 + 364 + while (time_before(jiffies, end_jiffies)) { 365 + schedule(); 366 + 367 + err = eval_vpcr(handle, 1, &val); 368 + if (err) 369 + return err; 370 + 371 + if (val == 0) 372 + return 0; 373 + } 374 + 375 + acpi_handle_err(handle, "timeout in %s\n", __func__); 376 + 377 + return -ETIMEDOUT; 347 378 } 348 379 349 380 /* ··· 554 419 char *buf) 555 420 { 556 421 struct ideapad_private *priv = dev_get_drvdata(dev); 557 - unsigned long result; 422 + unsigned long result = 0; 558 423 int err; 559 424 560 - scoped_guard(mutex, &priv->vpc_mutex) 425 + scoped_guard(mutex, &priv->vpc_mutex) { 561 426 err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); 562 - if (err) 563 - return err; 427 + if (err) 428 + return err; 429 + } 564 430 565 431 return sysfs_emit(buf, "%d\n", !!result); 566 432 } ··· 578 442 if (err) 579 443 return err; 580 444 581 - scoped_guard(mutex, &priv->vpc_mutex) 445 + scoped_guard(mutex, &priv->vpc_mutex) { 582 446 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); 583 - if (err) 584 - return err; 447 + if (err) 448 + return err; 449 + } 585 450 586 451 return count; 587 452 } ··· 630 493 char *buf) 631 494 { 632 495 struct ideapad_private *priv = dev_get_drvdata(dev); 633 - unsigned long result; 496 + unsigned long result = 0; 634 497 int err; 635 498 636 - scoped_guard(mutex, &priv->vpc_mutex) 499 + scoped_guard(mutex, &priv->vpc_mutex) { 637 500 err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); 638 - if (err) 639 - return err; 501 + if (err) 502 + return err; 503 + } 640 504 641 505 return sysfs_emit(buf, "%lu\n", result); 642 506 } ··· 657 519 if (state > 4 || state == 3) 658 520 return -EINVAL; 659 521 660 - scoped_guard(mutex, &priv->vpc_mutex) 522 + scoped_guard(mutex, &priv->vpc_mutex) { 661 523 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); 662 - if (err) 663 - return err; 524 + if (err) 525 + return err; 526 + } 664 527 665 528 return count; 666 529 } ··· 741 602 char *buf) 742 603 { 743 604 struct ideapad_private *priv = dev_get_drvdata(dev); 744 - unsigned long result; 605 + unsigned long result = 0; 745 606 int err; 746 607 747 - scoped_guard(mutex, &priv->vpc_mutex) 608 + scoped_guard(mutex, &priv->vpc_mutex) { 748 609 err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); 749 - if (err) 750 - return err; 610 + if (err) 611 + return err; 612 + } 751 613 752 614 priv->r_touchpad_val = result; 753 615 ··· 767 627 if (err) 768 628 return err; 769 629 770 - scoped_guard(mutex, &priv->vpc_mutex) 630 + scoped_guard(mutex, &priv->vpc_mutex) { 771 631 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); 772 - if (err) 773 - return err; 632 + if (err) 633 + return err; 634 + } 774 635 775 636 priv->r_touchpad_val = state; 776 637 ··· 1423 1282 return err; 1424 1283 1425 1284 err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER, 1426 - blightdev->props.power != FB_BLANK_POWERDOWN); 1285 + blightdev->props.power != BACKLIGHT_POWER_OFF); 1427 1286 if (err) 1428 1287 return err; 1429 1288 ··· 1473 1332 1474 1333 priv->blightdev = blightdev; 1475 1334 blightdev->props.brightness = now; 1476 - blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1335 + blightdev->props.power = power ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF; 1477 1336 1478 1337 backlight_update_status(blightdev); 1479 1338 ··· 1499 1358 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) 1500 1359 return; 1501 1360 1502 - blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 1361 + blightdev->props.power = power ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF; 1503 1362 } 1504 1363 1505 1364 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
-139
drivers/platform/x86/ideapad-laptop.h
··· 9 9 #ifndef _IDEAPAD_LAPTOP_H_ 10 10 #define _IDEAPAD_LAPTOP_H_ 11 11 12 - #include <linux/acpi.h> 13 - #include <linux/jiffies.h> 14 - #include <linux/errno.h> 15 12 #include <linux/notifier.h> 16 13 17 14 enum ideapad_laptop_notifier_actions { ··· 19 22 int ideapad_laptop_unregister_notifier(struct notifier_block *nb); 20 23 void ideapad_laptop_call_notifier(unsigned long action, void *data); 21 24 22 - enum { 23 - VPCCMD_R_VPC1 = 0x10, 24 - VPCCMD_R_BL_MAX, 25 - VPCCMD_R_BL, 26 - VPCCMD_W_BL, 27 - VPCCMD_R_WIFI, 28 - VPCCMD_W_WIFI, 29 - VPCCMD_R_BT, 30 - VPCCMD_W_BT, 31 - VPCCMD_R_BL_POWER, 32 - VPCCMD_R_NOVO, 33 - VPCCMD_R_VPC2, 34 - VPCCMD_R_TOUCHPAD, 35 - VPCCMD_W_TOUCHPAD, 36 - VPCCMD_R_CAMERA, 37 - VPCCMD_W_CAMERA, 38 - VPCCMD_R_3G, 39 - VPCCMD_W_3G, 40 - VPCCMD_R_ODD, /* 0x21 */ 41 - VPCCMD_W_FAN, 42 - VPCCMD_R_RF, 43 - VPCCMD_W_RF, 44 - VPCCMD_W_YMC = 0x2A, 45 - VPCCMD_R_FAN = 0x2B, 46 - VPCCMD_R_SPECIAL_BUTTONS = 0x31, 47 - VPCCMD_W_BL_POWER = 0x33, 48 - }; 49 - 50 - static inline int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg, unsigned long *res) 51 - { 52 - struct acpi_object_list params; 53 - unsigned long long result; 54 - union acpi_object in_obj; 55 - acpi_status status; 56 - 57 - params.count = 1; 58 - params.pointer = &in_obj; 59 - in_obj.type = ACPI_TYPE_INTEGER; 60 - in_obj.integer.value = arg; 61 - 62 - status = acpi_evaluate_integer(handle, (char *)name, &params, &result); 63 - if (ACPI_FAILURE(status)) 64 - return -EIO; 65 - 66 - if (res) 67 - *res = result; 68 - 69 - return 0; 70 - } 71 - 72 - static inline int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res) 73 - { 74 - return eval_int_with_arg(handle, "VPCR", cmd, res); 75 - } 76 - 77 - static inline int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data) 78 - { 79 - struct acpi_object_list params; 80 - union acpi_object in_obj[2]; 81 - acpi_status status; 82 - 83 - params.count = 2; 84 - params.pointer = in_obj; 85 - in_obj[0].type = ACPI_TYPE_INTEGER; 86 - in_obj[0].integer.value = cmd; 87 - in_obj[1].type = ACPI_TYPE_INTEGER; 88 - in_obj[1].integer.value = data; 89 - 90 - status = acpi_evaluate_object(handle, "VPCW", &params, NULL); 91 - if (ACPI_FAILURE(status)) 92 - return -EIO; 93 - 94 - return 0; 95 - } 96 - 97 - #define IDEAPAD_EC_TIMEOUT 200 /* in ms */ 98 - 99 - static inline int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data) 100 - { 101 - unsigned long end_jiffies, val; 102 - int err; 103 - 104 - err = eval_vpcw(handle, 1, cmd); 105 - if (err) 106 - return err; 107 - 108 - end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; 109 - 110 - while (time_before(jiffies, end_jiffies)) { 111 - schedule(); 112 - 113 - err = eval_vpcr(handle, 1, &val); 114 - if (err) 115 - return err; 116 - 117 - if (val == 0) 118 - return eval_vpcr(handle, 0, data); 119 - } 120 - 121 - acpi_handle_err(handle, "timeout in %s\n", __func__); 122 - 123 - return -ETIMEDOUT; 124 - } 125 - 126 - static inline int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data) 127 - { 128 - unsigned long end_jiffies, val; 129 - int err; 130 - 131 - err = eval_vpcw(handle, 0, data); 132 - if (err) 133 - return err; 134 - 135 - err = eval_vpcw(handle, 1, cmd); 136 - if (err) 137 - return err; 138 - 139 - end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; 140 - 141 - while (time_before(jiffies, end_jiffies)) { 142 - schedule(); 143 - 144 - err = eval_vpcr(handle, 1, &val); 145 - if (err) 146 - return err; 147 - 148 - if (val == 0) 149 - return 0; 150 - } 151 - 152 - acpi_handle_err(handle, "timeout in %s\n", __func__); 153 - 154 - return -ETIMEDOUT; 155 - } 156 - 157 - #undef IDEAPAD_EC_TIMEOUT 158 25 #endif /* !_IDEAPAD_LAPTOP_H_ */
+3 -4
drivers/platform/x86/intel/hid.c
··· 13 13 #include <linux/kernel.h> 14 14 #include <linux/module.h> 15 15 #include <linux/platform_device.h> 16 + #include <linux/string_choices.h> 16 17 #include <linux/suspend.h> 17 18 #include "../dual_accel_detect.h" 18 19 ··· 332 331 acpi_handle handle = ACPI_HANDLE(device); 333 332 334 333 /* Enable|disable features - power button is always enabled */ 335 - if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN, 336 - enable)) { 337 - dev_warn(device, "failed to %sable hotkeys\n", 338 - enable ? "en" : "dis"); 334 + if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN, enable)) { 335 + dev_warn(device, "failed to %s hotkeys\n", str_enable_disable(enable)); 339 336 return -EIO; 340 337 } 341 338
+33
drivers/platform/x86/intel/ifs/core.c
··· 32 32 static const struct ifs_test_caps scan_test = { 33 33 .integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT, 34 34 .test_num = IFS_TYPE_SAF, 35 + .image_suffix = "scan", 35 36 }; 36 37 37 38 static const struct ifs_test_caps array_test = { ··· 40 39 .test_num = IFS_TYPE_ARRAY_BIST, 41 40 }; 42 41 42 + static const struct ifs_test_msrs scan_msrs = { 43 + .copy_hashes = MSR_COPY_SCAN_HASHES, 44 + .copy_hashes_status = MSR_SCAN_HASHES_STATUS, 45 + .copy_chunks = MSR_AUTHENTICATE_AND_COPY_CHUNK, 46 + .copy_chunks_status = MSR_CHUNKS_AUTHENTICATION_STATUS, 47 + .test_ctrl = MSR_SAF_CTRL, 48 + }; 49 + 50 + static const struct ifs_test_msrs sbaf_msrs = { 51 + .copy_hashes = MSR_COPY_SBAF_HASHES, 52 + .copy_hashes_status = MSR_SBAF_HASHES_STATUS, 53 + .copy_chunks = MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK, 54 + .copy_chunks_status = MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS, 55 + .test_ctrl = MSR_SBAF_CTRL, 56 + }; 57 + 58 + static const struct ifs_test_caps sbaf_test = { 59 + .integrity_cap_bit = MSR_INTEGRITY_CAPS_SBAF_BIT, 60 + .test_num = IFS_TYPE_SBAF, 61 + .image_suffix = "sbft", 62 + }; 63 + 43 64 static struct ifs_device ifs_devices[] = { 44 65 [IFS_TYPE_SAF] = { 45 66 .test_caps = &scan_test, 67 + .test_msrs = &scan_msrs, 46 68 .misc = { 47 69 .name = "intel_ifs_0", 48 70 .minor = MISC_DYNAMIC_MINOR, ··· 78 54 .name = "intel_ifs_1", 79 55 .minor = MISC_DYNAMIC_MINOR, 80 56 .groups = plat_ifs_array_groups, 57 + }, 58 + }, 59 + [IFS_TYPE_SBAF] = { 60 + .test_caps = &sbaf_test, 61 + .test_msrs = &sbaf_msrs, 62 + .misc = { 63 + .name = "intel_ifs_2", 64 + .minor = MISC_DYNAMIC_MINOR, 65 + .groups = plat_ifs_groups, 81 66 }, 82 67 }, 83 68 };
+91 -1
drivers/platform/x86/intel/ifs/ifs.h
··· 126 126 * The driver does not make use of this, it only tests one core at a time. 127 127 * 128 128 * .. [#f1] https://github.com/intel/TBD 129 + * 130 + * 131 + * Structural Based Functional Test at Field (SBAF): 132 + * ------------------------------------------------- 133 + * 134 + * SBAF is a new type of testing that provides comprehensive core test 135 + * coverage complementing Scan at Field (SAF) testing. SBAF mimics the 136 + * manufacturing screening environment and leverages the same test suite. 137 + * It makes use of Design For Test (DFT) observation sites and features 138 + * to maximize coverage in minimum time. 139 + * 140 + * Similar to the SAF test, SBAF isolates the core under test from the 141 + * rest of the system during execution. Upon completion, the core 142 + * seamlessly resets to its pre-test state and resumes normal operation. 143 + * Any machine checks or hangs encountered during the test are confined to 144 + * the isolated core, preventing disruption to the overall system. 145 + * 146 + * Like the SAF test, the SBAF test is also divided into multiple batches, 147 + * and each batch test can take hundreds of milliseconds (100-200 ms) to 148 + * complete. If such a lengthy interruption is undesirable, it is 149 + * recommended to relocate the time-sensitive applications to other cores. 129 150 */ 130 151 #include <linux/device.h> 131 152 #include <linux/miscdevice.h> 132 153 133 154 #define MSR_ARRAY_BIST 0x00000105 155 + 156 + #define MSR_COPY_SBAF_HASHES 0x000002b8 157 + #define MSR_SBAF_HASHES_STATUS 0x000002b9 158 + #define MSR_AUTHENTICATE_AND_COPY_SBAF_CHUNK 0x000002ba 159 + #define MSR_SBAF_CHUNKS_AUTHENTICATION_STATUS 0x000002bb 160 + #define MSR_ACTIVATE_SBAF 0x000002bc 161 + #define MSR_SBAF_STATUS 0x000002bd 162 + 134 163 #define MSR_COPY_SCAN_HASHES 0x000002c2 135 164 #define MSR_SCAN_HASHES_STATUS 0x000002c3 136 165 #define MSR_AUTHENTICATE_AND_COPY_CHUNK 0x000002c4 ··· 169 140 #define MSR_ARRAY_TRIGGER 0x000002d6 170 141 #define MSR_ARRAY_STATUS 0x000002d7 171 142 #define MSR_SAF_CTRL 0x000004f0 143 + #define MSR_SBAF_CTRL 0x000004f8 172 144 173 145 #define SCAN_NOT_TESTED 0 174 146 #define SCAN_TEST_PASS 1 ··· 177 147 178 148 #define IFS_TYPE_SAF 0 179 149 #define IFS_TYPE_ARRAY_BIST 1 150 + #define IFS_TYPE_SBAF 2 180 151 181 152 #define ARRAY_GEN0 0 182 153 #define ARRAY_GEN1 1 ··· 227 196 u16 valid_chunks; 228 197 u16 total_chunks; 229 198 u32 error_code :8; 230 - u32 rsvd2 :24; 199 + u32 rsvd2 :8; 200 + u32 max_bundle :16; 231 201 }; 232 202 }; 233 203 ··· 285 253 }; 286 254 }; 287 255 256 + /* MSR_ACTIVATE_SBAF bit fields */ 257 + union ifs_sbaf { 258 + u64 data; 259 + struct { 260 + u32 bundle_idx :9; 261 + u32 rsvd1 :5; 262 + u32 pgm_idx :2; 263 + u32 rsvd2 :16; 264 + u32 delay :31; 265 + u32 sigmce :1; 266 + }; 267 + }; 268 + 269 + /* MSR_SBAF_STATUS bit fields */ 270 + union ifs_sbaf_status { 271 + u64 data; 272 + struct { 273 + u32 bundle_idx :9; 274 + u32 rsvd1 :5; 275 + u32 pgm_idx :2; 276 + u32 rsvd2 :16; 277 + u32 error_code :8; 278 + u32 rsvd3 :21; 279 + u32 test_fail :1; 280 + u32 sbaf_status :2; 281 + }; 282 + }; 283 + 288 284 /* 289 285 * Driver populated error-codes 290 286 * 0xFD: Test timed out before completing all the chunks. ··· 321 261 #define IFS_SW_TIMEOUT 0xFD 322 262 #define IFS_SW_PARTIAL_COMPLETION 0xFE 323 263 264 + #define IFS_SUFFIX_SZ 5 265 + 324 266 struct ifs_test_caps { 325 267 int integrity_cap_bit; 326 268 int test_num; 269 + char image_suffix[IFS_SUFFIX_SZ]; 270 + }; 271 + 272 + /** 273 + * struct ifs_test_msrs - MSRs used in IFS tests 274 + * @copy_hashes: Copy test hash data 275 + * @copy_hashes_status: Status of copied test hash data 276 + * @copy_chunks: Copy chunks of the test data 277 + * @copy_chunks_status: Status of the copied test data chunks 278 + * @test_ctrl: Control the test attributes 279 + */ 280 + struct ifs_test_msrs { 281 + u32 copy_hashes; 282 + u32 copy_hashes_status; 283 + u32 copy_chunks; 284 + u32 copy_chunks_status; 285 + u32 test_ctrl; 327 286 }; 328 287 329 288 /** ··· 357 278 * @generation: IFS test generation enumerated by hardware 358 279 * @chunk_size: size of a test chunk 359 280 * @array_gen: test generation of array test 281 + * @max_bundle: maximum bundle index 360 282 */ 361 283 struct ifs_data { 362 284 int loaded_version; ··· 370 290 u32 generation; 371 291 u32 chunk_size; 372 292 u32 array_gen; 293 + u32 max_bundle; 373 294 }; 374 295 375 296 struct ifs_work { ··· 380 299 381 300 struct ifs_device { 382 301 const struct ifs_test_caps *test_caps; 302 + const struct ifs_test_msrs *test_msrs; 383 303 struct ifs_data rw_data; 384 304 struct miscdevice misc; 385 305 }; ··· 399 317 struct ifs_device *d = container_of(m, struct ifs_device, misc); 400 318 401 319 return d->test_caps; 320 + } 321 + 322 + static inline const struct ifs_test_msrs *ifs_get_test_msrs(struct device *dev) 323 + { 324 + struct miscdevice *m = dev_get_drvdata(dev); 325 + struct ifs_device *d = container_of(m, struct ifs_device, misc); 326 + 327 + return d->test_msrs; 402 328 } 403 329 404 330 extern bool *ifs_pkg_auth;
+26 -14
drivers/platform/x86/intel/ifs/load.c
··· 118 118 union ifs_scan_hashes_status hashes_status; 119 119 union ifs_chunks_auth_status chunk_status; 120 120 struct device *dev = local_work->dev; 121 + const struct ifs_test_msrs *msrs; 121 122 int i, num_chunks, chunk_size; 122 123 struct ifs_data *ifsd; 123 124 u64 linear_addr, base; 124 125 u32 err_code; 125 126 126 127 ifsd = ifs_get_data(dev); 128 + msrs = ifs_get_test_msrs(dev); 127 129 /* run scan hash copy */ 128 - wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr); 129 - rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data); 130 + wrmsrl(msrs->copy_hashes, ifs_hash_ptr); 131 + rdmsrl(msrs->copy_hashes_status, hashes_status.data); 130 132 131 133 /* enumerate the scan image information */ 132 134 num_chunks = hashes_status.num_chunks; ··· 149 147 linear_addr = base + i * chunk_size; 150 148 linear_addr |= i; 151 149 152 - wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr); 153 - rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data); 150 + wrmsrl(msrs->copy_chunks, linear_addr); 151 + rdmsrl(msrs->copy_chunks_status, chunk_status.data); 154 152 155 153 ifsd->valid_chunks = chunk_status.valid_chunks; 156 154 err_code = chunk_status.error_code; ··· 182 180 union ifs_scan_hashes_status_gen2 hashes_status; 183 181 union ifs_chunks_auth_status_gen2 chunk_status; 184 182 u32 err_code, valid_chunks, total_chunks; 183 + const struct ifs_test_msrs *msrs; 185 184 int i, num_chunks, chunk_size; 186 185 union meta_data *ifs_meta; 187 186 int starting_chunk_nr; ··· 192 189 int retry_count; 193 190 194 191 ifsd = ifs_get_data(dev); 192 + msrs = ifs_get_test_msrs(dev); 195 193 196 194 if (need_copy_scan_hashes(ifsd)) { 197 - wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr); 198 - rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data); 195 + wrmsrl(msrs->copy_hashes, ifs_hash_ptr); 196 + rdmsrl(msrs->copy_hashes_status, hashes_status.data); 199 197 200 198 /* enumerate the scan image information */ 201 199 chunk_size = hashes_status.chunk_size * SZ_1K; ··· 216 212 } 217 213 218 214 if (ifsd->generation >= IFS_GEN_STRIDE_AWARE) { 219 - wrmsrl(MSR_SAF_CTRL, INVALIDATE_STRIDE); 220 - rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data); 215 + wrmsrl(msrs->test_ctrl, INVALIDATE_STRIDE); 216 + rdmsrl(msrs->copy_chunks_status, chunk_status.data); 221 217 if (chunk_status.valid_chunks != 0) { 222 218 dev_err(dev, "Couldn't invalidate installed stride - %d\n", 223 219 chunk_status.valid_chunks); ··· 238 234 chunk_table[1] = linear_addr; 239 235 do { 240 236 local_irq_disable(); 241 - wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, (u64)chunk_table); 237 + wrmsrl(msrs->copy_chunks, (u64)chunk_table); 242 238 local_irq_enable(); 243 - rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data); 239 + rdmsrl(msrs->copy_chunks_status, chunk_status.data); 244 240 err_code = chunk_status.error_code; 245 241 } while (err_code == AUTH_INTERRUPTED_ERROR && --retry_count); 246 242 ··· 261 257 return -EIO; 262 258 } 263 259 ifsd->valid_chunks = valid_chunks; 260 + ifsd->max_bundle = chunk_status.max_bundle; 264 261 265 262 return 0; 266 263 } 267 264 268 265 static int validate_ifs_metadata(struct device *dev) 269 266 { 267 + const struct ifs_test_caps *test = ifs_get_test_caps(dev); 270 268 struct ifs_data *ifsd = ifs_get_data(dev); 271 269 union meta_data *ifs_meta; 272 270 char test_file[64]; 273 271 int ret = -EINVAL; 274 272 275 - snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.scan", 273 + snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.%s", 276 274 boot_cpu_data.x86, boot_cpu_data.x86_model, 277 - boot_cpu_data.x86_stepping, ifsd->cur_batch); 275 + boot_cpu_data.x86_stepping, ifsd->cur_batch, test->image_suffix); 278 276 279 277 ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS); 280 278 if (!ifs_meta) { ··· 303 297 (ifs_meta->starting_chunk % ifs_meta->chunks_per_stride != 0)) { 304 298 dev_warn(dev, "Starting chunk num %u not a multiple of chunks_per_stride %u\n", 305 299 ifs_meta->starting_chunk, ifs_meta->chunks_per_stride); 300 + return ret; 301 + } 302 + 303 + if (ifs_meta->test_type != test->test_num) { 304 + dev_warn(dev, "Metadata test_type %d mismatches with device type\n", 305 + ifs_meta->test_type); 306 306 return ret; 307 307 } 308 308 ··· 399 387 char scan_path[64]; 400 388 int ret; 401 389 402 - snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.scan", 390 + snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.%s", 403 391 test->test_num, boot_cpu_data.x86, boot_cpu_data.x86_model, 404 - boot_cpu_data.x86_stepping, ifsd->cur_batch); 392 + boot_cpu_data.x86_stepping, ifsd->cur_batch, test->image_suffix); 405 393 406 394 ret = request_firmware_direct(&fw, scan_path, dev); 407 395 if (ret) {
+233
drivers/platform/x86/intel/ifs/runtest.c
··· 29 29 union ifs_status status; 30 30 }; 31 31 32 + struct sbaf_run_params { 33 + struct ifs_data *ifsd; 34 + int *retry_cnt; 35 + union ifs_sbaf *activate; 36 + union ifs_sbaf_status status; 37 + }; 38 + 32 39 /* 33 40 * Number of TSC cycles that a logical CPU will wait for the other 34 41 * logical CPU on the core in the WRMSR(ACTIVATE_SCAN). ··· 153 146 #define SPINUNIT 100 /* 100 nsec */ 154 147 static atomic_t array_cpus_in; 155 148 static atomic_t scan_cpus_in; 149 + static atomic_t sbaf_cpus_in; 156 150 157 151 /* 158 152 * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() ··· 395 387 ifsd->status = SCAN_TEST_PASS; 396 388 } 397 389 390 + #define SBAF_STATUS_PASS 0 391 + #define SBAF_STATUS_SIGN_FAIL 1 392 + #define SBAF_STATUS_INTR 2 393 + #define SBAF_STATUS_TEST_FAIL 3 394 + 395 + enum sbaf_status_err_code { 396 + IFS_SBAF_NO_ERROR = 0, 397 + IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN = 1, 398 + IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS = 2, 399 + IFS_SBAF_UNASSIGNED_ERROR_CODE3 = 3, 400 + IFS_SBAF_INVALID_BUNDLE_INDEX = 4, 401 + IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS = 5, 402 + IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY = 6, 403 + IFS_SBAF_UNASSIGNED_ERROR_CODE7 = 7, 404 + IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT = 8, 405 + IFS_SBAF_INTERRUPTED_DURING_EXECUTION = 9, 406 + IFS_SBAF_INVALID_PROGRAM_INDEX = 0xA, 407 + IFS_SBAF_CORRUPTED_CHUNK = 0xB, 408 + IFS_SBAF_DID_NOT_START = 0xC, 409 + }; 410 + 411 + static const char * const sbaf_test_status[] = { 412 + [IFS_SBAF_NO_ERROR] = "SBAF no error", 413 + [IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN] = "Other thread could not join.", 414 + [IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS] = "Interrupt occurred prior to SBAF coordination.", 415 + [IFS_SBAF_UNASSIGNED_ERROR_CODE3] = "Unassigned error code 0x3", 416 + [IFS_SBAF_INVALID_BUNDLE_INDEX] = "Non-valid sbaf bundles. Reload test image", 417 + [IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS] = "Mismatch in arguments between threads T0/T1.", 418 + [IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY] = "Core not capable of performing SBAF currently", 419 + [IFS_SBAF_UNASSIGNED_ERROR_CODE7] = "Unassigned error code 0x7", 420 + [IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT] = "Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently", 421 + [IFS_SBAF_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SBAF start", 422 + [IFS_SBAF_INVALID_PROGRAM_INDEX] = "SBAF program index not valid", 423 + [IFS_SBAF_CORRUPTED_CHUNK] = "SBAF operation aborted due to corrupted chunk", 424 + [IFS_SBAF_DID_NOT_START] = "SBAF operation did not start", 425 + }; 426 + 427 + static void sbaf_message_not_tested(struct device *dev, int cpu, u64 status_data) 428 + { 429 + union ifs_sbaf_status status = (union ifs_sbaf_status)status_data; 430 + 431 + if (status.error_code < ARRAY_SIZE(sbaf_test_status)) { 432 + dev_info(dev, "CPU(s) %*pbl: SBAF operation did not start. %s\n", 433 + cpumask_pr_args(cpu_smt_mask(cpu)), 434 + sbaf_test_status[status.error_code]); 435 + } else if (status.error_code == IFS_SW_TIMEOUT) { 436 + dev_info(dev, "CPU(s) %*pbl: software timeout during scan\n", 437 + cpumask_pr_args(cpu_smt_mask(cpu))); 438 + } else if (status.error_code == IFS_SW_PARTIAL_COMPLETION) { 439 + dev_info(dev, "CPU(s) %*pbl: %s\n", 440 + cpumask_pr_args(cpu_smt_mask(cpu)), 441 + "Not all SBAF bundles executed. Maximum forward progress retries exceeded"); 442 + } else { 443 + dev_info(dev, "CPU(s) %*pbl: SBAF unknown status %llx\n", 444 + cpumask_pr_args(cpu_smt_mask(cpu)), status.data); 445 + } 446 + } 447 + 448 + static void sbaf_message_fail(struct device *dev, int cpu, union ifs_sbaf_status status) 449 + { 450 + /* Failed signature check is set when SBAF signature did not match the expected value */ 451 + if (status.sbaf_status == SBAF_STATUS_SIGN_FAIL) { 452 + dev_err(dev, "CPU(s) %*pbl: Failed signature check\n", 453 + cpumask_pr_args(cpu_smt_mask(cpu))); 454 + } 455 + 456 + /* Failed to reach end of test */ 457 + if (status.sbaf_status == SBAF_STATUS_TEST_FAIL) { 458 + dev_err(dev, "CPU(s) %*pbl: Failed to complete test\n", 459 + cpumask_pr_args(cpu_smt_mask(cpu))); 460 + } 461 + } 462 + 463 + static bool sbaf_bundle_completed(union ifs_sbaf_status status) 464 + { 465 + return !(status.sbaf_status || status.error_code); 466 + } 467 + 468 + static bool sbaf_can_restart(union ifs_sbaf_status status) 469 + { 470 + enum sbaf_status_err_code err_code = status.error_code; 471 + 472 + /* Signature for chunk is bad, or scan test failed */ 473 + if (status.sbaf_status == SBAF_STATUS_SIGN_FAIL || 474 + status.sbaf_status == SBAF_STATUS_TEST_FAIL) 475 + return false; 476 + 477 + switch (err_code) { 478 + case IFS_SBAF_NO_ERROR: 479 + case IFS_SBAF_OTHER_THREAD_COULD_NOT_JOIN: 480 + case IFS_SBAF_INTERRUPTED_BEFORE_RENDEZVOUS: 481 + case IFS_SBAF_EXCEED_NUMBER_OF_THREADS_CONCURRENT: 482 + case IFS_SBAF_INTERRUPTED_DURING_EXECUTION: 483 + return true; 484 + case IFS_SBAF_UNASSIGNED_ERROR_CODE3: 485 + case IFS_SBAF_INVALID_BUNDLE_INDEX: 486 + case IFS_SBAF_MISMATCH_ARGS_BETWEEN_THREADS: 487 + case IFS_SBAF_CORE_NOT_CAPABLE_CURRENTLY: 488 + case IFS_SBAF_UNASSIGNED_ERROR_CODE7: 489 + case IFS_SBAF_INVALID_PROGRAM_INDEX: 490 + case IFS_SBAF_CORRUPTED_CHUNK: 491 + case IFS_SBAF_DID_NOT_START: 492 + break; 493 + } 494 + return false; 495 + } 496 + 497 + /* 498 + * Execute the SBAF test. Called "simultaneously" on all threads of a core 499 + * at high priority using the stop_cpus mechanism. 500 + */ 501 + static int dosbaf(void *data) 502 + { 503 + struct sbaf_run_params *run_params = data; 504 + int cpu = smp_processor_id(); 505 + union ifs_sbaf_status status; 506 + struct ifs_data *ifsd; 507 + int first; 508 + 509 + ifsd = run_params->ifsd; 510 + 511 + /* Only the first logical CPU on a core reports result */ 512 + first = cpumask_first(cpu_smt_mask(cpu)); 513 + wait_for_sibling_cpu(&sbaf_cpus_in, NSEC_PER_SEC); 514 + 515 + /* 516 + * This WRMSR will wait for other HT threads to also write 517 + * to this MSR (at most for activate.delay cycles). Then it 518 + * starts scan of each requested bundle. The core test happens 519 + * during the "execution" of the WRMSR. 520 + */ 521 + wrmsrl(MSR_ACTIVATE_SBAF, run_params->activate->data); 522 + rdmsrl(MSR_SBAF_STATUS, status.data); 523 + trace_ifs_sbaf(ifsd->cur_batch, *run_params->activate, status); 524 + 525 + /* Pass back the result of the test */ 526 + if (cpu == first) 527 + run_params->status = status; 528 + 529 + return 0; 530 + } 531 + 532 + static void ifs_sbaf_test_core(int cpu, struct device *dev) 533 + { 534 + struct sbaf_run_params run_params; 535 + union ifs_sbaf_status status = {}; 536 + union ifs_sbaf activate; 537 + unsigned long timeout; 538 + struct ifs_data *ifsd; 539 + int stop_bundle; 540 + int retries; 541 + 542 + ifsd = ifs_get_data(dev); 543 + 544 + activate.data = 0; 545 + activate.delay = IFS_THREAD_WAIT; 546 + 547 + timeout = jiffies + 2 * HZ; 548 + retries = MAX_IFS_RETRIES; 549 + activate.bundle_idx = 0; 550 + stop_bundle = ifsd->max_bundle; 551 + 552 + while (activate.bundle_idx <= stop_bundle) { 553 + if (time_after(jiffies, timeout)) { 554 + status.error_code = IFS_SW_TIMEOUT; 555 + break; 556 + } 557 + 558 + atomic_set(&sbaf_cpus_in, 0); 559 + 560 + run_params.ifsd = ifsd; 561 + run_params.activate = &activate; 562 + run_params.retry_cnt = &retries; 563 + stop_core_cpuslocked(cpu, dosbaf, &run_params); 564 + 565 + status = run_params.status; 566 + 567 + if (sbaf_bundle_completed(status)) { 568 + activate.bundle_idx = status.bundle_idx + 1; 569 + activate.pgm_idx = 0; 570 + retries = MAX_IFS_RETRIES; 571 + continue; 572 + } 573 + 574 + /* Some cases can be retried, give up for others */ 575 + if (!sbaf_can_restart(status)) 576 + break; 577 + 578 + if (status.pgm_idx == activate.pgm_idx) { 579 + /* If no progress retry */ 580 + if (--retries == 0) { 581 + if (status.error_code == IFS_NO_ERROR) 582 + status.error_code = IFS_SW_PARTIAL_COMPLETION; 583 + break; 584 + } 585 + } else { 586 + /* if some progress, more pgms remaining in bundle, reset retries */ 587 + retries = MAX_IFS_RETRIES; 588 + activate.bundle_idx = status.bundle_idx; 589 + activate.pgm_idx = status.pgm_idx; 590 + } 591 + } 592 + 593 + /* Update status for this core */ 594 + ifsd->scan_details = status.data; 595 + 596 + if (status.sbaf_status == SBAF_STATUS_SIGN_FAIL || 597 + status.sbaf_status == SBAF_STATUS_TEST_FAIL) { 598 + ifsd->status = SCAN_TEST_FAIL; 599 + sbaf_message_fail(dev, cpu, status); 600 + } else if (status.error_code || status.sbaf_status == SBAF_STATUS_INTR || 601 + (activate.bundle_idx < stop_bundle)) { 602 + ifsd->status = SCAN_NOT_TESTED; 603 + sbaf_message_not_tested(dev, cpu, status.data); 604 + } else { 605 + ifsd->status = SCAN_TEST_PASS; 606 + } 607 + } 608 + 398 609 /* 399 610 * Initiate per core test. It wakes up work queue threads on the target cpu and 400 611 * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and ··· 646 419 ifs_array_test_core(cpu, dev); 647 420 else 648 421 ifs_array_test_gen1(cpu, dev); 422 + break; 423 + case IFS_TYPE_SBAF: 424 + if (!ifsd->loaded) 425 + ret = -EPERM; 426 + else 427 + ifs_sbaf_test_core(cpu, dev); 649 428 break; 650 429 default: 651 430 ret = -EINVAL;
+6 -3
drivers/platform/x86/intel/int3472/Makefile
··· 1 1 obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \ 2 - intel_skl_int3472_tps68470.o 3 - intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o led.o common.o 4 - intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o 2 + intel_skl_int3472_tps68470.o \ 3 + intel_skl_int3472_common.o 4 + intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o led.o 5 + intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o 6 + 7 + intel_skl_int3472_common-y += common.o
+7
drivers/platform/x86/intel/int3472/common.c
··· 29 29 30 30 return obj; 31 31 } 32 + EXPORT_SYMBOL_GPL(skl_int3472_get_acpi_buffer); 32 33 33 34 int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb) 34 35 { ··· 53 52 kfree(obj); 54 53 return ret; 55 54 } 55 + EXPORT_SYMBOL_GPL(skl_int3472_fill_cldb); 56 56 57 57 /* sensor_adev_ret may be NULL, name_ret must not be NULL */ 58 58 int skl_int3472_get_sensor_adev_and_name(struct device *dev, ··· 82 80 83 81 return ret; 84 82 } 83 + EXPORT_SYMBOL_GPL(skl_int3472_get_sensor_adev_and_name); 84 + 85 + MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver library"); 86 + MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>"); 87 + MODULE_LICENSE("GPL");
+3 -6
drivers/platform/x86/intel/int3472/discrete.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/overflow.h> 13 13 #include <linux/platform_device.h> 14 + #include <linux/string_choices.h> 14 15 #include <linux/uuid.h> 15 16 16 17 #include "common.h" ··· 70 69 if (!adev) 71 70 return -ENODEV; 72 71 73 - table_entry->key = acpi_dev_name(adev); 74 - table_entry->chip_hwnum = agpio->pin_table[0]; 75 - table_entry->con_id = func; 76 - table_entry->idx = 0; 77 - table_entry->flags = polarity; 72 + *table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, polarity); 78 73 79 74 return 0; 80 75 } ··· 231 234 232 235 dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func, 233 236 agpio->resource_source.string_ptr, agpio->pin_table[0], 234 - (polarity == GPIO_ACTIVE_HIGH) ? "high" : "low"); 237 + str_high_low(polarity == GPIO_ACTIVE_HIGH)); 235 238 236 239 switch (type) { 237 240 case INT3472_GPIO_TYPE_RESET:
+1 -2
drivers/platform/x86/intel/oaktrail.c
··· 28 28 #include <linux/backlight.h> 29 29 #include <linux/dmi.h> 30 30 #include <linux/err.h> 31 - #include <linux/fb.h> 32 31 #include <linux/i2c.h> 33 32 #include <linux/kernel.h> 34 33 #include <linux/module.h> ··· 249 250 oaktrail_bl_device = bd; 250 251 251 252 bd->props.brightness = get_backlight_brightness(bd); 252 - bd->props.power = FB_BLANK_UNBLANK; 253 + bd->props.power = BACKLIGHT_POWER_ON; 253 254 backlight_update_status(bd); 254 255 255 256 return 0;
+71 -12
drivers/platform/x86/intel/pmc/core.c
··· 715 715 } 716 716 DEFINE_SHOW_ATTRIBUTE(pmc_core_s0ix_blocker); 717 717 718 + static void pmc_core_ltr_ignore_all(struct pmc_dev *pmcdev) 719 + { 720 + unsigned int i; 721 + 722 + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); i++) { 723 + struct pmc *pmc; 724 + u32 ltr_ign; 725 + 726 + pmc = pmcdev->pmcs[i]; 727 + if (!pmc) 728 + continue; 729 + 730 + guard(mutex)(&pmcdev->lock); 731 + pmc->ltr_ign = pmc_core_reg_read(pmc, pmc->map->ltr_ignore_offset); 732 + 733 + /* ltr_ignore_max is the max index value for LTR ignore register */ 734 + ltr_ign = pmc->ltr_ign | GENMASK(pmc->map->ltr_ignore_max, 0); 735 + pmc_core_reg_write(pmc, pmc->map->ltr_ignore_offset, ltr_ign); 736 + } 737 + 738 + /* 739 + * Ignoring ME during suspend is blocking platforms with ADL PCH to get to 740 + * deeper S0ix substate. 741 + */ 742 + pmc_core_send_ltr_ignore(pmcdev, 6, 0); 743 + } 744 + 745 + static void pmc_core_ltr_restore_all(struct pmc_dev *pmcdev) 746 + { 747 + unsigned int i; 748 + 749 + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); i++) { 750 + struct pmc *pmc; 751 + 752 + pmc = pmcdev->pmcs[i]; 753 + if (!pmc) 754 + continue; 755 + 756 + guard(mutex)(&pmcdev->lock); 757 + pmc_core_reg_write(pmc, pmc->map->ltr_ignore_offset, pmc->ltr_ign); 758 + } 759 + } 760 + 718 761 static inline u64 adjust_lpm_residency(struct pmc *pmc, u32 offset, 719 762 const int lpm_adj_x2) 720 763 { ··· 772 729 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 773 730 const int lpm_adj_x2 = pmc->map->lpm_res_counter_step_x2; 774 731 u32 offset = pmc->map->lpm_residency_offset; 775 - unsigned int i; 776 732 int mode; 777 733 778 734 seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); 779 735 780 - pmc_for_each_mode(i, mode, pmcdev) { 736 + pmc_for_each_mode(mode, pmcdev) { 781 737 seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], 782 738 adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); 783 739 } ··· 830 788 static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index) 831 789 { 832 790 struct pmc_dev *pmcdev = s->private; 833 - unsigned int i; 834 791 int mode; 835 792 836 793 seq_printf(s, "%30s |", "Element"); 837 - pmc_for_each_mode(i, mode, pmcdev) 794 + pmc_for_each_mode(mode, pmcdev) 838 795 seq_printf(s, " %9s |", pmc_lpm_modes[mode]); 839 796 840 - seq_printf(s, " %9s |\n", "Status"); 797 + seq_printf(s, " %9s |", "Status"); 798 + seq_printf(s, " %11s |\n", "Live Status"); 841 799 } 842 800 843 801 static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) 844 802 { 845 803 struct pmc_dev *pmcdev = s->private; 846 804 u32 sts_offset; 805 + u32 sts_offset_live; 847 806 u32 *lpm_req_regs; 848 807 unsigned int mp, pmc_index; 849 808 int num_maps; ··· 859 816 maps = pmc->map->lpm_sts; 860 817 num_maps = pmc->map->lpm_num_maps; 861 818 sts_offset = pmc->map->lpm_status_offset; 819 + sts_offset_live = pmc->map->lpm_live_status_offset; 862 820 lpm_req_regs = pmc->lpm_req_regs; 863 821 864 822 /* ··· 877 833 for (mp = 0; mp < num_maps; mp++) { 878 834 u32 req_mask = 0; 879 835 u32 lpm_status; 836 + u32 lpm_status_live; 880 837 const struct pmc_bit_map *map; 881 - int mode, idx, i, len = 32; 838 + int mode, i, len = 32; 882 839 883 840 /* 884 841 * Capture the requirements and create a mask so that we only 885 842 * show an element if it's required for at least one of the 886 843 * enabled low power modes 887 844 */ 888 - pmc_for_each_mode(idx, mode, pmcdev) 845 + pmc_for_each_mode(mode, pmcdev) 889 846 req_mask |= lpm_req_regs[mp + (mode * num_maps)]; 890 847 891 848 /* Get the last latched status for this map */ 892 849 lpm_status = pmc_core_reg_read(pmc, sts_offset + (mp * 4)); 850 + 851 + /* Get the runtime status for this map */ 852 + lpm_status_live = pmc_core_reg_read(pmc, sts_offset_live + (mp * 4)); 893 853 894 854 /* Loop over elements in this map */ 895 855 map = maps[mp]; ··· 912 864 seq_printf(s, "pmc%d: %26s |", pmc_index, map[i].name); 913 865 914 866 /* Loop over the enabled states and display if required */ 915 - pmc_for_each_mode(idx, mode, pmcdev) { 867 + pmc_for_each_mode(mode, pmcdev) { 916 868 bool required = lpm_req_regs[mp + (mode * num_maps)] & 917 869 bit_mask; 918 870 seq_printf(s, " %9s |", required ? "Required" : " "); ··· 920 872 921 873 /* In Status column, show the last captured state of this agent */ 922 874 seq_printf(s, " %9s |", lpm_status & bit_mask ? "Yes" : " "); 875 + 876 + /* In Live status column, show the live state of this agent */ 877 + seq_printf(s, " %11s |", lpm_status_live & bit_mask ? "Yes" : " "); 923 878 924 879 seq_puts(s, "\n"); 925 880 } ··· 977 926 { 978 927 struct pmc_dev *pmcdev = s->private; 979 928 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 980 - unsigned int idx; 981 929 bool c10; 982 930 u32 reg; 983 931 int mode; ··· 990 940 c10 = true; 991 941 } 992 942 993 - pmc_for_each_mode(idx, mode, pmcdev) { 943 + pmc_for_each_mode(mode, pmcdev) { 994 944 if ((BIT(mode) & reg) && !c10) 995 945 seq_printf(s, " [%s]", pmc_lpm_modes[mode]); 996 946 else ··· 1011 961 struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 1012 962 bool clear = false, c10 = false; 1013 963 unsigned char buf[8]; 1014 - unsigned int idx; 1015 964 int m, mode; 1016 965 u32 reg; 1017 966 ··· 1029 980 mode = sysfs_match_string(pmc_lpm_modes, buf); 1030 981 1031 982 /* Check string matches enabled mode */ 1032 - pmc_for_each_mode(idx, m, pmcdev) 983 + pmc_for_each_mode(m, pmcdev) 1033 984 if (mode == m) 1034 985 break; 1035 986 ··· 1573 1524 module_param(warn_on_s0ix_failures, bool, 0644); 1574 1525 MODULE_PARM_DESC(warn_on_s0ix_failures, "Check and warn for S0ix failures"); 1575 1526 1527 + static bool ltr_ignore_all_suspend = true; 1528 + module_param(ltr_ignore_all_suspend, bool, 0644); 1529 + MODULE_PARM_DESC(ltr_ignore_all_suspend, "Ignore all LTRs during suspend"); 1530 + 1576 1531 static __maybe_unused int pmc_core_suspend(struct device *dev) 1577 1532 { 1578 1533 struct pmc_dev *pmcdev = dev_get_drvdata(dev); ··· 1585 1532 1586 1533 if (pmcdev->suspend) 1587 1534 pmcdev->suspend(pmcdev); 1535 + 1536 + if (ltr_ignore_all_suspend) 1537 + pmc_core_ltr_ignore_all(pmcdev); 1588 1538 1589 1539 /* Check if the syspend will actually use S0ix */ 1590 1540 if (pm_suspend_via_firmware()) ··· 1694 1638 static __maybe_unused int pmc_core_resume(struct device *dev) 1695 1639 { 1696 1640 struct pmc_dev *pmcdev = dev_get_drvdata(dev); 1641 + 1642 + if (ltr_ignore_all_suspend) 1643 + pmc_core_ltr_restore_all(pmcdev); 1697 1644 1698 1645 if (pmcdev->resume) 1699 1646 return pmcdev->resume(pmcdev);
+8 -4
drivers/platform/x86/intel/pmc/core.h
··· 378 378 * @map: pointer to pmc_reg_map struct that contains platform 379 379 * specific attributes 380 380 * @lpm_req_regs: List of substate requirements 381 + * @ltr_ign: Holds LTR ignore data while suspended 381 382 * 382 383 * pmc contains info about one power management controller device. 383 384 */ ··· 387 386 void __iomem *regbase; 388 387 const struct pmc_reg_map *map; 389 388 u32 *lpm_req_regs; 389 + u32 ltr_ign; 390 390 }; 391 391 392 392 /** ··· 614 612 void cnl_suspend(struct pmc_dev *pmcdev); 615 613 int cnl_resume(struct pmc_dev *pmcdev); 616 614 617 - #define pmc_for_each_mode(i, mode, pmcdev) \ 618 - for (i = 0, mode = pmcdev->lpm_en_modes[i]; \ 619 - i < pmcdev->num_lpm_modes; \ 620 - i++, mode = pmcdev->lpm_en_modes[i]) 615 + #define pmc_for_each_mode(mode, pmcdev) \ 616 + for (unsigned int __i = 0, __cond; \ 617 + __cond = __i < (pmcdev)->num_lpm_modes, \ 618 + __cond && ((mode) = (pmcdev)->lpm_en_modes[__i]), \ 619 + __cond; \ 620 + __i++) 621 621 622 622 #define DEFINE_PMC_CORE_ATTR_WRITE(__name) \ 623 623 static int __name ## _open(struct inode *inode, struct file *file) \
+3 -3
drivers/platform/x86/intel/pmc/core_ssram.c
··· 9 9 */ 10 10 11 11 #include <linux/cleanup.h> 12 + #include <linux/intel_vsec.h> 12 13 #include <linux/pci.h> 13 14 #include <linux/io-64-nonatomic-lo-hi.h> 14 15 15 16 #include "core.h" 16 - #include "../vsec.h" 17 17 #include "../pmt/telemetry.h" 18 18 19 19 #define SSRAM_HDR_SIZE 0x100 ··· 45 45 struct telem_endpoint *ep; 46 46 const u8 *lpm_indices; 47 47 int num_maps, mode_offset = 0; 48 - int ret, mode, i; 48 + int ret, mode; 49 49 int lpm_size; 50 50 u32 guid; 51 51 ··· 116 116 * 117 117 */ 118 118 mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; 119 - pmc_for_each_mode(i, mode, pmcdev) { 119 + pmc_for_each_mode(mode, pmcdev) { 120 120 u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); 121 121 int m; 122 122
+21 -7
drivers/platform/x86/intel/pmt/class.c
··· 9 9 */ 10 10 11 11 #include <linux/kernel.h> 12 + #include <linux/intel_vsec.h> 12 13 #include <linux/io-64-nonatomic-lo-hi.h> 13 14 #include <linux/module.h> 14 15 #include <linux/mm.h> 15 16 #include <linux/pci.h> 16 17 17 - #include "../vsec.h" 18 18 #include "class.h" 19 19 20 20 #define PMT_XA_START 1 ··· 58 58 return count; 59 59 } 60 60 61 + int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, 62 + void __iomem *addr, u32 count) 63 + { 64 + if (cb && cb->read_telem) 65 + return cb->read_telem(pdev, guid, buf, count); 66 + 67 + if (guid == GUID_SPR_PUNIT) 68 + /* PUNIT on SPR only supports aligned 64-bit read */ 69 + return pmt_memcpy64_fromio(buf, addr, count); 70 + 71 + memcpy_fromio(buf, addr, count); 72 + 73 + return count; 74 + } 75 + EXPORT_SYMBOL_NS_GPL(pmt_telem_read_mmio, INTEL_PMT); 76 + 61 77 /* 62 78 * sysfs 63 79 */ ··· 95 79 if (count > entry->size - off) 96 80 count = entry->size - off; 97 81 98 - if (entry->guid == GUID_SPR_PUNIT) 99 - /* PUNIT on SPR only supports aligned 64-bit read */ 100 - count = pmt_memcpy64_fromio(buf, entry->base + off, count); 101 - else 102 - memcpy_fromio(buf, entry->base + off, count); 82 + count = pmt_telem_read_mmio(entry->ep->pcidev, entry->cb, entry->header.guid, buf, 83 + entry->base + off, count); 103 84 104 85 return count; 105 86 } ··· 252 239 253 240 entry->guid = header->guid; 254 241 entry->size = header->size; 242 + entry->cb = ivdev->priv_data; 255 243 256 244 return 0; 257 245 } ··· 314 300 goto fail_ioremap; 315 301 316 302 if (ns->pmt_add_endpoint) { 317 - ret = ns->pmt_add_endpoint(entry, ivdev->pcidev); 303 + ret = ns->pmt_add_endpoint(ivdev, entry); 318 304 if (ret) 319 305 goto fail_add_endpoint; 320 306 }
+7 -3
drivers/platform/x86/intel/pmt/class.h
··· 2 2 #ifndef _INTEL_PMT_CLASS_H 3 3 #define _INTEL_PMT_CLASS_H 4 4 5 + #include <linux/intel_vsec.h> 5 6 #include <linux/xarray.h> 6 7 #include <linux/types.h> 7 8 #include <linux/bits.h> 8 9 #include <linux/err.h> 9 10 #include <linux/io.h> 10 11 11 - #include "../vsec.h" 12 12 #include "telemetry.h" 13 13 14 14 /* PMT access types */ ··· 24 24 struct telem_endpoint { 25 25 struct pci_dev *pcidev; 26 26 struct telem_header header; 27 + struct pmt_callbacks *cb; 27 28 void __iomem *base; 28 29 bool present; 29 30 struct kref kref; ··· 44 43 struct kobject *kobj; 45 44 void __iomem *disc_table; 46 45 void __iomem *base; 46 + struct pmt_callbacks *cb; 47 47 unsigned long base_addr; 48 48 size_t size; 49 49 u32 guid; ··· 57 55 const struct attribute_group *attr_grp; 58 56 int (*pmt_header_decode)(struct intel_pmt_entry *entry, 59 57 struct device *dev); 60 - int (*pmt_add_endpoint)(struct intel_pmt_entry *entry, 61 - struct pci_dev *pdev); 58 + int (*pmt_add_endpoint)(struct intel_vsec_device *ivdev, 59 + struct intel_pmt_entry *entry); 62 60 }; 63 61 62 + int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid, void *buf, 63 + void __iomem *addr, u32 count); 64 64 bool intel_pmt_is_early_client_hw(struct device *dev); 65 65 int intel_pmt_dev_create(struct intel_pmt_entry *entry, 66 66 struct intel_pmt_namespace *ns,
+1 -1
drivers/platform/x86/intel/pmt/crashlog.c
··· 9 9 */ 10 10 11 11 #include <linux/auxiliary_bus.h> 12 + #include <linux/intel_vsec.h> 12 13 #include <linux/kernel.h> 13 14 #include <linux/module.h> 14 15 #include <linux/pci.h> ··· 17 16 #include <linux/uaccess.h> 18 17 #include <linux/overflow.h> 19 18 20 - #include "../vsec.h" 21 19 #include "class.h" 22 20 23 21 /* Crashlog discovery header types */
+7 -5
drivers/platform/x86/intel/pmt/telemetry.c
··· 9 9 */ 10 10 11 11 #include <linux/auxiliary_bus.h> 12 + #include <linux/intel_vsec.h> 12 13 #include <linux/kernel.h> 13 14 #include <linux/module.h> 14 15 #include <linux/pci.h> ··· 17 16 #include <linux/uaccess.h> 18 17 #include <linux/overflow.h> 19 18 20 - #include "../vsec.h" 21 19 #include "class.h" 22 20 23 21 #define TELEM_SIZE_OFFSET 0x0 ··· 93 93 return 0; 94 94 } 95 95 96 - static int pmt_telem_add_endpoint(struct intel_pmt_entry *entry, 97 - struct pci_dev *pdev) 96 + static int pmt_telem_add_endpoint(struct intel_vsec_device *ivdev, 97 + struct intel_pmt_entry *entry) 98 98 { 99 99 struct telem_endpoint *ep; 100 100 ··· 104 104 return -ENOMEM; 105 105 106 106 ep = entry->ep; 107 - ep->pcidev = pdev; 107 + ep->pcidev = ivdev->pcidev; 108 108 ep->header.access_type = entry->header.access_type; 109 109 ep->header.guid = entry->header.guid; 110 110 ep->header.base_offset = entry->header.base_offset; 111 111 ep->header.size = entry->header.size; 112 112 ep->base = entry->base; 113 113 ep->present = true; 114 + ep->cb = ivdev->priv_data; 114 115 115 116 kref_init(&ep->kref); 116 117 ··· 219 218 if (offset + NUM_BYTES_QWORD(count) > size) 220 219 return -EINVAL; 221 220 222 - memcpy_fromio(data, ep->base + offset, NUM_BYTES_QWORD(count)); 221 + pmt_telem_read_mmio(ep->pcidev, ep->cb, ep->header.guid, data, ep->base + offset, 222 + NUM_BYTES_QWORD(count)); 223 223 224 224 return ep->present ? 0 : -EPIPE; 225 225 }
+1 -2
drivers/platform/x86/intel/sdsi.c
··· 12 12 #include <linux/bits.h> 13 13 #include <linux/bitfield.h> 14 14 #include <linux/device.h> 15 + #include <linux/intel_vsec.h> 15 16 #include <linux/iopoll.h> 16 17 #include <linux/kernel.h> 17 18 #include <linux/module.h> ··· 22 21 #include <linux/sysfs.h> 23 22 #include <linux/types.h> 24 23 #include <linux/uaccess.h> 25 - 26 - #include "vsec.h" 27 24 28 25 #define ACCESS_TYPE_BARID 2 29 26 #define ACCESS_TYPE_LOCAL 3
+10 -30
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
··· 651 651 652 652 /* Lock to prevent module registration when already opened by user space */ 653 653 static DEFINE_MUTEX(punit_misc_dev_open_lock); 654 - /* Lock to allow one shared misc device for all ISST interfaces */ 655 - static DEFINE_MUTEX(punit_misc_dev_reg_lock); 656 - static int misc_usage_count; 657 - static int misc_device_ret; 658 654 static int misc_device_open; 659 655 660 656 static int isst_if_open(struct inode *inode, struct file *file) ··· 716 720 717 721 static int isst_misc_reg(void) 718 722 { 719 - mutex_lock(&punit_misc_dev_reg_lock); 720 - if (misc_device_ret) 721 - goto unlock_exit; 723 + int ret; 722 724 723 - if (!misc_usage_count) { 724 - misc_device_ret = isst_if_cpu_info_init(); 725 - if (misc_device_ret) 726 - goto unlock_exit; 725 + ret = isst_if_cpu_info_init(); 726 + if (ret) 727 + return ret; 727 728 728 - misc_device_ret = misc_register(&isst_if_char_driver); 729 - if (misc_device_ret) { 730 - isst_if_cpu_info_exit(); 731 - goto unlock_exit; 732 - } 733 - } 734 - misc_usage_count++; 729 + ret = misc_register(&isst_if_char_driver); 730 + if (ret) 731 + isst_if_cpu_info_exit(); 735 732 736 - unlock_exit: 737 - mutex_unlock(&punit_misc_dev_reg_lock); 738 - 739 - return misc_device_ret; 733 + return ret; 740 734 } 741 735 742 736 static void isst_misc_unreg(void) 743 737 { 744 - mutex_lock(&punit_misc_dev_reg_lock); 745 - if (misc_usage_count) 746 - misc_usage_count--; 747 - if (!misc_usage_count && !misc_device_ret) { 748 - misc_deregister(&isst_if_char_driver); 749 - isst_if_cpu_info_exit(); 750 - } 751 - mutex_unlock(&punit_misc_dev_reg_lock); 738 + misc_deregister(&isst_if_char_driver); 739 + isst_if_cpu_info_exit(); 752 740 } 753 741 754 742 /**
+1 -2
drivers/platform/x86/intel/tpmi.c
··· 51 51 #include <linux/debugfs.h> 52 52 #include <linux/delay.h> 53 53 #include <linux/intel_tpmi.h> 54 + #include <linux/intel_vsec.h> 54 55 #include <linux/io.h> 55 56 #include <linux/iopoll.h> 56 57 #include <linux/module.h> ··· 59 58 #include <linux/security.h> 60 59 #include <linux/sizes.h> 61 60 #include <linux/string_helpers.h> 62 - 63 - #include "vsec.h" 64 61 65 62 /** 66 63 * struct intel_tpmi_pfs_entry - TPMI PM Feature Structure (PFS) entry
+37 -5
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
··· 60 60 static ssize_t store_attr(struct uncore_data *data, const char *buf, ssize_t count, 61 61 enum uncore_index index) 62 62 { 63 - unsigned int input; 63 + unsigned int input = 0; 64 64 int ret; 65 65 66 - if (kstrtouint(buf, 10, &input)) 67 - return -EINVAL; 66 + if (index == UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE) { 67 + if (kstrtobool(buf, (bool *)&input)) 68 + return -EINVAL; 69 + } else { 70 + if (kstrtouint(buf, 10, &input)) 71 + return -EINVAL; 72 + } 68 73 69 74 mutex_lock(&uncore_lock); 70 75 ret = uncore_write(data, input, index); ··· 107 102 show_uncore_attr(max_freq_khz, UNCORE_INDEX_MAX_FREQ); 108 103 109 104 show_uncore_attr(current_freq_khz, UNCORE_INDEX_CURRENT_FREQ); 105 + 106 + store_uncore_attr(elc_low_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD); 107 + store_uncore_attr(elc_high_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD); 108 + store_uncore_attr(elc_high_threshold_enable, 109 + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE); 110 + store_uncore_attr(elc_floor_freq_khz, UNCORE_INDEX_EFF_LAT_CTRL_FREQ); 111 + 112 + show_uncore_attr(elc_low_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD); 113 + show_uncore_attr(elc_high_threshold_percent, UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD); 114 + show_uncore_attr(elc_high_threshold_enable, 115 + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE); 116 + show_uncore_attr(elc_floor_freq_khz, UNCORE_INDEX_EFF_LAT_CTRL_FREQ); 110 117 111 118 #define show_uncore_data(member_name) \ 112 119 static ssize_t show_##member_name(struct kobject *kobj, \ ··· 163 146 164 147 static int create_attr_group(struct uncore_data *data, char *name) 165 148 { 166 - int ret, freq, index = 0; 149 + int ret, index = 0; 150 + unsigned int val; 167 151 168 152 init_attribute_rw(max_freq_khz); 169 153 init_attribute_rw(min_freq_khz); ··· 186 168 data->uncore_attrs[index++] = &data->initial_min_freq_khz_kobj_attr.attr; 187 169 data->uncore_attrs[index++] = &data->initial_max_freq_khz_kobj_attr.attr; 188 170 189 - ret = uncore_read(data, &freq, UNCORE_INDEX_CURRENT_FREQ); 171 + ret = uncore_read(data, &val, UNCORE_INDEX_CURRENT_FREQ); 190 172 if (!ret) 191 173 data->uncore_attrs[index++] = &data->current_freq_khz_kobj_attr.attr; 174 + 175 + ret = uncore_read(data, &val, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD); 176 + if (!ret) { 177 + init_attribute_rw(elc_low_threshold_percent); 178 + init_attribute_rw(elc_high_threshold_percent); 179 + init_attribute_rw(elc_high_threshold_enable); 180 + init_attribute_rw(elc_floor_freq_khz); 181 + 182 + data->uncore_attrs[index++] = &data->elc_low_threshold_percent_kobj_attr.attr; 183 + data->uncore_attrs[index++] = &data->elc_high_threshold_percent_kobj_attr.attr; 184 + data->uncore_attrs[index++] = 185 + &data->elc_high_threshold_enable_kobj_attr.attr; 186 + data->uncore_attrs[index++] = &data->elc_floor_freq_khz_kobj_attr.attr; 187 + } 192 188 193 189 data->uncore_attrs[index] = NULL; 194 190
+16 -1
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
··· 34 34 * @domain_id_kobj_attr: Storage for kobject attribute domain_id 35 35 * @fabric_cluster_id_kobj_attr: Storage for kobject attribute fabric_cluster_id 36 36 * @package_id_kobj_attr: Storage for kobject attribute package_id 37 + * @elc_low_threshold_percent_kobj_attr: 38 + Storage for kobject attribute elc_low_threshold_percent 39 + * @elc_high_threshold_percent_kobj_attr: 40 + Storage for kobject attribute elc_high_threshold_percent 41 + * @elc_high_threshold_enable_kobj_attr: 42 + Storage for kobject attribute elc_high_threshold_enable 43 + * @elc_floor_freq_khz_kobj_attr: Storage for kobject attribute elc_floor_freq_khz 37 44 * @uncore_attrs: Attribute storage for group creation 38 45 * 39 46 * This structure is used to encapsulate all data related to uncore sysfs ··· 68 61 struct kobj_attribute domain_id_kobj_attr; 69 62 struct kobj_attribute fabric_cluster_id_kobj_attr; 70 63 struct kobj_attribute package_id_kobj_attr; 71 - struct attribute *uncore_attrs[9]; 64 + struct kobj_attribute elc_low_threshold_percent_kobj_attr; 65 + struct kobj_attribute elc_high_threshold_percent_kobj_attr; 66 + struct kobj_attribute elc_high_threshold_enable_kobj_attr; 67 + struct kobj_attribute elc_floor_freq_khz_kobj_attr; 68 + struct attribute *uncore_attrs[13]; 72 69 }; 73 70 74 71 #define UNCORE_DOMAIN_ID_INVALID -1 ··· 81 70 UNCORE_INDEX_MIN_FREQ, 82 71 UNCORE_INDEX_MAX_FREQ, 83 72 UNCORE_INDEX_CURRENT_FREQ, 73 + UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD, 74 + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD, 75 + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, 76 + UNCORE_INDEX_EFF_LAT_CTRL_FREQ, 84 77 }; 85 78 86 79 int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *value,
+162 -3
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
··· 30 30 31 31 #define UNCORE_MAJOR_VERSION 0 32 32 #define UNCORE_MINOR_VERSION 2 33 + #define UNCORE_ELC_SUPPORTED_VERSION 2 33 34 #define UNCORE_HEADER_INDEX 0 34 35 #define UNCORE_FABRIC_CLUSTER_OFFSET 8 35 36 ··· 47 46 /* Information for each cluster */ 48 47 struct tpmi_uncore_cluster_info { 49 48 bool root_domain; 49 + bool elc_supported; 50 50 u8 __iomem *cluster_base; 51 51 struct uncore_data uncore_data; 52 52 struct tpmi_uncore_struct *uncore_root; ··· 77 75 /* Bit definitions for CONTROL register */ 78 76 #define UNCORE_MAX_RATIO_MASK GENMASK_ULL(14, 8) 79 77 #define UNCORE_MIN_RATIO_MASK GENMASK_ULL(21, 15) 78 + #define UNCORE_EFF_LAT_CTRL_RATIO_MASK GENMASK_ULL(28, 22) 79 + #define UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK GENMASK_ULL(38, 32) 80 + #define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE BIT(39) 81 + #define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK GENMASK_ULL(46, 40) 80 82 81 83 /* Helper function to read MMIO offset for max/min control frequency */ 82 84 static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, ··· 93 87 *value = FIELD_GET(UNCORE_MAX_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; 94 88 else 95 89 *value = FIELD_GET(UNCORE_MIN_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; 90 + } 91 + 92 + /* Helper function to read efficiency latency control values over MMIO */ 93 + static int read_eff_lat_ctrl(struct uncore_data *data, unsigned int *val, enum uncore_index index) 94 + { 95 + struct tpmi_uncore_cluster_info *cluster_info; 96 + u64 ctrl; 97 + 98 + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); 99 + if (cluster_info->root_domain) 100 + return -ENODATA; 101 + 102 + if (!cluster_info->elc_supported) 103 + return -EOPNOTSUPP; 104 + 105 + ctrl = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); 106 + 107 + switch (index) { 108 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 109 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK, ctrl); 110 + *val *= 100; 111 + *val = DIV_ROUND_UP(*val, FIELD_MAX(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK)); 112 + break; 113 + 114 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 115 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK, ctrl); 116 + *val *= 100; 117 + *val = DIV_ROUND_UP(*val, FIELD_MAX(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK)); 118 + break; 119 + 120 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 121 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, ctrl); 122 + break; 123 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 124 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_RATIO_MASK, ctrl) * UNCORE_FREQ_KHZ_MULTIPLIER; 125 + break; 126 + 127 + default: 128 + return -EOPNOTSUPP; 129 + } 130 + 131 + return 0; 96 132 } 97 133 98 134 #define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK) ··· 185 137 return 0; 186 138 } 187 139 140 + /* Helper function for writing efficiency latency control values over MMIO */ 141 + static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index) 142 + { 143 + struct tpmi_uncore_cluster_info *cluster_info; 144 + u64 control; 145 + 146 + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); 147 + 148 + if (cluster_info->root_domain) 149 + return -ENODATA; 150 + 151 + if (!cluster_info->elc_supported) 152 + return -EOPNOTSUPP; 153 + 154 + switch (index) { 155 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 156 + if (val > 100) 157 + return -EINVAL; 158 + break; 159 + 160 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 161 + if (val > 100) 162 + return -EINVAL; 163 + break; 164 + 165 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 166 + if (val > 1) 167 + return -EINVAL; 168 + break; 169 + 170 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 171 + val /= UNCORE_FREQ_KHZ_MULTIPLIER; 172 + if (val > FIELD_MAX(UNCORE_EFF_LAT_CTRL_RATIO_MASK)) 173 + return -EINVAL; 174 + break; 175 + 176 + default: 177 + return -EOPNOTSUPP; 178 + } 179 + 180 + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); 181 + 182 + switch (index) { 183 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 184 + val *= FIELD_MAX(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK); 185 + val /= 100; 186 + control &= ~UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK; 187 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK, val); 188 + break; 189 + 190 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 191 + val *= FIELD_MAX(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK); 192 + val /= 100; 193 + control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK; 194 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK, val); 195 + break; 196 + 197 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 198 + control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE; 199 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, val); 200 + break; 201 + 202 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 203 + control &= ~UNCORE_EFF_LAT_CTRL_RATIO_MASK; 204 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_RATIO_MASK, val); 205 + break; 206 + 207 + default: 208 + break; 209 + } 210 + 211 + writeq(control, cluster_info->cluster_base + UNCORE_CONTROL_INDEX); 212 + 213 + return 0; 214 + } 215 + 188 216 /* Helper function to write MMIO offset for max/min control frequency */ 189 217 static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input, 190 218 unsigned int index) ··· 280 156 writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX)); 281 157 } 282 158 283 - /* Callback for sysfs write for max/min frequencies. Called under mutex locks */ 159 + /* Helper for sysfs write for max/min frequencies. Called under mutex locks */ 284 160 static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, 285 161 enum uncore_index index) 286 162 { ··· 358 234 case UNCORE_INDEX_CURRENT_FREQ: 359 235 return uncore_read_freq(data, value); 360 236 237 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 238 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 239 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 240 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 241 + return read_eff_lat_ctrl(data, value, index); 242 + 243 + default: 244 + break; 245 + } 246 + 247 + return -EOPNOTSUPP; 248 + } 249 + 250 + /* Callback for sysfs write for TPMI uncore data. Called under mutex locks. */ 251 + static int uncore_write(struct uncore_data *data, unsigned int value, enum uncore_index index) 252 + { 253 + switch (index) { 254 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 255 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 256 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 257 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 258 + return write_eff_lat_ctrl(data, value, index); 259 + 260 + case UNCORE_INDEX_MIN_FREQ: 261 + case UNCORE_INDEX_MAX_FREQ: 262 + return uncore_write_control_freq(data, value, index); 263 + 361 264 default: 362 265 break; 363 266 } ··· 442 291 return -EINVAL; 443 292 444 293 /* Register callbacks to uncore core */ 445 - ret = uncore_freq_common_init(uncore_read, uncore_write_control_freq); 294 + ret = uncore_freq_common_init(uncore_read, uncore_write); 446 295 if (ret) 447 296 return ret; 448 297 ··· 560 409 561 410 cluster_info->uncore_root = tpmi_uncore; 562 411 412 + if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) >= UNCORE_ELC_SUPPORTED_VERSION) 413 + cluster_info->elc_supported = true; 414 + 563 415 ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0); 564 416 if (ret) { 565 417 cluster_info->cluster_base = NULL; ··· 580 426 } 581 427 582 428 auxiliary_set_drvdata(auxdev, tpmi_uncore); 429 + 430 + if (topology_max_dies_per_package() > 1) 431 + return 0; 583 432 584 433 tpmi_uncore->root_cluster.root_domain = true; 585 434 tpmi_uncore->root_cluster.uncore_root = tpmi_uncore; ··· 607 450 { 608 451 struct tpmi_uncore_struct *tpmi_uncore = auxiliary_get_drvdata(auxdev); 609 452 610 - uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data); 453 + if (tpmi_uncore->root_cluster.root_domain) 454 + uncore_freq_remove_die_entry(&tpmi_uncore->root_cluster.uncore_data); 455 + 611 456 remove_cluster_entries(tpmi_uncore); 612 457 613 458 uncore_freq_common_exit();
+4 -4
drivers/platform/x86/intel/vsec.c
··· 17 17 #include <linux/bits.h> 18 18 #include <linux/cleanup.h> 19 19 #include <linux/delay.h> 20 - #include <linux/kernel.h> 21 20 #include <linux/idr.h> 21 + #include <linux/intel_vsec.h> 22 + #include <linux/kernel.h> 22 23 #include <linux/module.h> 23 24 #include <linux/pci.h> 24 25 #include <linux/types.h> 25 - 26 - #include "vsec.h" 27 26 28 27 #define PMT_XA_START 0 29 28 #define PMT_XA_MAX INT_MAX ··· 212 213 intel_vsec_dev->num_resources = header->num_entries; 213 214 intel_vsec_dev->quirks = info->quirks; 214 215 intel_vsec_dev->base_addr = info->base_addr; 216 + intel_vsec_dev->priv_data = info->priv_data; 215 217 216 218 if (header->id == VSEC_ID_SDSI) 217 219 intel_vsec_dev->ida = &intel_vsec_sdsi_ida; ··· 341 341 void intel_vsec_register(struct pci_dev *pdev, 342 342 struct intel_vsec_platform_info *info) 343 343 { 344 - if (!pdev || !info) 344 + if (!pdev || !info || !info->headers) 345 345 return; 346 346 347 347 intel_vsec_walk_header(pdev, info);
+44 -3
drivers/platform/x86/intel/vsec.h include/linux/intel_vsec.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _VSEC_H 3 - #define _VSEC_H 2 + #ifndef _INTEL_VSEC_H 3 + #define _INTEL_VSEC_H 4 4 5 5 #include <linux/auxiliary_bus.h> 6 6 #include <linux/bits.h> ··· 67 67 VSEC_QUIRK_EARLY_HW = BIT(4), 68 68 }; 69 69 70 - /* Platform specific data */ 70 + /** 71 + * struct pmt_callbacks - Callback infrastructure for PMT devices 72 + * ->read_telem() when specified, called by client driver to access PMT data (instead 73 + * of direct copy). 74 + * @pdev: PCI device reference for the callback's use 75 + * @guid: ID of data to acccss 76 + * @data: buffer for the data to be copied 77 + * @count: size of buffer 78 + */ 79 + struct pmt_callbacks { 80 + int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, u32 count); 81 + }; 82 + 83 + /** 84 + * struct intel_vsec_platform_info - Platform specific data 85 + * @parent: parent device in the auxbus chain 86 + * @headers: list of headers to define the PMT client devices to create 87 + * @priv_data: private data, usable by parent devices, currently a callback 88 + * @caps: bitmask of PMT capabilities for the given headers 89 + * @quirks: bitmask of VSEC device quirks 90 + * @base_addr: allow a base address to be specified (rather than derived) 91 + */ 71 92 struct intel_vsec_platform_info { 72 93 struct device *parent; 73 94 struct intel_vsec_header **headers; 95 + void *priv_data; 74 96 unsigned long caps; 75 97 unsigned long quirks; 76 98 u64 base_addr; 77 99 }; 78 100 101 + /** 102 + * struct intel_sec_device - Auxbus specific device information 103 + * @auxdev: auxbus device struct for auxbus access 104 + * @pcidev: pci device associated with the device 105 + * @resource: any resources shared by the parent 106 + * @ida: id reference 107 + * @num_resources: number of resources 108 + * @id: xarray id 109 + * @priv_data: any private data needed 110 + * @quirks: specified quirks 111 + * @base_addr: base address of entries (if specified) 112 + */ 79 113 struct intel_vsec_device { 80 114 struct auxiliary_device auxdev; 81 115 struct pci_dev *pcidev; ··· 137 103 return container_of(auxdev, struct intel_vsec_device, auxdev); 138 104 } 139 105 106 + #if IS_ENABLED(CONFIG_INTEL_VSEC) 140 107 void intel_vsec_register(struct pci_dev *pdev, 141 108 struct intel_vsec_platform_info *info); 109 + #else 110 + static inline void intel_vsec_register(struct pci_dev *pdev, 111 + struct intel_vsec_platform_info *info) 112 + { 113 + } 114 + #endif 142 115 #endif
+1 -1
drivers/platform/x86/intel_scu_ipc.c
··· 23 23 #include <linux/module.h> 24 24 #include <linux/slab.h> 25 25 26 - #include <asm/intel_scu_ipc.h> 26 + #include <linux/platform_data/x86/intel_scu_ipc.h> 27 27 28 28 /* IPC defines the following message types */ 29 29 #define IPCMSG_PCNTRL 0xff /* Power controller unit read/write */
+1 -1
drivers/platform/x86/intel_scu_ipcutil.c
··· 18 18 #include <linux/types.h> 19 19 #include <linux/uaccess.h> 20 20 21 - #include <asm/intel_scu_ipc.h> 21 + #include <linux/platform_data/x86/intel_scu_ipc.h> 22 22 23 23 static int major; 24 24
+1 -1
drivers/platform/x86/intel_scu_pcidrv.c
··· 11 11 #include <linux/init.h> 12 12 #include <linux/pci.h> 13 13 14 - #include <asm/intel_scu_ipc.h> 14 + #include <linux/platform_data/x86/intel_scu_ipc.h> 15 15 16 16 static int intel_scu_pci_probe(struct pci_dev *pdev, 17 17 const struct pci_device_id *id)
+1 -1
drivers/platform/x86/intel_scu_pltdrv.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/platform_device.h> 17 17 18 - #include <asm/intel_scu_ipc.h> 18 + #include <linux/platform_data/x86/intel_scu_ipc.h> 19 19 20 20 static int intel_scu_platform_probe(struct platform_device *pdev) 21 21 {
+2 -1
drivers/platform/x86/intel_scu_wdt.c
··· 9 9 #include <linux/init.h> 10 10 #include <linux/interrupt.h> 11 11 #include <linux/platform_device.h> 12 - #include <linux/platform_data/intel-mid_wdt.h> 13 12 14 13 #include <asm/cpu_device_id.h> 15 14 #include <asm/intel-family.h> 16 15 #include <asm/io_apic.h> 17 16 #include <asm/hw_irq.h> 17 + 18 + #include <linux/platform_data/x86/intel-mid_wdt.h> 18 19 19 20 #define TANGIER_EXT_TIMER0_MSI 12 20 21
+2
drivers/platform/x86/lenovo-ymc.c
··· 43 43 }; 44 44 45 45 static const struct key_entry lenovo_ymc_keymap[] = { 46 + /* Ignore the uninitialized state */ 47 + { KE_IGNORE, 0x00 }, 46 48 /* Laptop */ 47 49 { KE_SW, 0x01, { .sw = { SW_TABLET_MODE, 0 } } }, 48 50 /* Tablet */
+137 -12
drivers/platform/x86/lg-laptop.c
··· 8 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 9 10 10 #include <linux/acpi.h> 11 + #include <linux/bits.h> 12 + #include <linux/device.h> 13 + #include <linux/dev_printk.h> 11 14 #include <linux/dmi.h> 12 15 #include <linux/input.h> 13 16 #include <linux/input/sparse-keymap.h> ··· 33 30 MODULE_AUTHOR("Matan Ziv-Av"); 34 31 MODULE_DESCRIPTION("LG WMI Hotkey Driver"); 35 32 MODULE_LICENSE("GPL"); 33 + 34 + static bool fw_debug; 35 + module_param(fw_debug, bool, 0); 36 + MODULE_PARM_DESC(fw_debug, "Enable printing of firmware debug messages"); 37 + 38 + #define LG_ADDRESS_SPACE_ID 0x8F 39 + 40 + #define LG_ADDRESS_SPACE_DEBUG_FLAG_ADR 0x00 41 + #define LG_ADDRESS_SPACE_FAN_MODE_ADR 0x03 42 + 43 + #define LG_ADDRESS_SPACE_DTTM_FLAG_ADR 0x20 44 + #define LG_ADDRESS_SPACE_CPU_TEMP_ADR 0x21 45 + #define LG_ADDRESS_SPACE_CPU_TRIP_LOW_ADR 0x22 46 + #define LG_ADDRESS_SPACE_CPU_TRIP_HIGH_ADR 0x23 47 + #define LG_ADDRESS_SPACE_MB_TEMP_ADR 0x24 48 + #define LG_ADDRESS_SPACE_MB_TRIP_LOW_ADR 0x25 49 + #define LG_ADDRESS_SPACE_MB_TRIP_HIGH_ADR 0x26 50 + 51 + #define LG_ADDRESS_SPACE_DEBUG_MSG_START_ADR 0x3E8 52 + #define LG_ADDRESS_SPACE_DEBUG_MSG_END_ADR 0x5E8 36 53 37 54 #define WMI_EVENT_GUID0 "E4FB94F9-7F2B-4173-AD1A-CD1D95086248" 38 55 #define WMI_EVENT_GUID1 "023B133E-49D1-4E10-B313-698220140DC2" ··· 205 182 return (union acpi_object *)buffer.pointer; 206 183 } 207 184 208 - static void wmi_notify(u32 value, void *context) 185 + static void wmi_notify(union acpi_object *obj, void *context) 209 186 { 210 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 211 - union acpi_object *obj; 212 - acpi_status status; 213 187 long data = (long)context; 214 188 215 189 pr_debug("event guid %li\n", data); 216 - status = wmi_get_event_data(value, &response); 217 - if (ACPI_FAILURE(status)) { 218 - pr_err("Bad event status 0x%x\n", status); 219 - return; 220 - } 221 - 222 - obj = (union acpi_object *)response.pointer; 223 190 if (!obj) 224 191 return; 225 192 ··· 231 218 232 219 pr_debug("Type: %i Eventcode: 0x%llx\n", obj->type, 233 220 obj->integer.value); 234 - kfree(response.pointer); 235 221 } 236 222 237 223 static void wmi_input_setup(void) ··· 658 646 } 659 647 }; 660 648 649 + static acpi_status lg_laptop_address_space_write(struct device *dev, acpi_physical_address address, 650 + size_t size, u64 value) 651 + { 652 + u8 byte; 653 + 654 + /* Ignore any debug messages */ 655 + if (address >= LG_ADDRESS_SPACE_DEBUG_MSG_START_ADR && 656 + address <= LG_ADDRESS_SPACE_DEBUG_MSG_END_ADR) 657 + return AE_OK; 658 + 659 + if (size != sizeof(byte)) 660 + return AE_BAD_PARAMETER; 661 + 662 + byte = value & 0xFF; 663 + 664 + switch (address) { 665 + case LG_ADDRESS_SPACE_FAN_MODE_ADR: 666 + /* 667 + * The fan mode field is not affected by the DTTM flag, so we 668 + * have to manually check fw_debug. 669 + */ 670 + if (fw_debug) 671 + dev_dbg(dev, "Fan mode set to mode %u\n", byte); 672 + 673 + return AE_OK; 674 + case LG_ADDRESS_SPACE_CPU_TEMP_ADR: 675 + dev_dbg(dev, "CPU temperature is %u °C\n", byte); 676 + return AE_OK; 677 + case LG_ADDRESS_SPACE_CPU_TRIP_LOW_ADR: 678 + dev_dbg(dev, "CPU lower trip point set to %u °C\n", byte); 679 + return AE_OK; 680 + case LG_ADDRESS_SPACE_CPU_TRIP_HIGH_ADR: 681 + dev_dbg(dev, "CPU higher trip point set to %u °C\n", byte); 682 + return AE_OK; 683 + case LG_ADDRESS_SPACE_MB_TEMP_ADR: 684 + dev_dbg(dev, "Motherboard temperature is %u °C\n", byte); 685 + return AE_OK; 686 + case LG_ADDRESS_SPACE_MB_TRIP_LOW_ADR: 687 + dev_dbg(dev, "Motherboard lower trip point set to %u °C\n", byte); 688 + return AE_OK; 689 + case LG_ADDRESS_SPACE_MB_TRIP_HIGH_ADR: 690 + dev_dbg(dev, "Motherboard higher trip point set to %u °C\n", byte); 691 + return AE_OK; 692 + default: 693 + dev_notice_ratelimited(dev, "Ignoring write to unknown opregion address %llu\n", 694 + address); 695 + return AE_OK; 696 + } 697 + } 698 + 699 + static acpi_status lg_laptop_address_space_read(struct device *dev, acpi_physical_address address, 700 + size_t size, u64 *value) 701 + { 702 + if (size != 1) 703 + return AE_BAD_PARAMETER; 704 + 705 + switch (address) { 706 + case LG_ADDRESS_SPACE_DEBUG_FLAG_ADR: 707 + /* Debug messages are already printed using the standard ACPI Debug object */ 708 + *value = 0x00; 709 + return AE_OK; 710 + case LG_ADDRESS_SPACE_DTTM_FLAG_ADR: 711 + *value = fw_debug; 712 + return AE_OK; 713 + default: 714 + dev_notice_ratelimited(dev, "Attempt to read unknown opregion address %llu\n", 715 + address); 716 + return AE_BAD_PARAMETER; 717 + } 718 + } 719 + 720 + static acpi_status lg_laptop_address_space_handler(u32 function, acpi_physical_address address, 721 + u32 bits, u64 *value, void *handler_context, 722 + void *region_context) 723 + { 724 + struct device *dev = handler_context; 725 + size_t size; 726 + 727 + if (bits % BITS_PER_BYTE) 728 + return AE_BAD_PARAMETER; 729 + 730 + size = bits / BITS_PER_BYTE; 731 + 732 + switch (function) { 733 + case ACPI_READ: 734 + return lg_laptop_address_space_read(dev, address, size, value); 735 + case ACPI_WRITE: 736 + return lg_laptop_address_space_write(dev, address, size, *value); 737 + default: 738 + return AE_BAD_PARAMETER; 739 + } 740 + } 741 + 742 + static void lg_laptop_remove_address_space_handler(void *data) 743 + { 744 + struct acpi_device *device = data; 745 + 746 + acpi_remove_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID, 747 + &lg_laptop_address_space_handler); 748 + } 749 + 661 750 static int acpi_add(struct acpi_device *device) 662 751 { 663 752 struct platform_device_info pdev_info = { ··· 766 653 .name = PLATFORM_NAME, 767 654 .id = PLATFORM_DEVID_NONE, 768 655 }; 656 + acpi_status status; 769 657 int ret; 770 658 const char *product; 771 659 int year = 2017; 772 660 773 661 if (pf_device) 774 662 return 0; 663 + 664 + status = acpi_install_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID, 665 + &lg_laptop_address_space_handler, 666 + NULL, &device->dev); 667 + if (ACPI_FAILURE(status)) 668 + return -ENODEV; 669 + 670 + ret = devm_add_action_or_reset(&device->dev, lg_laptop_remove_address_space_handler, 671 + device); 672 + if (ret < 0) 673 + return ret; 775 674 776 675 ret = platform_driver_register(&pf_driver); 777 676 if (ret)
+3 -17
drivers/platform/x86/msi-wmi.c
··· 170 170 .update_status = bl_set_status, 171 171 }; 172 172 173 - static void msi_wmi_notify(u32 value, void *context) 173 + static void msi_wmi_notify(union acpi_object *obj, void *context) 174 174 { 175 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 176 175 struct key_entry *key; 177 - union acpi_object *obj; 178 - acpi_status status; 179 - 180 - status = wmi_get_event_data(value, &response); 181 - if (status != AE_OK) { 182 - pr_info("bad event status 0x%x\n", status); 183 - return; 184 - } 185 - 186 - obj = (union acpi_object *)response.pointer; 187 176 188 177 if (obj && obj->type == ACPI_TYPE_INTEGER) { 189 178 int eventcode = obj->integer.value; ··· 181 192 eventcode); 182 193 if (!key) { 183 194 pr_info("Unknown key pressed - %x\n", eventcode); 184 - goto msi_wmi_notify_exit; 195 + return; 185 196 } 186 197 187 198 if (event_wmi->quirk_last_pressed) { ··· 193 204 pr_debug("Suppressed key event 0x%X - " 194 205 "Last press was %lld us ago\n", 195 206 key->code, ktime_to_us(diff)); 196 - goto msi_wmi_notify_exit; 207 + return; 197 208 } 198 209 last_pressed = cur; 199 210 } ··· 210 221 } 211 222 } else 212 223 pr_info("Unknown event received\n"); 213 - 214 - msi_wmi_notify_exit: 215 - kfree(response.pointer); 216 224 } 217 225 218 226 static int __init msi_wmi_backlight_setup(void)
+14 -2
drivers/platform/x86/panasonic-laptop.c
··· 121 121 122 122 #include <linux/acpi.h> 123 123 #include <linux/backlight.h> 124 + #include <linux/bits.h> 124 125 #include <linux/ctype.h> 125 126 #include <linux/i8042.h> 126 127 #include <linux/init.h> ··· 225 224 { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */ 226 225 { KE_KEY, 9, { KEY_BATTERY } }, 227 226 { KE_KEY, 10, { KEY_SUSPEND } }, 227 + { KE_KEY, 21, { KEY_MACRO1 } }, 228 + { KE_KEY, 22, { KEY_MACRO2 } }, 229 + { KE_KEY, 24, { KEY_MACRO3 } }, 230 + { KE_KEY, 25, { KEY_MACRO4 } }, 231 + { KE_KEY, 34, { KEY_MACRO5 } }, 232 + { KE_KEY, 35, { KEY_MACRO6 } }, 233 + { KE_KEY, 36, { KEY_MACRO7 } }, 234 + { KE_KEY, 37, { KEY_MACRO8 } }, 235 + { KE_KEY, 41, { KEY_MACRO9 } }, 236 + { KE_KEY, 42, { KEY_MACRO10 } }, 237 + { KE_KEY, 43, { KEY_MACRO11 } }, 228 238 { KE_END, 0 } 229 239 }; 230 240 ··· 842 830 return; 843 831 } 844 832 845 - key = result & 0xf; 846 - updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */ 833 + key = result & GENMASK(6, 0); 834 + updown = result & BIT(7); /* 0x80 == key down; 0x00 = key up */ 847 835 848 836 /* hack: some firmware sends no key down for sleep / hibernate */ 849 837 if (key == 7 || key == 10) {
+2 -3
drivers/platform/x86/samsung-laptop.c
··· 14 14 #include <linux/pci.h> 15 15 #include <linux/backlight.h> 16 16 #include <linux/leds.h> 17 - #include <linux/fb.h> 18 17 #include <linux/dmi.h> 19 18 #include <linux/platform_device.h> 20 19 #include <linux/rfkill.h> ··· 553 554 554 555 set_brightness(samsung, bd->props.brightness); 555 556 556 - if (bd->props.power == FB_BLANK_UNBLANK) 557 + if (bd->props.power == BACKLIGHT_POWER_ON) 557 558 sabi_set_commandb(samsung, commands->set_backlight, 1); 558 559 else 559 560 sabi_set_commandb(samsung, commands->set_backlight, 0); ··· 1188 1189 1189 1190 samsung->backlight_device = bd; 1190 1191 samsung->backlight_device->props.brightness = read_brightness(samsung); 1191 - samsung->backlight_device->props.power = FB_BLANK_UNBLANK; 1192 + samsung->backlight_device->props.power = BACKLIGHT_POWER_ON; 1192 1193 backlight_update_status(samsung->backlight_device); 1193 1194 1194 1195 return 0;
+24 -8
drivers/platform/x86/serial-multi-instantiate.c
··· 83 83 84 84 static void smi_devs_unregister(struct smi *smi) 85 85 { 86 + #if IS_REACHABLE(CONFIG_I2C) 86 87 while (smi->i2c_num--) 87 88 i2c_unregister_device(smi->i2c_devs[smi->i2c_num]); 89 + #endif 88 90 89 - while (smi->spi_num--) 90 - spi_unregister_device(smi->spi_devs[smi->spi_num]); 91 + if (IS_REACHABLE(CONFIG_SPI)) { 92 + while (smi->spi_num--) 93 + spi_unregister_device(smi->spi_devs[smi->spi_num]); 94 + } 91 95 } 92 96 93 97 /** ··· 262 258 263 259 switch (node->bus_type) { 264 260 case SMI_I2C: 265 - return smi_i2c_probe(pdev, smi, node->instances); 261 + if (IS_REACHABLE(CONFIG_I2C)) 262 + return smi_i2c_probe(pdev, smi, node->instances); 263 + 264 + return -ENODEV; 266 265 case SMI_SPI: 267 - return smi_spi_probe(pdev, smi, node->instances); 266 + if (IS_REACHABLE(CONFIG_SPI)) 267 + return smi_spi_probe(pdev, smi, node->instances); 268 + 269 + return -ENODEV; 268 270 case SMI_AUTO_DETECT: 269 271 /* 270 272 * For backwards-compatibility with the existing nodes I2C ··· 280 270 * SpiSerialBus nodes that were previously ignored, and this 281 271 * preserves that behavior. 282 272 */ 283 - ret = smi_i2c_probe(pdev, smi, node->instances); 284 - if (ret != -ENOENT) 285 - return ret; 286 - return smi_spi_probe(pdev, smi, node->instances); 273 + if (IS_REACHABLE(CONFIG_I2C)) { 274 + ret = smi_i2c_probe(pdev, smi, node->instances); 275 + if (ret != -ENOENT) 276 + return ret; 277 + } 278 + 279 + if (IS_REACHABLE(CONFIG_SPI)) 280 + return smi_spi_probe(pdev, smi, node->instances); 281 + 282 + return -ENODEV; 287 283 default: 288 284 return -EINVAL; 289 285 }
+143 -2
drivers/platform/x86/thinkpad_acpi.c
··· 7749 7749 * EC 0x2f (HFSP) might be available *for reading*, but do not use 7750 7750 * it for writing. 7751 7751 * 7752 + * TPACPI_FAN_RD_ACPI_FANG: 7753 + * ACPI FANG method: returns fan control register 7754 + * 7755 + * Takes one parameter which is 0x8100 plus the offset to EC memory 7756 + * address 0xf500 and returns the byte at this address. 7757 + * 7758 + * 0xf500: 7759 + * When the value is less than 9 automatic mode is enabled 7760 + * 0xf502: 7761 + * Contains the current fan speed from 0-100% 7762 + * 0xf506: 7763 + * Bit 7 has to be set in order to enable manual control by 7764 + * writing a value >= 9 to 0xf500 7765 + * 7766 + * TPACPI_FAN_WR_ACPI_FANW: 7767 + * ACPI FANW method: sets fan control registers 7768 + * 7769 + * Takes 0x8100 plus the offset to EC memory address 0xf500 and the 7770 + * value to be written there as parameters. 7771 + * 7772 + * see TPACPI_FAN_RD_ACPI_FANG 7773 + * 7752 7774 * TPACPI_FAN_WR_TPEC: 7753 7775 * ThinkPad EC register 0x2f (HFSP): fan control loop mode 7754 7776 * Supported on almost all ThinkPads ··· 7904 7882 enum fan_status_access_mode { 7905 7883 TPACPI_FAN_NONE = 0, /* No fan status or control */ 7906 7884 TPACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ 7885 + TPACPI_FAN_RD_ACPI_FANG, /* Use ACPI FANG */ 7907 7886 TPACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */ 7908 7887 TPACPI_FAN_RD_TPEC_NS, /* Use non-standard ACPI EC regs (eg: L13 Yoga gen2 etc.) */ 7909 7888 }; ··· 7912 7889 enum fan_control_access_mode { 7913 7890 TPACPI_FAN_WR_NONE = 0, /* No fan control */ 7914 7891 TPACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */ 7892 + TPACPI_FAN_WR_ACPI_FANW, /* Use ACPI FANW */ 7915 7893 TPACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */ 7916 7894 TPACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */ 7917 7895 }; ··· 7946 7922 TPACPI_HANDLE(gfan, ec, "GFAN", /* 570 */ 7947 7923 "\\FSPD", /* 600e/x, 770e, 770x */ 7948 7924 ); /* all others */ 7925 + TPACPI_HANDLE(fang, ec, "FANG", /* E531 */ 7926 + ); /* all others */ 7949 7927 TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */ 7950 7928 "JFNS", /* 770x-JL */ 7929 + ); /* all others */ 7930 + TPACPI_HANDLE(fanw, ec, "FANW", /* E531 */ 7951 7931 ); /* all others */ 7952 7932 7953 7933 /* ··· 8056 8028 8057 8029 if (likely(status)) 8058 8030 *status = res & 0x07; 8031 + 8032 + break; 8033 + } 8034 + case TPACPI_FAN_RD_ACPI_FANG: { 8035 + /* E531 */ 8036 + int mode, speed; 8037 + 8038 + if (unlikely(!acpi_evalf(fang_handle, &mode, NULL, "dd", 0x8100))) 8039 + return -EIO; 8040 + if (unlikely(!acpi_evalf(fang_handle, &speed, NULL, "dd", 0x8102))) 8041 + return -EIO; 8042 + 8043 + if (likely(status)) { 8044 + *status = speed * 7 / 100; 8045 + if (mode < 9) 8046 + *status |= TP_EC_FAN_AUTO; 8047 + } 8059 8048 8060 8049 break; 8061 8050 } ··· 8190 8145 if (speed) 8191 8146 *speed = lo ? FAN_RPM_CAL_CONST / lo : 0; 8192 8147 break; 8148 + case TPACPI_FAN_RD_ACPI_FANG: { 8149 + /* E531 */ 8150 + int speed_tmp; 8151 + 8152 + if (unlikely(!acpi_evalf(fang_handle, &speed_tmp, NULL, "dd", 0x8102))) 8153 + return -EIO; 8154 + 8155 + if (likely(speed)) 8156 + *speed = speed_tmp * 65535 / 100; 8157 + break; 8158 + } 8193 8159 8194 8160 default: 8195 8161 return -ENXIO; ··· 8260 8204 tp_features.fan_ctrl_status_undef = 0; 8261 8205 break; 8262 8206 8207 + case TPACPI_FAN_WR_ACPI_FANW: 8208 + if (!(level & TP_EC_FAN_AUTO) && (level < 0 || level > 7)) 8209 + return -EINVAL; 8210 + if (level & TP_EC_FAN_FULLSPEED) 8211 + return -EINVAL; 8212 + 8213 + if (level & TP_EC_FAN_AUTO) { 8214 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8106, 0x05)) { 8215 + return -EIO; 8216 + } 8217 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8100, 0x00)) { 8218 + return -EIO; 8219 + } 8220 + } else { 8221 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8106, 0x45)) { 8222 + return -EIO; 8223 + } 8224 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8100, 0xff)) { 8225 + return -EIO; 8226 + } 8227 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8102, level * 100 / 7)) { 8228 + return -EIO; 8229 + } 8230 + } 8231 + break; 8232 + 8263 8233 default: 8264 8234 return -ENXIO; 8265 8235 } ··· 8318 8236 8319 8237 static int fan_set_enable(void) 8320 8238 { 8321 - u8 s; 8239 + u8 s = 0; 8322 8240 int rc; 8323 8241 8324 8242 if (!fan_control_allowed) ··· 8364 8282 rc = 0; 8365 8283 break; 8366 8284 8285 + case TPACPI_FAN_WR_ACPI_FANW: 8286 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8106, 0x05)) { 8287 + rc = -EIO; 8288 + break; 8289 + } 8290 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8100, 0x00)) { 8291 + rc = -EIO; 8292 + break; 8293 + } 8294 + 8295 + rc = 0; 8296 + break; 8297 + 8367 8298 default: 8368 8299 rc = -ENXIO; 8369 8300 } ··· 8419 8324 fan_control_desired_level = 0; 8420 8325 break; 8421 8326 8327 + case TPACPI_FAN_WR_ACPI_FANW: 8328 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8106, 0x45)) { 8329 + rc = -EIO; 8330 + break; 8331 + } 8332 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8100, 0xff)) { 8333 + rc = -EIO; 8334 + break; 8335 + } 8336 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8102, 0x00)) { 8337 + rc = -EIO; 8338 + break; 8339 + } 8340 + rc = 0; 8341 + break; 8342 + 8422 8343 default: 8423 8344 rc = -ENXIO; 8424 8345 } ··· 8463 8352 if (speed >= 0 && speed <= 65535) { 8464 8353 if (!acpi_evalf(fans_handle, NULL, NULL, "vddd", 8465 8354 speed, speed, speed)) 8355 + rc = -EIO; 8356 + } else 8357 + rc = -EINVAL; 8358 + break; 8359 + 8360 + case TPACPI_FAN_WR_ACPI_FANW: 8361 + if (speed >= 0 && speed <= 65535) { 8362 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8106, 0x45)) { 8363 + rc = -EIO; 8364 + break; 8365 + } 8366 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 0x8100, 0xff)) { 8367 + rc = -EIO; 8368 + break; 8369 + } 8370 + if (!acpi_evalf(fanw_handle, NULL, NULL, "vdd", 8371 + 0x8102, speed * 100 / 65535)) 8466 8372 rc = -EIO; 8467 8373 } else 8468 8374 rc = -EINVAL; ··· 8827 8699 TPACPI_ACPIHANDLE_INIT(gfan); 8828 8700 TPACPI_ACPIHANDLE_INIT(sfan); 8829 8701 } 8702 + if (tpacpi_is_lenovo()) { 8703 + TPACPI_ACPIHANDLE_INIT(fang); 8704 + TPACPI_ACPIHANDLE_INIT(fanw); 8705 + } 8830 8706 8831 8707 quirks = tpacpi_check_quirks(fan_quirk_table, 8832 8708 ARRAY_SIZE(fan_quirk_table)); ··· 8850 8718 if (gfan_handle) { 8851 8719 /* 570, 600e/x, 770e, 770x */ 8852 8720 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; 8721 + } else if (fang_handle) { 8722 + /* E531 */ 8723 + fan_status_access_mode = TPACPI_FAN_RD_ACPI_FANG; 8853 8724 } else { 8854 8725 /* all other ThinkPads: note that even old-style 8855 8726 * ThinkPad ECs supports the fan control register */ ··· 8899 8764 fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN; 8900 8765 fan_control_commands |= 8901 8766 TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE; 8767 + } else if (fanw_handle) { 8768 + /* E531 */ 8769 + fan_control_access_mode = TPACPI_FAN_WR_ACPI_FANW; 8770 + fan_control_commands |= 8771 + TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_SPEED | TPACPI_FAN_CMD_ENABLE; 8902 8772 } else { 8903 8773 if (!gfan_handle) { 8904 8774 /* gfan without sfan means no fan control */ ··· 9055 8915 9056 8916 case TPACPI_FAN_RD_TPEC_NS: 9057 8917 case TPACPI_FAN_RD_TPEC: 8918 + case TPACPI_FAN_RD_ACPI_FANG: 9058 8919 /* all except 570, 600e/x, 770e, 770x */ 9059 8920 rc = fan_get_status_safe(&status); 9060 8921 if (rc) ··· 9076 8935 * No other levels settings available 9077 8936 */ 9078 8937 seq_printf(m, "level:\t\t%s\n", status & FAN_NS_CTRL ? "unknown" : "auto"); 9079 - } else { 8938 + } else if (fan_status_access_mode == TPACPI_FAN_RD_TPEC) { 9080 8939 if (status & TP_EC_FAN_FULLSPEED) 9081 8940 /* Disengaged mode takes precedence */ 9082 8941 seq_printf(m, "level:\t\tdisengaged\n");
+1 -14
drivers/platform/x86/toshiba-wmi.c
··· 32 32 { KE_END, 0 } 33 33 }; 34 34 35 - static void toshiba_wmi_notify(u32 value, void *context) 35 + static void toshiba_wmi_notify(union acpi_object *obj, void *context) 36 36 { 37 - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 38 - union acpi_object *obj; 39 - acpi_status status; 40 - 41 - status = wmi_get_event_data(value, &response); 42 - if (ACPI_FAILURE(status)) { 43 - pr_err("Bad event status 0x%x\n", status); 44 - return; 45 - } 46 - 47 - obj = (union acpi_object *)response.pointer; 48 37 if (!obj) 49 38 return; 50 39 51 40 /* TODO: Add proper checks once we have data */ 52 41 pr_debug("Unknown event received, obj type %x\n", obj->type); 53 - 54 - kfree(response.pointer); 55 42 } 56 43 57 44 static const struct dmi_system_id toshiba_wmi_dmi_table[] __initconst = {
+26
drivers/platform/x86/touchscreen_dmi.c
··· 840 840 .properties = rwc_nanote_p8_props, 841 841 }; 842 842 843 + static const struct property_entry rwc_nanote_next_props[] = { 844 + PROPERTY_ENTRY_U32("touchscreen-min-x", 5), 845 + PROPERTY_ENTRY_U32("touchscreen-min-y", 5), 846 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1785), 847 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1145), 848 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 849 + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-rwc-nanote-next.fw"), 850 + { } 851 + }; 852 + 853 + static const struct ts_dmi_data rwc_nanote_next_data = { 854 + .acpi_name = "MSSL1680:00", 855 + .properties = rwc_nanote_next_props, 856 + }; 857 + 843 858 static const struct property_entry schneider_sct101ctm_props[] = { 844 859 PROPERTY_ENTRY_U32("touchscreen-size-x", 1715), 845 860 PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), ··· 1602 1587 DMI_MATCH(DMI_BOARD_VENDOR, "Default string"), 1603 1588 DMI_MATCH(DMI_PRODUCT_NAME, "AY07J"), 1604 1589 DMI_MATCH(DMI_PRODUCT_SKU, "0001") 1590 + }, 1591 + }, 1592 + { 1593 + /* RWC NANOTE NEXT */ 1594 + .driver_data = (void *)&rwc_nanote_next_data, 1595 + .matches = { 1596 + DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."), 1597 + DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."), 1598 + DMI_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), 1599 + /* Above matches are too generic, add bios-version match */ 1600 + DMI_MATCH(DMI_BIOS_VERSION, "S8A70R100-V005"), 1605 1601 }, 1606 1602 }, 1607 1603 {
+34 -109
drivers/platform/x86/wmi.c
··· 166 166 return ACPI_TYPE_BUFFER; 167 167 } 168 168 169 - static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_buffer *out) 170 - { 171 - union acpi_object param = { 172 - .integer = { 173 - .type = ACPI_TYPE_INTEGER, 174 - .value = wblock->gblock.notify_id, 175 - } 176 - }; 177 - struct acpi_object_list input = { 178 - .count = 1, 179 - .pointer = &param, 180 - }; 181 - 182 - return acpi_evaluate_object(wblock->acpi_device->handle, "_WED", &input, out); 183 - } 184 - 185 169 static int wmidev_match_guid(struct device *dev, const void *data) 186 170 { 187 171 struct wmi_block *wblock = dev_to_wblock(dev); ··· 178 194 return 0; 179 195 180 196 if (guid_equal(guid, &wblock->gblock.guid)) 181 - return 1; 182 - 183 - return 0; 184 - } 185 - 186 - static int wmidev_match_notify_id(struct device *dev, const void *data) 187 - { 188 - struct wmi_block *wblock = dev_to_wblock(dev); 189 - const u32 *notify_id = data; 190 - 191 - /* Legacy GUID-based functions are restricted to only see 192 - * a single WMI device for each GUID. 193 - */ 194 - if (test_bit(WMI_GUID_DUPLICATED, &wblock->flags)) 195 - return 0; 196 - 197 - if (wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *notify_id) 198 197 return 1; 199 198 200 199 return 0; ··· 200 233 return ERR_PTR(-ENODEV); 201 234 202 235 return dev_to_wdev(dev); 203 - } 204 - 205 - static struct wmi_device *wmi_find_event_by_notify_id(const u32 notify_id) 206 - { 207 - struct device *dev; 208 - 209 - dev = bus_find_device(&wmi_bus_type, NULL, &notify_id, wmidev_match_notify_id); 210 - if (!dev) 211 - return ERR_PTR(-ENODEV); 212 - 213 - return to_wmi_device(dev); 214 236 } 215 237 216 238 static void wmi_device_put(struct wmi_device *wdev) ··· 604 648 return status; 605 649 } 606 650 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); 607 - 608 - /** 609 - * wmi_get_event_data - Get WMI data associated with an event (deprecated) 610 - * 611 - * @event: Event to find 612 - * @out: Buffer to hold event data 613 - * 614 - * Get extra data associated with an WMI event, the caller needs to free @out. 615 - * 616 - * Return: acpi_status signaling success or error. 617 - */ 618 - acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) 619 - { 620 - struct wmi_block *wblock; 621 - struct wmi_device *wdev; 622 - acpi_status status; 623 - 624 - wdev = wmi_find_event_by_notify_id(event); 625 - if (IS_ERR(wdev)) 626 - return AE_NOT_FOUND; 627 - 628 - wblock = container_of(wdev, struct wmi_block, dev); 629 - status = get_event_data(wblock, out); 630 - 631 - wmi_device_put(wdev); 632 - 633 - return status; 634 - } 635 - EXPORT_SYMBOL_GPL(wmi_get_event_data); 636 651 637 652 /** 638 653 * wmi_has_guid - Check if a GUID is available ··· 1113 1186 static int wmi_get_notify_data(struct wmi_block *wblock, union acpi_object **obj) 1114 1187 { 1115 1188 struct acpi_buffer data = { ACPI_ALLOCATE_BUFFER, NULL }; 1189 + union acpi_object param = { 1190 + .integer = { 1191 + .type = ACPI_TYPE_INTEGER, 1192 + .value = wblock->gblock.notify_id, 1193 + } 1194 + }; 1195 + struct acpi_object_list input = { 1196 + .count = 1, 1197 + .pointer = &param, 1198 + }; 1116 1199 acpi_status status; 1117 1200 1118 - if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags)) { 1119 - *obj = NULL; 1120 - return 0; 1121 - } 1122 - 1123 - status = get_event_data(wblock, &data); 1201 + status = acpi_evaluate_object(wblock->acpi_device->handle, "_WED", &input, &data); 1124 1202 if (ACPI_FAILURE(status)) { 1125 1203 dev_warn(&wblock->dev.dev, "Failed to get event data\n"); 1126 1204 return -EIO; ··· 1152 1220 static int wmi_notify_device(struct device *dev, void *data) 1153 1221 { 1154 1222 struct wmi_block *wblock = dev_to_wblock(dev); 1155 - union acpi_object *obj; 1223 + union acpi_object *obj = NULL; 1156 1224 u32 *event = data; 1157 1225 int ret; 1158 1226 1159 1227 if (!(wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *event)) 1160 1228 return 0; 1161 1229 1162 - down_read(&wblock->notify_lock); 1163 - /* The WMI driver notify handler conflicts with the legacy WMI handler. 1164 - * Because of this the WMI driver notify handler takes precedence. 1230 + /* The ACPI WMI specification says that _WED should be 1231 + * evaluated every time an notification is received, even 1232 + * if no consumers are present. 1233 + * 1234 + * Some firmware implementations actually depend on this 1235 + * by using a queue for events which will fill up if the 1236 + * WMI driver core stops evaluating _WED due to missing 1237 + * WMI event consumers. 1165 1238 */ 1166 - if (wblock->dev.dev.driver && wblock->driver_ready) { 1239 + if (!test_bit(WMI_NO_EVENT_DATA, &wblock->flags)) { 1167 1240 ret = wmi_get_notify_data(wblock, &obj); 1168 - if (ret >= 0) { 1169 - wmi_notify_driver(wblock, obj); 1170 - kfree(obj); 1171 - } 1172 - } else { 1173 - if (wblock->handler) { 1174 - wblock->handler(*event, wblock->handler_data); 1175 - } else { 1176 - /* The ACPI WMI specification says that _WED should be 1177 - * evaluated every time an notification is received, even 1178 - * if no consumers are present. 1179 - * 1180 - * Some firmware implementations actually depend on this 1181 - * by using a queue for events which will fill up if the 1182 - * WMI driver core stops evaluating _WED due to missing 1183 - * WMI event consumers. 1184 - * 1185 - * Because of this we need this seemingly useless call to 1186 - * wmi_get_notify_data() which in turn evaluates _WED. 1187 - */ 1188 - ret = wmi_get_notify_data(wblock, &obj); 1189 - if (ret >= 0) 1190 - kfree(obj); 1191 - } 1192 - 1241 + if (ret < 0) 1242 + return -EIO; 1193 1243 } 1244 + 1245 + down_read(&wblock->notify_lock); 1246 + 1247 + if (wblock->dev.dev.driver && wblock->driver_ready) 1248 + wmi_notify_driver(wblock, obj); 1249 + 1250 + if (wblock->handler) 1251 + wblock->handler(obj, wblock->handler_data); 1252 + 1194 1253 up_read(&wblock->notify_lock); 1254 + 1255 + kfree(obj); 1195 1256 1196 1257 acpi_bus_generate_netlink_event("wmi", acpi_dev_name(wblock->acpi_device), *event, 0); 1197 1258
+1 -1
drivers/platform/x86/x86-android-tablets/Kconfig
··· 20 20 are missing from the DSDT. 21 21 22 22 If you have a x86 Android tablet say Y or M here, for a generic x86 23 - distro config say M here. 23 + distro configuration say M here.
+4 -4
drivers/platform/x86/x86-android-tablets/asus.c
··· 37 37 .pin = 12, 38 38 }; 39 39 40 - /* Asus ME176C tablets have an Android factory img with everything hardcoded */ 40 + /* Asus ME176C tablets have an Android factory image with everything hardcoded */ 41 41 static const char * const asus_me176c_accel_mount_matrix[] = { 42 42 "-1", "0", "0", 43 43 "0", "1", "0", ··· 112 112 }, 113 113 .adapter_path = "\\_SB_.I2C5", 114 114 }, { 115 - /* kxtj21009 accel */ 115 + /* kxtj21009 accelerometer */ 116 116 .board_info = { 117 117 .type = "kxtj21009", 118 118 .addr = 0x0f, ··· 181 181 .modules = bq24190_modules, 182 182 }; 183 183 184 - /* Asus TF103C tablets have an Android factory img with everything hardcoded */ 184 + /* Asus TF103C tablets have an Android factory image with everything hardcoded */ 185 185 static const char * const asus_tf103c_accel_mount_matrix[] = { 186 186 "0", "-1", "0", 187 187 "-1", "0", "0", ··· 280 280 }, 281 281 .adapter_path = "\\_SB_.I2C5", 282 282 }, { 283 - /* kxtj21009 accel */ 283 + /* kxtj21009 accelerometer */ 284 284 .board_info = { 285 285 .type = "kxtj21009", 286 286 .addr = 0x0f,
+10 -10
drivers/platform/x86/x86-android-tablets/core.c
··· 26 26 static struct platform_device *x86_android_tablet_device; 27 27 28 28 /* 29 - * This helper allows getting a gpio_desc *before* the actual device consuming 30 - * the GPIO has been instantiated. This function _must_ only be used to handle 31 - * this special case such as e.g. : 29 + * This helper allows getting a GPIO descriptor *before* the actual device 30 + * consuming it has been instantiated. This function MUST only be used to 31 + * handle this special case such as, e.g.: 32 32 * 33 33 * 1. Getting an IRQ from a GPIO for i2c_board_info.irq which is passed to 34 34 * i2c_client_new() to instantiate i2c_client-s; or 35 - * 2. Calling desc_to_gpio() to get an old style GPIO number for gpio_keys 35 + * 2. Calling desc_to_gpio() to get an old style GPIO number for gpio-keys 36 36 * platform_data which still uses old style GPIO numbers. 37 37 * 38 - * Since the consuming device has not been instatiated yet a dynamic lookup 39 - * is generated using the special x86_android_tablet dev for dev_id. 38 + * Since the consuming device has not been instantiated yet a dynamic lookup 39 + * is generated using the special x86_android_tablet device for dev_id. 40 40 * 41 - * For normal GPIO lookups a standard static gpiod_lookup_table _must_ be used. 41 + * For normal GPIO lookups a standard static struct gpiod_lookup_table MUST be used. 42 42 */ 43 43 int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, 44 44 bool active_low, enum gpiod_flags dflags, ··· 87 87 /* 88 88 * The DSDT may already reference the GSI in a device skipped by 89 89 * acpi_quirk_skip_i2c_client_enumeration(). Unregister the GSI 90 - * to avoid EBUSY errors in this case. 90 + * to avoid -EBUSY errors in this case. 91 91 */ 92 92 acpi_unregister_gsi(data->index); 93 93 irq = acpi_register_gsi(NULL, data->index, data->trigger, data->polarity); ··· 379 379 } 380 380 } 381 381 382 - /* + 1 to make space for (optional) gpio_keys_button pdev */ 382 + /* + 1 to make space for the (optional) gpio_keys_button platform device */ 383 383 pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL); 384 384 if (!pdevs) { 385 385 x86_android_tablet_remove(pdev); ··· 432 432 433 433 buttons[i] = dev_info->gpio_button[i].button; 434 434 buttons[i].gpio = desc_to_gpio(gpiod); 435 - /* Release gpiod so that gpio-keys can request it */ 435 + /* Release GPIO descriptor so that gpio-keys can request it */ 436 436 devm_gpiod_put(&x86_android_tablet_device->dev, gpiod); 437 437 } 438 438
+8 -8
drivers/platform/x86/x86-android-tablets/dmi.c
··· 99 99 { 100 100 /* Lenovo Yoga Book X91F / X91L */ 101 101 .matches = { 102 - /* Non exact match to match F + L versions */ 102 + /* Inexact match to match F + L versions */ 103 103 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"), 104 104 }, 105 105 .driver_data = (void *)&lenovo_yogabook_x91_info, 106 106 }, 107 107 { 108 108 /* 109 - * Lenovo Yoga Tablet 2 Pro 1380F/L (13") This has more or less 110 - * the same BIOS as the 830F/L or 1050F/L (8" and 10") below, 111 - * but unlike the 8" / 10" models which share the same mainboard 112 - * this model has a different mainboard. 109 + * Lenovo Yoga Tablet 2 Pro 1380F/L (13") 110 + * This has more or less the same BIOS as the 830F/L or 1050F/L 111 + * (8" and 10") below, but unlike the 8"/10" models which share 112 + * the same mainboard this model has a different mainboard. 113 113 * This match for the 13" model MUST come before the 8" + 10" 114 114 * match since that one will also match the 13" model! 115 115 */ ··· 124 124 }, 125 125 { 126 126 /* 127 - * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10" 128 - * Lenovo Yoga Tablet 2 use the same mainboard) 127 + * Lenovo Yoga Tablet 2 830F/L or 1050F/L 128 + * The 8" and 10" Lenovo Yoga Tablet 2 use the same mainboard. 129 129 */ 130 130 .matches = { 131 131 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), ··· 163 163 .driver_data = (void *)&nextbook_ares8_info, 164 164 }, 165 165 { 166 - /* Nextbook Ares 8A (CHT version)*/ 166 + /* Nextbook Ares 8A (CHT version) */ 167 167 .matches = { 168 168 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 169 169 DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
+11 -11
drivers/platform/x86/x86-android-tablets/lenovo.c
··· 59 59 .initial_brightness = 128, 60 60 }; 61 61 62 - /* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */ 62 + /* Lenovo Yoga Book X90F / X90L's Android factory image has everything hardcoded */ 63 63 64 64 static const struct property_entry lenovo_yb1_x90_wacom_props[] = { 65 65 PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001), ··· 262 262 .init = lenovo_yb1_x90_init, 263 263 }; 264 264 265 - /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */ 265 + /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fuel-gauge client */ 266 266 static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = { 267 267 { 268 268 /* BQ27542 fuel-gauge */ ··· 281 281 .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients), 282 282 }; 283 283 284 - /* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */ 284 + /* Lenovo Yoga Tablet 2 1050F/L's Android factory image has everything hardcoded */ 285 285 static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = { 286 286 PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1), 287 287 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node), ··· 521 521 } 522 522 523 523 /* 524 - * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off 524 + * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off() 525 525 * gets used as pm_power_off handler. This causes "poweroff" on these tablets 526 - * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice* 526 + * to hang hard. Requiring pressing the power button for 30 seconds *twice* 527 527 * followed by a normal 3 second press to recover. Avoid this by doing an EFI 528 528 * poweroff instead. 529 529 */ ··· 546 546 if (ret) 547 547 return ret; 548 548 549 - /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */ 549 + /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off() */ 550 550 lenovo_yoga_tab2_830_1050_sys_off_handler = 551 551 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1, 552 552 lenovo_yoga_tab2_830_1050_power_off, NULL); ··· 742 742 if (ret) 743 743 return ret; 744 744 745 - /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */ 745 + /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off() */ 746 746 lenovo_yoga_tab2_830_1050_sys_off_handler = 747 747 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1, 748 748 lenovo_yoga_tab2_830_1050_power_off, NULL); ··· 799 799 .properties = fg_bq25890_1_supply_props, 800 800 }; 801 801 802 - /* bq25892 charger settings for the flat lipo battery behind the screen */ 802 + /* bq25892 charger settings for the flat LiPo battery behind the screen */ 803 803 static const struct property_entry lenovo_yt3_bq25892_0_props[] = { 804 804 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers), 805 805 PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40), ··· 833 833 834 834 static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { 835 835 { 836 - /* bq27500 fuel-gauge for the flat lipo battery behind the screen */ 836 + /* bq27500 fuel-gauge for the flat LiPo battery behind the screen */ 837 837 .board_info = { 838 838 .type = "bq27500", 839 839 .addr = 0x55, ··· 842 842 }, 843 843 .adapter_path = "\\_SB_.PCI0.I2C1", 844 844 }, { 845 - /* bq25892 charger for the flat lipo battery behind the screen */ 845 + /* bq25892 charger for the flat LiPo battery behind the screen */ 846 846 .board_info = { 847 847 .type = "bq25892", 848 848 .addr = 0x6b, ··· 859 859 .con_id = "bq25892_0_irq", 860 860 }, 861 861 }, { 862 - /* bq27500 fuel-gauge for the round li-ion cells in the hinge */ 862 + /* bq27500 fuel-gauge for the round Li-ion cells in the hinge */ 863 863 .board_info = { 864 864 .type = "bq27500", 865 865 .addr = 0x55,
+20 -20
drivers/platform/x86/x86-android-tablets/other.c
··· 20 20 #include "shared-psy-info.h" 21 21 #include "x86-android-tablets.h" 22 22 23 - /* Acer Iconia One 7 B1-750 has an Android factory img with everything hardcoded */ 23 + /* Acer Iconia One 7 B1-750 has an Android factory image with everything hardcoded */ 24 24 static const char * const acer_b1_750_mount_matrix[] = { 25 25 "-1", "0", "0", 26 26 "0", "1", "0", ··· 98 98 * Advantech MICA-071 99 99 * This is a standard Windows tablet, but it has an extra "quick launch" button 100 100 * which is not described in the ACPI tables in anyway. 101 - * Use the x86-android-tablets infra to create a gpio-button device for this. 101 + * Use the x86-android-tablets infra to create a gpio-keys device for this. 102 102 */ 103 103 static const struct x86_gpio_button advantech_mica_071_button __initconst = { 104 104 .button = { ··· 209 209 * This comes in both Windows and Android versions and even on Android 210 210 * the DSDT is mostly sane. This tablet has 2 extra general purpose buttons 211 211 * in the button row with the power + volume-buttons labeled P and F. 212 - * Use the x86-android-tablets infra to create a gpio-button device for these. 212 + * Use the x86-android-tablets infra to create a gpio-keys device for these. 213 213 */ 214 214 static const struct x86_gpio_button cyberbook_t116_buttons[] __initconst = { 215 215 { ··· 276 276 .init = czc_p10t_init, 277 277 }; 278 278 279 - /* Medion Lifetab S10346 tablets have an Android factory img with everything hardcoded */ 279 + /* Medion Lifetab S10346 tablets have an Android factory image with everything hardcoded */ 280 280 static const char * const medion_lifetab_s10346_accel_mount_matrix[] = { 281 281 "0", "1", "0", 282 282 "1", "0", "0", ··· 305 305 306 306 static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __initconst = { 307 307 { 308 - /* kxtj21009 accel */ 308 + /* kxtj21009 accelerometer */ 309 309 .board_info = { 310 310 .type = "kxtj21009", 311 311 .addr = 0x0f, ··· 359 359 .gpiod_lookup_tables = medion_lifetab_s10346_gpios, 360 360 }; 361 361 362 - /* Nextbook Ares 8 (BYT) tablets have an Android factory img with everything hardcoded */ 362 + /* Nextbook Ares 8 (BYT) tablets have an Android factory image with everything hardcoded */ 363 363 static const char * const nextbook_ares8_accel_mount_matrix[] = { 364 364 "0", "-1", "0", 365 365 "-1", "0", "0", ··· 387 387 388 388 static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst = { 389 389 { 390 - /* Freescale MMA8653FC accel */ 390 + /* Freescale MMA8653FC accelerometer */ 391 391 .board_info = { 392 392 .type = "mma8653", 393 393 .addr = 0x1d, ··· 428 428 .gpiod_lookup_tables = nextbook_ares8_gpios, 429 429 }; 430 430 431 - /* Nextbook Ares 8A (CHT) tablets have an Android factory img with everything hardcoded */ 431 + /* Nextbook Ares 8A (CHT) tablets have an Android factory image with everything hardcoded */ 432 432 static const char * const nextbook_ares8a_accel_mount_matrix[] = { 433 433 "1", "0", "0", 434 434 "0", "-1", "0", ··· 446 446 447 447 static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initconst = { 448 448 { 449 - /* Freescale MMA8653FC accel */ 449 + /* Freescale MMA8653FC accelerometer */ 450 450 .board_info = { 451 451 .type = "mma8653", 452 452 .addr = 0x1d, ··· 497 497 * Peaq C1010 498 498 * This is a standard Windows tablet, but it has a special Dolby button. 499 499 * This button has a WMI interface, but that is broken. Instead of trying to 500 - * use the broken WMI interface, instantiate a gpio_keys device for this. 500 + * use the broken WMI interface, instantiate a gpio-keys device for this. 501 501 */ 502 502 static const struct x86_gpio_button peaq_c1010_button __initconst = { 503 503 .button = { ··· 521 521 * Whitelabel (sold as various brands) TM800A550L tablets. 522 522 * These tablet's DSDT contains a whole bunch of bogus ACPI I2C devices 523 523 * (removed through acpi_quirk_skip_i2c_client_enumeration()) and 524 - * the touchscreen fwnode has the wrong GPIOs. 524 + * the touchscreen firmware node has the wrong GPIOs. 525 525 */ 526 526 static const char * const whitelabel_tm800a550l_accel_mount_matrix[] = { 527 527 "-1", "0", "0", ··· 566 566 .polarity = ACPI_ACTIVE_HIGH, 567 567 }, 568 568 }, { 569 - /* kxcj91008 accel */ 569 + /* kxcj91008 accelerometer */ 570 570 .board_info = { 571 571 .type = "kxcj91008", 572 572 .addr = 0x0f, ··· 598 598 }; 599 599 600 600 /* 601 - * The fwnode for ktd2026 on Xaomi pad2. It composed of a RGB LED node 601 + * The firmware node for ktd2026 on Xaomi pad2. It composed of a RGB LED node 602 602 * with three subnodes for each color (B/G/R). The RGB LED node is named 603 603 * "multi-led" to align with the name in the device tree. 604 604 */ 605 605 606 - /* main fwnode for ktd2026 */ 606 + /* Main firmware node for ktd2026 */ 607 607 static const struct software_node ktd2026_node = { 608 608 .name = "ktd2026", 609 609 }; ··· 665 665 }; 666 666 667 667 /* 668 - * For the LEDs which backlight the menu / home / back capacitive buttons on 668 + * For the LEDs which backlight the Menu / Home / Back capacitive buttons on 669 669 * the bottom bezel. These are attached to a TPS61158 LED controller which 670 670 * is controlled by the "pwm_soc_lpss_2" PWM output. 671 671 */ 672 672 #define XIAOMI_MIPAD2_LED_PERIOD_NS 19200 673 - #define XIAOMI_MIPAD2_LED_DEFAULT_DUTY 6000 /* From Android kernel */ 673 + #define XIAOMI_MIPAD2_LED_MAX_DUTY_NS 6000 /* From Android kernel */ 674 674 675 675 static struct pwm_device *xiaomi_mipad2_led_pwm; 676 676 ··· 679 679 { 680 680 struct pwm_state state = { 681 681 .period = XIAOMI_MIPAD2_LED_PERIOD_NS, 682 - .duty_cycle = val, 682 + .duty_cycle = XIAOMI_MIPAD2_LED_MAX_DUTY_NS * val / LED_FULL, 683 683 /* Always set PWM enabled to avoid the pin floating */ 684 684 .enabled = true, 685 685 }; ··· 701 701 return -ENOMEM; 702 702 703 703 led_cdev->name = "mipad2:white:touch-buttons-backlight"; 704 - led_cdev->max_brightness = XIAOMI_MIPAD2_LED_PERIOD_NS; 705 - /* "input-events" trigger uses blink_brightness */ 706 - led_cdev->blink_brightness = XIAOMI_MIPAD2_LED_DEFAULT_DUTY; 704 + led_cdev->max_brightness = LED_FULL; 707 705 led_cdev->default_trigger = "input-events"; 708 706 led_cdev->brightness_set_blocking = xiaomi_mipad2_brightness_set; 707 + /* Turn LED off during suspend */ 708 + led_cdev->flags = LED_CORE_SUSPENDRESUME; 709 709 710 710 ret = devm_led_classdev_register(dev, led_cdev); 711 711 if (ret)
+2 -2
drivers/platform/x86/x86-android-tablets/shared-psy-info.c
··· 39 39 .properties = fg_bq25890_supply_props, 40 40 }; 41 41 42 - /* LiPo HighVoltage (max 4.35V) settings used by most devs with a HV bat. */ 42 + /* LiPo HighVoltage (max 4.35V) settings used by most devs with a HV battery */ 43 43 static const struct property_entry generic_lipo_hv_4v35_battery_props[] = { 44 44 PROPERTY_ENTRY_STRING("compatible", "simple-battery"), 45 45 PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion"), ··· 80 80 NULL 81 81 }; 82 82 83 - /* Generic pdevs array and gpio-lookups for micro USB ID pin handling */ 83 + /* Generic platform device array and GPIO lookup table for micro USB ID pin handling */ 84 84 const struct platform_device_info int3496_pdevs[] __initconst = { 85 85 { 86 86 /* For micro USB ID pin handling */
+1 -1
drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
··· 61 61 const char *ctrl_uid; 62 62 const char *ctrl_devname; 63 63 /* 64 - * ATM the serdev core only supports of or ACPI matching; and sofar all 64 + * ATM the serdev core only supports of or ACPI matching; and so far all 65 65 * Android x86 tablets DSDTs have usable serdev nodes, but sometimes 66 66 * under the wrong controller. So we just tie the existing serdev ACPI 67 67 * node to the right controller.
+1 -2
drivers/usb/typec/mux/intel_pmc_mux.c
··· 8 8 9 9 #include <linux/acpi.h> 10 10 #include <linux/module.h> 11 + #include <linux/platform_data/x86/intel_scu_ipc.h> 11 12 #include <linux/platform_device.h> 12 13 #include <linux/property.h> 13 14 #include <linux/usb/pd.h> ··· 18 17 #include <linux/usb/typec_tbt.h> 19 18 #include <linux/debugfs.h> 20 19 #include <linux/usb.h> 21 - 22 - #include <asm/intel_scu_ipc.h> 23 20 24 21 #define PMC_USBC_CMD 0xa7 25 22
+2 -3
drivers/watchdog/intel-mid_wdt.c
··· 20 20 #include <linux/types.h> 21 21 #include <linux/watchdog.h> 22 22 23 - #include <linux/platform_data/intel-mid_wdt.h> 24 - 25 - #include <asm/intel_scu_ipc.h> 23 + #include <linux/platform_data/x86/intel-mid_wdt.h> 24 + #include <linux/platform_data/x86/intel_scu_ipc.h> 26 25 27 26 #define IPC_WATCHDOG 0xf8 28 27
+1 -2
include/linux/acpi.h
··· 387 387 388 388 #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) 389 389 390 - typedef void (*wmi_notify_handler) (u32 value, void *context); 390 + typedef void (*wmi_notify_handler) (union acpi_object *data, void *context); 391 391 392 392 int wmi_instance_count(const char *guid); 393 393 ··· 402 402 extern acpi_status wmi_install_notify_handler(const char *guid, 403 403 wmi_notify_handler handler, void *data); 404 404 extern acpi_status wmi_remove_notify_handler(const char *guid); 405 - extern acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out); 406 405 extern bool wmi_has_guid(const char *guid); 407 406 extern char *wmi_get_acpi_device_uid(const char *guid); 408 407
+3 -3
include/linux/platform_data/intel-mid_wdt.h include/linux/platform_data/x86/intel-mid_wdt.h
··· 6 6 * Contact: David Cohen <david.a.cohen@linux.intel.com> 7 7 */ 8 8 9 - #ifndef __INTEL_MID_WDT_H__ 10 - #define __INTEL_MID_WDT_H__ 9 + #ifndef __PLATFORM_X86_INTEL_MID_WDT_H_ 10 + #define __PLATFORM_X86_INTEL_MID_WDT_H_ 11 11 12 12 #include <linux/platform_device.h> 13 13 ··· 16 16 int (*probe)(struct platform_device *pdev); 17 17 }; 18 18 19 - #endif /*__INTEL_MID_WDT_H__*/ 19 + #endif /* __PLATFORM_X86_INTEL_MID_WDT_H_ */
+37
include/linux/platform_data/x86/asus-wmi.h
··· 4 4 5 5 #include <linux/errno.h> 6 6 #include <linux/types.h> 7 + #include <linux/dmi.h> 7 8 8 9 /* WMI Methods */ 9 10 #define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ ··· 70 69 #define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 71 70 #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 72 71 #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 72 + #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO 0x00110019 73 73 74 74 /* Misc */ 75 75 #define ASUS_WMI_DEVID_PANEL_OD 0x00050019 ··· 166 164 return -ENODEV; 167 165 } 168 166 #endif 167 + 168 + /* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */ 169 + static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = { 170 + { 171 + .matches = { 172 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Zephyrus"), 173 + }, 174 + }, 175 + { 176 + .matches = { 177 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Strix"), 178 + }, 179 + }, 180 + { 181 + .matches = { 182 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"), 183 + }, 184 + }, 185 + { 186 + .matches = { 187 + DMI_MATCH(DMI_BOARD_NAME, "GA403U"), 188 + }, 189 + }, 190 + { 191 + .matches = { 192 + DMI_MATCH(DMI_BOARD_NAME, "GU605M"), 193 + }, 194 + }, 195 + { 196 + .matches = { 197 + DMI_MATCH(DMI_BOARD_NAME, "RC71L"), 198 + }, 199 + }, 200 + { }, 201 + }; 169 202 170 203 #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */
+27
include/trace/events/intel_ifs.h
··· 35 35 __entry->status) 36 36 ); 37 37 38 + TRACE_EVENT(ifs_sbaf, 39 + 40 + TP_PROTO(int batch, union ifs_sbaf activate, union ifs_sbaf_status status), 41 + 42 + TP_ARGS(batch, activate, status), 43 + 44 + TP_STRUCT__entry( 45 + __field( u64, status ) 46 + __field( int, batch ) 47 + __field( u16, bundle ) 48 + __field( u16, pgm ) 49 + ), 50 + 51 + TP_fast_assign( 52 + __entry->status = status.data; 53 + __entry->batch = batch; 54 + __entry->bundle = activate.bundle_idx; 55 + __entry->pgm = activate.pgm_idx; 56 + ), 57 + 58 + TP_printk("batch: 0x%.2x, bundle_idx: 0x%.4x, pgm_idx: 0x%.4x, status: 0x%.16llx", 59 + __entry->batch, 60 + __entry->bundle, 61 + __entry->pgm, 62 + __entry->status) 63 + ); 64 + 38 65 #endif /* _TRACE_IFS_H */ 39 66 40 67 /* This part must be outside protection */