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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull x86 platform driver updates from Ilpo Järvinen:
"acer-wmi:
- Add support for PH14-51, PH16-72, and Nitro AN515-58
- Add proper hwmon support
- Improve error handling when reading "gaming system info"
- Replace direct EC reads for the current platform profile with WMI
calls to handle EC address variations
- Replace custom platform_profile cycling with the generic one

ACPI:
- platform_profile: Major refactoring and improvements
- Support registering multiple platform_profile handlers concurrently
to avoid the need to quirk which handler takes precedence
- Support reporting "custom" profile for cases where the current
profile is ambiguous or when settings tweaks are done outside the
pre-defined profile
- Abstract and layer platform_profile API better using the class_dev
and drvdata
- Various minor improvements
- Add Documentation and kerneldoc

amd/hsmp:
- Add support for HSMP protocol v7

amd/pmc:
- Support AMD 1Ah family 70h
- Support STB with Ryzen desktop SoCs

amd/pmf:
- Support Custom BIOS inputs for PMF TA
- Support passing SRA sensor data from AMD SFH (HID) to PMF TA

dell-smo8800:
- Move SMO88xx quirk away from the generic i2c-i801 driver
- Add accelerometer support for Dell Latitude E6330/E6430 and XPS
9550
- Support probing accelerometer for models yet to be listed in the
DMI mapping table because ACPI lacks i2c-address for the
accelerometer (behind a module parameter because probing might be
dangerous)

HID:
- amd_sfh: Add support for exporting SRA sensor data

hp-wmi:
- Add fan and thermal support for Victus 16-s1000

input:
- Add key for phone linking
- i8042: Add context for the i8042 filter to enable cleaning up the
filter related global variables from pdx86 drivers

lenovo-wmi-camera:
- Use SW_CAMERA_LENS_COVER instead of KEY_CAMERA_ACCESS

mellanox mlxbf-pmc:
- Add support for monitoring cycle count
- Add Documentation

thinkpad_acpi:
- Add support for phone link key

tools/power/x86/intel-speed-select:
- Fix Turbo Ratio Limit restore

x86-android-tables:
- Add support for Vexia EDU ATLA 10 Bluetooth and EC battery driver

And miscellaneous cleanups / refactoring / improvements"

* tag 'platform-drivers-x86-v6.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (133 commits)
platform/x86: acer-wmi: Fix initialization of last_non_turbo_profile
platform/x86: acer-wmi: Ignore AC events
platform/mellanox: mlxreg-io: use sysfs_emit() instead of sprintf()
platform/mellanox: mlxreg-hotplug: use sysfs_emit() instead of sprintf()
platform/mellanox: mlxbf-bootctl: use sysfs_emit() instead of sprintf()
platform/x86: hp-wmi: Add fan and thermal profile support for Victus 16-s1000
ACPI: platform_profile: Add a prefix to log messages
ACPI: platform_profile: Add documentation
ACPI: platform_profile: Clean platform_profile_handler
ACPI: platform_profile: Move platform_profile_handler
ACPI: platform_profile: Remove platform_profile_handler from exported symbols
platform/x86: thinkpad_acpi: Use devm_platform_profile_register()
platform/x86: inspur_platform_profile: Use devm_platform_profile_register()
platform/x86: hp-wmi: Use devm_platform_profile_register()
platform/x86: ideapad-laptop: Use devm_platform_profile_register()
platform/x86: dell-pc: Use devm_platform_profile_register()
platform/x86: asus-wmi: Use devm_platform_profile_register()
platform/x86: amd: pmf: sps: Use devm_platform_profile_register()
platform/x86: acer-wmi: Use devm_platform_profile_register()
platform/surface: surface_platform_profile: Use devm_platform_profile_register()
...

+3794 -1682
+48
Documentation/ABI/testing/sysfs-class-platform-profile
··· 1 + What: /sys/class/platform-profile/platform-profile-X/name 2 + Date: March 2025 3 + KernelVersion: 6.14 4 + Description: Name of the class device given by the driver. 5 + 6 + RO 7 + 8 + What: /sys/class/platform-profile/platform-profile-X/choices 9 + Date: March 2025 10 + KernelVersion: 6.14 11 + Description: This file contains a space-separated list of profiles supported 12 + for this device. 13 + 14 + Drivers must use the following standard profile-names: 15 + 16 + ==================== ======================================== 17 + low-power Low power consumption 18 + cool Cooler operation 19 + quiet Quieter operation 20 + balanced Balance between low power consumption 21 + and performance 22 + balanced-performance Balance between performance and low 23 + power consumption with a slight bias 24 + towards performance 25 + performance High performance operation 26 + custom Driver defined custom profile 27 + ==================== ======================================== 28 + 29 + RO 30 + 31 + What: /sys/class/platform-profile/platform-profile-X/profile 32 + Date: March 2025 33 + KernelVersion: 6.14 34 + Description: Reading this file gives the current selected profile for this 35 + device. Writing this file with one of the strings from 36 + platform_profile_choices changes the profile to the new value. 37 + 38 + This file can be monitored for changes by polling for POLLPRI, 39 + POLLPRI will be signaled on any changes, independent of those 40 + changes coming from a userspace write; or coming from another 41 + source such as e.g. a hotkey triggered profile change handled 42 + either directly by the embedded-controller or fully handled 43 + inside the kernel. 44 + 45 + This file may also emit the string 'custom' to indicate 46 + that the driver is using a driver defined custom profile. 47 + 48 + RW
+64
Documentation/ABI/testing/sysfs-platform-mellanox-pmc
··· 1 + HID Driver Description 2 + MLNXBFD0 mlxbf-pmc Performance counters (BlueField-1) 3 + MLNXBFD1 mlxbf-pmc Performance counters (BlueField-2) 4 + MLNXBFD2 mlxbf-pmc Performance counters (BlueField-3) 5 + 6 + What: /sys/bus/platform/devices/<HID>/hwmon/hwmonX/<block>/event_list 7 + Date: Dec 2020 8 + KernelVersion: 5.10 9 + Contact: "Shravan Kumar Ramani <shravankr@nvidia.com>" 10 + Description: 11 + List of events supported by the counters in the specific block. 12 + It is used to extract the event number or ID associated with 13 + each event. 14 + 15 + What: /sys/bus/platform/devices/<HID>/hwmon/hwmonX/<block>/event<N> 16 + Date: Dec 2020 17 + KernelVersion: 5.10 18 + Contact: "Shravan Kumar Ramani <shravankr@nvidia.com>" 19 + Description: 20 + Event monitored by corresponding counter. This is used to 21 + program or read back the event that should be or is currently 22 + being monitored by counter<N>. 23 + 24 + What: /sys/bus/platform/devices/<HID>/hwmon/hwmonX/<block>/counter<N> 25 + Date: Dec 2020 26 + KernelVersion: 5.10 27 + Contact: "Shravan Kumar Ramani <shravankr@nvidia.com>" 28 + Description: 29 + Counter value of the event being monitored. This is used to 30 + read the counter value of the event which was programmed using 31 + event<N>. This is also used to clear or reset the counter value 32 + by writing 0 to the counter sysfs. 33 + 34 + What: /sys/bus/platform/devices/<HID>/hwmon/hwmonX/<block>/enable 35 + Date: Dec 2020 36 + KernelVersion: 5.10 37 + Contact: "Shravan Kumar Ramani <shravankr@nvidia.com>" 38 + Description: 39 + Start or stop counters. This is used to start the counters 40 + for monitoring the programmed events and also to stop the 41 + counters after the desired duration. Writing value 1 will 42 + start all the counters in the block, and writing 0 will 43 + stop all the counters together. 44 + 45 + What: /sys/bus/platform/devices/<HID>/hwmon/hwmonX/<block>/<reg> 46 + Date: Dec 2020 47 + KernelVersion: 5.10 48 + Contact: "Shravan Kumar Ramani <shravankr@nvidia.com>" 49 + Description: 50 + Value of register. This is used to read or reset the registers 51 + where various performance statistics are counted for each block. 52 + Writing 0 to the sysfs will clear the counter, writing any other 53 + value is not allowed. 54 + 55 + What: /sys/bus/platform/devices/<HID>/hwmon/hwmonX/<block>/count_clock 56 + Date: Mar 2025 57 + KernelVersion: 6.14 58 + Contact: "Shravan Kumar Ramani <shravankr@nvidia.com>" 59 + Description: 60 + Use a counter for counting cycles. This is used to repurpose/dedicate 61 + any of the counters in the block to counting cycles. Each counter is 62 + represented by a bit (bit 0 for counter0, bit1 for counter1 and so on) 63 + and setting the corresponding bit will reserve that specific counter 64 + for counting cycles and override the event<N> setting.
+5
Documentation/ABI/testing/sysfs-platform_profile
··· 33 33 source such as e.g. a hotkey triggered profile change handled 34 34 either directly by the embedded-controller or fully handled 35 35 inside the kernel. 36 + 37 + This file may also emit the string 'custom' to indicate 38 + that multiple platform profiles drivers are in use but 39 + have different values. This string can not be written to 40 + this interface and is solely for informational purposes.
+38
Documentation/userspace-api/sysfs-platform_profile.rst
··· 40 40 1. Explain why the existing profile names cannot be used. 41 41 2. Add the new profile name, along with a clear description of the 42 42 expected behaviour, to the sysfs-platform_profile ABI documentation. 43 + 44 + "Custom" profile support 45 + ======================== 46 + The platform_profile class also supports profiles advertising a "custom" 47 + profile. This is intended to be set by drivers when the setttings in the 48 + driver have been modified in a way that a standard profile doesn't represent 49 + the current state. 50 + 51 + Multiple driver support 52 + ======================= 53 + When multiple drivers on a system advertise a platform profile handler, the 54 + platform profile handler core will only advertise the profiles that are 55 + common between all drivers to the ``/sys/firmware/acpi`` interfaces. 56 + 57 + This is to ensure there is no ambiguity on what the profile names mean when 58 + all handlers don't support a profile. 59 + 60 + Individual drivers will register a 'platform_profile' class device that has 61 + similar semantics as the ``/sys/firmware/acpi/platform_profile`` interface. 62 + 63 + To discover which driver is associated with a platform profile handler the 64 + user can read the ``name`` attribute of the class device. 65 + 66 + To discover available profiles from the class interface the user can read the 67 + ``choices`` attribute. 68 + 69 + If a user wants to select a profile for a specific driver, they can do so 70 + by writing to the ``profile`` attribute of the driver's class device. 71 + 72 + This will allow users to set different profiles for different drivers on the 73 + same system. If the selected profile by individual drivers differs the 74 + platform profile handler core will display the profile 'custom' to indicate 75 + that the profiles are not the same. 76 + 77 + While the ``platform_profile`` attribute has the value ``custom``, writing a 78 + common profile from ``platform_profile_choices`` to the platform_profile 79 + attribute of the platform profile handler core will set the profile for all 80 + drivers.
+4
Documentation/wmi/driver-development-guide.rst
··· 41 41 method associated with a given WMI device can be retrieved using the ``lswmi`` utility 42 42 as mentioned above. 43 43 44 + If you are attempting to port a driver to Linux and are working on a Windows 45 + system, `WMIExplorer <https://github.com/vinaypamnani/wmie2>`_ can be useful 46 + for inspecting available WMI methods and invoking them directly. 47 + 44 48 Basic WMI driver structure 45 49 -------------------------- 46 50
+1 -1
MAINTAINERS
··· 1148 1148 AMD PMC DRIVER 1149 1149 M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 1150 1150 L: platform-driver-x86@vger.kernel.org 1151 - S: Maintained 1151 + S: Supported 1152 1152 F: drivers/platform/x86/amd/pmc/ 1153 1153 1154 1154 AMD PMF DRIVER
-7
arch/x86/include/asm/intel_punit_ipc.h
··· 80 80 81 81 #if IS_ENABLED(CONFIG_INTEL_PUNIT_IPC) 82 82 83 - int intel_punit_ipc_simple_command(int cmd, int para1, int para2); 84 83 int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out); 85 84 86 85 #else 87 - 88 - static inline int intel_punit_ipc_simple_command(int cmd, 89 - int para1, int para2) 90 - { 91 - return -ENODEV; 92 - } 93 86 94 87 static inline int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, 95 88 u32 *in, u32 *out)
+62 -2
arch/x86/include/uapi/asm/amd_hsmp.h
··· 50 50 HSMP_GET_METRIC_TABLE_VER, /* 23h Get metrics table version */ 51 51 HSMP_GET_METRIC_TABLE, /* 24h Get metrics table */ 52 52 HSMP_GET_METRIC_TABLE_DRAM_ADDR,/* 25h Get metrics table dram address */ 53 + HSMP_SET_XGMI_PSTATE_RANGE, /* 26h Set xGMI P-state range */ 54 + HSMP_CPU_RAIL_ISO_FREQ_POLICY, /* 27h Get/Set Cpu Iso frequency policy */ 55 + HSMP_DFC_ENABLE_CTRL, /* 28h Enable/Disable DF C-state */ 56 + HSMP_GET_RAPL_UNITS = 0x30, /* 30h Get scaling factor for energy */ 57 + HSMP_GET_RAPL_CORE_COUNTER, /* 31h Get core energy counter value */ 58 + HSMP_GET_RAPL_PACKAGE_COUNTER, /* 32h Get package energy counter value */ 53 59 HSMP_MSG_ID_MAX, 54 60 }; 55 61 ··· 71 65 HSMP_RSVD = -1, 72 66 HSMP_SET = 0, 73 67 HSMP_GET = 1, 68 + HSMP_SET_GET = 2, 74 69 }; 75 70 76 71 enum hsmp_proto_versions { ··· 79 72 HSMP_PROTO_VER3, 80 73 HSMP_PROTO_VER4, 81 74 HSMP_PROTO_VER5, 82 - HSMP_PROTO_VER6 75 + HSMP_PROTO_VER6, 76 + HSMP_PROTO_VER7 83 77 }; 84 78 85 79 struct hsmp_msg_desc { ··· 308 300 * HSMP_SET_POWER_MODE, num_args = 1, response_sz = 0 309 301 * input: args[0] = power efficiency mode[2:0] 310 302 */ 311 - {1, 0, HSMP_SET}, 303 + {1, 1, HSMP_SET_GET}, 312 304 313 305 /* 314 306 * HSMP_SET_PSTATE_MAX_MIN, num_args = 1, response_sz = 0 ··· 333 325 * output: args[1] = upper 32 bits of the address 334 326 */ 335 327 {0, 2, HSMP_GET}, 328 + 329 + /* 330 + * HSMP_SET_XGMI_PSTATE_RANGE, num_args = 1, response_sz = 0 331 + * input: args[0] = min xGMI p-state[15:8] + max xGMI p-state[7:0] 332 + */ 333 + {1, 0, HSMP_SET}, 334 + 335 + /* 336 + * HSMP_CPU_RAIL_ISO_FREQ_POLICY, num_args = 1, response_sz = 1 337 + * input: args[0] = set/get policy[31] + 338 + * disable/enable independent control[0] 339 + * output: args[0] = current policy[0] 340 + */ 341 + {1, 1, HSMP_SET_GET}, 342 + 343 + /* 344 + * HSMP_DFC_ENABLE_CTRL, num_args = 1, response_sz = 1 345 + * input: args[0] = set/get policy[31] + enable/disable DFC[0] 346 + * output: args[0] = current policy[0] 347 + */ 348 + {1, 1, HSMP_SET_GET}, 349 + 350 + /* RESERVED(0x29-0x2f) */ 351 + {0, 0, HSMP_RSVD}, 352 + {0, 0, HSMP_RSVD}, 353 + {0, 0, HSMP_RSVD}, 354 + {0, 0, HSMP_RSVD}, 355 + {0, 0, HSMP_RSVD}, 356 + {0, 0, HSMP_RSVD}, 357 + {0, 0, HSMP_RSVD}, 358 + 359 + /* 360 + * HSMP_GET_RAPL_UNITS, response_sz = 1 361 + * output: args[0] = tu value[19:16] + esu value[12:8] 362 + */ 363 + {0, 1, HSMP_GET}, 364 + 365 + /* 366 + * HSMP_GET_RAPL_CORE_COUNTER, num_args = 1, response_sz = 1 367 + * input: args[0] = apic id[15:0] 368 + * output: args[0] = lower 32 bits of energy 369 + * output: args[1] = upper 32 bits of energy 370 + */ 371 + {1, 2, HSMP_GET}, 372 + 373 + /* 374 + * HSMP_GET_RAPL_PACKAGE_COUNTER, num_args = 0, response_sz = 1 375 + * output: args[0] = lower 32 bits of energy 376 + * output: args[1] = upper 32 bits of energy 377 + */ 378 + {0, 2, HSMP_GET}, 379 + 336 380 }; 337 381 338 382 /* Metrics table (supported only with proto version 6) */
+549 -112
drivers/acpi/platform_profile.c
··· 2 2 3 3 /* Platform profile sysfs interface */ 4 4 5 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 6 + 5 7 #include <linux/acpi.h> 6 8 #include <linux/bits.h> 9 + #include <linux/cleanup.h> 7 10 #include <linux/init.h> 8 11 #include <linux/mutex.h> 9 12 #include <linux/platform_profile.h> 10 13 #include <linux/sysfs.h> 11 14 12 - static struct platform_profile_handler *cur_profile; 15 + #define to_pprof_handler(d) (container_of(d, struct platform_profile_handler, dev)) 16 + 13 17 static DEFINE_MUTEX(profile_lock); 18 + 19 + struct platform_profile_handler { 20 + const char *name; 21 + struct device dev; 22 + int minor; 23 + unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 24 + const struct platform_profile_ops *ops; 25 + }; 14 26 15 27 static const char * const profile_names[] = { 16 28 [PLATFORM_PROFILE_LOW_POWER] = "low-power", ··· 31 19 [PLATFORM_PROFILE_BALANCED] = "balanced", 32 20 [PLATFORM_PROFILE_BALANCED_PERFORMANCE] = "balanced-performance", 33 21 [PLATFORM_PROFILE_PERFORMANCE] = "performance", 22 + [PLATFORM_PROFILE_CUSTOM] = "custom", 34 23 }; 35 24 static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); 36 25 37 - static ssize_t platform_profile_choices_show(struct device *dev, 38 - struct device_attribute *attr, 39 - char *buf) 26 + static DEFINE_IDA(platform_profile_ida); 27 + 28 + /** 29 + * _commmon_choices_show - Show the available profile choices 30 + * @choices: The available profile choices 31 + * @buf: The buffer to write to 32 + * 33 + * Return: The number of bytes written 34 + */ 35 + static ssize_t _commmon_choices_show(unsigned long *choices, char *buf) 40 36 { 41 - int len = 0; 42 - int err, i; 37 + int i, len = 0; 43 38 44 - err = mutex_lock_interruptible(&profile_lock); 45 - if (err) 46 - return err; 47 - 48 - if (!cur_profile) { 49 - mutex_unlock(&profile_lock); 50 - return -ENODEV; 51 - } 52 - 53 - for_each_set_bit(i, cur_profile->choices, PLATFORM_PROFILE_LAST) { 39 + for_each_set_bit(i, choices, PLATFORM_PROFILE_LAST) { 54 40 if (len == 0) 55 41 len += sysfs_emit_at(buf, len, "%s", profile_names[i]); 56 42 else 57 43 len += sysfs_emit_at(buf, len, " %s", profile_names[i]); 58 44 } 59 45 len += sysfs_emit_at(buf, len, "\n"); 60 - mutex_unlock(&profile_lock); 46 + 61 47 return len; 62 48 } 63 49 64 - static ssize_t platform_profile_show(struct device *dev, 65 - struct device_attribute *attr, 66 - char *buf) 50 + /** 51 + * _store_class_profile - Set the profile for a class device 52 + * @dev: The class device 53 + * @data: The profile to set 54 + * 55 + * Return: 0 on success, -errno on failure 56 + */ 57 + static int _store_class_profile(struct device *dev, void *data) 67 58 { 68 - enum platform_profile_option profile = PLATFORM_PROFILE_BALANCED; 59 + struct platform_profile_handler *handler; 60 + int *bit = (int *)data; 61 + 62 + lockdep_assert_held(&profile_lock); 63 + handler = to_pprof_handler(dev); 64 + if (!test_bit(*bit, handler->choices)) 65 + return -EOPNOTSUPP; 66 + 67 + return handler->ops->profile_set(dev, *bit); 68 + } 69 + 70 + /** 71 + * _notify_class_profile - Notify the class device of a profile change 72 + * @dev: The class device 73 + * @data: Unused 74 + * 75 + * Return: 0 on success, -errno on failure 76 + */ 77 + static int _notify_class_profile(struct device *dev, void *data) 78 + { 79 + struct platform_profile_handler *handler = to_pprof_handler(dev); 80 + 81 + lockdep_assert_held(&profile_lock); 82 + sysfs_notify(&handler->dev.kobj, NULL, "profile"); 83 + kobject_uevent(&handler->dev.kobj, KOBJ_CHANGE); 84 + 85 + return 0; 86 + } 87 + 88 + /** 89 + * get_class_profile - Show the current profile for a class device 90 + * @dev: The class device 91 + * @profile: The profile to return 92 + * 93 + * Return: 0 on success, -errno on failure 94 + */ 95 + static int get_class_profile(struct device *dev, 96 + enum platform_profile_option *profile) 97 + { 98 + struct platform_profile_handler *handler; 99 + enum platform_profile_option val; 69 100 int err; 70 101 71 - err = mutex_lock_interruptible(&profile_lock); 72 - if (err) 102 + lockdep_assert_held(&profile_lock); 103 + handler = to_pprof_handler(dev); 104 + err = handler->ops->profile_get(dev, &val); 105 + if (err) { 106 + pr_err("Failed to get profile for handler %s\n", handler->name); 73 107 return err; 74 - 75 - if (!cur_profile) { 76 - mutex_unlock(&profile_lock); 77 - return -ENODEV; 78 108 } 79 109 80 - err = cur_profile->profile_get(cur_profile, &profile); 81 - mutex_unlock(&profile_lock); 82 - if (err) 83 - return err; 110 + if (WARN_ON(val >= PLATFORM_PROFILE_LAST)) 111 + return -EINVAL; 112 + *profile = val; 84 113 85 - /* Check that profile is valid index */ 86 - if (WARN_ON((profile < 0) || (profile >= ARRAY_SIZE(profile_names)))) 87 - return -EIO; 114 + return 0; 115 + } 116 + 117 + /** 118 + * name_show - Show the name of the profile handler 119 + * @dev: The device 120 + * @attr: The attribute 121 + * @buf: The buffer to write to 122 + * 123 + * Return: The number of bytes written 124 + */ 125 + static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) 126 + { 127 + struct platform_profile_handler *handler = to_pprof_handler(dev); 128 + 129 + return sysfs_emit(buf, "%s\n", handler->name); 130 + } 131 + static DEVICE_ATTR_RO(name); 132 + 133 + /** 134 + * choices_show - Show the available profile choices 135 + * @dev: The device 136 + * @attr: The attribute 137 + * @buf: The buffer to write to 138 + * 139 + * Return: The number of bytes written 140 + */ 141 + static ssize_t choices_show(struct device *dev, 142 + struct device_attribute *attr, 143 + char *buf) 144 + { 145 + struct platform_profile_handler *handler = to_pprof_handler(dev); 146 + 147 + return _commmon_choices_show(handler->choices, buf); 148 + } 149 + static DEVICE_ATTR_RO(choices); 150 + 151 + /** 152 + * profile_show - Show the current profile for a class device 153 + * @dev: The device 154 + * @attr: The attribute 155 + * @buf: The buffer to write to 156 + * 157 + * Return: The number of bytes written 158 + */ 159 + static ssize_t profile_show(struct device *dev, 160 + struct device_attribute *attr, 161 + char *buf) 162 + { 163 + enum platform_profile_option profile = PLATFORM_PROFILE_LAST; 164 + int err; 165 + 166 + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 167 + err = get_class_profile(dev, &profile); 168 + if (err) 169 + return err; 170 + } 88 171 89 172 return sysfs_emit(buf, "%s\n", profile_names[profile]); 90 173 } 91 174 92 - static ssize_t platform_profile_store(struct device *dev, 93 - struct device_attribute *attr, 94 - const char *buf, size_t count) 175 + /** 176 + * profile_store - Set the profile for a class device 177 + * @dev: The device 178 + * @attr: The attribute 179 + * @buf: The buffer to read from 180 + * @count: The number of bytes to read 181 + * 182 + * Return: The number of bytes read 183 + */ 184 + static ssize_t profile_store(struct device *dev, 185 + struct device_attribute *attr, 186 + const char *buf, size_t count) 95 187 { 96 - int err, i; 188 + int index, ret; 97 189 98 - err = mutex_lock_interruptible(&profile_lock); 190 + index = sysfs_match_string(profile_names, buf); 191 + if (index < 0) 192 + return -EINVAL; 193 + 194 + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 195 + ret = _store_class_profile(dev, &index); 196 + if (ret) 197 + return ret; 198 + } 199 + 200 + sysfs_notify(acpi_kobj, NULL, "platform_profile"); 201 + 202 + return count; 203 + } 204 + static DEVICE_ATTR_RW(profile); 205 + 206 + static struct attribute *profile_attrs[] = { 207 + &dev_attr_name.attr, 208 + &dev_attr_choices.attr, 209 + &dev_attr_profile.attr, 210 + NULL 211 + }; 212 + ATTRIBUTE_GROUPS(profile); 213 + 214 + static void pprof_device_release(struct device *dev) 215 + { 216 + struct platform_profile_handler *pprof = to_pprof_handler(dev); 217 + 218 + kfree(pprof); 219 + } 220 + 221 + static const struct class platform_profile_class = { 222 + .name = "platform-profile", 223 + .dev_groups = profile_groups, 224 + .dev_release = pprof_device_release, 225 + }; 226 + 227 + /** 228 + * _aggregate_choices - Aggregate the available profile choices 229 + * @dev: The device 230 + * @data: The available profile choices 231 + * 232 + * Return: 0 on success, -errno on failure 233 + */ 234 + static int _aggregate_choices(struct device *dev, void *data) 235 + { 236 + struct platform_profile_handler *handler; 237 + unsigned long *aggregate = data; 238 + 239 + lockdep_assert_held(&profile_lock); 240 + handler = to_pprof_handler(dev); 241 + if (test_bit(PLATFORM_PROFILE_LAST, aggregate)) 242 + bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST); 243 + else 244 + bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST); 245 + 246 + return 0; 247 + } 248 + 249 + /** 250 + * platform_profile_choices_show - Show the available profile choices for legacy sysfs interface 251 + * @dev: The device 252 + * @attr: The attribute 253 + * @buf: The buffer to write to 254 + * 255 + * Return: The number of bytes written 256 + */ 257 + static ssize_t platform_profile_choices_show(struct device *dev, 258 + struct device_attribute *attr, 259 + char *buf) 260 + { 261 + unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 262 + int err; 263 + 264 + set_bit(PLATFORM_PROFILE_LAST, aggregate); 265 + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 266 + err = class_for_each_device(&platform_profile_class, NULL, 267 + aggregate, _aggregate_choices); 268 + if (err) 269 + return err; 270 + } 271 + 272 + /* no profile handler registered any more */ 273 + if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST)) 274 + return -EINVAL; 275 + 276 + return _commmon_choices_show(aggregate, buf); 277 + } 278 + 279 + /** 280 + * _aggregate_profiles - Aggregate the profiles for legacy sysfs interface 281 + * @dev: The device 282 + * @data: The profile to return 283 + * 284 + * Return: 0 on success, -errno on failure 285 + */ 286 + static int _aggregate_profiles(struct device *dev, void *data) 287 + { 288 + enum platform_profile_option *profile = data; 289 + enum platform_profile_option val; 290 + int err; 291 + 292 + err = get_class_profile(dev, &val); 99 293 if (err) 100 294 return err; 101 295 102 - if (!cur_profile) { 103 - mutex_unlock(&profile_lock); 104 - return -ENODEV; 296 + if (*profile != PLATFORM_PROFILE_LAST && *profile != val) 297 + *profile = PLATFORM_PROFILE_CUSTOM; 298 + else 299 + *profile = val; 300 + 301 + return 0; 302 + } 303 + 304 + /** 305 + * _store_and_notify - Store and notify a class from legacy sysfs interface 306 + * @dev: The device 307 + * @data: The profile to return 308 + * 309 + * Return: 0 on success, -errno on failure 310 + */ 311 + static int _store_and_notify(struct device *dev, void *data) 312 + { 313 + enum platform_profile_option *profile = data; 314 + int err; 315 + 316 + err = _store_class_profile(dev, profile); 317 + if (err) 318 + return err; 319 + return _notify_class_profile(dev, NULL); 320 + } 321 + 322 + /** 323 + * platform_profile_show - Show the current profile for legacy sysfs interface 324 + * @dev: The device 325 + * @attr: The attribute 326 + * @buf: The buffer to write to 327 + * 328 + * Return: The number of bytes written 329 + */ 330 + static ssize_t platform_profile_show(struct device *dev, 331 + struct device_attribute *attr, 332 + char *buf) 333 + { 334 + enum platform_profile_option profile = PLATFORM_PROFILE_LAST; 335 + int err; 336 + 337 + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 338 + err = class_for_each_device(&platform_profile_class, NULL, 339 + &profile, _aggregate_profiles); 340 + if (err) 341 + return err; 105 342 } 343 + 344 + /* no profile handler registered any more */ 345 + if (profile == PLATFORM_PROFILE_LAST) 346 + return -EINVAL; 347 + 348 + return sysfs_emit(buf, "%s\n", profile_names[profile]); 349 + } 350 + 351 + /** 352 + * platform_profile_store - Set the profile for legacy sysfs interface 353 + * @dev: The device 354 + * @attr: The attribute 355 + * @buf: The buffer to read from 356 + * @count: The number of bytes to read 357 + * 358 + * Return: The number of bytes read 359 + */ 360 + static ssize_t platform_profile_store(struct device *dev, 361 + struct device_attribute *attr, 362 + const char *buf, size_t count) 363 + { 364 + unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 365 + int ret; 366 + int i; 106 367 107 368 /* Scan for a matching profile */ 108 369 i = sysfs_match_string(profile_names, buf); 109 - if (i < 0) { 110 - mutex_unlock(&profile_lock); 370 + if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) 111 371 return -EINVAL; 372 + set_bit(PLATFORM_PROFILE_LAST, choices); 373 + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 374 + ret = class_for_each_device(&platform_profile_class, NULL, 375 + choices, _aggregate_choices); 376 + if (ret) 377 + return ret; 378 + if (!test_bit(i, choices)) 379 + return -EOPNOTSUPP; 380 + 381 + ret = class_for_each_device(&platform_profile_class, NULL, &i, 382 + _store_and_notify); 383 + if (ret) 384 + return ret; 112 385 } 113 386 114 - /* Check that platform supports this profile choice */ 115 - if (!test_bit(i, cur_profile->choices)) { 116 - mutex_unlock(&profile_lock); 117 - return -EOPNOTSUPP; 118 - } 387 + sysfs_notify(acpi_kobj, NULL, "platform_profile"); 119 388 120 - err = cur_profile->profile_set(cur_profile, i); 121 - if (!err) 122 - sysfs_notify(acpi_kobj, NULL, "platform_profile"); 123 - 124 - mutex_unlock(&profile_lock); 125 - if (err) 126 - return err; 127 389 return count; 128 390 } 129 391 ··· 410 124 NULL 411 125 }; 412 126 127 + static int profile_class_registered(struct device *dev, const void *data) 128 + { 129 + return 1; 130 + } 131 + 132 + static umode_t profile_class_is_visible(struct kobject *kobj, struct attribute *attr, int idx) 133 + { 134 + if (!class_find_device(&platform_profile_class, NULL, NULL, profile_class_registered)) 135 + return 0; 136 + return attr->mode; 137 + } 138 + 413 139 static const struct attribute_group platform_profile_group = { 414 - .attrs = platform_profile_attrs 140 + .attrs = platform_profile_attrs, 141 + .is_visible = profile_class_is_visible, 415 142 }; 416 143 417 - void platform_profile_notify(void) 144 + /** 145 + * platform_profile_notify - Notify class device and legacy sysfs interface 146 + * @dev: The class device 147 + */ 148 + void platform_profile_notify(struct device *dev) 418 149 { 419 - if (!cur_profile) 420 - return; 150 + scoped_cond_guard(mutex_intr, return, &profile_lock) { 151 + _notify_class_profile(dev, NULL); 152 + } 421 153 sysfs_notify(acpi_kobj, NULL, "platform_profile"); 422 154 } 423 155 EXPORT_SYMBOL_GPL(platform_profile_notify); 424 156 157 + /** 158 + * platform_profile_cycle - Cycles profiles available on all registered class devices 159 + * 160 + * Return: 0 on success, -errno on failure 161 + */ 425 162 int platform_profile_cycle(void) 426 163 { 427 - enum platform_profile_option profile; 428 - enum platform_profile_option next; 164 + enum platform_profile_option next = PLATFORM_PROFILE_LAST; 165 + enum platform_profile_option profile = PLATFORM_PROFILE_LAST; 166 + unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 429 167 int err; 430 168 431 - err = mutex_lock_interruptible(&profile_lock); 432 - if (err) 433 - return err; 169 + set_bit(PLATFORM_PROFILE_LAST, choices); 170 + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 171 + err = class_for_each_device(&platform_profile_class, NULL, 172 + &profile, _aggregate_profiles); 173 + if (err) 174 + return err; 434 175 435 - if (!cur_profile) { 436 - mutex_unlock(&profile_lock); 437 - return -ENODEV; 176 + if (profile == PLATFORM_PROFILE_CUSTOM || 177 + profile == PLATFORM_PROFILE_LAST) 178 + return -EINVAL; 179 + 180 + err = class_for_each_device(&platform_profile_class, NULL, 181 + choices, _aggregate_choices); 182 + if (err) 183 + return err; 184 + 185 + /* never iterate into a custom if all drivers supported it */ 186 + clear_bit(PLATFORM_PROFILE_CUSTOM, choices); 187 + 188 + next = find_next_bit_wrap(choices, 189 + PLATFORM_PROFILE_LAST, 190 + profile + 1); 191 + 192 + err = class_for_each_device(&platform_profile_class, NULL, &next, 193 + _store_and_notify); 194 + 195 + if (err) 196 + return err; 438 197 } 439 198 440 - err = cur_profile->profile_get(cur_profile, &profile); 441 - if (err) { 442 - mutex_unlock(&profile_lock); 443 - return err; 444 - } 199 + sysfs_notify(acpi_kobj, NULL, "platform_profile"); 445 200 446 - next = find_next_bit_wrap(cur_profile->choices, PLATFORM_PROFILE_LAST, 447 - profile + 1); 448 - 449 - if (WARN_ON(next == PLATFORM_PROFILE_LAST)) { 450 - mutex_unlock(&profile_lock); 451 - return -EINVAL; 452 - } 453 - 454 - err = cur_profile->profile_set(cur_profile, next); 455 - mutex_unlock(&profile_lock); 456 - 457 - if (!err) 458 - sysfs_notify(acpi_kobj, NULL, "platform_profile"); 459 - 460 - return err; 201 + return 0; 461 202 } 462 203 EXPORT_SYMBOL_GPL(platform_profile_cycle); 463 204 464 - int platform_profile_register(struct platform_profile_handler *pprof) 205 + /** 206 + * platform_profile_register - Creates and registers a platform profile class device 207 + * @dev: Parent device 208 + * @name: Name of the class device 209 + * @drvdata: Driver data that will be attached to the class device 210 + * @ops: Platform profile's mandatory operations 211 + * 212 + * Return: pointer to the new class device on success, ERR_PTR on failure 213 + */ 214 + struct device *platform_profile_register(struct device *dev, const char *name, 215 + void *drvdata, 216 + const struct platform_profile_ops *ops) 465 217 { 218 + struct device *ppdev; 219 + int minor; 466 220 int err; 467 221 468 - mutex_lock(&profile_lock); 469 - /* We can only have one active profile */ 470 - if (cur_profile) { 471 - mutex_unlock(&profile_lock); 472 - return -EEXIST; 473 - } 222 + /* Sanity check */ 223 + if (WARN_ON_ONCE(!dev || !name || !ops || !ops->profile_get || 224 + !ops->profile_set || !ops->probe)) 225 + return ERR_PTR(-EINVAL); 474 226 475 - /* Sanity check the profile handler field are set */ 476 - if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) || 477 - !pprof->profile_set || !pprof->profile_get) { 478 - mutex_unlock(&profile_lock); 479 - return -EINVAL; 480 - } 227 + struct platform_profile_handler *pprof __free(kfree) = kzalloc( 228 + sizeof(*pprof), GFP_KERNEL); 229 + if (!pprof) 230 + return ERR_PTR(-ENOMEM); 481 231 482 - err = sysfs_create_group(acpi_kobj, &platform_profile_group); 232 + err = ops->probe(drvdata, pprof->choices); 483 233 if (err) { 484 - mutex_unlock(&profile_lock); 485 - return err; 234 + dev_err(dev, "platform_profile probe failed\n"); 235 + return ERR_PTR(err); 486 236 } 487 237 488 - cur_profile = pprof; 489 - mutex_unlock(&profile_lock); 490 - return 0; 238 + if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { 239 + dev_err(dev, "Failed to register platform_profile class device with empty choices\n"); 240 + return ERR_PTR(-EINVAL); 241 + } 242 + 243 + guard(mutex)(&profile_lock); 244 + 245 + /* create class interface for individual handler */ 246 + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL); 247 + if (minor < 0) 248 + return ERR_PTR(minor); 249 + 250 + pprof->name = name; 251 + pprof->ops = ops; 252 + pprof->minor = minor; 253 + pprof->dev.class = &platform_profile_class; 254 + pprof->dev.parent = dev; 255 + dev_set_drvdata(&pprof->dev, drvdata); 256 + dev_set_name(&pprof->dev, "platform-profile-%d", pprof->minor); 257 + /* device_register() takes ownership of pprof/ppdev */ 258 + ppdev = &no_free_ptr(pprof)->dev; 259 + err = device_register(ppdev); 260 + if (err) { 261 + put_device(ppdev); 262 + goto cleanup_ida; 263 + } 264 + 265 + sysfs_notify(acpi_kobj, NULL, "platform_profile"); 266 + 267 + err = sysfs_update_group(acpi_kobj, &platform_profile_group); 268 + if (err) 269 + goto cleanup_cur; 270 + 271 + return ppdev; 272 + 273 + cleanup_cur: 274 + device_unregister(ppdev); 275 + 276 + cleanup_ida: 277 + ida_free(&platform_profile_ida, minor); 278 + 279 + return ERR_PTR(err); 491 280 } 492 281 EXPORT_SYMBOL_GPL(platform_profile_register); 493 282 494 - int platform_profile_remove(void) 283 + /** 284 + * platform_profile_remove - Unregisters a platform profile class device 285 + * @dev: Class device 286 + * 287 + * Return: 0 288 + */ 289 + int platform_profile_remove(struct device *dev) 495 290 { 496 - sysfs_remove_group(acpi_kobj, &platform_profile_group); 291 + struct platform_profile_handler *pprof = to_pprof_handler(dev); 292 + int id; 293 + guard(mutex)(&profile_lock); 497 294 498 - mutex_lock(&profile_lock); 499 - cur_profile = NULL; 500 - mutex_unlock(&profile_lock); 295 + id = pprof->minor; 296 + device_unregister(&pprof->dev); 297 + ida_free(&platform_profile_ida, id); 298 + 299 + sysfs_notify(acpi_kobj, NULL, "platform_profile"); 300 + 301 + sysfs_update_group(acpi_kobj, &platform_profile_group); 302 + 501 303 return 0; 502 304 } 503 305 EXPORT_SYMBOL_GPL(platform_profile_remove); 306 + 307 + static void devm_platform_profile_release(struct device *dev, void *res) 308 + { 309 + struct device **ppdev = res; 310 + 311 + platform_profile_remove(*ppdev); 312 + } 313 + 314 + /** 315 + * devm_platform_profile_register - Device managed version of platform_profile_register 316 + * @dev: Parent device 317 + * @name: Name of the class device 318 + * @drvdata: Driver data that will be attached to the class device 319 + * @ops: Platform profile's mandatory operations 320 + * 321 + * Return: pointer to the new class device on success, ERR_PTR on failure 322 + */ 323 + struct device *devm_platform_profile_register(struct device *dev, const char *name, 324 + void *drvdata, 325 + const struct platform_profile_ops *ops) 326 + { 327 + struct device *ppdev; 328 + struct device **dr; 329 + 330 + dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL); 331 + if (!dr) 332 + return ERR_PTR(-ENOMEM); 333 + 334 + ppdev = platform_profile_register(dev, name, drvdata, ops); 335 + if (IS_ERR(ppdev)) { 336 + devres_free(dr); 337 + return ppdev; 338 + } 339 + 340 + *dr = ppdev; 341 + devres_add(dev, dr); 342 + 343 + return ppdev; 344 + } 345 + EXPORT_SYMBOL_GPL(devm_platform_profile_register); 346 + 347 + static int __init platform_profile_init(void) 348 + { 349 + int err; 350 + 351 + err = class_register(&platform_profile_class); 352 + if (err) 353 + return err; 354 + 355 + err = sysfs_create_group(acpi_kobj, &platform_profile_group); 356 + if (err) 357 + class_unregister(&platform_profile_class); 358 + 359 + return err; 360 + } 361 + 362 + static void __exit platform_profile_exit(void) 363 + { 364 + sysfs_remove_group(acpi_kobj, &platform_profile_group); 365 + class_unregister(&platform_profile_class); 366 + } 367 + module_init(platform_profile_init); 368 + module_exit(platform_profile_exit); 504 369 505 370 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); 506 371 MODULE_DESCRIPTION("ACPI platform profile sysfs interface");
+1
drivers/hid/amd-sfh-hid/amd_sfh_common.h
··· 43 43 struct sfh_dev_status { 44 44 bool is_hpd_present; 45 45 bool is_als_present; 46 + bool is_sra_present; 46 47 }; 47 48 48 49 struct amd_mp2_dev {
+22
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
··· 30 30 case ACCEL_IDX: 31 31 case GYRO_IDX: 32 32 case MAG_IDX: 33 + case SRA_IDX: 33 34 case ALS_IDX: 34 35 case HPD_IDX: 35 36 if (BIT(i) & slist->sl.sensors) ··· 59 58 return "gyroscope"; 60 59 case MAG_IDX: 61 60 return "magnetometer"; 61 + case SRA_IDX: 62 + return "SRA"; 62 63 case ALS_IDX: 63 64 return "ALS"; 64 65 case HPD_IDX: ··· 133 130 134 131 for (i = 0; i < cl_data->num_hid_devices; i++) { 135 132 cl_data->sensor_sts[i] = SENSOR_DISABLED; 133 + 134 + if (cl_data->num_hid_devices == 1 && cl_data->sensor_idx[0] == SRA_IDX) 135 + break; 136 + 137 + if (cl_data->sensor_idx[i] == SRA_IDX) { 138 + info.sensor_idx = cl_data->sensor_idx[i]; 139 + writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0)); 140 + mp2_ops->start(privdata, info); 141 + status = amd_sfh_wait_for_response 142 + (privdata, cl_data->sensor_idx[i], ENABLE_SENSOR); 143 + 144 + cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; 145 + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) 146 + privdata->dev_en.is_sra_present = true; 147 + continue; 148 + } 149 + 136 150 cl_data->sensor_requested_cnt[i] = 0; 137 151 cl_data->cur_hid_dev = i; 138 152 cl_idx = cl_data->sensor_idx[i]; ··· 201 181 } 202 182 203 183 for (i = 0; i < cl_data->num_hid_devices; i++) { 184 + if (cl_data->sensor_idx[i] == SRA_IDX) 185 + continue; 204 186 cl_data->cur_hid_dev = i; 205 187 if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { 206 188 cl_data->is_any_sensor_enabled = true;
+38
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
··· 87 87 emp2 = mp2; 88 88 } 89 89 90 + static int amd_sfh_mode_info(u32 *platform_type, u32 *laptop_placement) 91 + { 92 + struct sfh_op_mode mode; 93 + 94 + if (!platform_type || !laptop_placement) 95 + return -EINVAL; 96 + 97 + if (!emp2 || !emp2->dev_en.is_sra_present) 98 + return -ENODEV; 99 + 100 + mode.val = readl(emp2->mmio + amd_get_c2p_val(emp2, 3)); 101 + 102 + *platform_type = mode.op_mode.devicemode; 103 + 104 + if (mode.op_mode.ontablestate == 1) { 105 + *laptop_placement = ON_TABLE; 106 + } else if (mode.op_mode.ontablestate == 2) { 107 + *laptop_placement = ON_LAP_MOTION; 108 + } else if (mode.op_mode.inbagstate == 1) { 109 + *laptop_placement = IN_BAG; 110 + } else if (mode.op_mode.outbagstate == 1) { 111 + *laptop_placement = OUT_OF_BAG; 112 + } else if (mode.op_mode.ontablestate == 0 || mode.op_mode.inbagstate == 0 || 113 + mode.op_mode.outbagstate == 0) { 114 + *laptop_placement = LP_UNKNOWN; 115 + pr_warn_once("Unknown laptop placement\n"); 116 + } else if (mode.op_mode.ontablestate == 3 || mode.op_mode.inbagstate == 3 || 117 + mode.op_mode.outbagstate == 3) { 118 + *laptop_placement = LP_UNDEFINED; 119 + pr_warn_once("Undefined laptop placement\n"); 120 + } 121 + 122 + return 0; 123 + } 124 + 90 125 static int amd_sfh_hpd_info(u8 *user_present) 91 126 { 92 127 struct hpd_status hpdstatus; ··· 166 131 return amd_sfh_hpd_info(&sfh_info->user_present); 167 132 case MT_ALS: 168 133 return amd_sfh_als_info(&sfh_info->ambient_light); 134 + case MT_SRA: 135 + return amd_sfh_mode_info(&sfh_info->platform_type, 136 + &sfh_info->laptop_placement); 169 137 } 170 138 } 171 139 return -EINVAL;
+22 -2
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
··· 22 22 ACCEL_IDX, 23 23 GYRO_IDX, 24 24 MAG_IDX, 25 - ALS_IDX = 4, 26 - HPD_IDX = 5, 25 + SRA_IDX, 26 + ALS_IDX, 27 + HPD_IDX, 27 28 MAX_IDX = 15, 28 29 }; 29 30 ··· 162 161 u32 state : 1; 163 162 } shpd; 164 163 u32 val; 164 + }; 165 + }; 166 + 167 + struct sfh_op_mode { 168 + union { 169 + u32 val; 170 + struct { 171 + u32 mode : 3; 172 + u32 lidstatus : 1; 173 + u32 angle : 10; 174 + u32 inbagstatedbg : 2; 175 + u32 ontablestate : 2; 176 + u32 inbagstate : 2; 177 + u32 outbagstate : 2; 178 + u32 inbagmlcstate : 1; 179 + u32 powerstate : 2; 180 + u32 data : 3; 181 + u32 devicemode : 4; 182 + } op_mode; 165 183 }; 166 184 }; 167 185
-125
drivers/i2c/busses/i2c-i801.c
··· 1162 1162 } 1163 1163 } 1164 1164 1165 - /* NOTE: Keep this list in sync with drivers/platform/x86/dell-smo8800.c */ 1166 - static const char *const acpi_smo8800_ids[] = { 1167 - "SMO8800", 1168 - "SMO8801", 1169 - "SMO8810", 1170 - "SMO8811", 1171 - "SMO8820", 1172 - "SMO8821", 1173 - "SMO8830", 1174 - "SMO8831", 1175 - }; 1176 - 1177 - static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle, 1178 - u32 nesting_level, 1179 - void *context, 1180 - void **return_value) 1181 - { 1182 - struct acpi_device_info *info; 1183 - acpi_status status; 1184 - char *hid; 1185 - int i; 1186 - 1187 - status = acpi_get_object_info(obj_handle, &info); 1188 - if (ACPI_FAILURE(status)) 1189 - return AE_OK; 1190 - 1191 - if (!(info->valid & ACPI_VALID_HID)) 1192 - goto smo88xx_not_found; 1193 - 1194 - hid = info->hardware_id.string; 1195 - if (!hid) 1196 - goto smo88xx_not_found; 1197 - 1198 - i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid); 1199 - if (i < 0) 1200 - goto smo88xx_not_found; 1201 - 1202 - kfree(info); 1203 - 1204 - *return_value = NULL; 1205 - return AE_CTRL_TERMINATE; 1206 - 1207 - smo88xx_not_found: 1208 - kfree(info); 1209 - return AE_OK; 1210 - } 1211 - 1212 - static bool is_dell_system_with_lis3lv02d(void) 1213 - { 1214 - void *err = ERR_PTR(-ENOENT); 1215 - 1216 - if (!dmi_match(DMI_SYS_VENDOR, "Dell Inc.")) 1217 - return false; 1218 - 1219 - /* 1220 - * Check that ACPI device SMO88xx is present and is functioning. 1221 - * Function acpi_get_devices() already filters all ACPI devices 1222 - * which are not present or are not functioning. 1223 - * ACPI device SMO88xx represents our ST microelectronics lis3lv02d 1224 - * accelerometer but unfortunately ACPI does not provide any other 1225 - * information (like I2C address). 1226 - */ 1227 - acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL, &err); 1228 - 1229 - return !IS_ERR(err); 1230 - } 1231 - 1232 - /* 1233 - * Accelerometer's I2C address is not specified in DMI nor ACPI, 1234 - * so it is needed to define mapping table based on DMI product names. 1235 - */ 1236 - static const struct { 1237 - const char *dmi_product_name; 1238 - unsigned short i2c_addr; 1239 - } dell_lis3lv02d_devices[] = { 1240 - /* 1241 - * Dell platform team told us that these Latitude devices have 1242 - * ST microelectronics accelerometer at I2C address 0x29. 1243 - */ 1244 - { "Latitude E5250", 0x29 }, 1245 - { "Latitude E5450", 0x29 }, 1246 - { "Latitude E5550", 0x29 }, 1247 - { "Latitude E6440", 0x29 }, 1248 - { "Latitude E6440 ATG", 0x29 }, 1249 - { "Latitude E6540", 0x29 }, 1250 - /* 1251 - * Additional individual entries were added after verification. 1252 - */ 1253 - { "Latitude 5480", 0x29 }, 1254 - { "Precision 3540", 0x29 }, 1255 - { "Precision M6800", 0x29 }, 1256 - { "Vostro V131", 0x1d }, 1257 - { "Vostro 5568", 0x29 }, 1258 - { "XPS 15 7590", 0x29 }, 1259 - }; 1260 - 1261 - static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv) 1262 - { 1263 - struct i2c_board_info info; 1264 - const char *dmi_product_name; 1265 - int i; 1266 - 1267 - dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); 1268 - for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) { 1269 - if (strcmp(dmi_product_name, 1270 - dell_lis3lv02d_devices[i].dmi_product_name) == 0) 1271 - break; 1272 - } 1273 - 1274 - if (i == ARRAY_SIZE(dell_lis3lv02d_devices)) { 1275 - dev_warn(&priv->pci_dev->dev, 1276 - "Accelerometer lis3lv02d is present on SMBus but its" 1277 - " address is unknown, skipping registration\n"); 1278 - return; 1279 - } 1280 - 1281 - memset(&info, 0, sizeof(struct i2c_board_info)); 1282 - info.addr = dell_lis3lv02d_devices[i].i2c_addr; 1283 - strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); 1284 - i2c_new_client_device(&priv->adapter, &info); 1285 - } 1286 - 1287 1165 /* Register optional targets */ 1288 1166 static void i801_probe_optional_targets(struct i801_priv *priv) 1289 1167 { ··· 1180 1302 1181 1303 if (dmi_name_in_vendors("FUJITSU")) 1182 1304 dmi_walk(dmi_check_onboard_devices, &priv->adapter); 1183 - 1184 - if (is_dell_system_with_lis3lv02d()) 1185 - register_dell_lis3lv02d_i2c_device(priv); 1186 1305 1187 1306 /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ 1188 1307 #ifdef CONFIG_I2C_I801_MUX
+2 -2
drivers/input/misc/ideapad_slidebar.c
··· 121 121 } 122 122 123 123 static bool slidebar_i8042_filter(unsigned char data, unsigned char str, 124 - struct serio *port) 124 + struct serio *port, void *context) 125 125 { 126 126 static bool extended = false; 127 127 ··· 219 219 input_set_capability(slidebar_input_dev, EV_ABS, ABS_X); 220 220 input_set_abs_params(slidebar_input_dev, ABS_X, 0, 0xff, 0, 0); 221 221 222 - err = i8042_install_filter(slidebar_i8042_filter); 222 + err = i8042_install_filter(slidebar_i8042_filter, NULL); 223 223 if (err) { 224 224 dev_err(&pdev->dev, 225 225 "Failed to install i8042 filter: %d\n", err);
+10 -7
drivers/input/serio/i8042.c
··· 179 179 static struct notifier_block i8042_kbd_bind_notifier_block; 180 180 181 181 static bool i8042_handle_data(int irq); 182 - static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, 183 - struct serio *serio); 182 + static i8042_filter_t i8042_platform_filter; 183 + static void *i8042_platform_filter_context; 184 184 185 185 void i8042_lock_chip(void) 186 186 { ··· 194 194 } 195 195 EXPORT_SYMBOL(i8042_unlock_chip); 196 196 197 - int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, 198 - struct serio *serio)) 197 + int i8042_install_filter(i8042_filter_t filter, void *context) 199 198 { 200 199 guard(spinlock_irqsave)(&i8042_lock); 201 200 ··· 202 203 return -EBUSY; 203 204 204 205 i8042_platform_filter = filter; 206 + i8042_platform_filter_context = context; 205 207 return 0; 206 208 } 207 209 EXPORT_SYMBOL(i8042_install_filter); 208 210 209 - int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, 210 - struct serio *port)) 211 + int i8042_remove_filter(i8042_filter_t filter) 211 212 { 212 213 guard(spinlock_irqsave)(&i8042_lock); 213 214 ··· 215 216 return -EINVAL; 216 217 217 218 i8042_platform_filter = NULL; 219 + i8042_platform_filter_context = NULL; 218 220 return 0; 219 221 } 220 222 EXPORT_SYMBOL(i8042_remove_filter); ··· 480 480 } 481 481 } 482 482 483 - if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { 483 + if (!i8042_platform_filter) 484 + return false; 485 + 486 + if (i8042_platform_filter(data, str, serio, i8042_platform_filter_context)) { 484 487 dbg("Filtered out by platform filter\n"); 485 488 return true; 486 489 }
+10 -10
drivers/platform/mellanox/mlxbf-bootctl.c
··· 177 177 if (ret < 0) 178 178 return ret; 179 179 180 - return sprintf(buf, "%d\n", ret); 180 + return sysfs_emit(buf, "%d\n", ret); 181 181 } 182 182 183 183 static ssize_t post_reset_wdog_store(struct device *dev, ··· 206 206 if (action < 0) 207 207 return action; 208 208 209 - return sprintf(buf, "%s\n", mlxbf_bootctl_action_to_string(action)); 209 + return sysfs_emit(buf, "%s\n", mlxbf_bootctl_action_to_string(action)); 210 210 } 211 211 212 212 static int mlxbf_bootctl_store(int smc_op, const char *buf, size_t count) ··· 274 274 * due to using the test bits. 275 275 */ 276 276 if (test_state) { 277 - return sprintf(buf, "%s(test)\n", 277 + return sysfs_emit(buf, "%s(test)\n", 278 278 mlxbf_bootctl_lifecycle_states[lc_state]); 279 279 } else if (use_dev_key && 280 280 (lc_state == MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE)) { 281 - return sprintf(buf, "Secured (development)\n"); 281 + return sysfs_emit(buf, "Secured (development)\n"); 282 282 } 283 283 284 - return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]); 284 + return sysfs_emit(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]); 285 285 } 286 286 287 287 static ssize_t secure_boot_fuse_state_show(struct device *dev, ··· 332 332 else 333 333 status = valid ? "Invalid" : "Free"; 334 334 } 335 - buf_len += sprintf(buf + buf_len, "%d:%s ", key, status); 335 + buf_len += sysfs_emit(buf + buf_len, "%d:%s ", key, status); 336 336 } 337 - buf_len += sprintf(buf + buf_len, "\n"); 337 + buf_len += sysfs_emit(buf + buf_len, "\n"); 338 338 339 339 return buf_len; 340 340 } ··· 939 939 940 940 static ssize_t mlxbf_bootctl_bootfifo_read(struct file *filp, 941 941 struct kobject *kobj, 942 - struct bin_attribute *bin_attr, 942 + const struct bin_attribute *bin_attr, 943 943 char *buf, loff_t pos, 944 944 size_t count) 945 945 { ··· 971 971 return p - buf; 972 972 } 973 973 974 - static struct bin_attribute mlxbf_bootctl_bootfifo_sysfs_attr = { 974 + static const struct bin_attribute mlxbf_bootctl_bootfifo_sysfs_attr = { 975 975 .attr = { .name = "bootfifo", .mode = 0400 }, 976 - .read = mlxbf_bootctl_bootfifo_read, 976 + .read_new = mlxbf_bootctl_bootfifo_read, 977 977 }; 978 978 979 979 static bool mlxbf_bootctl_guid_match(const guid_t *guid,
+106 -7
drivers/platform/mellanox/mlxbf-pmc.c
··· 88 88 #define MLXBF_PMC_CRSPACE_PERFMON_CTL(n) (n * MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ) 89 89 #define MLXBF_PMC_CRSPACE_PERFMON_EN BIT(30) 90 90 #define MLXBF_PMC_CRSPACE_PERFMON_CLR BIT(28) 91 + #define MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0x4) 91 92 #define MLXBF_PMC_CRSPACE_PERFMON_VAL0(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0xc) 92 93 93 94 /** ··· 115 114 * @attr_event: Attributes for "event" sysfs files 116 115 * @attr_event_list: Attributes for "event_list" sysfs files 117 116 * @attr_enable: Attributes for "enable" sysfs files 117 + * @attr_count_clock: Attributes for "count_clock" sysfs files 118 118 * @block_attr: All attributes needed for the block 119 119 * @block_attr_grp: Attribute group for the block 120 120 */ ··· 128 126 struct mlxbf_pmc_attribute *attr_event; 129 127 struct mlxbf_pmc_attribute attr_event_list; 130 128 struct mlxbf_pmc_attribute attr_enable; 129 + struct mlxbf_pmc_attribute attr_count_clock; 131 130 struct attribute *block_attr[MLXBF_PMC_MAX_ATTRS]; 132 131 struct attribute_group block_attr_grp; 133 132 }; ··· 862 859 {75, "HISTOGRAM_HISTOGRAM_BIN9"}, 863 860 }; 864 861 862 + static const struct mlxbf_pmc_events mlxbf_pmc_clock_events[] = { 863 + { 0x0, "FMON_CLK_LAST_COUNT_PLL_D1_INST0" }, 864 + { 0x4, "REFERENCE_WINDOW_WIDTH_PLL_D1_INST0" }, 865 + { 0x8, "FMON_CLK_LAST_COUNT_PLL_D1_INST1" }, 866 + { 0xc, "REFERENCE_WINDOW_WIDTH_PLL_D1_INST1" }, 867 + { 0x10, "FMON_CLK_LAST_COUNT_PLL_G1" }, 868 + { 0x14, "REFERENCE_WINDOW_WIDTH_PLL_G1" }, 869 + { 0x18, "FMON_CLK_LAST_COUNT_PLL_W1" }, 870 + { 0x1c, "REFERENCE_WINDOW_WIDTH_PLL_W1" }, 871 + { 0x20, "FMON_CLK_LAST_COUNT_PLL_T1" }, 872 + { 0x24, "REFERENCE_WINDOW_WIDTH_PLL_T1" }, 873 + { 0x28, "FMON_CLK_LAST_COUNT_PLL_A0" }, 874 + { 0x2c, "REFERENCE_WINDOW_WIDTH_PLL_A0" }, 875 + { 0x30, "FMON_CLK_LAST_COUNT_PLL_C0" }, 876 + { 0x34, "REFERENCE_WINDOW_WIDTH_PLL_C0" }, 877 + { 0x38, "FMON_CLK_LAST_COUNT_PLL_N1" }, 878 + { 0x3c, "REFERENCE_WINDOW_WIDTH_PLL_N1" }, 879 + { 0x40, "FMON_CLK_LAST_COUNT_PLL_I1" }, 880 + { 0x44, "REFERENCE_WINDOW_WIDTH_PLL_I1" }, 881 + { 0x48, "FMON_CLK_LAST_COUNT_PLL_R1" }, 882 + { 0x4c, "REFERENCE_WINDOW_WIDTH_PLL_R1" }, 883 + { 0x50, "FMON_CLK_LAST_COUNT_PLL_P1" }, 884 + { 0x54, "REFERENCE_WINDOW_WIDTH_PLL_P1" }, 885 + { 0x58, "FMON_CLK_LAST_COUNT_REF_100_INST0" }, 886 + { 0x5c, "REFERENCE_WINDOW_WIDTH_REF_100_INST0" }, 887 + { 0x60, "FMON_CLK_LAST_COUNT_REF_100_INST1" }, 888 + { 0x64, "REFERENCE_WINDOW_WIDTH_REF_100_INST1" }, 889 + { 0x68, "FMON_CLK_LAST_COUNT_REF_156" }, 890 + { 0x6c, "REFERENCE_WINDOW_WIDTH_REF_156" }, 891 + }; 892 + 865 893 static struct mlxbf_pmc_context *pmc; 866 894 867 895 /* UUID used to probe ATF service. */ ··· 1066 1032 } else if (strstr(blk, "llt")) { 1067 1033 events = mlxbf_pmc_llt_events; 1068 1034 size = ARRAY_SIZE(mlxbf_pmc_llt_events); 1035 + } else if (strstr(blk, "clock_measure")) { 1036 + events = mlxbf_pmc_clock_events; 1037 + size = ARRAY_SIZE(mlxbf_pmc_clock_events); 1069 1038 } else { 1070 1039 events = NULL; 1071 1040 size = 0; ··· 1205 1168 /* Method to handle crspace counter programming */ 1206 1169 static int mlxbf_pmc_program_crspace_counter(unsigned int blk_num, u32 cnt_num, u32 evt) 1207 1170 { 1208 - void *addr; 1171 + void __iomem *addr; 1209 1172 u32 word; 1210 1173 int ret; 1211 1174 ··· 1229 1192 /* Method to clear crspace counter value */ 1230 1193 static int mlxbf_pmc_clear_crspace_counter(unsigned int blk_num, u32 cnt_num) 1231 1194 { 1232 - void *addr; 1195 + void __iomem *addr; 1233 1196 1234 1197 addr = pmc->block[blk_num].mmio_base + 1235 1198 MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) + ··· 1442 1405 static int mlxbf_pmc_read_crspace_event(unsigned int blk_num, u32 cnt_num, u64 *result) 1443 1406 { 1444 1407 u32 word, evt; 1445 - void *addr; 1408 + void __iomem *addr; 1446 1409 int ret; 1447 1410 1448 1411 addr = pmc->block[blk_num].mmio_base + ··· 1503 1466 /* Method to read a register */ 1504 1467 static int mlxbf_pmc_read_reg(unsigned int blk_num, u32 offset, u64 *result) 1505 1468 { 1506 - u32 ecc_out; 1469 + u32 reg; 1507 1470 1508 - if (strstr(pmc->block_name[blk_num], "ecc")) { 1471 + if ((strstr(pmc->block_name[blk_num], "ecc")) || 1472 + (strstr(pmc->block_name[blk_num], "clock_measure"))) { 1509 1473 if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + offset, 1510 - &ecc_out)) 1474 + &reg)) 1511 1475 return -EFAULT; 1512 1476 1513 - *result = ecc_out; 1477 + *result = reg; 1514 1478 return 0; 1515 1479 } 1516 1480 ··· 1525 1487 /* Method to write to a register */ 1526 1488 static int mlxbf_pmc_write_reg(unsigned int blk_num, u32 offset, u64 data) 1527 1489 { 1490 + if (strstr(pmc->block_name[blk_num], "clock_measure")) 1491 + return -EINVAL; 1492 + 1528 1493 if (strstr(pmc->block_name[blk_num], "ecc")) { 1529 1494 return mlxbf_pmc_write(pmc->block[blk_num].mmio_base + offset, 1530 1495 MLXBF_PMC_WRITE_REG_32, data); ··· 1804 1763 return count; 1805 1764 } 1806 1765 1766 + /* Show function for "count_clock" sysfs files - only for crspace */ 1767 + static ssize_t mlxbf_pmc_count_clock_show(struct device *dev, 1768 + struct device_attribute *attr, char *buf) 1769 + { 1770 + struct mlxbf_pmc_attribute *attr_count_clock = container_of( 1771 + attr, struct mlxbf_pmc_attribute, dev_attr); 1772 + unsigned int blk_num; 1773 + u32 reg; 1774 + 1775 + blk_num = attr_count_clock->nr; 1776 + 1777 + if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base + 1778 + MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters), 1779 + &reg)) 1780 + return -EINVAL; 1781 + 1782 + return sysfs_emit(buf, "%u\n", reg); 1783 + } 1784 + 1785 + /* Store function for "count_clock" sysfs files - only for crspace */ 1786 + static ssize_t mlxbf_pmc_count_clock_store(struct device *dev, 1787 + struct device_attribute *attr, 1788 + const char *buf, size_t count) 1789 + { 1790 + struct mlxbf_pmc_attribute *attr_count_clock = container_of( 1791 + attr, struct mlxbf_pmc_attribute, dev_attr); 1792 + unsigned int blk_num; 1793 + u32 reg; 1794 + int err; 1795 + 1796 + blk_num = attr_count_clock->nr; 1797 + 1798 + err = kstrtouint(buf, 0, &reg); 1799 + if (err < 0) 1800 + return err; 1801 + 1802 + mlxbf_pmc_write(pmc->block[blk_num].mmio_base + 1803 + MLXBF_PMC_CRSPACE_PERFMON_COUNT_CLOCK(pmc->block[blk_num].counters), 1804 + MLXBF_PMC_WRITE_REG_32, reg); 1805 + 1806 + return count; 1807 + } 1808 + 1807 1809 /* Populate attributes for blocks with counters to monitor performance */ 1808 1810 static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_num) 1809 1811 { ··· 1879 1795 attr->nr = blk_num; 1880 1796 attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 1881 1797 "enable"); 1798 + if (!attr->dev_attr.attr.name) 1799 + return -ENOMEM; 1800 + pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr; 1801 + attr = NULL; 1802 + } 1803 + 1804 + if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { 1805 + /* Program crspace counters to count clock cycles using "count_clock" sysfs */ 1806 + attr = &pmc->block[blk_num].attr_count_clock; 1807 + attr->dev_attr.attr.mode = 0644; 1808 + attr->dev_attr.show = mlxbf_pmc_count_clock_show; 1809 + attr->dev_attr.store = mlxbf_pmc_count_clock_store; 1810 + attr->nr = blk_num; 1811 + attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, 1812 + "count_clock"); 1882 1813 if (!attr->dev_attr.attr.name) 1883 1814 return -ENOMEM; 1884 1815 pmc->block[blk_num].block_attr[++i] = &attr->dev_attr.attr;
+1 -1
drivers/platform/mellanox/mlxreg-hotplug.c
··· 232 232 regval = !!(regval & data->mask); 233 233 } 234 234 235 - return sprintf(buf, "%u\n", regval); 235 + return sysfs_emit(buf, "%u\n", regval); 236 236 } 237 237 238 238 #define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i]
+1 -1
drivers/platform/mellanox/mlxreg-io.c
··· 126 126 127 127 mutex_unlock(&priv->io_lock); 128 128 129 - return sprintf(buf, "%u\n", regval); 129 + return sysfs_emit(buf, "%u\n", regval); 130 130 131 131 access_error: 132 132 mutex_unlock(&priv->io_lock);
+25 -19
drivers/platform/surface/surface_platform_profile.c
··· 40 40 41 41 struct ssam_platform_profile_device { 42 42 struct ssam_device *sdev; 43 - struct platform_profile_handler handler; 43 + struct device *ppdev; 44 44 bool has_fan; 45 45 }; 46 46 ··· 154 154 } 155 155 } 156 156 157 - static int ssam_platform_profile_get(struct platform_profile_handler *pprof, 157 + static int ssam_platform_profile_get(struct device *dev, 158 158 enum platform_profile_option *profile) 159 159 { 160 160 struct ssam_platform_profile_device *tpd; 161 161 enum ssam_tmp_profile tp; 162 162 int status; 163 163 164 - tpd = container_of(pprof, struct ssam_platform_profile_device, handler); 164 + tpd = dev_get_drvdata(dev); 165 165 166 166 status = ssam_tmp_profile_get(tpd->sdev, &tp); 167 167 if (status) ··· 175 175 return 0; 176 176 } 177 177 178 - static int ssam_platform_profile_set(struct platform_profile_handler *pprof, 178 + static int ssam_platform_profile_set(struct device *dev, 179 179 enum platform_profile_option profile) 180 180 { 181 181 struct ssam_platform_profile_device *tpd; 182 182 int tp; 183 183 184 - tpd = container_of(pprof, struct ssam_platform_profile_device, handler); 184 + tpd = dev_get_drvdata(dev); 185 185 186 186 tp = convert_profile_to_ssam_tmp(tpd->sdev, profile); 187 187 if (tp < 0) ··· 201 201 return tp; 202 202 } 203 203 204 + static int ssam_platform_profile_probe(void *drvdata, unsigned long *choices) 205 + { 206 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 207 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 208 + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); 209 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 210 + 211 + return 0; 212 + } 213 + 214 + static const struct platform_profile_ops ssam_platform_profile_ops = { 215 + .probe = ssam_platform_profile_probe, 216 + .profile_get = ssam_platform_profile_get, 217 + .profile_set = ssam_platform_profile_set, 218 + }; 219 + 204 220 static int surface_platform_profile_probe(struct ssam_device *sdev) 205 221 { 206 222 struct ssam_platform_profile_device *tpd; ··· 226 210 return -ENOMEM; 227 211 228 212 tpd->sdev = sdev; 229 - 230 - tpd->handler.profile_get = ssam_platform_profile_get; 231 - tpd->handler.profile_set = ssam_platform_profile_set; 213 + ssam_device_set_drvdata(sdev, tpd); 232 214 233 215 tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan"); 234 216 235 - set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices); 236 - set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices); 237 - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices); 238 - set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices); 217 + tpd->ppdev = devm_platform_profile_register(&sdev->dev, "Surface Platform Profile", 218 + tpd, &ssam_platform_profile_ops); 239 219 240 - return platform_profile_register(&tpd->handler); 241 - } 242 - 243 - static void surface_platform_profile_remove(struct ssam_device *sdev) 244 - { 245 - platform_profile_remove(); 220 + return PTR_ERR_OR_ZERO(tpd->ppdev); 246 221 } 247 222 248 223 static const struct ssam_device_id ssam_platform_profile_match[] = { ··· 244 237 245 238 static struct ssam_device_driver surface_platform_profile = { 246 239 .probe = surface_platform_profile_probe, 247 - .remove = surface_platform_profile_remove, 248 240 .match_table = ssam_platform_profile_match, 249 241 .driver = { 250 242 .name = "surface_platform_profile",
+376 -178
drivers/platform/x86/acer-wmi.c
··· 30 30 #include <linux/input/sparse-keymap.h> 31 31 #include <acpi/video.h> 32 32 #include <linux/hwmon.h> 33 + #include <linux/units.h> 34 + #include <linux/unaligned.h> 33 35 #include <linux/bitfield.h> 36 + #include <linux/bitmap.h> 34 37 35 38 MODULE_AUTHOR("Carlos Corbacho"); 36 39 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver"); ··· 70 67 #define ACER_WMID_GET_GAMING_SYS_INFO_METHODID 5 71 68 #define ACER_WMID_SET_GAMING_FAN_BEHAVIOR 14 72 69 #define ACER_WMID_SET_GAMING_MISC_SETTING_METHODID 22 70 + #define ACER_WMID_GET_GAMING_MISC_SETTING_METHODID 23 73 71 74 - #define ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET 0x54 72 + #define ACER_GAMING_MISC_SETTING_STATUS_MASK GENMASK_ULL(7, 0) 73 + #define ACER_GAMING_MISC_SETTING_INDEX_MASK GENMASK_ULL(7, 0) 74 + #define ACER_GAMING_MISC_SETTING_VALUE_MASK GENMASK_ULL(15, 8) 75 75 76 - #define ACER_PREDATOR_V4_FAN_SPEED_READ_BIT_MASK GENMASK(20, 8) 76 + #define ACER_PREDATOR_V4_RETURN_STATUS_BIT_MASK GENMASK_ULL(7, 0) 77 + #define ACER_PREDATOR_V4_SENSOR_INDEX_BIT_MASK GENMASK_ULL(15, 8) 78 + #define ACER_PREDATOR_V4_SENSOR_READING_BIT_MASK GENMASK_ULL(23, 8) 79 + #define ACER_PREDATOR_V4_SUPPORTED_SENSORS_BIT_MASK GENMASK_ULL(39, 24) 77 80 78 81 /* 79 82 * Acer ACPI method GUIDs ··· 104 95 WMID_HOTKEY_EVENT = 0x1, 105 96 WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5, 106 97 WMID_GAMING_TURBO_KEY_EVENT = 0x7, 98 + WMID_AC_EVENT = 0x8, 107 99 }; 108 100 109 101 enum acer_wmi_predator_v4_sys_info_command { 110 - ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS = 0x02, 111 - ACER_WMID_CMD_GET_PREDATOR_V4_CPU_FAN_SPEED = 0x0201, 112 - ACER_WMID_CMD_GET_PREDATOR_V4_GPU_FAN_SPEED = 0x0601, 102 + ACER_WMID_CMD_GET_PREDATOR_V4_SUPPORTED_SENSORS = 0x0000, 103 + ACER_WMID_CMD_GET_PREDATOR_V4_SENSOR_READING = 0x0001, 104 + ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS = 0x0002, 105 + }; 106 + 107 + enum acer_wmi_predator_v4_sensor_id { 108 + ACER_WMID_SENSOR_CPU_TEMPERATURE = 0x01, 109 + ACER_WMID_SENSOR_CPU_FAN_SPEED = 0x02, 110 + ACER_WMID_SENSOR_EXTERNAL_TEMPERATURE_2 = 0x03, 111 + ACER_WMID_SENSOR_GPU_FAN_SPEED = 0x06, 112 + ACER_WMID_SENSOR_GPU_TEMPERATURE = 0x0A, 113 + }; 114 + 115 + enum acer_wmi_predator_v4_oc { 116 + ACER_WMID_OC_NORMAL = 0x0000, 117 + ACER_WMID_OC_TURBO = 0x0002, 118 + }; 119 + 120 + enum acer_wmi_gaming_misc_setting { 121 + ACER_WMID_MISC_SETTING_OC_1 = 0x0005, 122 + ACER_WMID_MISC_SETTING_OC_2 = 0x0007, 123 + ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES = 0x000A, 124 + ACER_WMID_MISC_SETTING_PLATFORM_PROFILE = 0x000B, 113 125 }; 114 126 115 127 static const struct key_entry acer_wmi_keymap[] __initconst = { ··· 276 246 #define ACER_CAP_TURBO_LED BIT(8) 277 247 #define ACER_CAP_TURBO_FAN BIT(9) 278 248 #define ACER_CAP_PLATFORM_PROFILE BIT(10) 279 - #define ACER_CAP_FAN_SPEED_READ BIT(11) 249 + #define ACER_CAP_HWMON BIT(11) 280 250 281 251 /* 282 252 * Interface type flags ··· 301 271 static u8 commun_fn_key_number; 302 272 static bool cycle_gaming_thermal_profile = true; 303 273 static bool predator_v4; 274 + static u64 supported_sensors; 304 275 305 276 module_param(mailled, int, 0444); 306 277 module_param(brightness, int, 0444); ··· 389 358 390 359 if (quirks->predator_v4) 391 360 interface->capability |= ACER_CAP_PLATFORM_PROFILE | 392 - ACER_CAP_FAN_SPEED_READ; 361 + ACER_CAP_HWMON; 393 362 } 394 363 395 364 static int __init dmi_matched(const struct dmi_system_id *dmi) ··· 422 391 .turbo = 1, 423 392 .cpu_fans = 1, 424 393 .gpu_fans = 1, 394 + }; 395 + 396 + static struct quirk_entry quirk_acer_predator_ph16_72 = { 397 + .turbo = 1, 398 + .cpu_fans = 1, 399 + .gpu_fans = 1, 400 + .predator_v4 = 1, 401 + }; 402 + 403 + static struct quirk_entry quirk_acer_predator_pt14_51 = { 404 + .turbo = 1, 405 + .cpu_fans = 1, 406 + .gpu_fans = 1, 407 + .predator_v4 = 1, 425 408 }; 426 409 427 410 static struct quirk_entry quirk_acer_predator_v4 = { ··· 611 566 }, 612 567 { 613 568 .callback = dmi_matched, 569 + .ident = "Acer Nitro AN515-58", 570 + .matches = { 571 + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 572 + DMI_MATCH(DMI_PRODUCT_NAME, "Nitro AN515-58"), 573 + }, 574 + .driver_data = &quirk_acer_predator_v4, 575 + }, 576 + { 577 + .callback = dmi_matched, 614 578 .ident = "Acer Predator PH315-53", 615 579 .matches = { 616 580 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ··· 647 593 }, 648 594 { 649 595 .callback = dmi_matched, 596 + .ident = "Acer Predator PH16-72", 597 + .matches = { 598 + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 599 + DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH16-72"), 600 + }, 601 + .driver_data = &quirk_acer_predator_ph16_72, 602 + }, 603 + { 604 + .callback = dmi_matched, 650 605 .ident = "Acer Predator PH18-71", 651 606 .matches = { 652 607 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 653 608 DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH18-71"), 654 609 }, 655 610 .driver_data = &quirk_acer_predator_v4, 611 + }, 612 + { 613 + .callback = dmi_matched, 614 + .ident = "Acer Predator PT14-51", 615 + .matches = { 616 + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 617 + DMI_MATCH(DMI_PRODUCT_NAME, "Predator PT14-51"), 618 + }, 619 + .driver_data = &quirk_acer_predator_pt14_51, 656 620 }, 657 621 { 658 622 .callback = set_force_caps, ··· 785 713 {} 786 714 }; 787 715 788 - static struct platform_profile_handler platform_profile_handler; 716 + static struct device *platform_profile_device; 789 717 static bool platform_profile_support; 790 718 791 719 /* 792 720 * The profile used before turbo mode. This variable is needed for 793 721 * returning from turbo mode when the mode key is in toggle mode. 794 722 */ 795 - static int last_non_turbo_profile; 723 + static int last_non_turbo_profile = INT_MIN; 796 724 797 - enum acer_predator_v4_thermal_profile_ec { 798 - ACER_PREDATOR_V4_THERMAL_PROFILE_ECO = 0x04, 799 - ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO = 0x03, 800 - ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE = 0x02, 801 - ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET = 0x01, 802 - ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED = 0x00, 803 - }; 725 + /* The most performant supported profile */ 726 + static int acer_predator_v4_max_perf; 804 727 805 - enum acer_predator_v4_thermal_profile_wmi { 806 - ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI = 0x060B, 807 - ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI = 0x050B, 808 - ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE_WMI = 0x040B, 809 - ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET_WMI = 0x0B, 810 - ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI = 0x010B, 728 + enum acer_predator_v4_thermal_profile { 729 + ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET = 0x00, 730 + ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED = 0x01, 731 + ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE = 0x04, 732 + ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO = 0x05, 733 + ACER_PREDATOR_V4_THERMAL_PROFILE_ECO = 0x06, 811 734 }; 812 735 813 736 /* Find which quirks are needed for a particular vendor/ model pair */ ··· 1515 1448 return status; 1516 1449 } 1517 1450 1451 + static int WMI_gaming_execute_u32_u64(u32 method_id, u32 in, u64 *out) 1452 + { 1453 + struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; 1454 + struct acpi_buffer input = { 1455 + .length = sizeof(in), 1456 + .pointer = &in, 1457 + }; 1458 + union acpi_object *obj; 1459 + acpi_status status; 1460 + int ret = 0; 1461 + 1462 + status = wmi_evaluate_method(WMID_GUID4, 0, method_id, &input, &result); 1463 + if (ACPI_FAILURE(status)) 1464 + return -EIO; 1465 + 1466 + obj = result.pointer; 1467 + if (obj && out) { 1468 + switch (obj->type) { 1469 + case ACPI_TYPE_INTEGER: 1470 + *out = obj->integer.value; 1471 + break; 1472 + case ACPI_TYPE_BUFFER: 1473 + if (obj->buffer.length < sizeof(*out)) 1474 + ret = -ENOMSG; 1475 + else 1476 + *out = get_unaligned_le64(obj->buffer.pointer); 1477 + 1478 + break; 1479 + default: 1480 + ret = -ENOMSG; 1481 + break; 1482 + } 1483 + } 1484 + 1485 + kfree(obj); 1486 + 1487 + return ret; 1488 + } 1489 + 1518 1490 static acpi_status WMID_gaming_set_u64(u64 value, u32 cap) 1519 1491 { 1520 1492 u32 method_id = 0; ··· 1567 1461 break; 1568 1462 case ACER_CAP_TURBO_FAN: 1569 1463 method_id = ACER_WMID_SET_GAMING_FAN_BEHAVIOR; 1570 - break; 1571 - case ACER_CAP_TURBO_OC: 1572 - method_id = ACER_WMID_SET_GAMING_MISC_SETTING_METHODID; 1573 1464 break; 1574 1465 default: 1575 1466 return AE_BAD_PARAMETER; ··· 1600 1497 return status; 1601 1498 } 1602 1499 1500 + static int WMID_gaming_get_sys_info(u32 command, u64 *out) 1501 + { 1502 + acpi_status status; 1503 + u64 result; 1504 + 1505 + status = WMI_gaming_execute_u64(ACER_WMID_GET_GAMING_SYS_INFO_METHODID, command, &result); 1506 + if (ACPI_FAILURE(status)) 1507 + return -EIO; 1508 + 1509 + /* The return status must be zero for the operation to have succeeded */ 1510 + if (FIELD_GET(ACER_PREDATOR_V4_RETURN_STATUS_BIT_MASK, result)) 1511 + return -EIO; 1512 + 1513 + *out = result; 1514 + 1515 + return 0; 1516 + } 1517 + 1603 1518 static void WMID_gaming_set_fan_mode(u8 fan_mode) 1604 1519 { 1605 1520 /* fan_mode = 1 is used for auto, fan_mode = 2 used for turbo*/ ··· 1637 1516 for (i = 0; i < quirks->gpu_fans; ++i) 1638 1517 gpu_fan_config1 |= fan_mode << (2 * i + 6); 1639 1518 WMID_gaming_set_u64(gpu_fan_config2 | gpu_fan_config1 << 16, ACER_CAP_TURBO_FAN); 1519 + } 1520 + 1521 + static int WMID_gaming_set_misc_setting(enum acer_wmi_gaming_misc_setting setting, u8 value) 1522 + { 1523 + acpi_status status; 1524 + u64 input = 0; 1525 + u64 result; 1526 + 1527 + input |= FIELD_PREP(ACER_GAMING_MISC_SETTING_INDEX_MASK, setting); 1528 + input |= FIELD_PREP(ACER_GAMING_MISC_SETTING_VALUE_MASK, value); 1529 + 1530 + status = WMI_gaming_execute_u64(ACER_WMID_SET_GAMING_MISC_SETTING_METHODID, input, &result); 1531 + if (ACPI_FAILURE(status)) 1532 + return -EIO; 1533 + 1534 + /* The return status must be zero for the operation to have succeeded */ 1535 + if (FIELD_GET(ACER_GAMING_MISC_SETTING_STATUS_MASK, result)) 1536 + return -EIO; 1537 + 1538 + return 0; 1539 + } 1540 + 1541 + static int WMID_gaming_get_misc_setting(enum acer_wmi_gaming_misc_setting setting, u8 *value) 1542 + { 1543 + u64 input = 0; 1544 + u64 result; 1545 + int ret; 1546 + 1547 + input |= FIELD_PREP(ACER_GAMING_MISC_SETTING_INDEX_MASK, setting); 1548 + 1549 + ret = WMI_gaming_execute_u32_u64(ACER_WMID_GET_GAMING_MISC_SETTING_METHODID, input, 1550 + &result); 1551 + if (ret < 0) 1552 + return ret; 1553 + 1554 + /* The return status must be zero for the operation to have succeeded */ 1555 + if (FIELD_GET(ACER_GAMING_MISC_SETTING_STATUS_MASK, result)) 1556 + return -EIO; 1557 + 1558 + *value = FIELD_GET(ACER_GAMING_MISC_SETTING_VALUE_MASK, result); 1559 + 1560 + return 0; 1640 1561 } 1641 1562 1642 1563 /* ··· 1907 1744 return 0; 1908 1745 } 1909 1746 1910 - static int acer_get_fan_speed(int fan) 1911 - { 1912 - if (quirks->predator_v4) { 1913 - acpi_status status; 1914 - u64 fanspeed; 1915 - 1916 - status = WMI_gaming_execute_u64( 1917 - ACER_WMID_GET_GAMING_SYS_INFO_METHODID, 1918 - fan == 0 ? ACER_WMID_CMD_GET_PREDATOR_V4_CPU_FAN_SPEED : 1919 - ACER_WMID_CMD_GET_PREDATOR_V4_GPU_FAN_SPEED, 1920 - &fanspeed); 1921 - 1922 - if (ACPI_FAILURE(status)) 1923 - return -EIO; 1924 - 1925 - return FIELD_GET(ACER_PREDATOR_V4_FAN_SPEED_READ_BIT_MASK, fanspeed); 1926 - } 1927 - return -EOPNOTSUPP; 1928 - } 1929 - 1930 1747 /* 1931 1748 * Predator series turbo button 1932 1749 */ ··· 1926 1783 WMID_gaming_set_fan_mode(0x1); 1927 1784 1928 1785 /* Set OC to normal */ 1929 - WMID_gaming_set_u64(0x5, ACER_CAP_TURBO_OC); 1930 - WMID_gaming_set_u64(0x7, ACER_CAP_TURBO_OC); 1786 + if (has_cap(ACER_CAP_TURBO_OC)) { 1787 + WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_1, 1788 + ACER_WMID_OC_NORMAL); 1789 + WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_2, 1790 + ACER_WMID_OC_NORMAL); 1791 + } 1931 1792 } else { 1932 1793 /* Turn on turbo led */ 1933 1794 WMID_gaming_set_u64(0x10001, ACER_CAP_TURBO_LED); ··· 1940 1793 WMID_gaming_set_fan_mode(0x2); 1941 1794 1942 1795 /* Set OC to turbo mode */ 1943 - WMID_gaming_set_u64(0x205, ACER_CAP_TURBO_OC); 1944 - WMID_gaming_set_u64(0x207, ACER_CAP_TURBO_OC); 1796 + if (has_cap(ACER_CAP_TURBO_OC)) { 1797 + WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_1, 1798 + ACER_WMID_OC_TURBO); 1799 + WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_OC_2, 1800 + ACER_WMID_OC_TURBO); 1801 + } 1945 1802 } 1946 1803 return turbo_led_state; 1947 1804 } 1948 1805 1949 1806 static int 1950 - acer_predator_v4_platform_profile_get(struct platform_profile_handler *pprof, 1807 + acer_predator_v4_platform_profile_get(struct device *dev, 1951 1808 enum platform_profile_option *profile) 1952 1809 { 1953 1810 u8 tp; 1954 1811 int err; 1955 1812 1956 - err = ec_read(ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET, &tp); 1957 - 1958 - if (err < 0) 1813 + err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, &tp); 1814 + if (err) 1959 1815 return err; 1960 1816 1961 1817 switch (tp) { ··· 1985 1835 } 1986 1836 1987 1837 static int 1988 - acer_predator_v4_platform_profile_set(struct platform_profile_handler *pprof, 1838 + acer_predator_v4_platform_profile_set(struct device *dev, 1989 1839 enum platform_profile_option profile) 1990 1840 { 1991 - int tp; 1992 - acpi_status status; 1841 + int err, tp; 1993 1842 1994 1843 switch (profile) { 1995 1844 case PLATFORM_PROFILE_PERFORMANCE: 1996 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI; 1845 + tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; 1997 1846 break; 1998 1847 case PLATFORM_PROFILE_BALANCED_PERFORMANCE: 1999 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE_WMI; 1848 + tp = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; 2000 1849 break; 2001 1850 case PLATFORM_PROFILE_BALANCED: 2002 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 1851 + tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; 2003 1852 break; 2004 1853 case PLATFORM_PROFILE_QUIET: 2005 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET_WMI; 1854 + tp = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; 2006 1855 break; 2007 1856 case PLATFORM_PROFILE_LOW_POWER: 2008 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI; 1857 + tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; 2009 1858 break; 2010 1859 default: 2011 1860 return -EOPNOTSUPP; 2012 1861 } 2013 1862 2014 - status = WMI_gaming_execute_u64( 2015 - ACER_WMID_SET_GAMING_MISC_SETTING_METHODID, tp, NULL); 1863 + err = WMID_gaming_set_misc_setting(ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, tp); 1864 + if (err) 1865 + return err; 2016 1866 2017 - if (ACPI_FAILURE(status)) 2018 - return -EIO; 2019 - 2020 - if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI) 1867 + if (tp != acer_predator_v4_max_perf) 2021 1868 last_non_turbo_profile = tp; 2022 1869 2023 1870 return 0; 2024 1871 } 2025 1872 2026 - static int acer_platform_profile_setup(void) 1873 + static int 1874 + acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices) 1875 + { 1876 + unsigned long supported_profiles; 1877 + int err; 1878 + 1879 + err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES, 1880 + (u8 *)&supported_profiles); 1881 + if (err) 1882 + return err; 1883 + 1884 + /* Iterate through supported profiles in order of increasing performance */ 1885 + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_ECO, &supported_profiles)) { 1886 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 1887 + acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; 1888 + last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; 1889 + } 1890 + 1891 + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET, &supported_profiles)) { 1892 + set_bit(PLATFORM_PROFILE_QUIET, choices); 1893 + acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; 1894 + last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; 1895 + } 1896 + 1897 + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED, &supported_profiles)) { 1898 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 1899 + acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; 1900 + last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; 1901 + } 1902 + 1903 + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE, &supported_profiles)) { 1904 + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); 1905 + acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; 1906 + 1907 + /* We only use this profile as a fallback option in case no prior 1908 + * profile is supported. 1909 + */ 1910 + if (last_non_turbo_profile < 0) 1911 + last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; 1912 + } 1913 + 1914 + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO, &supported_profiles)) { 1915 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1916 + acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; 1917 + 1918 + /* We need to handle the hypothetical case where only the turbo profile 1919 + * is supported. In this case the turbo toggle will essentially be a 1920 + * no-op. 1921 + */ 1922 + if (last_non_turbo_profile < 0) 1923 + last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; 1924 + } 1925 + 1926 + return 0; 1927 + } 1928 + 1929 + static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = { 1930 + .probe = acer_predator_v4_platform_profile_probe, 1931 + .profile_get = acer_predator_v4_platform_profile_get, 1932 + .profile_set = acer_predator_v4_platform_profile_set, 1933 + }; 1934 + 1935 + static int acer_platform_profile_setup(struct platform_device *device) 2027 1936 { 2028 1937 if (quirks->predator_v4) { 2029 - int err; 2030 - 2031 - platform_profile_handler.profile_get = 2032 - acer_predator_v4_platform_profile_get; 2033 - platform_profile_handler.profile_set = 2034 - acer_predator_v4_platform_profile_set; 2035 - 2036 - set_bit(PLATFORM_PROFILE_PERFORMANCE, 2037 - platform_profile_handler.choices); 2038 - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, 2039 - platform_profile_handler.choices); 2040 - set_bit(PLATFORM_PROFILE_BALANCED, 2041 - platform_profile_handler.choices); 2042 - set_bit(PLATFORM_PROFILE_QUIET, 2043 - platform_profile_handler.choices); 2044 - set_bit(PLATFORM_PROFILE_LOW_POWER, 2045 - platform_profile_handler.choices); 2046 - 2047 - err = platform_profile_register(&platform_profile_handler); 2048 - if (err) 2049 - return err; 1938 + platform_profile_device = devm_platform_profile_register( 1939 + &device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops); 1940 + if (IS_ERR(platform_profile_device)) 1941 + return PTR_ERR(platform_profile_device); 2050 1942 2051 1943 platform_profile_support = true; 2052 - 2053 - /* Set default non-turbo profile */ 2054 - last_non_turbo_profile = 2055 - ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 2056 1944 } 2057 1945 return 0; 2058 1946 } ··· 2098 1910 static int acer_thermal_profile_change(void) 2099 1911 { 2100 1912 /* 2101 - * This mode key can rotate each mode or toggle turbo mode. 2102 - * On battery, only ECO and BALANCED mode are available. 1913 + * This mode key will either cycle through each mode or toggle the 1914 + * most performant profile. 2103 1915 */ 2104 1916 if (quirks->predator_v4) { 2105 1917 u8 current_tp; 2106 - int tp, err; 2107 - u64 on_AC; 2108 - acpi_status status; 1918 + int err, tp; 2109 1919 2110 - err = ec_read(ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET, 2111 - &current_tp); 1920 + if (cycle_gaming_thermal_profile) { 1921 + platform_profile_cycle(); 1922 + } else { 1923 + /* Do nothing if no suitable platform profiles where found */ 1924 + if (last_non_turbo_profile < 0) 1925 + return 0; 2112 1926 2113 - if (err < 0) 2114 - return err; 1927 + err = WMID_gaming_get_misc_setting( 1928 + ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, &current_tp); 1929 + if (err) 1930 + return err; 2115 1931 2116 - /* Check power source */ 2117 - status = WMI_gaming_execute_u64( 2118 - ACER_WMID_GET_GAMING_SYS_INFO_METHODID, 2119 - ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS, &on_AC); 2120 - 2121 - if (ACPI_FAILURE(status)) 2122 - return -EIO; 2123 - 2124 - switch (current_tp) { 2125 - case ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO: 2126 - if (!on_AC) 2127 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 2128 - else if (cycle_gaming_thermal_profile) 2129 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI; 2130 - else 1932 + if (current_tp == acer_predator_v4_max_perf) 2131 1933 tp = last_non_turbo_profile; 2132 - break; 2133 - case ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE: 2134 - if (!on_AC) 2135 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 2136 1934 else 2137 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI; 2138 - break; 2139 - case ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED: 2140 - if (!on_AC) 2141 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI; 2142 - else if (cycle_gaming_thermal_profile) 2143 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE_WMI; 2144 - else 2145 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI; 2146 - break; 2147 - case ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET: 2148 - if (!on_AC) 2149 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 2150 - else if (cycle_gaming_thermal_profile) 2151 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 2152 - else 2153 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI; 2154 - break; 2155 - case ACER_PREDATOR_V4_THERMAL_PROFILE_ECO: 2156 - if (!on_AC) 2157 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI; 2158 - else if (cycle_gaming_thermal_profile) 2159 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET_WMI; 2160 - else 2161 - tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI; 2162 - break; 2163 - default: 2164 - return -EOPNOTSUPP; 1935 + tp = acer_predator_v4_max_perf; 1936 + 1937 + err = WMID_gaming_set_misc_setting( 1938 + ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, tp); 1939 + if (err) 1940 + return err; 1941 + 1942 + /* Store last profile for toggle */ 1943 + if (current_tp != acer_predator_v4_max_perf) 1944 + last_non_turbo_profile = current_tp; 1945 + 1946 + platform_profile_notify(platform_profile_device); 2165 1947 } 2166 - 2167 - status = WMI_gaming_execute_u64( 2168 - ACER_WMID_SET_GAMING_MISC_SETTING_METHODID, tp, NULL); 2169 - 2170 - if (ACPI_FAILURE(status)) 2171 - return -EIO; 2172 - 2173 - /* Store non-turbo profile for turbo mode toggle*/ 2174 - if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI) 2175 - last_non_turbo_profile = tp; 2176 - 2177 - platform_profile_notify(); 2178 1948 } 2179 1949 2180 1950 return 0; ··· 2426 2280 if (return_value.key_num == 0x5 && has_cap(ACER_CAP_PLATFORM_PROFILE)) 2427 2281 acer_thermal_profile_change(); 2428 2282 break; 2283 + case WMID_AC_EVENT: 2284 + /* We ignore AC events here */ 2285 + break; 2429 2286 default: 2430 2287 pr_warn("Unknown function number - %d - %d\n", 2431 2288 return_value.function, return_value.key_num); ··· 2679 2530 goto error_rfkill; 2680 2531 2681 2532 if (has_cap(ACER_CAP_PLATFORM_PROFILE)) { 2682 - err = acer_platform_profile_setup(); 2533 + err = acer_platform_profile_setup(device); 2683 2534 if (err) 2684 2535 goto error_platform_profile; 2685 2536 } 2686 2537 2687 - if (has_cap(ACER_CAP_FAN_SPEED_READ)) { 2538 + if (has_cap(ACER_CAP_HWMON)) { 2688 2539 err = acer_wmi_hwmon_init(); 2689 2540 if (err) 2690 2541 goto error_hwmon; ··· 2693 2544 return 0; 2694 2545 2695 2546 error_hwmon: 2696 - if (platform_profile_support) 2697 - platform_profile_remove(); 2698 2547 error_platform_profile: 2699 2548 acer_rfkill_exit(); 2700 2549 error_rfkill: ··· 2713 2566 acer_backlight_exit(); 2714 2567 2715 2568 acer_rfkill_exit(); 2716 - 2717 - if (platform_profile_support) 2718 - platform_profile_remove(); 2719 2569 } 2720 2570 2721 2571 #ifdef CONFIG_PM_SLEEP ··· 2799 2655 &interface->debug.wmid_devices); 2800 2656 } 2801 2657 2658 + static const enum acer_wmi_predator_v4_sensor_id acer_wmi_temp_channel_to_sensor_id[] = { 2659 + [0] = ACER_WMID_SENSOR_CPU_TEMPERATURE, 2660 + [1] = ACER_WMID_SENSOR_GPU_TEMPERATURE, 2661 + [2] = ACER_WMID_SENSOR_EXTERNAL_TEMPERATURE_2, 2662 + }; 2663 + 2664 + static const enum acer_wmi_predator_v4_sensor_id acer_wmi_fan_channel_to_sensor_id[] = { 2665 + [0] = ACER_WMID_SENSOR_CPU_FAN_SPEED, 2666 + [1] = ACER_WMID_SENSOR_GPU_FAN_SPEED, 2667 + }; 2668 + 2802 2669 static umode_t acer_wmi_hwmon_is_visible(const void *data, 2803 2670 enum hwmon_sensor_types type, u32 attr, 2804 2671 int channel) 2805 2672 { 2673 + enum acer_wmi_predator_v4_sensor_id sensor_id; 2674 + const u64 *supported_sensors = data; 2675 + 2806 2676 switch (type) { 2677 + case hwmon_temp: 2678 + sensor_id = acer_wmi_temp_channel_to_sensor_id[channel]; 2679 + break; 2807 2680 case hwmon_fan: 2808 - if (acer_get_fan_speed(channel) >= 0) 2809 - return 0444; 2681 + sensor_id = acer_wmi_fan_channel_to_sensor_id[channel]; 2810 2682 break; 2811 2683 default: 2812 2684 return 0; 2813 2685 } 2686 + 2687 + if (*supported_sensors & BIT(sensor_id - 1)) 2688 + return 0444; 2814 2689 2815 2690 return 0; 2816 2691 } ··· 2837 2674 static int acer_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 2838 2675 u32 attr, int channel, long *val) 2839 2676 { 2677 + u64 command = ACER_WMID_CMD_GET_PREDATOR_V4_SENSOR_READING; 2678 + u64 result; 2840 2679 int ret; 2841 2680 2842 2681 switch (type) { 2843 - case hwmon_fan: 2844 - ret = acer_get_fan_speed(channel); 2682 + case hwmon_temp: 2683 + command |= FIELD_PREP(ACER_PREDATOR_V4_SENSOR_INDEX_BIT_MASK, 2684 + acer_wmi_temp_channel_to_sensor_id[channel]); 2685 + 2686 + ret = WMID_gaming_get_sys_info(command, &result); 2845 2687 if (ret < 0) 2846 2688 return ret; 2847 - *val = ret; 2848 - break; 2689 + 2690 + result = FIELD_GET(ACER_PREDATOR_V4_SENSOR_READING_BIT_MASK, result); 2691 + *val = result * MILLIDEGREE_PER_DEGREE; 2692 + return 0; 2693 + case hwmon_fan: 2694 + command |= FIELD_PREP(ACER_PREDATOR_V4_SENSOR_INDEX_BIT_MASK, 2695 + acer_wmi_fan_channel_to_sensor_id[channel]); 2696 + 2697 + ret = WMID_gaming_get_sys_info(command, &result); 2698 + if (ret < 0) 2699 + return ret; 2700 + 2701 + *val = FIELD_GET(ACER_PREDATOR_V4_SENSOR_READING_BIT_MASK, result); 2702 + return 0; 2849 2703 default: 2850 2704 return -EOPNOTSUPP; 2851 2705 } 2852 - 2853 - return 0; 2854 2706 } 2855 2707 2856 2708 static const struct hwmon_channel_info *const acer_wmi_hwmon_info[] = { 2857 - HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), NULL 2709 + HWMON_CHANNEL_INFO(temp, 2710 + HWMON_T_INPUT, 2711 + HWMON_T_INPUT, 2712 + HWMON_T_INPUT 2713 + ), 2714 + HWMON_CHANNEL_INFO(fan, 2715 + HWMON_F_INPUT, 2716 + HWMON_F_INPUT 2717 + ), 2718 + NULL 2858 2719 }; 2859 2720 2860 2721 static const struct hwmon_ops acer_wmi_hwmon_ops = { ··· 2895 2708 { 2896 2709 struct device *dev = &acer_platform_device->dev; 2897 2710 struct device *hwmon; 2711 + u64 result; 2712 + int ret; 2713 + 2714 + ret = WMID_gaming_get_sys_info(ACER_WMID_CMD_GET_PREDATOR_V4_SUPPORTED_SENSORS, &result); 2715 + if (ret < 0) 2716 + return ret; 2717 + 2718 + /* Return early if no sensors are available */ 2719 + supported_sensors = FIELD_GET(ACER_PREDATOR_V4_SUPPORTED_SENSORS_BIT_MASK, result); 2720 + if (!supported_sensors) 2721 + return 0; 2898 2722 2899 2723 hwmon = devm_hwmon_device_register_with_info(dev, "acer", 2900 - &acer_platform_driver, 2724 + &supported_sensors, 2901 2725 &acer_wmi_hwmon_chip_info, 2902 2726 NULL); 2903 2727
+6 -6
drivers/platform/x86/amd/hsmp/acpi.c
··· 226 226 } 227 227 228 228 static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj, 229 - struct bin_attribute *bin_attr, char *buf, 229 + const struct bin_attribute *bin_attr, char *buf, 230 230 loff_t off, size_t count) 231 231 { 232 232 struct device *dev = container_of(kobj, struct device, kobj); ··· 285 285 return ret; 286 286 } 287 287 288 - static struct bin_attribute hsmp_metric_tbl_attr = { 288 + static const struct bin_attribute hsmp_metric_tbl_attr = { 289 289 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, 290 - .read = hsmp_metric_tbl_acpi_read, 290 + .read_new = hsmp_metric_tbl_acpi_read, 291 291 .size = sizeof(struct hsmp_metric_table), 292 292 }; 293 293 294 - static struct bin_attribute *hsmp_attr_list[] = { 294 + static const struct bin_attribute *hsmp_attr_list[] = { 295 295 &hsmp_metric_tbl_attr, 296 296 NULL 297 297 }; 298 298 299 - static struct attribute_group hsmp_attr_grp = { 300 - .bin_attrs = hsmp_attr_list, 299 + static const struct attribute_group hsmp_attr_grp = { 300 + .bin_attrs_new = hsmp_attr_list, 301 301 .is_bin_visible = hsmp_is_sock_attr_visible, 302 302 }; 303 303
+41 -6
drivers/platform/x86/amd/hsmp/hsmp.c
··· 33 33 #define HSMP_WR true 34 34 #define HSMP_RD false 35 35 36 - #define DRIVER_VERSION "2.3" 36 + #define DRIVER_VERSION "2.4" 37 + 38 + /* 39 + * When same message numbers are used for both GET and SET operation, 40 + * bit:31 indicates whether its SET or GET operation. 41 + */ 42 + #define CHECK_GET_BIT BIT(31) 37 43 38 44 static struct hsmp_plat_device hsmp_pdev; 39 45 ··· 173 167 if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD) 174 168 return -ENOMSG; 175 169 176 - /* num_args and response_sz against the HSMP spec */ 177 - if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args || 178 - msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz) 170 + /* 171 + * num_args passed by user should match the num_args specified in 172 + * message description table. 173 + */ 174 + if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args) 179 175 return -EINVAL; 180 176 177 + /* 178 + * Some older HSMP SET messages are updated to add GET in the same message. 179 + * In these messages, GET returns the current value and SET also returns 180 + * the successfully set value. To support this GET and SET in same message 181 + * while maintaining backward compatibility for the HSMP users, 182 + * hsmp_msg_desc_table[] indicates only maximum allowed response_sz. 183 + */ 184 + if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_SET_GET) { 185 + if (msg->response_sz > hsmp_msg_desc_table[msg->msg_id].response_sz) 186 + return -EINVAL; 187 + } else { 188 + /* only HSMP_SET or HSMP_GET messages go through this strict check */ 189 + if (msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz) 190 + return -EINVAL; 191 + } 181 192 return 0; 182 193 } 183 194 ··· 262 239 } 263 240 EXPORT_SYMBOL_NS_GPL(hsmp_test, "AMD_HSMP"); 264 241 242 + static bool is_get_msg(struct hsmp_message *msg) 243 + { 244 + if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_GET) 245 + return true; 246 + 247 + if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_SET_GET && 248 + (msg->args[0] & CHECK_GET_BIT)) 249 + return true; 250 + 251 + return false; 252 + } 253 + 265 254 long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) 266 255 { 267 256 int __user *arguser = (int __user *)arg; ··· 296 261 * Device is opened in O_WRONLY mode 297 262 * Execute only set/configure commands 298 263 */ 299 - if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET) 264 + if (is_get_msg(&msg)) 300 265 return -EPERM; 301 266 break; 302 267 case FMODE_READ: ··· 304 269 * Device is opened in O_RDONLY mode 305 270 * Execute only get/monitor commands 306 271 */ 307 - if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET) 272 + if (!is_get_msg(&msg)) 308 273 return -EPERM; 309 274 break; 310 275 case FMODE_READ | FMODE_WRITE:
+6 -6
drivers/platform/x86/amd/hsmp/plat.c
··· 59 59 } 60 60 61 61 static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj, 62 - struct bin_attribute *bin_attr, char *buf, 62 + const struct bin_attribute *bin_attr, char *buf, 63 63 loff_t off, size_t count) 64 64 { 65 65 struct hsmp_socket *sock; ··· 97 97 * is_bin_visible function is used to show / hide the necessary groups. 98 98 */ 99 99 #define HSMP_BIN_ATTR(index, _list) \ 100 - static struct bin_attribute attr##index = { \ 100 + static const struct bin_attribute attr##index = { \ 101 101 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ 102 102 .private = (void *)index, \ 103 - .read = hsmp_metric_tbl_plat_read, \ 103 + .read_new = hsmp_metric_tbl_plat_read, \ 104 104 .size = sizeof(struct hsmp_metric_table), \ 105 105 }; \ 106 - static struct bin_attribute _list[] = { \ 106 + static const struct bin_attribute _list[] = { \ 107 107 &attr##index, \ 108 108 NULL \ 109 109 } ··· 118 118 HSMP_BIN_ATTR(7, *sock7_attr_list); 119 119 120 120 #define HSMP_BIN_ATTR_GRP(index, _list, _name) \ 121 - static struct attribute_group sock##index##_attr_grp = { \ 122 - .bin_attrs = _list, \ 121 + static const struct attribute_group sock##index##_attr_grp = { \ 122 + .bin_attrs_new = _list, \ 123 123 .is_bin_visible = hsmp_is_sock_attr_visible, \ 124 124 .name = #_name, \ 125 125 }
+1 -1
drivers/platform/x86/amd/pmc/Makefile
··· 4 4 # AMD Power Management Controller Driver 5 5 # 6 6 7 - amd-pmc-objs := pmc.o pmc-quirks.o 7 + amd-pmc-objs := pmc.o pmc-quirks.o mp1_stb.o 8 8 obj-$(CONFIG_AMD_PMC) += amd-pmc.o 9 9 amd-pmc-$(CONFIG_AMD_MP2_STB) += mp2_stb.o
+332
drivers/platform/x86/amd/pmc/mp1_stb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * AMD MP1 Smart Trace Buffer (STB) Layer 4 + * 5 + * Copyright (c) 2024, Advanced Micro Devices, Inc. 6 + * All Rights Reserved. 7 + * 8 + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 9 + * Sanket Goswami <Sanket.Goswami@amd.com> 10 + */ 11 + 12 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 + 14 + #include <asm/amd_nb.h> 15 + #include <linux/debugfs.h> 16 + #include <linux/seq_file.h> 17 + #include <linux/uaccess.h> 18 + 19 + #include "pmc.h" 20 + 21 + /* STB Spill to DRAM Parameters */ 22 + #define S2D_TELEMETRY_DRAMBYTES_MAX 0x1000000 23 + #define S2D_TELEMETRY_BYTES_MAX 0x100000U 24 + #define S2D_RSVD_RAM_SPACE 0x100000 25 + 26 + /* STB Registers */ 27 + #define AMD_STB_PMI_0 0x03E30600 28 + #define AMD_PMC_STB_DUMMY_PC 0xC6000007 29 + 30 + /* STB Spill to DRAM Message Definition */ 31 + #define STB_FORCE_FLUSH_DATA 0xCF 32 + #define FIFO_SIZE 4096 33 + 34 + /* STB S2D(Spill to DRAM) has different message port offset */ 35 + #define AMD_S2D_REGISTER_MESSAGE 0xA20 36 + #define AMD_S2D_REGISTER_RESPONSE 0xA80 37 + #define AMD_S2D_REGISTER_ARGUMENT 0xA88 38 + 39 + /* STB S2D (Spill to DRAM) message port offset for 44h model */ 40 + #define AMD_GNR_REGISTER_MESSAGE 0x524 41 + #define AMD_GNR_REGISTER_RESPONSE 0x570 42 + #define AMD_GNR_REGISTER_ARGUMENT 0xA40 43 + 44 + static bool enable_stb; 45 + module_param(enable_stb, bool, 0644); 46 + MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); 47 + 48 + static bool dump_custom_stb; 49 + module_param(dump_custom_stb, bool, 0644); 50 + MODULE_PARM_DESC(dump_custom_stb, "Enable to dump full STB buffer"); 51 + 52 + enum s2d_arg { 53 + S2D_TELEMETRY_SIZE = 0x01, 54 + S2D_PHYS_ADDR_LOW, 55 + S2D_PHYS_ADDR_HIGH, 56 + S2D_NUM_SAMPLES, 57 + S2D_DRAM_SIZE, 58 + }; 59 + 60 + struct amd_stb_v2_data { 61 + size_t size; 62 + u8 data[] __counted_by(size); 63 + }; 64 + 65 + int amd_stb_write(struct amd_pmc_dev *dev, u32 data) 66 + { 67 + int err; 68 + 69 + err = amd_smn_write(0, AMD_STB_PMI_0, data); 70 + if (err) { 71 + dev_err(dev->dev, "failed to write data in stb: 0x%X\n", AMD_STB_PMI_0); 72 + return pcibios_err_to_errno(err); 73 + } 74 + 75 + return 0; 76 + } 77 + 78 + int amd_stb_read(struct amd_pmc_dev *dev, u32 *buf) 79 + { 80 + int i, err; 81 + 82 + for (i = 0; i < FIFO_SIZE; i++) { 83 + err = amd_smn_read(0, AMD_STB_PMI_0, buf++); 84 + if (err) { 85 + dev_err(dev->dev, "error reading data from stb: 0x%X\n", AMD_STB_PMI_0); 86 + return pcibios_err_to_errno(err); 87 + } 88 + } 89 + 90 + return 0; 91 + } 92 + 93 + static int amd_stb_debugfs_open(struct inode *inode, struct file *filp) 94 + { 95 + struct amd_pmc_dev *dev = filp->f_inode->i_private; 96 + u32 size = FIFO_SIZE * sizeof(u32); 97 + u32 *buf; 98 + int rc; 99 + 100 + buf = kzalloc(size, GFP_KERNEL); 101 + if (!buf) 102 + return -ENOMEM; 103 + 104 + rc = amd_stb_read(dev, buf); 105 + if (rc) { 106 + kfree(buf); 107 + return rc; 108 + } 109 + 110 + filp->private_data = buf; 111 + return rc; 112 + } 113 + 114 + static ssize_t amd_stb_debugfs_read(struct file *filp, char __user *buf, size_t size, loff_t *pos) 115 + { 116 + if (!filp->private_data) 117 + return -EINVAL; 118 + 119 + return simple_read_from_buffer(buf, size, pos, filp->private_data, 120 + FIFO_SIZE * sizeof(u32)); 121 + } 122 + 123 + static int amd_stb_debugfs_release(struct inode *inode, struct file *filp) 124 + { 125 + kfree(filp->private_data); 126 + return 0; 127 + } 128 + 129 + static const struct file_operations amd_stb_debugfs_fops = { 130 + .owner = THIS_MODULE, 131 + .open = amd_stb_debugfs_open, 132 + .read = amd_stb_debugfs_read, 133 + .release = amd_stb_debugfs_release, 134 + }; 135 + 136 + /* Enhanced STB Firmware Reporting Mechanism */ 137 + static int amd_stb_handle_efr(struct file *filp) 138 + { 139 + struct amd_pmc_dev *dev = filp->f_inode->i_private; 140 + struct amd_stb_v2_data *stb_data_arr; 141 + u32 fsize; 142 + 143 + fsize = dev->dram_size - S2D_RSVD_RAM_SPACE; 144 + stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL); 145 + if (!stb_data_arr) 146 + return -ENOMEM; 147 + 148 + stb_data_arr->size = fsize; 149 + memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr, fsize); 150 + filp->private_data = stb_data_arr; 151 + 152 + return 0; 153 + } 154 + 155 + static int amd_stb_debugfs_open_v2(struct inode *inode, struct file *filp) 156 + { 157 + struct amd_pmc_dev *dev = filp->f_inode->i_private; 158 + u32 fsize, num_samples, val, stb_rdptr_offset = 0; 159 + struct amd_stb_v2_data *stb_data_arr; 160 + int ret; 161 + 162 + /* Write dummy postcode while reading the STB buffer */ 163 + ret = amd_stb_write(dev, AMD_PMC_STB_DUMMY_PC); 164 + if (ret) 165 + dev_err(dev->dev, "error writing to STB: %d\n", ret); 166 + 167 + /* Spill to DRAM num_samples uses separate SMU message port */ 168 + dev->msg_port = MSG_PORT_S2D; 169 + 170 + ret = amd_pmc_send_cmd(dev, 0, &val, STB_FORCE_FLUSH_DATA, 1); 171 + if (ret) 172 + dev_dbg_once(dev->dev, "S2D force flush not supported: %d\n", ret); 173 + 174 + /* 175 + * We have a custom stb size and the PMFW is supposed to give 176 + * the enhanced dram size. Note that we land here only for the 177 + * platforms that support enhanced dram size reporting. 178 + */ 179 + if (dump_custom_stb) 180 + return amd_stb_handle_efr(filp); 181 + 182 + /* Get the num_samples to calculate the last push location */ 183 + ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->stb_arg.s2d_msg_id, true); 184 + /* Clear msg_port for other SMU operation */ 185 + dev->msg_port = MSG_PORT_PMC; 186 + if (ret) { 187 + dev_err(dev->dev, "error: S2D_NUM_SAMPLES not supported : %d\n", ret); 188 + return ret; 189 + } 190 + 191 + fsize = min(num_samples, S2D_TELEMETRY_BYTES_MAX); 192 + stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL); 193 + if (!stb_data_arr) 194 + return -ENOMEM; 195 + 196 + stb_data_arr->size = fsize; 197 + 198 + /* 199 + * Start capturing data from the last push location. 200 + * This is for general cases, where the stb limits 201 + * are meant for standard usage. 202 + */ 203 + if (num_samples > S2D_TELEMETRY_BYTES_MAX) { 204 + /* First read oldest data starting 1 behind last write till end of ringbuffer */ 205 + stb_rdptr_offset = num_samples % S2D_TELEMETRY_BYTES_MAX; 206 + fsize = S2D_TELEMETRY_BYTES_MAX - stb_rdptr_offset; 207 + 208 + memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr + stb_rdptr_offset, fsize); 209 + /* Second copy the newer samples from offset 0 - last write */ 210 + memcpy_fromio(stb_data_arr->data + fsize, dev->stb_virt_addr, stb_rdptr_offset); 211 + } else { 212 + memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr, fsize); 213 + } 214 + 215 + filp->private_data = stb_data_arr; 216 + 217 + return 0; 218 + } 219 + 220 + static ssize_t amd_stb_debugfs_read_v2(struct file *filp, char __user *buf, size_t size, 221 + loff_t *pos) 222 + { 223 + struct amd_stb_v2_data *data = filp->private_data; 224 + 225 + return simple_read_from_buffer(buf, size, pos, data->data, data->size); 226 + } 227 + 228 + static int amd_stb_debugfs_release_v2(struct inode *inode, struct file *filp) 229 + { 230 + kfree(filp->private_data); 231 + return 0; 232 + } 233 + 234 + static const struct file_operations amd_stb_debugfs_fops_v2 = { 235 + .owner = THIS_MODULE, 236 + .open = amd_stb_debugfs_open_v2, 237 + .read = amd_stb_debugfs_read_v2, 238 + .release = amd_stb_debugfs_release_v2, 239 + }; 240 + 241 + static void amd_stb_update_args(struct amd_pmc_dev *dev) 242 + { 243 + if (cpu_feature_enabled(X86_FEATURE_ZEN5)) 244 + switch (boot_cpu_data.x86_model) { 245 + case 0x44: 246 + dev->stb_arg.msg = AMD_GNR_REGISTER_MESSAGE; 247 + dev->stb_arg.arg = AMD_GNR_REGISTER_ARGUMENT; 248 + dev->stb_arg.resp = AMD_GNR_REGISTER_RESPONSE; 249 + return; 250 + default: 251 + break; 252 + } 253 + 254 + dev->stb_arg.msg = AMD_S2D_REGISTER_MESSAGE; 255 + dev->stb_arg.arg = AMD_S2D_REGISTER_ARGUMENT; 256 + dev->stb_arg.resp = AMD_S2D_REGISTER_RESPONSE; 257 + } 258 + 259 + static bool amd_is_stb_supported(struct amd_pmc_dev *dev) 260 + { 261 + switch (dev->cpu_id) { 262 + case AMD_CPU_ID_YC: 263 + case AMD_CPU_ID_CB: 264 + if (boot_cpu_data.x86_model == 0x44) 265 + dev->stb_arg.s2d_msg_id = 0x9B; 266 + else 267 + dev->stb_arg.s2d_msg_id = 0xBE; 268 + break; 269 + case AMD_CPU_ID_PS: 270 + dev->stb_arg.s2d_msg_id = 0x85; 271 + break; 272 + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: 273 + case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: 274 + if (boot_cpu_data.x86_model == 0x70) 275 + dev->stb_arg.s2d_msg_id = 0xF1; 276 + else 277 + dev->stb_arg.s2d_msg_id = 0xDE; 278 + break; 279 + default: 280 + return false; 281 + } 282 + 283 + amd_stb_update_args(dev); 284 + return true; 285 + } 286 + 287 + int amd_stb_s2d_init(struct amd_pmc_dev *dev) 288 + { 289 + u32 phys_addr_low, phys_addr_hi; 290 + u64 stb_phys_addr; 291 + u32 size = 0; 292 + int ret; 293 + 294 + if (!enable_stb) 295 + return 0; 296 + 297 + if (amd_is_stb_supported(dev)) { 298 + debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, 299 + &amd_stb_debugfs_fops_v2); 300 + } else { 301 + debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, 302 + &amd_stb_debugfs_fops); 303 + return 0; 304 + } 305 + 306 + /* Spill to DRAM feature uses separate SMU message port */ 307 + dev->msg_port = MSG_PORT_S2D; 308 + 309 + amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->stb_arg.s2d_msg_id, true); 310 + if (size != S2D_TELEMETRY_BYTES_MAX) 311 + return -EIO; 312 + 313 + /* Get DRAM size */ 314 + ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->stb_arg.s2d_msg_id, true); 315 + if (ret || !dev->dram_size) 316 + dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX; 317 + 318 + /* Get STB DRAM address */ 319 + amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->stb_arg.s2d_msg_id, true); 320 + amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->stb_arg.s2d_msg_id, true); 321 + 322 + stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low); 323 + 324 + /* Clear msg_port for other SMU operation */ 325 + dev->msg_port = MSG_PORT_PMC; 326 + 327 + dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size); 328 + if (!dev->stb_virt_addr) 329 + return -ENOMEM; 330 + 331 + return 0; 332 + }
+76 -315
drivers/platform/x86/amd/pmc/pmc.c
··· 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 12 13 13 #include <linux/acpi.h> 14 + #include <linux/array_size.h> 14 15 #include <linux/bitfield.h> 15 16 #include <linux/bits.h> 16 17 #include <linux/debugfs.h> ··· 42 41 #define AMD_PMC_SCRATCH_REG_1AH 0xF14 43 42 44 43 /* STB Registers */ 45 - #define AMD_PMC_STB_PMI_0 0x03E30600 46 44 #define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001 47 45 #define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002 48 46 #define AMD_PMC_STB_S2IDLE_CHECK 0xC6000003 49 - #define AMD_PMC_STB_DUMMY_PC 0xC6000007 50 - 51 - /* STB S2D(Spill to DRAM) has different message port offset */ 52 - #define AMD_S2D_REGISTER_MESSAGE 0xA20 53 - #define AMD_S2D_REGISTER_RESPONSE 0xA80 54 - #define AMD_S2D_REGISTER_ARGUMENT 0xA88 55 - 56 - /* STB Spill to DRAM Parameters */ 57 - #define S2D_TELEMETRY_BYTES_MAX 0x100000U 58 - #define S2D_RSVD_RAM_SPACE 0x100000 59 - #define S2D_TELEMETRY_DRAMBYTES_MAX 0x1000000 60 - 61 - /* STB Spill to DRAM Message Definition */ 62 - #define STB_FORCE_FLUSH_DATA 0xCF 63 47 64 48 /* Base address of SMU for mapping physical address to virtual address */ 65 49 #define AMD_PMC_MAPPING_SIZE 0x01000 ··· 84 98 85 99 #define DELAY_MIN_US 2000 86 100 #define DELAY_MAX_US 3000 87 - #define FIFO_SIZE 4096 88 101 89 102 enum amd_pmc_def { 90 103 MSG_TEST = 0x01, ··· 91 106 MSG_OS_HINT_RN, 92 107 }; 93 108 94 - enum s2d_arg { 95 - S2D_TELEMETRY_SIZE = 0x01, 96 - S2D_PHYS_ADDR_LOW, 97 - S2D_PHYS_ADDR_HIGH, 98 - S2D_NUM_SAMPLES, 99 - S2D_DRAM_SIZE, 100 - }; 101 - 102 - struct amd_pmc_stb_v2_data { 103 - size_t size; 104 - u8 data[] __counted_by(size); 105 - }; 106 - 107 109 struct amd_pmc_bit_map { 108 110 const char *name; 109 111 u32 bit_mask; 112 + }; 113 + 114 + static const struct amd_pmc_bit_map soc15_ip_blk_v2[] = { 115 + {"DISPLAY", BIT(0)}, 116 + {"CPU", BIT(1)}, 117 + {"GFX", BIT(2)}, 118 + {"VDD", BIT(3)}, 119 + {"VDD_CCX", BIT(4)}, 120 + {"ACP", BIT(5)}, 121 + {"VCN_0", BIT(6)}, 122 + {"VCN_1", BIT(7)}, 123 + {"ISP", BIT(8)}, 124 + {"NBIO", BIT(9)}, 125 + {"DF", BIT(10)}, 126 + {"USB3_0", BIT(11)}, 127 + {"USB3_1", BIT(12)}, 128 + {"LAPIC", BIT(13)}, 129 + {"USB3_2", BIT(14)}, 130 + {"USB4_RT0", BIT(15)}, 131 + {"USB4_RT1", BIT(16)}, 132 + {"USB4_0", BIT(17)}, 133 + {"USB4_1", BIT(18)}, 134 + {"MPM", BIT(19)}, 135 + {"JPEG_0", BIT(20)}, 136 + {"JPEG_1", BIT(21)}, 137 + {"IPU", BIT(22)}, 138 + {"UMSCH", BIT(23)}, 139 + {"VPE", BIT(24)}, 110 140 }; 111 141 112 142 static const struct amd_pmc_bit_map soc15_ip_blk[] = { ··· 147 147 {"IPU", BIT(19)}, 148 148 {"UMSCH", BIT(20)}, 149 149 {"VPE", BIT(21)}, 150 - {} 151 150 }; 152 - 153 - static bool enable_stb; 154 - module_param(enable_stb, bool, 0644); 155 - MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); 156 151 157 152 static bool disable_workarounds; 158 153 module_param(disable_workarounds, bool, 0644); 159 154 MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs"); 160 155 161 - static bool dump_custom_stb; 162 - module_param(dump_custom_stb, bool, 0644); 163 - MODULE_PARM_DESC(dump_custom_stb, "Enable to dump full STB buffer"); 164 - 165 156 static struct amd_pmc_dev pmc; 166 - static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret); 167 - static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf); 168 - static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data); 169 157 170 158 static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset) 171 159 { ··· 182 194 u64 timecondition_notmet_totaltime[32]; 183 195 } __packed; 184 196 185 - static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp) 186 - { 187 - struct amd_pmc_dev *dev = filp->f_inode->i_private; 188 - u32 size = FIFO_SIZE * sizeof(u32); 189 - u32 *buf; 190 - int rc; 191 - 192 - buf = kzalloc(size, GFP_KERNEL); 193 - if (!buf) 194 - return -ENOMEM; 195 - 196 - rc = amd_pmc_read_stb(dev, buf); 197 - if (rc) { 198 - kfree(buf); 199 - return rc; 200 - } 201 - 202 - filp->private_data = buf; 203 - return rc; 204 - } 205 - 206 - static ssize_t amd_pmc_stb_debugfs_read(struct file *filp, char __user *buf, size_t size, 207 - loff_t *pos) 208 - { 209 - if (!filp->private_data) 210 - return -EINVAL; 211 - 212 - return simple_read_from_buffer(buf, size, pos, filp->private_data, 213 - FIFO_SIZE * sizeof(u32)); 214 - } 215 - 216 - static int amd_pmc_stb_debugfs_release(struct inode *inode, struct file *filp) 217 - { 218 - kfree(filp->private_data); 219 - return 0; 220 - } 221 - 222 - static const struct file_operations amd_pmc_stb_debugfs_fops = { 223 - .owner = THIS_MODULE, 224 - .open = amd_pmc_stb_debugfs_open, 225 - .read = amd_pmc_stb_debugfs_read, 226 - .release = amd_pmc_stb_debugfs_release, 227 - }; 228 - 229 - /* Enhanced STB Firmware Reporting Mechanism */ 230 - static int amd_pmc_stb_handle_efr(struct file *filp) 231 - { 232 - struct amd_pmc_dev *dev = filp->f_inode->i_private; 233 - struct amd_pmc_stb_v2_data *stb_data_arr; 234 - u32 fsize; 235 - 236 - fsize = dev->dram_size - S2D_RSVD_RAM_SPACE; 237 - stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL); 238 - if (!stb_data_arr) 239 - return -ENOMEM; 240 - 241 - stb_data_arr->size = fsize; 242 - memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr, fsize); 243 - filp->private_data = stb_data_arr; 244 - 245 - return 0; 246 - } 247 - 248 - static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) 249 - { 250 - struct amd_pmc_dev *dev = filp->f_inode->i_private; 251 - u32 fsize, num_samples, val, stb_rdptr_offset = 0; 252 - struct amd_pmc_stb_v2_data *stb_data_arr; 253 - int ret; 254 - 255 - /* Write dummy postcode while reading the STB buffer */ 256 - ret = amd_pmc_write_stb(dev, AMD_PMC_STB_DUMMY_PC); 257 - if (ret) 258 - dev_err(dev->dev, "error writing to STB: %d\n", ret); 259 - 260 - /* Spill to DRAM num_samples uses separate SMU message port */ 261 - dev->msg_port = 1; 262 - 263 - ret = amd_pmc_send_cmd(dev, 0, &val, STB_FORCE_FLUSH_DATA, 1); 264 - if (ret) 265 - dev_dbg_once(dev->dev, "S2D force flush not supported: %d\n", ret); 266 - 267 - /* 268 - * We have a custom stb size and the PMFW is supposed to give 269 - * the enhanced dram size. Note that we land here only for the 270 - * platforms that support enhanced dram size reporting. 271 - */ 272 - if (dump_custom_stb) 273 - return amd_pmc_stb_handle_efr(filp); 274 - 275 - /* Get the num_samples to calculate the last push location */ 276 - ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->s2d_msg_id, true); 277 - /* Clear msg_port for other SMU operation */ 278 - dev->msg_port = 0; 279 - if (ret) { 280 - dev_err(dev->dev, "error: S2D_NUM_SAMPLES not supported : %d\n", ret); 281 - return ret; 282 - } 283 - 284 - fsize = min(num_samples, S2D_TELEMETRY_BYTES_MAX); 285 - stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL); 286 - if (!stb_data_arr) 287 - return -ENOMEM; 288 - 289 - stb_data_arr->size = fsize; 290 - 291 - /* 292 - * Start capturing data from the last push location. 293 - * This is for general cases, where the stb limits 294 - * are meant for standard usage. 295 - */ 296 - if (num_samples > S2D_TELEMETRY_BYTES_MAX) { 297 - /* First read oldest data starting 1 behind last write till end of ringbuffer */ 298 - stb_rdptr_offset = num_samples % S2D_TELEMETRY_BYTES_MAX; 299 - fsize = S2D_TELEMETRY_BYTES_MAX - stb_rdptr_offset; 300 - 301 - memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr + stb_rdptr_offset, fsize); 302 - /* Second copy the newer samples from offset 0 - last write */ 303 - memcpy_fromio(stb_data_arr->data + fsize, dev->stb_virt_addr, stb_rdptr_offset); 304 - } else { 305 - memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr, fsize); 306 - } 307 - 308 - filp->private_data = stb_data_arr; 309 - 310 - return 0; 311 - } 312 - 313 - static ssize_t amd_pmc_stb_debugfs_read_v2(struct file *filp, char __user *buf, size_t size, 314 - loff_t *pos) 315 - { 316 - struct amd_pmc_stb_v2_data *data = filp->private_data; 317 - 318 - return simple_read_from_buffer(buf, size, pos, data->data, data->size); 319 - } 320 - 321 - static int amd_pmc_stb_debugfs_release_v2(struct inode *inode, struct file *filp) 322 - { 323 - kfree(filp->private_data); 324 - return 0; 325 - } 326 - 327 - static const struct file_operations amd_pmc_stb_debugfs_fops_v2 = { 328 - .owner = THIS_MODULE, 329 - .open = amd_pmc_stb_debugfs_open_v2, 330 - .read = amd_pmc_stb_debugfs_read_v2, 331 - .release = amd_pmc_stb_debugfs_release_v2, 332 - }; 333 - 334 197 static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev) 335 198 { 336 199 switch (dev->cpu_id) { ··· 190 351 case AMD_CPU_ID_YC: 191 352 case AMD_CPU_ID_CB: 192 353 dev->num_ips = 12; 193 - dev->s2d_msg_id = 0xBE; 354 + dev->ips_ptr = soc15_ip_blk; 194 355 dev->smu_msg = 0x538; 195 356 break; 196 357 case AMD_CPU_ID_PS: 197 358 dev->num_ips = 21; 198 - dev->s2d_msg_id = 0x85; 359 + dev->ips_ptr = soc15_ip_blk; 199 360 dev->smu_msg = 0x538; 200 361 break; 201 362 case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: 202 363 case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: 203 - dev->num_ips = 22; 204 - dev->s2d_msg_id = 0xDE; 364 + if (boot_cpu_data.x86_model == 0x70) { 365 + dev->num_ips = ARRAY_SIZE(soc15_ip_blk_v2); 366 + dev->ips_ptr = soc15_ip_blk_v2; 367 + } else { 368 + dev->num_ips = ARRAY_SIZE(soc15_ip_blk); 369 + dev->ips_ptr = soc15_ip_blk; 370 + } 205 371 dev->smu_msg = 0x938; 206 372 break; 207 373 } ··· 374 530 375 531 seq_puts(s, "\n=== Active time (in us) ===\n"); 376 532 for (idx = 0 ; idx < dev->num_ips ; idx++) { 377 - if (soc15_ip_blk[idx].bit_mask & dev->active_ips) 378 - seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name, 533 + if (dev->ips_ptr[idx].bit_mask & dev->active_ips) 534 + seq_printf(s, "%-8s : %lld\n", dev->ips_ptr[idx].name, 379 535 table.timecondition_notmet_lastcapture[idx]); 380 536 } 381 537 ··· 470 626 debugfs_remove_recursive(dev->dbgfs_dir); 471 627 } 472 628 473 - static bool amd_pmc_is_stb_supported(struct amd_pmc_dev *dev) 474 - { 475 - switch (dev->cpu_id) { 476 - case AMD_CPU_ID_YC: 477 - case AMD_CPU_ID_CB: 478 - case AMD_CPU_ID_PS: 479 - case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: 480 - case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: 481 - return true; 482 - default: 483 - return false; 484 - } 485 - } 486 - 487 629 static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) 488 630 { 489 631 dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL); ··· 479 649 &s0ix_stats_fops); 480 650 debugfs_create_file("amd_pmc_idlemask", 0644, dev->dbgfs_dir, dev, 481 651 &amd_pmc_idlemask_fops); 482 - /* Enable STB only when the module_param is set */ 483 - if (enable_stb) { 484 - if (amd_pmc_is_stb_supported(dev)) 485 - debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, 486 - &amd_pmc_stb_debugfs_fops_v2); 487 - else 488 - debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev, 489 - &amd_pmc_stb_debugfs_fops); 652 + } 653 + 654 + static char *amd_pmc_get_msg_port(struct amd_pmc_dev *dev) 655 + { 656 + switch (dev->msg_port) { 657 + case MSG_PORT_PMC: 658 + return "PMC"; 659 + case MSG_PORT_S2D: 660 + return "S2D"; 661 + default: 662 + return "Invalid message port"; 490 663 } 491 664 } 492 665 ··· 497 664 { 498 665 u32 value, message, argument, response; 499 666 500 - if (dev->msg_port) { 501 - message = AMD_S2D_REGISTER_MESSAGE; 502 - argument = AMD_S2D_REGISTER_ARGUMENT; 503 - response = AMD_S2D_REGISTER_RESPONSE; 667 + if (dev->msg_port == MSG_PORT_S2D) { 668 + message = dev->stb_arg.msg; 669 + argument = dev->stb_arg.arg; 670 + response = dev->stb_arg.resp; 504 671 } else { 505 672 message = dev->smu_msg; 506 673 argument = AMD_PMC_REGISTER_ARGUMENT; ··· 508 675 } 509 676 510 677 value = amd_pmc_reg_read(dev, response); 511 - dev_dbg(dev->dev, "AMD_%s_REGISTER_RESPONSE:%x\n", dev->msg_port ? "S2D" : "PMC", value); 678 + dev_dbg(dev->dev, "AMD_%s_REGISTER_RESPONSE:%x\n", amd_pmc_get_msg_port(dev), value); 512 679 513 680 value = amd_pmc_reg_read(dev, argument); 514 - dev_dbg(dev->dev, "AMD_%s_REGISTER_ARGUMENT:%x\n", dev->msg_port ? "S2D" : "PMC", value); 681 + dev_dbg(dev->dev, "AMD_%s_REGISTER_ARGUMENT:%x\n", amd_pmc_get_msg_port(dev), value); 515 682 516 683 value = amd_pmc_reg_read(dev, message); 517 - dev_dbg(dev->dev, "AMD_%s_REGISTER_MESSAGE:%x\n", dev->msg_port ? "S2D" : "PMC", value); 684 + dev_dbg(dev->dev, "AMD_%s_REGISTER_MESSAGE:%x\n", amd_pmc_get_msg_port(dev), value); 518 685 } 519 686 520 - static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret) 687 + int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret) 521 688 { 522 689 int rc; 523 690 u32 val, message, argument, response; 524 691 525 - mutex_lock(&dev->lock); 692 + guard(mutex)(&dev->lock); 526 693 527 - if (dev->msg_port) { 528 - message = AMD_S2D_REGISTER_MESSAGE; 529 - argument = AMD_S2D_REGISTER_ARGUMENT; 530 - response = AMD_S2D_REGISTER_RESPONSE; 694 + if (dev->msg_port == MSG_PORT_S2D) { 695 + message = dev->stb_arg.msg; 696 + argument = dev->stb_arg.arg; 697 + response = dev->stb_arg.resp; 531 698 } else { 532 699 message = dev->smu_msg; 533 700 argument = AMD_PMC_REGISTER_ARGUMENT; ··· 540 707 PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX); 541 708 if (rc) { 542 709 dev_err(dev->dev, "failed to talk to SMU\n"); 543 - goto out_unlock; 710 + return rc; 544 711 } 545 712 546 713 /* Write zero to response register */ ··· 558 725 PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX); 559 726 if (rc) { 560 727 dev_err(dev->dev, "SMU response timed out\n"); 561 - goto out_unlock; 728 + return rc; 562 729 } 563 730 564 731 switch (val) { ··· 572 739 case AMD_PMC_RESULT_CMD_REJECT_BUSY: 573 740 dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val); 574 741 rc = -EBUSY; 575 - goto out_unlock; 742 + break; 576 743 case AMD_PMC_RESULT_CMD_UNKNOWN: 577 744 dev_err(dev->dev, "SMU cmd unknown. err: 0x%x\n", val); 578 745 rc = -EINVAL; 579 - goto out_unlock; 746 + break; 580 747 case AMD_PMC_RESULT_CMD_REJECT_PREREQ: 581 748 case AMD_PMC_RESULT_FAILED: 582 749 default: 583 750 dev_err(dev->dev, "SMU cmd failed. err: 0x%x\n", val); 584 751 rc = -EIO; 585 - goto out_unlock; 752 + break; 586 753 } 587 754 588 - out_unlock: 589 - mutex_unlock(&dev->lock); 590 755 amd_pmc_dump_registers(dev); 591 756 return rc; 592 757 } ··· 713 882 return; 714 883 } 715 884 716 - rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_S2IDLE_PREPARE); 885 + rc = amd_stb_write(pdev, AMD_PMC_STB_S2IDLE_PREPARE); 717 886 if (rc) 718 887 dev_err(pdev->dev, "error writing to STB: %d\n", rc); 719 888 } ··· 732 901 /* Dump the IdleMask before we add to the STB */ 733 902 amd_pmc_idlemask_read(pdev, pdev->dev, NULL); 734 903 735 - rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_S2IDLE_CHECK); 904 + rc = amd_stb_write(pdev, AMD_PMC_STB_S2IDLE_CHECK); 736 905 if (rc) 737 906 dev_err(pdev->dev, "error writing to STB: %d\n", rc); 738 907 } ··· 759 928 /* Let SMU know that we are looking for stats */ 760 929 amd_pmc_dump_data(pdev); 761 930 762 - rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_S2IDLE_RESTORE); 931 + rc = amd_stb_write(pdev, AMD_PMC_STB_S2IDLE_RESTORE); 763 932 if (rc) 764 933 dev_err(pdev->dev, "error writing to STB: %d\n", rc); 765 934 ··· 812 981 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) }, 813 982 { } 814 983 }; 815 - 816 - static int amd_pmc_s2d_init(struct amd_pmc_dev *dev) 817 - { 818 - u32 phys_addr_low, phys_addr_hi; 819 - u64 stb_phys_addr; 820 - u32 size = 0; 821 - int ret; 822 - 823 - /* Spill to DRAM feature uses separate SMU message port */ 824 - dev->msg_port = 1; 825 - 826 - amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->s2d_msg_id, true); 827 - if (size != S2D_TELEMETRY_BYTES_MAX) 828 - return -EIO; 829 - 830 - /* Get DRAM size */ 831 - ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true); 832 - if (ret || !dev->dram_size) 833 - dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX; 834 - 835 - /* Get STB DRAM address */ 836 - amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->s2d_msg_id, true); 837 - amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->s2d_msg_id, true); 838 - 839 - if (!phys_addr_hi && !phys_addr_low) { 840 - dev_err(dev->dev, "STB is not enabled on the system; disable enable_stb or contact system vendor\n"); 841 - return -EINVAL; 842 - } 843 - 844 - stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low); 845 - 846 - /* Clear msg_port for other SMU operation */ 847 - dev->msg_port = 0; 848 - 849 - dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size); 850 - if (!dev->stb_virt_addr) 851 - return -ENOMEM; 852 - 853 - return 0; 854 - } 855 - 856 - static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data) 857 - { 858 - int err; 859 - 860 - err = amd_smn_write(0, AMD_PMC_STB_PMI_0, data); 861 - if (err) { 862 - dev_err(dev->dev, "failed to write data in stb: 0x%X\n", AMD_PMC_STB_PMI_0); 863 - return pcibios_err_to_errno(err); 864 - } 865 - 866 - return 0; 867 - } 868 - 869 - static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf) 870 - { 871 - int i, err; 872 - 873 - for (i = 0; i < FIFO_SIZE; i++) { 874 - err = amd_smn_read(0, AMD_PMC_STB_PMI_0, buf++); 875 - if (err) { 876 - dev_err(dev->dev, "error reading data from stb: 0x%X\n", AMD_PMC_STB_PMI_0); 877 - return pcibios_err_to_errno(err); 878 - } 879 - } 880 - 881 - return 0; 882 - } 883 984 884 985 static int amd_pmc_probe(struct platform_device *pdev) 885 986 { ··· 870 1107 /* Get num of IP blocks within the SoC */ 871 1108 amd_pmc_get_ip_info(dev); 872 1109 873 - if (enable_stb && amd_pmc_is_stb_supported(dev)) { 874 - err = amd_pmc_s2d_init(dev); 875 - if (err) 876 - goto err_pci_dev_put; 877 - } 878 - 879 1110 platform_set_drvdata(pdev, dev); 880 1111 if (IS_ENABLED(CONFIG_SUSPEND)) { 881 1112 err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops); ··· 880 1123 } 881 1124 882 1125 amd_pmc_dbgfs_register(dev); 1126 + err = amd_stb_s2d_init(dev); 1127 + if (err) 1128 + goto err_pci_dev_put; 1129 + 883 1130 if (IS_ENABLED(CONFIG_AMD_MP2_STB)) 884 1131 amd_mp2_stb_init(dev); 885 1132 pm_report_max_hw_sleep(U64_MAX);
+21 -3
drivers/platform/x86/amd/pmc/pmc.h
··· 14 14 #include <linux/types.h> 15 15 #include <linux/mutex.h> 16 16 17 + enum s2d_msg_port { 18 + MSG_PORT_PMC, 19 + MSG_PORT_S2D, 20 + }; 21 + 17 22 struct amd_mp2_dev { 18 23 void __iomem *mmio; 19 24 void __iomem *vslbase; ··· 30 25 bool is_stb_data; 31 26 }; 32 27 28 + struct stb_arg { 29 + u32 s2d_msg_id; 30 + u32 msg; 31 + u32 arg; 32 + u32 resp; 33 + }; 34 + 33 35 struct amd_pmc_dev { 34 36 void __iomem *regbase; 35 37 void __iomem *smu_virt_addr; 36 38 void __iomem *stb_virt_addr; 37 39 void __iomem *fch_virt_addr; 38 - bool msg_port; 39 40 u32 base_addr; 40 41 u32 cpu_id; 41 - u32 active_ips; 42 42 u32 dram_size; 43 + u32 active_ips; 44 + const struct amd_pmc_bit_map *ips_ptr; 43 45 u32 num_ips; 44 - u32 s2d_msg_id; 45 46 u32 smu_msg; 46 47 /* SMU version information */ 47 48 u8 smu_program; 48 49 u8 major; 49 50 u8 minor; 50 51 u8 rev; 52 + u8 msg_port; 51 53 struct device *dev; 52 54 struct pci_dev *rdev; 53 55 struct mutex lock; /* generic mutex lock */ ··· 62 50 struct quirk_entry *quirks; 63 51 bool disable_8042_wakeup; 64 52 struct amd_mp2_dev *mp2; 53 + struct stb_arg stb_arg; 65 54 }; 66 55 67 56 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev); ··· 82 69 #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 83 70 #define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 84 71 #define PCI_DEVICE_ID_AMD_MP2_STB 0x172c 72 + 73 + int amd_stb_s2d_init(struct amd_pmc_dev *dev); 74 + int amd_stb_read(struct amd_pmc_dev *dev, u32 *buf); 75 + int amd_stb_write(struct amd_pmc_dev *dev, u32 data); 76 + int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret); 85 77 86 78 #endif /* PMC_H */
+1 -1
drivers/platform/x86/amd/pmf/Makefile
··· 7 7 obj-$(CONFIG_AMD_PMF) += amd-pmf.o 8 8 amd-pmf-objs := core.o acpi.o sps.o \ 9 9 auto-mode.o cnqf.o \ 10 - tee-if.o spc.o pmf-quirks.o 10 + tee-if.o spc.o
+26 -4
drivers/platform/x86/amd/pmf/acpi.c
··· 321 321 req, sizeof(*req)); 322 322 } 323 323 324 + static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data) 325 + { 326 + struct amd_pmf_dev *pmf_dev = data; 327 + int ret; 328 + 329 + guard(mutex)(&pmf_dev->cb_mutex); 330 + 331 + ret = apmf_get_sbios_requests_v2(pmf_dev, &pmf_dev->req); 332 + if (ret) 333 + dev_err(pmf_dev->dev, "Failed to get v2 SBIOS requests: %d\n", ret); 334 + } 335 + 324 336 static void apmf_event_handler(acpi_handle handle, u32 event, void *data) 325 337 { 326 338 struct amd_pmf_dev *pmf_dev = data; 327 339 struct apmf_sbios_req req; 328 340 int ret; 329 341 330 - mutex_lock(&pmf_dev->update_mutex); 342 + guard(mutex)(&pmf_dev->update_mutex); 331 343 ret = apmf_get_sbios_requests(pmf_dev, &req); 332 344 if (ret) { 333 345 dev_err(pmf_dev->dev, "Failed to get SBIOS requests:%d\n", ret); 334 - goto out; 346 + return; 335 347 } 336 348 337 349 if (req.pending_req & BIT(APMF_AMT_NOTIFICATION)) { ··· 365 353 if (pmf_dev->amt_enabled) 366 354 amd_pmf_update_2_cql(pmf_dev, req.cql_event); 367 355 } 368 - out: 369 - mutex_unlock(&pmf_dev->update_mutex); 370 356 } 371 357 372 358 static int apmf_if_verify_interface(struct amd_pmf_dev *pdev) ··· 440 430 apmf_event_handler(ahandle, 0, pmf_dev); 441 431 } 442 432 433 + if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) { 434 + status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY, 435 + apmf_event_handler_v2, pmf_dev); 436 + if (ACPI_FAILURE(status)) { 437 + dev_err(pmf_dev->dev, "failed to install notify handler for custom BIOS inputs\n"); 438 + return -ENODEV; 439 + } 440 + } 441 + 443 442 return 0; 444 443 } 445 444 ··· 499 480 if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) && 500 481 is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS)) 501 482 acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler); 483 + 484 + if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) 485 + acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler_v2); 502 486 } 503 487 504 488 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
+8 -12
drivers/platform/x86/amd/pmf/core.c
··· 127 127 ktime_t time_elapsed_ms; 128 128 int socket_power; 129 129 130 - mutex_lock(&dev->update_mutex); 130 + guard(mutex)(&dev->update_mutex); 131 + 131 132 /* Transfer table contents */ 132 133 memset(dev->buf, 0, sizeof(dev->m_table)); 133 134 amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL); ··· 150 149 151 150 dev->start_time = ktime_to_ms(ktime_get()); 152 151 schedule_delayed_work(&dev->work_buffer, msecs_to_jiffies(metrics_table_loop_ms)); 153 - mutex_unlock(&dev->update_mutex); 154 152 } 155 153 156 154 static inline u32 amd_pmf_reg_read(struct amd_pmf_dev *dev, int reg_offset) ··· 181 181 int rc; 182 182 u32 val; 183 183 184 - mutex_lock(&dev->lock); 184 + guard(mutex)(&dev->lock); 185 185 186 186 /* Wait until we get a valid response */ 187 187 rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMF_REGISTER_RESPONSE, ··· 189 189 PMF_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX); 190 190 if (rc) { 191 191 dev_err(dev->dev, "failed to talk to SMU\n"); 192 - goto out_unlock; 192 + return rc; 193 193 } 194 194 195 195 /* Write zero to response register */ ··· 207 207 PMF_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX); 208 208 if (rc) { 209 209 dev_err(dev->dev, "SMU response timed out\n"); 210 - goto out_unlock; 210 + return rc; 211 211 } 212 212 213 213 switch (val) { ··· 221 221 case AMD_PMF_RESULT_CMD_REJECT_BUSY: 222 222 dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val); 223 223 rc = -EBUSY; 224 - goto out_unlock; 224 + break; 225 225 case AMD_PMF_RESULT_CMD_UNKNOWN: 226 226 dev_err(dev->dev, "SMU cmd unknown. err: 0x%x\n", val); 227 227 rc = -EINVAL; 228 - goto out_unlock; 228 + break; 229 229 case AMD_PMF_RESULT_CMD_REJECT_PREREQ: 230 230 case AMD_PMF_RESULT_FAILED: 231 231 default: 232 232 dev_err(dev->dev, "SMU cmd failed. err: 0x%x\n", val); 233 233 rc = -EIO; 234 - goto out_unlock; 234 + break; 235 235 } 236 236 237 - out_unlock: 238 - mutex_unlock(&dev->lock); 239 237 amd_pmf_dump_registers(dev); 240 238 return rc; 241 239 } ··· 371 373 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) || 372 374 is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) { 373 375 power_supply_unreg_notifier(&dev->pwr_src_notifier); 374 - amd_pmf_deinit_sps(dev); 375 376 } 376 377 377 378 if (dev->smart_pc_enabled) { ··· 453 456 mutex_init(&dev->lock); 454 457 mutex_init(&dev->update_mutex); 455 458 456 - amd_pmf_quirks_init(dev); 457 459 apmf_acpi_init(dev); 458 460 platform_set_drvdata(pdev, dev); 459 461 amd_pmf_dbgfs_register(dev);
-66
drivers/platform/x86/amd/pmf/pmf-quirks.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * AMD Platform Management Framework Driver Quirks 4 - * 5 - * Copyright (c) 2024, Advanced Micro Devices, Inc. 6 - * All Rights Reserved. 7 - * 8 - * Author: Mario Limonciello <mario.limonciello@amd.com> 9 - */ 10 - 11 - #include <linux/dmi.h> 12 - 13 - #include "pmf.h" 14 - 15 - struct quirk_entry { 16 - u32 supported_func; 17 - }; 18 - 19 - static struct quirk_entry quirk_no_sps_bug = { 20 - .supported_func = 0x4003, 21 - }; 22 - 23 - static const struct dmi_system_id fwbug_list[] = { 24 - { 25 - .ident = "ROG Zephyrus G14", 26 - .matches = { 27 - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 28 - DMI_MATCH(DMI_PRODUCT_NAME, "GA403U"), 29 - }, 30 - .driver_data = &quirk_no_sps_bug, 31 - }, 32 - { 33 - .ident = "ROG Ally X", 34 - .matches = { 35 - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 36 - DMI_MATCH(DMI_PRODUCT_NAME, "RC72LA"), 37 - }, 38 - .driver_data = &quirk_no_sps_bug, 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 - }, 48 - {} 49 - }; 50 - 51 - void amd_pmf_quirks_init(struct amd_pmf_dev *dev) 52 - { 53 - const struct dmi_system_id *dmi_id; 54 - struct quirk_entry *quirks; 55 - 56 - dmi_id = dmi_first_match(fwbug_list); 57 - if (!dmi_id) 58 - return; 59 - 60 - quirks = dmi_id->driver_data; 61 - if (quirks->supported_func) { 62 - dev->supported_func = quirks->supported_func; 63 - pr_info("Using supported funcs quirk to avoid %s platform firmware bug\n", 64 - dmi_id->ident); 65 - } 66 - }
+32 -7
drivers/platform/x86/amd/pmf/pmf.h
··· 338 338 struct mutex lock; /* protects the PMF interface */ 339 339 u32 supported_func; 340 340 enum platform_profile_option current_profile; 341 - struct platform_profile_handler pprof; 341 + struct device *ppdev; /* platform profile class device */ 342 342 struct dentry *dbgfs_dir; 343 343 int hb_interval; /* SBIOS heartbeat interval */ 344 344 struct delayed_work heart_beat; ··· 370 370 struct input_dev *pmf_idev; 371 371 size_t mtable_size; 372 372 struct resource *res; 373 + struct apmf_sbios_req_v2 req; /* To get custom bios pending request */ 374 + struct mutex cb_mutex; 373 375 }; 374 376 375 377 struct apmf_sps_prop_granular_v2 { ··· 618 616 TA_MAX, 619 617 }; 620 618 619 + enum apmf_smartpc_custom_bios_inputs { 620 + APMF_SMARTPC_CUSTOM_BIOS_INPUT1, 621 + APMF_SMARTPC_CUSTOM_BIOS_INPUT2, 622 + }; 623 + 624 + enum apmf_preq_smartpc { 625 + NOTIFY_CUSTOM_BIOS_INPUT1 = 5, 626 + NOTIFY_CUSTOM_BIOS_INPUT2, 627 + }; 628 + 629 + enum platform_type { 630 + PTYPE_UNKNOWN = 0, 631 + LID_CLOSE, 632 + CLAMSHELL, 633 + FLAT, 634 + TENT, 635 + STAND, 636 + TABLET, 637 + BOOK, 638 + PRESENTATION, 639 + PULL_FWD, 640 + PTYPE_INVALID = 0xf, 641 + }; 642 + 621 643 /* Command ids for TA communication */ 622 644 enum ta_pmf_command { 623 645 TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE, ··· 683 657 u32 power_slider; 684 658 u32 lid_state; 685 659 bool user_present; 686 - u32 rsvd1[2]; 660 + u32 bios_input1; 661 + u32 bios_input2; 687 662 u32 monitor_count; 688 663 u32 rsvd2[2]; 689 664 u32 bat_design; ··· 694 667 u32 device_state; 695 668 u32 socket_power; 696 669 u32 skin_temperature; 697 - u32 rsvd3[5]; 670 + u32 rsvd3[2]; 671 + u32 platform_type; 672 + u32 rsvd3_1[2]; 698 673 u32 ambient_light; 699 674 u32 length; 700 675 u32 avg_c0residency; ··· 780 751 void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx, 781 752 struct amd_pmf_static_slider_granular *table); 782 753 int amd_pmf_init_sps(struct amd_pmf_dev *dev); 783 - void amd_pmf_deinit_sps(struct amd_pmf_dev *dev); 784 754 int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev, 785 755 struct apmf_static_slider_granular_output *output); 786 756 bool is_pprof_balanced(struct amd_pmf_dev *pmf); ··· 824 796 /* Smart PC - TA interfaces */ 825 797 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); 826 798 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); 827 - 828 - /* Quirk infrastructure */ 829 - void amd_pmf_quirks_init(struct amd_pmf_dev *dev); 830 799 831 800 #endif /* PMF_H */
+75
drivers/platform/x86/amd/pmf/spc.c
··· 16 16 #include "pmf.h" 17 17 18 18 #ifdef CONFIG_AMD_PMF_DEBUG 19 + static const char *platform_type_as_str(u16 platform_type) 20 + { 21 + switch (platform_type) { 22 + case CLAMSHELL: 23 + return "CLAMSHELL"; 24 + case FLAT: 25 + return "FLAT"; 26 + case TENT: 27 + return "TENT"; 28 + case STAND: 29 + return "STAND"; 30 + case TABLET: 31 + return "TABLET"; 32 + case BOOK: 33 + return "BOOK"; 34 + case PRESENTATION: 35 + return "PRESENTATION"; 36 + case PULL_FWD: 37 + return "PULL_FWD"; 38 + default: 39 + return "UNKNOWN"; 40 + } 41 + } 42 + 43 + static const char *laptop_placement_as_str(u16 device_state) 44 + { 45 + switch (device_state) { 46 + case ON_TABLE: 47 + return "ON_TABLE"; 48 + case ON_LAP_MOTION: 49 + return "ON_LAP_MOTION"; 50 + case IN_BAG: 51 + return "IN_BAG"; 52 + case OUT_OF_BAG: 53 + return "OUT_OF_BAG"; 54 + default: 55 + return "UNKNOWN"; 56 + } 57 + } 58 + 19 59 static const char *ta_slider_as_str(unsigned int state) 20 60 { 21 61 switch (state) { ··· 87 47 dev_dbg(dev->dev, "LID State: %s\n", in->ev_info.lid_state ? "close" : "open"); 88 48 dev_dbg(dev->dev, "User Presence: %s\n", in->ev_info.user_present ? "Present" : "Away"); 89 49 dev_dbg(dev->dev, "Ambient Light: %d\n", in->ev_info.ambient_light); 50 + dev_dbg(dev->dev, "Platform type: %s\n", platform_type_as_str(in->ev_info.platform_type)); 51 + dev_dbg(dev->dev, "Laptop placement: %s\n", 52 + laptop_placement_as_str(in->ev_info.device_state)); 53 + dev_dbg(dev->dev, "Custom BIOS input1: %u\n", in->ev_info.bios_input1); 54 + dev_dbg(dev->dev, "Custom BIOS input2: %u\n", in->ev_info.bios_input2); 90 55 dev_dbg(dev->dev, "==== TA inputs END ====\n"); 91 56 } 92 57 #else 93 58 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {} 94 59 #endif 60 + 61 + static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev, 62 + struct ta_pmf_enact_table *in) 63 + { 64 + if (!pdev->req.pending_req) 65 + return; 66 + 67 + switch (pdev->req.pending_req) { 68 + case BIT(NOTIFY_CUSTOM_BIOS_INPUT1): 69 + in->ev_info.bios_input1 = pdev->req.custom_policy[APMF_SMARTPC_CUSTOM_BIOS_INPUT1]; 70 + break; 71 + case BIT(NOTIFY_CUSTOM_BIOS_INPUT2): 72 + in->ev_info.bios_input2 = pdev->req.custom_policy[APMF_SMARTPC_CUSTOM_BIOS_INPUT2]; 73 + break; 74 + default: 75 + dev_dbg(pdev->dev, "Invalid preq for BIOS input: 0x%x\n", pdev->req.pending_req); 76 + } 77 + 78 + /* Clear pending requests after handling */ 79 + memset(&pdev->req, 0, sizeof(pdev->req)); 80 + } 95 81 96 82 static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in) 97 83 { ··· 256 190 } else { 257 191 dev_dbg(dev->dev, "HPD is not enabled/detected\n"); 258 192 } 193 + 194 + /* Get SRA (Secondary Accelerometer) data */ 195 + if (!amd_get_sfh_info(&sfh_info, MT_SRA)) { 196 + in->ev_info.platform_type = sfh_info.platform_type; 197 + in->ev_info.device_state = sfh_info.laptop_placement; 198 + } else { 199 + dev_dbg(dev->dev, "SRA is not enabled/detected\n"); 200 + } 259 201 } 260 202 261 203 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) ··· 275 201 amd_pmf_get_battery_info(dev, in); 276 202 amd_pmf_get_slider_info(dev, in); 277 203 amd_pmf_get_sensor_info(dev, in); 204 + amd_pmf_get_custom_bios_inputs(dev, in); 278 205 }
+25 -24
drivers/platform/x86/amd/pmf/sps.c
··· 282 282 return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false; 283 283 } 284 284 285 - static int amd_pmf_profile_get(struct platform_profile_handler *pprof, 285 + static int amd_pmf_profile_get(struct device *dev, 286 286 enum platform_profile_option *profile) 287 287 { 288 - struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof); 288 + struct amd_pmf_dev *pmf = dev_get_drvdata(dev); 289 289 290 290 *profile = pmf->current_profile; 291 291 return 0; ··· 363 363 return 0; 364 364 } 365 365 366 - static int amd_pmf_profile_set(struct platform_profile_handler *pprof, 366 + static int amd_pmf_profile_set(struct device *dev, 367 367 enum platform_profile_option profile) 368 368 { 369 - struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof); 369 + struct amd_pmf_dev *pmf = dev_get_drvdata(dev); 370 370 int ret = 0; 371 371 372 372 pmf->current_profile = profile; ··· 387 387 return 0; 388 388 } 389 389 390 + static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices) 391 + { 392 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 393 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 394 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 395 + 396 + return 0; 397 + } 398 + 399 + static const struct platform_profile_ops amd_pmf_profile_ops = { 400 + .probe = amd_pmf_profile_probe, 401 + .profile_get = amd_pmf_profile_get, 402 + .profile_set = amd_pmf_profile_set, 403 + }; 404 + 390 405 int amd_pmf_init_sps(struct amd_pmf_dev *dev) 391 406 { 392 - int err; 393 - 394 407 dev->current_profile = PLATFORM_PROFILE_BALANCED; 395 408 396 409 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) { ··· 418 405 amd_pmf_set_sps_power_limits(dev); 419 406 } 420 407 421 - dev->pprof.profile_get = amd_pmf_profile_get; 422 - dev->pprof.profile_set = amd_pmf_profile_set; 423 - 424 - /* Setup supported modes */ 425 - set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices); 426 - set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices); 427 - set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices); 428 - 429 408 /* Create platform_profile structure and register */ 430 - err = platform_profile_register(&dev->pprof); 431 - if (err) 432 - dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n", 433 - err); 409 + dev->ppdev = devm_platform_profile_register(dev->dev, "amd-pmf", dev, 410 + &amd_pmf_profile_ops); 411 + if (IS_ERR(dev->ppdev)) 412 + dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n", 413 + PTR_ERR(dev->ppdev)); 434 414 435 - return err; 436 - } 437 - 438 - void amd_pmf_deinit_sps(struct amd_pmf_dev *dev) 439 - { 440 - platform_profile_remove(); 415 + return PTR_ERR_OR_ZERO(dev->ppdev); 441 416 }
+2 -1
drivers/platform/x86/asus-nb-wmi.c
··· 50 50 static struct quirk_entry *quirks; 51 51 static bool atkbd_reports_vol_keys; 52 52 53 - static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port) 53 + static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port, 54 + void *context) 54 55 { 55 56 static bool extended_e0; 56 57 static bool extended_e1;
+27 -28
drivers/platform/x86/asus-wmi.c
··· 313 313 bool mid_fan_curve_available; 314 314 struct fan_curve_data custom_fan_curves[3]; 315 315 316 - struct platform_profile_handler platform_profile_handler; 316 + struct device *ppdev; 317 317 bool platform_profile_support; 318 318 319 319 // The RSOC controls the maximum charging percentage. ··· 3782 3782 * Ensure that platform_profile updates userspace with the change to ensure 3783 3783 * that platform_profile and throttle_thermal_policy_mode are in sync. 3784 3784 */ 3785 - platform_profile_notify(); 3785 + platform_profile_notify(asus->ppdev); 3786 3786 3787 3787 return count; 3788 3788 } ··· 3793 3793 static DEVICE_ATTR_RW(throttle_thermal_policy); 3794 3794 3795 3795 /* Platform profile ***********************************************************/ 3796 - static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, 3796 + static int asus_wmi_platform_profile_get(struct device *dev, 3797 3797 enum platform_profile_option *profile) 3798 3798 { 3799 3799 struct asus_wmi *asus; 3800 3800 int tp; 3801 3801 3802 - asus = container_of(pprof, struct asus_wmi, platform_profile_handler); 3802 + asus = dev_get_drvdata(dev); 3803 3803 tp = asus->throttle_thermal_policy_mode; 3804 3804 3805 3805 switch (tp) { ··· 3819 3819 return 0; 3820 3820 } 3821 3821 3822 - static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof, 3822 + static int asus_wmi_platform_profile_set(struct device *dev, 3823 3823 enum platform_profile_option profile) 3824 3824 { 3825 3825 struct asus_wmi *asus; 3826 3826 int tp; 3827 3827 3828 - asus = container_of(pprof, struct asus_wmi, platform_profile_handler); 3828 + asus = dev_get_drvdata(dev); 3829 3829 3830 3830 switch (profile) { 3831 3831 case PLATFORM_PROFILE_PERFORMANCE: ··· 3844 3844 asus->throttle_thermal_policy_mode = tp; 3845 3845 return throttle_thermal_policy_write(asus); 3846 3846 } 3847 + 3848 + static int asus_wmi_platform_profile_probe(void *drvdata, unsigned long *choices) 3849 + { 3850 + set_bit(PLATFORM_PROFILE_QUIET, choices); 3851 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 3852 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 3853 + 3854 + return 0; 3855 + } 3856 + 3857 + static const struct platform_profile_ops asus_wmi_platform_profile_ops = { 3858 + .probe = asus_wmi_platform_profile_probe, 3859 + .profile_get = asus_wmi_platform_profile_get, 3860 + .profile_set = asus_wmi_platform_profile_set, 3861 + }; 3847 3862 3848 3863 static int platform_profile_setup(struct asus_wmi *asus) 3849 3864 { ··· 3884 3869 3885 3870 dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n"); 3886 3871 3887 - asus->platform_profile_handler.profile_get = asus_wmi_platform_profile_get; 3888 - asus->platform_profile_handler.profile_set = asus_wmi_platform_profile_set; 3889 - 3890 - set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices); 3891 - set_bit(PLATFORM_PROFILE_BALANCED, 3892 - asus->platform_profile_handler.choices); 3893 - set_bit(PLATFORM_PROFILE_PERFORMANCE, 3894 - asus->platform_profile_handler.choices); 3895 - 3896 - err = platform_profile_register(&asus->platform_profile_handler); 3897 - if (err == -EEXIST) { 3898 - pr_warn("%s, a platform_profile handler is already registered\n", __func__); 3899 - return 0; 3900 - } else if (err) { 3901 - pr_err("%s, failed at platform_profile_register: %d\n", __func__, err); 3902 - return err; 3872 + asus->ppdev = devm_platform_profile_register(dev, "asus-wmi", asus, 3873 + &asus_wmi_platform_profile_ops); 3874 + if (IS_ERR(asus->ppdev)) { 3875 + dev_err(dev, "Failed to register a platform_profile class device\n"); 3876 + return PTR_ERR(asus->ppdev); 3903 3877 } 3904 3878 3905 3879 asus->platform_profile_support = true; ··· 4819 4815 } 4820 4816 4821 4817 if (asus->driver->i8042_filter) { 4822 - err = i8042_install_filter(asus->driver->i8042_filter); 4818 + err = i8042_install_filter(asus->driver->i8042_filter, NULL); 4823 4819 if (err) 4824 4820 pr_warn("Unable to install key filter - %d\n", err); 4825 4821 } ··· 4846 4842 fail_sysfs: 4847 4843 fail_custom_fan_curve: 4848 4844 fail_platform_profile_setup: 4849 - if (asus->platform_profile_support) 4850 - platform_profile_remove(); 4851 4845 fail_fan_boost_mode: 4852 4846 fail_platform: 4853 4847 kfree(asus); ··· 4870 4868 asus_fan_set_auto(asus); 4871 4869 throttle_thermal_policy_set_default(asus); 4872 4870 asus_wmi_battery_exit(asus); 4873 - 4874 - if (asus->platform_profile_support) 4875 - platform_profile_remove(); 4876 4871 4877 4872 kfree(asus); 4878 4873 }
+1 -2
drivers/platform/x86/asus-wmi.h
··· 73 73 void (*key_filter) (struct asus_wmi_driver *driver, int *code, 74 74 unsigned int *value, bool *autorelease); 75 75 /* Optional standard i8042 filter */ 76 - bool (*i8042_filter)(unsigned char data, unsigned char str, 77 - struct serio *serio); 76 + i8042_filter_t i8042_filter; 78 77 79 78 int (*probe) (struct platform_device *device); 80 79 void (*detect_quirks) (struct asus_wmi_driver *driver);
+1
drivers/platform/x86/dell/Kconfig
··· 152 152 config DELL_SMO8800 153 153 tristate "Dell Latitude freefall driver (ACPI SMO88XX)" 154 154 default m 155 + depends on I2C 155 156 depends on ACPI || COMPILE_TEST 156 157 help 157 158 Say Y here if you want to support SMO88XX freefall devices
+1
drivers/platform/x86/dell/Makefile
··· 15 15 dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o 16 16 dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o 17 17 obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o 18 + obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o 18 19 obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o 19 20 obj-$(CONFIG_DELL_WMI) += dell-wmi.o 20 21 dell-wmi-objs := dell-wmi-base.o
+245 -277
drivers/platform/x86/dell/alienware-wmi.c
··· 385 385 u8 red; 386 386 } __packed; 387 387 388 - struct platform_zone { 389 - u8 location; 390 - struct device_attribute *attr; 391 - struct color_platform colors; 392 - }; 393 - 394 388 struct wmax_brightness_args { 395 389 u32 led_mask; 396 390 u32 percentage; ··· 414 420 }; 415 421 416 422 static struct platform_device *platform_device; 417 - static struct device_attribute *zone_dev_attrs; 418 - static struct attribute **zone_attrs; 419 - static struct platform_zone *zone_data; 420 - static struct platform_profile_handler pp_handler; 423 + static struct color_platform colors[4]; 421 424 static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; 422 - 423 - static struct platform_driver platform_driver = { 424 - .driver = { 425 - .name = "alienware-wmi", 426 - } 427 - }; 428 - 429 - static struct attribute_group zone_attribute_group = { 430 - .name = "rgb_zones", 431 - }; 432 425 433 426 static u8 interface; 434 427 static u8 lighting_control_state; ··· 424 443 /* 425 444 * Helpers used for zone control 426 445 */ 427 - static int parse_rgb(const char *buf, struct platform_zone *zone) 446 + static int parse_rgb(const char *buf, struct color_platform *colors) 428 447 { 429 448 long unsigned int rgb; 430 449 int ret; ··· 444 463 repackager.package = rgb & 0x0f0f0f0f; 445 464 pr_debug("alienware-wmi: r: %d g:%d b: %d\n", 446 465 repackager.cp.red, repackager.cp.green, repackager.cp.blue); 447 - zone->colors = repackager.cp; 466 + *colors = repackager.cp; 448 467 return 0; 449 - } 450 - 451 - static struct platform_zone *match_zone(struct device_attribute *attr) 452 - { 453 - u8 zone; 454 - 455 - for (zone = 0; zone < quirks->num_zones; zone++) { 456 - if ((struct device_attribute *)zone_data[zone].attr == attr) { 457 - pr_debug("alienware-wmi: matched zone location: %d\n", 458 - zone_data[zone].location); 459 - return &zone_data[zone]; 460 - } 461 - } 462 - return NULL; 463 468 } 464 469 465 470 /* 466 471 * Individual RGB zone control 467 472 */ 468 - static int alienware_update_led(struct platform_zone *zone) 473 + static int alienware_update_led(u8 location) 469 474 { 470 475 int method_id; 471 476 acpi_status status; ··· 460 493 struct legacy_led_args legacy_args; 461 494 struct wmax_led_args wmax_basic_args; 462 495 if (interface == WMAX) { 463 - wmax_basic_args.led_mask = 1 << zone->location; 464 - wmax_basic_args.colors = zone->colors; 496 + wmax_basic_args.led_mask = 1 << location; 497 + wmax_basic_args.colors = colors[location]; 465 498 wmax_basic_args.state = lighting_control_state; 466 499 guid = WMAX_CONTROL_GUID; 467 500 method_id = WMAX_METHOD_ZONE_CONTROL; ··· 469 502 input.length = sizeof(wmax_basic_args); 470 503 input.pointer = &wmax_basic_args; 471 504 } else { 472 - legacy_args.colors = zone->colors; 505 + legacy_args.colors = colors[location]; 473 506 legacy_args.brightness = global_brightness; 474 507 legacy_args.state = 0; 475 508 if (lighting_control_state == LEGACY_BOOTING || ··· 478 511 legacy_args.state = lighting_control_state; 479 512 } else 480 513 guid = LEGACY_CONTROL_GUID; 481 - method_id = zone->location + 1; 514 + method_id = location + 1; 482 515 483 516 input.length = sizeof(legacy_args); 484 517 input.pointer = &legacy_args; ··· 492 525 } 493 526 494 527 static ssize_t zone_show(struct device *dev, struct device_attribute *attr, 495 - char *buf) 528 + char *buf, u8 location) 496 529 { 497 - struct platform_zone *target_zone; 498 - target_zone = match_zone(attr); 499 - if (target_zone == NULL) 500 - return sprintf(buf, "red: -1, green: -1, blue: -1\n"); 501 530 return sprintf(buf, "red: %d, green: %d, blue: %d\n", 502 - target_zone->colors.red, 503 - target_zone->colors.green, target_zone->colors.blue); 531 + colors[location].red, colors[location].green, 532 + colors[location].blue); 504 533 505 534 } 506 535 507 - static ssize_t zone_set(struct device *dev, struct device_attribute *attr, 508 - const char *buf, size_t count) 536 + static ssize_t zone_store(struct device *dev, struct device_attribute *attr, 537 + const char *buf, size_t count, u8 location) 509 538 { 510 - struct platform_zone *target_zone; 511 539 int ret; 512 - target_zone = match_zone(attr); 513 - if (target_zone == NULL) { 514 - pr_err("alienware-wmi: invalid target zone\n"); 515 - return 1; 516 - } 517 - ret = parse_rgb(buf, target_zone); 540 + 541 + ret = parse_rgb(buf, &colors[location]); 518 542 if (ret) 519 543 return ret; 520 - ret = alienware_update_led(target_zone); 544 + 545 + ret = alienware_update_led(location); 546 + 521 547 return ret ? ret : count; 522 548 } 549 + 550 + static ssize_t zone00_show(struct device *dev, struct device_attribute *attr, 551 + char *buf) 552 + { 553 + return zone_show(dev, attr, buf, 0); 554 + } 555 + 556 + static ssize_t zone00_store(struct device *dev, struct device_attribute *attr, 557 + const char *buf, size_t count) 558 + { 559 + return zone_store(dev, attr, buf, count, 0); 560 + } 561 + 562 + static DEVICE_ATTR_RW(zone00); 563 + 564 + static ssize_t zone01_show(struct device *dev, struct device_attribute *attr, 565 + char *buf) 566 + { 567 + return zone_show(dev, attr, buf, 1); 568 + } 569 + 570 + static ssize_t zone01_store(struct device *dev, struct device_attribute *attr, 571 + const char *buf, size_t count) 572 + { 573 + return zone_store(dev, attr, buf, count, 1); 574 + } 575 + 576 + static DEVICE_ATTR_RW(zone01); 577 + 578 + static ssize_t zone02_show(struct device *dev, struct device_attribute *attr, 579 + char *buf) 580 + { 581 + return zone_show(dev, attr, buf, 2); 582 + } 583 + 584 + static ssize_t zone02_store(struct device *dev, struct device_attribute *attr, 585 + const char *buf, size_t count) 586 + { 587 + return zone_store(dev, attr, buf, count, 2); 588 + } 589 + 590 + static DEVICE_ATTR_RW(zone02); 591 + 592 + static ssize_t zone03_show(struct device *dev, struct device_attribute *attr, 593 + char *buf) 594 + { 595 + return zone_show(dev, attr, buf, 3); 596 + } 597 + 598 + static ssize_t zone03_store(struct device *dev, struct device_attribute *attr, 599 + const char *buf, size_t count) 600 + { 601 + return zone_store(dev, attr, buf, count, 3); 602 + } 603 + 604 + static DEVICE_ATTR_RW(zone03); 605 + 606 + /* 607 + * Lighting control state device attribute (Global) 608 + */ 609 + static ssize_t lighting_control_state_show(struct device *dev, 610 + struct device_attribute *attr, 611 + char *buf) 612 + { 613 + if (lighting_control_state == LEGACY_BOOTING) 614 + return sysfs_emit(buf, "[booting] running suspend\n"); 615 + else if (lighting_control_state == LEGACY_SUSPEND) 616 + return sysfs_emit(buf, "booting running [suspend]\n"); 617 + 618 + return sysfs_emit(buf, "booting [running] suspend\n"); 619 + } 620 + 621 + static ssize_t lighting_control_state_store(struct device *dev, 622 + struct device_attribute *attr, 623 + const char *buf, size_t count) 624 + { 625 + u8 val; 626 + 627 + if (strcmp(buf, "booting\n") == 0) 628 + val = LEGACY_BOOTING; 629 + else if (strcmp(buf, "suspend\n") == 0) 630 + val = LEGACY_SUSPEND; 631 + else if (interface == LEGACY) 632 + val = LEGACY_RUNNING; 633 + else 634 + val = WMAX_RUNNING; 635 + 636 + lighting_control_state = val; 637 + pr_debug("alienware-wmi: updated control state to %d\n", 638 + lighting_control_state); 639 + 640 + return count; 641 + } 642 + 643 + static DEVICE_ATTR_RW(lighting_control_state); 644 + 645 + static umode_t zone_attr_visible(struct kobject *kobj, 646 + struct attribute *attr, int n) 647 + { 648 + if (n < quirks->num_zones + 1) 649 + return attr->mode; 650 + 651 + return 0; 652 + } 653 + 654 + static bool zone_group_visible(struct kobject *kobj) 655 + { 656 + return quirks->num_zones > 0; 657 + } 658 + DEFINE_SYSFS_GROUP_VISIBLE(zone); 659 + 660 + static struct attribute *zone_attrs[] = { 661 + &dev_attr_lighting_control_state.attr, 662 + &dev_attr_zone00.attr, 663 + &dev_attr_zone01.attr, 664 + &dev_attr_zone02.attr, 665 + &dev_attr_zone03.attr, 666 + NULL 667 + }; 668 + 669 + static struct attribute_group zone_attribute_group = { 670 + .name = "rgb_zones", 671 + .is_visible = SYSFS_GROUP_VISIBLE(zone), 672 + .attrs = zone_attrs, 673 + }; 523 674 524 675 /* 525 676 * LED Brightness (Global) ··· 667 582 if (interface == WMAX) 668 583 ret = wmax_brightness(brightness); 669 584 else 670 - ret = alienware_update_led(&zone_data[0]); 585 + ret = alienware_update_led(0); 671 586 if (ret) 672 587 pr_err("LED brightness update failed\n"); 673 588 } ··· 683 598 .name = "alienware::global_brightness", 684 599 }; 685 600 686 - /* 687 - * Lighting control state device attribute (Global) 688 - */ 689 - static ssize_t show_control_state(struct device *dev, 690 - struct device_attribute *attr, char *buf) 691 - { 692 - if (lighting_control_state == LEGACY_BOOTING) 693 - return sysfs_emit(buf, "[booting] running suspend\n"); 694 - else if (lighting_control_state == LEGACY_SUSPEND) 695 - return sysfs_emit(buf, "booting running [suspend]\n"); 696 - return sysfs_emit(buf, "booting [running] suspend\n"); 697 - } 698 - 699 - static ssize_t store_control_state(struct device *dev, 700 - struct device_attribute *attr, 701 - const char *buf, size_t count) 702 - { 703 - long unsigned int val; 704 - if (strcmp(buf, "booting\n") == 0) 705 - val = LEGACY_BOOTING; 706 - else if (strcmp(buf, "suspend\n") == 0) 707 - val = LEGACY_SUSPEND; 708 - else if (interface == LEGACY) 709 - val = LEGACY_RUNNING; 710 - else 711 - val = WMAX_RUNNING; 712 - lighting_control_state = val; 713 - pr_debug("alienware-wmi: updated control state to %d\n", 714 - lighting_control_state); 715 - return count; 716 - } 717 - 718 - static DEVICE_ATTR(lighting_control_state, 0644, show_control_state, 719 - store_control_state); 720 - 721 601 static int alienware_zone_init(struct platform_device *dev) 722 602 { 723 - u8 zone; 724 - char *name; 725 - 726 603 if (interface == WMAX) { 727 604 lighting_control_state = WMAX_RUNNING; 728 605 } else if (interface == LEGACY) { ··· 693 646 global_led.max_brightness = 0x0F; 694 647 global_brightness = global_led.max_brightness; 695 648 696 - /* 697 - * - zone_dev_attrs num_zones + 1 is for individual zones and then 698 - * null terminated 699 - * - zone_attrs num_zones + 2 is for all attrs in zone_dev_attrs + 700 - * the lighting control + null terminated 701 - * - zone_data num_zones is for the distinct zones 702 - */ 703 - zone_dev_attrs = 704 - kcalloc(quirks->num_zones + 1, sizeof(struct device_attribute), 705 - GFP_KERNEL); 706 - if (!zone_dev_attrs) 707 - return -ENOMEM; 708 - 709 - zone_attrs = 710 - kcalloc(quirks->num_zones + 2, sizeof(struct attribute *), 711 - GFP_KERNEL); 712 - if (!zone_attrs) 713 - return -ENOMEM; 714 - 715 - zone_data = 716 - kcalloc(quirks->num_zones, sizeof(struct platform_zone), 717 - GFP_KERNEL); 718 - if (!zone_data) 719 - return -ENOMEM; 720 - 721 - for (zone = 0; zone < quirks->num_zones; zone++) { 722 - name = kasprintf(GFP_KERNEL, "zone%02hhX", zone); 723 - if (name == NULL) 724 - return 1; 725 - sysfs_attr_init(&zone_dev_attrs[zone].attr); 726 - zone_dev_attrs[zone].attr.name = name; 727 - zone_dev_attrs[zone].attr.mode = 0644; 728 - zone_dev_attrs[zone].show = zone_show; 729 - zone_dev_attrs[zone].store = zone_set; 730 - zone_data[zone].location = zone; 731 - zone_attrs[zone] = &zone_dev_attrs[zone].attr; 732 - zone_data[zone].attr = &zone_dev_attrs[zone]; 733 - } 734 - zone_attrs[quirks->num_zones] = &dev_attr_lighting_control_state.attr; 735 - zone_attribute_group.attrs = zone_attrs; 736 - 737 - led_classdev_register(&dev->dev, &global_led); 738 - 739 - return sysfs_create_group(&dev->dev.kobj, &zone_attribute_group); 649 + return led_classdev_register(&dev->dev, &global_led); 740 650 } 741 651 742 652 static void alienware_zone_exit(struct platform_device *dev) 743 653 { 744 - u8 zone; 745 - 746 654 if (!quirks->num_zones) 747 655 return; 748 656 749 - sysfs_remove_group(&dev->dev.kobj, &zone_attribute_group); 750 657 led_classdev_unregister(&global_led); 751 - if (zone_dev_attrs) { 752 - for (zone = 0; zone < quirks->num_zones; zone++) 753 - kfree(zone_dev_attrs[zone].attr.name); 754 - } 755 - kfree(zone_dev_attrs); 756 - kfree(zone_data); 757 - kfree(zone_attrs); 758 658 } 759 659 760 660 static acpi_status alienware_wmax_command(void *in_args, size_t in_size, ··· 736 742 * The HDMI mux sysfs node indicates the status of the HDMI input mux. 737 743 * It can toggle between standard system GPU output and HDMI input. 738 744 */ 739 - static ssize_t show_hdmi_cable(struct device *dev, 740 - struct device_attribute *attr, char *buf) 745 + static ssize_t cable_show(struct device *dev, struct device_attribute *attr, 746 + char *buf) 741 747 { 742 - acpi_status status; 743 - u32 out_data; 744 748 struct wmax_basic_args in_args = { 745 749 .arg = 0, 746 750 }; 751 + acpi_status status; 752 + u32 out_data; 753 + 747 754 status = 748 755 alienware_wmax_command(&in_args, sizeof(in_args), 749 756 WMAX_METHOD_HDMI_CABLE, &out_data); ··· 758 763 return sysfs_emit(buf, "unconnected connected [unknown]\n"); 759 764 } 760 765 761 - static ssize_t show_hdmi_source(struct device *dev, 762 - struct device_attribute *attr, char *buf) 766 + static ssize_t source_show(struct device *dev, struct device_attribute *attr, 767 + char *buf) 763 768 { 764 - acpi_status status; 765 - u32 out_data; 766 769 struct wmax_basic_args in_args = { 767 770 .arg = 0, 768 771 }; 772 + acpi_status status; 773 + u32 out_data; 774 + 769 775 status = 770 776 alienware_wmax_command(&in_args, sizeof(in_args), 771 777 WMAX_METHOD_HDMI_STATUS, &out_data); ··· 781 785 return sysfs_emit(buf, "input gpu [unknown]\n"); 782 786 } 783 787 784 - static ssize_t toggle_hdmi_source(struct device *dev, 785 - struct device_attribute *attr, 786 - const char *buf, size_t count) 788 + static ssize_t source_store(struct device *dev, struct device_attribute *attr, 789 + const char *buf, size_t count) 787 790 { 788 - acpi_status status; 789 791 struct wmax_basic_args args; 792 + acpi_status status; 793 + 790 794 if (strcmp(buf, "gpu\n") == 0) 791 795 args.arg = 1; 792 796 else if (strcmp(buf, "input\n") == 0) ··· 804 808 return count; 805 809 } 806 810 807 - static DEVICE_ATTR(cable, S_IRUGO, show_hdmi_cable, NULL); 808 - static DEVICE_ATTR(source, S_IRUGO | S_IWUSR, show_hdmi_source, 809 - toggle_hdmi_source); 811 + static DEVICE_ATTR_RO(cable); 812 + static DEVICE_ATTR_RW(source); 813 + 814 + static bool hdmi_group_visible(struct kobject *kobj) 815 + { 816 + return quirks->hdmi_mux; 817 + } 818 + DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi); 810 819 811 820 static struct attribute *hdmi_attrs[] = { 812 821 &dev_attr_cable.attr, ··· 821 820 822 821 static const struct attribute_group hdmi_attribute_group = { 823 822 .name = "hdmi", 823 + .is_visible = SYSFS_GROUP_VISIBLE(hdmi), 824 824 .attrs = hdmi_attrs, 825 825 }; 826 - 827 - static void remove_hdmi(struct platform_device *dev) 828 - { 829 - if (quirks->hdmi_mux > 0) 830 - sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); 831 - } 832 - 833 - static int create_hdmi(struct platform_device *dev) 834 - { 835 - int ret; 836 - 837 - ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group); 838 - if (ret) 839 - remove_hdmi(dev); 840 - return ret; 841 - } 842 826 843 827 /* 844 828 * Alienware GFX amplifier support 845 829 * - Currently supports reading cable status 846 830 * - Leaving expansion room to possibly support dock/undock events later 847 831 */ 848 - static ssize_t show_amplifier_status(struct device *dev, 849 - struct device_attribute *attr, char *buf) 832 + static ssize_t status_show(struct device *dev, struct device_attribute *attr, 833 + char *buf) 850 834 { 851 - acpi_status status; 852 - u32 out_data; 853 835 struct wmax_basic_args in_args = { 854 836 .arg = 0, 855 837 }; 838 + acpi_status status; 839 + u32 out_data; 840 + 856 841 status = 857 842 alienware_wmax_command(&in_args, sizeof(in_args), 858 843 WMAX_METHOD_AMPLIFIER_CABLE, &out_data); ··· 852 865 return sysfs_emit(buf, "unconnected connected [unknown]\n"); 853 866 } 854 867 855 - static DEVICE_ATTR(status, S_IRUGO, show_amplifier_status, NULL); 868 + static DEVICE_ATTR_RO(status); 869 + 870 + static bool amplifier_group_visible(struct kobject *kobj) 871 + { 872 + return quirks->amplifier; 873 + } 874 + DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier); 856 875 857 876 static struct attribute *amplifier_attrs[] = { 858 877 &dev_attr_status.attr, ··· 867 874 868 875 static const struct attribute_group amplifier_attribute_group = { 869 876 .name = "amplifier", 877 + .is_visible = SYSFS_GROUP_VISIBLE(amplifier), 870 878 .attrs = amplifier_attrs, 871 879 }; 872 - 873 - static void remove_amplifier(struct platform_device *dev) 874 - { 875 - if (quirks->amplifier > 0) 876 - sysfs_remove_group(&dev->dev.kobj, &amplifier_attribute_group); 877 - } 878 - 879 - static int create_amplifier(struct platform_device *dev) 880 - { 881 - int ret; 882 - 883 - ret = sysfs_create_group(&dev->dev.kobj, &amplifier_attribute_group); 884 - if (ret) 885 - remove_amplifier(dev); 886 - return ret; 887 - } 888 880 889 881 /* 890 882 * Deep Sleep Control support 891 883 * - Modifies BIOS setting for deep sleep control allowing extra wakeup events 892 884 */ 893 - static ssize_t show_deepsleep_status(struct device *dev, 894 - struct device_attribute *attr, char *buf) 885 + static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr, 886 + char *buf) 895 887 { 896 - acpi_status status; 897 - u32 out_data; 898 888 struct wmax_basic_args in_args = { 899 889 .arg = 0, 900 890 }; 891 + acpi_status status; 892 + u32 out_data; 893 + 901 894 status = alienware_wmax_command(&in_args, sizeof(in_args), 902 895 WMAX_METHOD_DEEP_SLEEP_STATUS, &out_data); 903 896 if (ACPI_SUCCESS(status)) { ··· 898 919 return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n"); 899 920 } 900 921 901 - static ssize_t toggle_deepsleep(struct device *dev, 902 - struct device_attribute *attr, 903 - const char *buf, size_t count) 922 + static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr, 923 + const char *buf, size_t count) 904 924 { 905 - acpi_status status; 906 925 struct wmax_basic_args args; 926 + acpi_status status; 907 927 908 928 if (strcmp(buf, "disabled\n") == 0) 909 929 args.arg = 0; ··· 921 943 return count; 922 944 } 923 945 924 - static DEVICE_ATTR(deepsleep, S_IRUGO | S_IWUSR, show_deepsleep_status, toggle_deepsleep); 946 + static DEVICE_ATTR_RW(deepsleep); 947 + 948 + static bool deepsleep_group_visible(struct kobject *kobj) 949 + { 950 + return quirks->deepslp; 951 + } 952 + DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep); 925 953 926 954 static struct attribute *deepsleep_attrs[] = { 927 955 &dev_attr_deepsleep.attr, ··· 936 952 937 953 static const struct attribute_group deepsleep_attribute_group = { 938 954 .name = "deepsleep", 955 + .is_visible = SYSFS_GROUP_VISIBLE(deepsleep), 939 956 .attrs = deepsleep_attrs, 940 957 }; 941 - 942 - static void remove_deepsleep(struct platform_device *dev) 943 - { 944 - if (quirks->deepslp > 0) 945 - sysfs_remove_group(&dev->dev.kobj, &deepsleep_attribute_group); 946 - } 947 - 948 - static int create_deepsleep(struct platform_device *dev) 949 - { 950 - int ret; 951 - 952 - ret = sysfs_create_group(&dev->dev.kobj, &deepsleep_attribute_group); 953 - if (ret) 954 - remove_deepsleep(dev); 955 - return ret; 956 - } 957 958 958 959 /* 959 960 * Thermal Profile control ··· 969 1000 970 1001 static int wmax_thermal_information(u8 operation, u8 arg, u32 *out_data) 971 1002 { 972 - acpi_status status; 973 1003 struct wmax_u32_args in_args = { 974 1004 .operation = operation, 975 1005 .arg1 = arg, 976 1006 .arg2 = 0, 977 1007 .arg3 = 0, 978 1008 }; 1009 + acpi_status status; 979 1010 980 1011 status = alienware_wmax_command(&in_args, sizeof(in_args), 981 1012 WMAX_METHOD_THERMAL_INFORMATION, ··· 992 1023 993 1024 static int wmax_thermal_control(u8 profile) 994 1025 { 995 - acpi_status status; 996 1026 struct wmax_u32_args in_args = { 997 1027 .operation = WMAX_OPERATION_ACTIVATE_PROFILE, 998 1028 .arg1 = profile, 999 1029 .arg2 = 0, 1000 1030 .arg3 = 0, 1001 1031 }; 1032 + acpi_status status; 1002 1033 u32 out_data; 1003 1034 1004 1035 status = alienware_wmax_command(&in_args, sizeof(in_args), ··· 1016 1047 1017 1048 static int wmax_game_shift_status(u8 operation, u32 *out_data) 1018 1049 { 1019 - acpi_status status; 1020 1050 struct wmax_u32_args in_args = { 1021 1051 .operation = operation, 1022 1052 .arg1 = 0, 1023 1053 .arg2 = 0, 1024 1054 .arg3 = 0, 1025 1055 }; 1056 + acpi_status status; 1026 1057 1027 1058 status = alienware_wmax_command(&in_args, sizeof(in_args), 1028 1059 WMAX_METHOD_GAME_SHIFT_STATUS, ··· 1037 1068 return 0; 1038 1069 } 1039 1070 1040 - static int thermal_profile_get(struct platform_profile_handler *pprof, 1071 + static int thermal_profile_get(struct device *dev, 1041 1072 enum platform_profile_option *profile) 1042 1073 { 1043 1074 u32 out_data; ··· 1063 1094 return 0; 1064 1095 } 1065 1096 1066 - static int thermal_profile_set(struct platform_profile_handler *pprof, 1097 + static int thermal_profile_set(struct device *dev, 1067 1098 enum platform_profile_option profile) 1068 1099 { 1069 1100 if (quirks->gmode) { ··· 1089 1120 return wmax_thermal_control(supported_thermal_profiles[profile]); 1090 1121 } 1091 1122 1092 - static int create_thermal_profile(void) 1123 + static int thermal_profile_probe(void *drvdata, unsigned long *choices) 1093 1124 { 1094 - u32 out_data; 1125 + enum platform_profile_option profile; 1126 + enum wmax_thermal_mode mode; 1095 1127 u8 sys_desc[4]; 1096 1128 u32 first_mode; 1097 - enum wmax_thermal_mode mode; 1098 - enum platform_profile_option profile; 1129 + u32 out_data; 1099 1130 int ret; 1100 1131 1101 1132 ret = wmax_thermal_information(WMAX_OPERATION_SYS_DESCRIPTION, ··· 1122 1153 profile = wmax_mode_to_platform_profile[mode]; 1123 1154 supported_thermal_profiles[profile] = out_data; 1124 1155 1125 - set_bit(profile, pp_handler.choices); 1156 + set_bit(profile, choices); 1126 1157 } 1127 1158 1128 - if (bitmap_empty(pp_handler.choices, PLATFORM_PROFILE_LAST)) 1159 + if (bitmap_empty(choices, PLATFORM_PROFILE_LAST)) 1129 1160 return -ENODEV; 1130 1161 1131 1162 if (quirks->gmode) { 1132 1163 supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] = 1133 1164 WMAX_THERMAL_MODE_GMODE; 1134 1165 1135 - set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices); 1166 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1136 1167 } 1137 1168 1138 - pp_handler.profile_get = thermal_profile_get; 1139 - pp_handler.profile_set = thermal_profile_set; 1140 - 1141 - return platform_profile_register(&pp_handler); 1169 + return 0; 1142 1170 } 1143 1171 1144 - static void remove_thermal_profile(void) 1172 + static const struct platform_profile_ops awcc_platform_profile_ops = { 1173 + .probe = thermal_profile_probe, 1174 + .profile_get = thermal_profile_get, 1175 + .profile_set = thermal_profile_set, 1176 + }; 1177 + 1178 + static int create_thermal_profile(struct platform_device *platform_device) 1145 1179 { 1146 - if (quirks->thermal) 1147 - platform_profile_remove(); 1180 + struct device *ppdev; 1181 + 1182 + ppdev = devm_platform_profile_register(&platform_device->dev, "alienware-wmi", 1183 + NULL, &awcc_platform_profile_ops); 1184 + 1185 + return PTR_ERR_OR_ZERO(ppdev); 1148 1186 } 1187 + 1188 + /* 1189 + * Platform Driver 1190 + */ 1191 + static const struct attribute_group *alienfx_groups[] = { 1192 + &zone_attribute_group, 1193 + &hdmi_attribute_group, 1194 + &amplifier_attribute_group, 1195 + &deepsleep_attribute_group, 1196 + NULL 1197 + }; 1198 + 1199 + static struct platform_driver platform_driver = { 1200 + .driver = { 1201 + .name = "alienware-wmi", 1202 + .dev_groups = alienfx_groups, 1203 + }, 1204 + }; 1149 1205 1150 1206 static int __init alienware_wmi_init(void) 1151 1207 { ··· 1211 1217 if (ret) 1212 1218 goto fail_platform_device2; 1213 1219 1214 - if (quirks->hdmi_mux > 0) { 1215 - ret = create_hdmi(platform_device); 1216 - if (ret) 1217 - goto fail_prep_hdmi; 1218 - } 1219 - 1220 - if (quirks->amplifier > 0) { 1221 - ret = create_amplifier(platform_device); 1222 - if (ret) 1223 - goto fail_prep_amplifier; 1224 - } 1225 - 1226 - if (quirks->deepslp > 0) { 1227 - ret = create_deepsleep(platform_device); 1228 - if (ret) 1229 - goto fail_prep_deepsleep; 1230 - } 1231 - 1232 1220 if (quirks->thermal) { 1233 - ret = create_thermal_profile(); 1221 + ret = create_thermal_profile(platform_device); 1234 1222 if (ret) 1235 1223 goto fail_prep_thermal_profile; 1236 1224 } ··· 1227 1251 1228 1252 fail_prep_zones: 1229 1253 alienware_zone_exit(platform_device); 1230 - remove_thermal_profile(); 1231 1254 fail_prep_thermal_profile: 1232 - fail_prep_deepsleep: 1233 - fail_prep_amplifier: 1234 - fail_prep_hdmi: 1235 1255 platform_device_del(platform_device); 1236 1256 fail_platform_device2: 1237 1257 platform_device_put(platform_device); ··· 1241 1269 1242 1270 static void __exit alienware_wmi_exit(void) 1243 1271 { 1244 - if (platform_device) { 1245 - alienware_zone_exit(platform_device); 1246 - remove_hdmi(platform_device); 1247 - remove_thermal_profile(); 1248 - platform_device_unregister(platform_device); 1249 - platform_driver_unregister(&platform_driver); 1250 - } 1272 + alienware_zone_exit(platform_device); 1273 + platform_device_unregister(platform_device); 1274 + platform_driver_unregister(&platform_driver); 1251 1275 } 1252 1276 1253 1277 module_exit(alienware_wmi_exit);
+5 -5
drivers/platform/x86/dell/dcdbas.c
··· 163 163 } 164 164 165 165 static ssize_t smi_data_read(struct file *filp, struct kobject *kobj, 166 - struct bin_attribute *bin_attr, 166 + const struct bin_attribute *bin_attr, 167 167 char *buf, loff_t pos, size_t count) 168 168 { 169 169 ssize_t ret; ··· 176 176 } 177 177 178 178 static ssize_t smi_data_write(struct file *filp, struct kobject *kobj, 179 - struct bin_attribute *bin_attr, 179 + const struct bin_attribute *bin_attr, 180 180 char *buf, loff_t pos, size_t count) 181 181 { 182 182 ssize_t ret; ··· 636 636 .priority = INT_MIN 637 637 }; 638 638 639 - static DCDBAS_BIN_ATTR_RW(smi_data); 639 + static const BIN_ATTR_ADMIN_RW(smi_data, 0); 640 640 641 - static struct bin_attribute *dcdbas_bin_attrs[] = { 641 + static const struct bin_attribute *const dcdbas_bin_attrs[] = { 642 642 &bin_attr_smi_data, 643 643 NULL 644 644 }; ··· 662 662 663 663 static const struct attribute_group dcdbas_attr_group = { 664 664 .attrs = dcdbas_dev_attrs, 665 - .bin_attrs = dcdbas_bin_attrs, 665 + .bin_attrs_new = dcdbas_bin_attrs, 666 666 }; 667 667 668 668 static int dcdbas_probe(struct platform_device *dev)
-8
drivers/platform/x86/dell/dcdbas.h
··· 56 56 #define DCDBAS_DEV_ATTR_WO(_name) \ 57 57 DEVICE_ATTR(_name,0200,NULL,_name##_store); 58 58 59 - #define DCDBAS_BIN_ATTR_RW(_name) \ 60 - struct bin_attribute bin_attr_##_name = { \ 61 - .attr = { .name = __stringify(_name), \ 62 - .mode = 0600 }, \ 63 - .read = _name##_read, \ 64 - .write = _name##_write, \ 65 - } 66 - 67 59 struct smi_cmd { 68 60 __u32 magic; 69 61 __u32 ebx;
+3 -3
drivers/platform/x86/dell/dell-laptop.c
··· 725 725 } 726 726 static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); 727 727 728 - static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, 729 - struct serio *port) 728 + static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, struct serio *port, 729 + void *context) 730 730 { 731 731 static bool extended; 732 732 ··· 884 884 pr_warn("Unable to register dell rbtn notifier\n"); 885 885 goto err_filter; 886 886 } else { 887 - ret = i8042_install_filter(dell_laptop_i8042_filter); 887 + ret = i8042_install_filter(dell_laptop_i8042_filter, NULL); 888 888 if (ret) { 889 889 pr_warn("Unable to install key filter\n"); 890 890 goto err_filter;
+256
drivers/platform/x86/dell/dell-lis3lv02d.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * lis3lv02d i2c-client instantiation for ACPI SMO88xx devices without I2C resources. 4 + * 5 + * Copyright (C) 2024 Hans de Goede <hansg@kernel.org> 6 + */ 7 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 + 9 + #include <linux/device/bus.h> 10 + #include <linux/dmi.h> 11 + #include <linux/i2c.h> 12 + #include <linux/module.h> 13 + #include <linux/notifier.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/workqueue.h> 16 + #include "dell-smo8800-ids.h" 17 + 18 + #define LIS3_WHO_AM_I 0x0f 19 + 20 + #define DELL_LIS3LV02D_DMI_ENTRY(product_name, i2c_addr) \ 21 + { \ 22 + .matches = { \ 23 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), \ 24 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, product_name), \ 25 + }, \ 26 + .driver_data = (void *)(uintptr_t)(i2c_addr), \ 27 + } 28 + 29 + /* 30 + * Accelerometer's I2C address is not specified in DMI nor ACPI, 31 + * so it is needed to define mapping table based on DMI product names. 32 + */ 33 + static const struct dmi_system_id lis3lv02d_devices[] __initconst = { 34 + /* 35 + * Dell platform team told us that these Latitude devices have 36 + * ST microelectronics accelerometer at I2C address 0x29. 37 + */ 38 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E5250", 0x29), 39 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E5450", 0x29), 40 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E5550", 0x29), 41 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E6440", 0x29), 42 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E6440 ATG", 0x29), 43 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E6540", 0x29), 44 + /* 45 + * Additional individual entries were added after verification. 46 + */ 47 + DELL_LIS3LV02D_DMI_ENTRY("Latitude 5480", 0x29), 48 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E6330", 0x29), 49 + DELL_LIS3LV02D_DMI_ENTRY("Latitude E6430", 0x29), 50 + DELL_LIS3LV02D_DMI_ENTRY("Precision 3540", 0x29), 51 + DELL_LIS3LV02D_DMI_ENTRY("Precision M6800", 0x29), 52 + DELL_LIS3LV02D_DMI_ENTRY("Vostro V131", 0x1d), 53 + DELL_LIS3LV02D_DMI_ENTRY("Vostro 5568", 0x29), 54 + DELL_LIS3LV02D_DMI_ENTRY("XPS 15 7590", 0x29), 55 + DELL_LIS3LV02D_DMI_ENTRY("XPS 15 9550", 0x29), 56 + { } 57 + }; 58 + 59 + static u8 i2c_addr; 60 + static struct i2c_client *i2c_dev; 61 + static bool notifier_registered; 62 + 63 + static bool probe_i2c_addr; 64 + module_param(probe_i2c_addr, bool, 0444); 65 + MODULE_PARM_DESC(probe_i2c_addr, "Probe the i801 I2C bus for the accelerometer on models where the address is unknown, this may be dangerous."); 66 + 67 + static int detect_lis3lv02d(struct i2c_adapter *adap, unsigned short addr) 68 + { 69 + union i2c_smbus_data smbus_data; 70 + int err; 71 + 72 + dev_info(&adap->dev, "Probing for lis3lv02d on address 0x%02x\n", addr); 73 + 74 + err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, LIS3_WHO_AM_I, 75 + I2C_SMBUS_BYTE_DATA, &smbus_data); 76 + if (err < 0) 77 + return 0; /* Not found */ 78 + 79 + /* valid who-am-i values are from drivers/misc/lis3lv02d/lis3lv02d.c */ 80 + switch (smbus_data.byte) { 81 + case 0x32: 82 + case 0x33: 83 + case 0x3a: 84 + case 0x3b: 85 + break; 86 + default: 87 + dev_warn(&adap->dev, "Unknown who-am-i register value 0x%02x\n", 88 + smbus_data.byte); 89 + return 0; /* Not found */ 90 + } 91 + 92 + dev_info(&adap->dev, 93 + "Detected lis3lv02d on address 0x%02x, please report this upstream to platform-driver-x86@vger.kernel.org so that a quirk can be added\n", 94 + addr); 95 + 96 + return 1; /* Found */ 97 + } 98 + 99 + static bool i2c_adapter_is_main_i801(struct i2c_adapter *adap) 100 + { 101 + /* 102 + * Only match the main I801 adapter and reject secondary adapters 103 + * which names start with "SMBus I801 IDF adapter". 104 + */ 105 + return strstarts(adap->name, "SMBus I801 adapter"); 106 + } 107 + 108 + static int find_i801(struct device *dev, void *data) 109 + { 110 + struct i2c_adapter *adap, **adap_ret = data; 111 + 112 + adap = i2c_verify_adapter(dev); 113 + if (!adap) 114 + return 0; 115 + 116 + if (!i2c_adapter_is_main_i801(adap)) 117 + return 0; 118 + 119 + *adap_ret = i2c_get_adapter(adap->nr); 120 + return 1; 121 + } 122 + 123 + static void instantiate_i2c_client(struct work_struct *work) 124 + { 125 + struct i2c_board_info info = { }; 126 + struct i2c_adapter *adap = NULL; 127 + 128 + if (i2c_dev) 129 + return; 130 + 131 + /* 132 + * bus_for_each_dev() and not i2c_for_each_dev() to avoid 133 + * a deadlock when find_i801() calls i2c_get_adapter(). 134 + */ 135 + bus_for_each_dev(&i2c_bus_type, NULL, &adap, find_i801); 136 + if (!adap) 137 + return; 138 + 139 + strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); 140 + 141 + if (i2c_addr) { 142 + info.addr = i2c_addr; 143 + i2c_dev = i2c_new_client_device(adap, &info); 144 + } else { 145 + /* First try address 0x29 (most used) and then try 0x1d */ 146 + static const unsigned short addr_list[] = { 0x29, 0x1d, I2C_CLIENT_END }; 147 + 148 + i2c_dev = i2c_new_scanned_device(adap, &info, addr_list, detect_lis3lv02d); 149 + } 150 + 151 + if (IS_ERR(i2c_dev)) { 152 + dev_err(&adap->dev, "error %ld registering i2c_client\n", PTR_ERR(i2c_dev)); 153 + i2c_dev = NULL; 154 + } else { 155 + dev_dbg(&adap->dev, "registered lis3lv02d on address 0x%02x\n", info.addr); 156 + } 157 + 158 + i2c_put_adapter(adap); 159 + } 160 + static DECLARE_WORK(i2c_work, instantiate_i2c_client); 161 + 162 + static int i2c_bus_notify(struct notifier_block *nb, unsigned long action, void *data) 163 + { 164 + struct device *dev = data; 165 + struct i2c_client *client; 166 + struct i2c_adapter *adap; 167 + 168 + switch (action) { 169 + case BUS_NOTIFY_ADD_DEVICE: 170 + adap = i2c_verify_adapter(dev); 171 + if (!adap) 172 + break; 173 + 174 + if (i2c_adapter_is_main_i801(adap)) 175 + queue_work(system_long_wq, &i2c_work); 176 + break; 177 + case BUS_NOTIFY_REMOVED_DEVICE: 178 + client = i2c_verify_client(dev); 179 + if (!client) 180 + break; 181 + 182 + if (i2c_dev == client) { 183 + dev_dbg(&client->adapter->dev, "lis3lv02d i2c_client removed\n"); 184 + i2c_dev = NULL; 185 + } 186 + break; 187 + default: 188 + break; 189 + } 190 + 191 + return 0; 192 + } 193 + static struct notifier_block i2c_nb = { .notifier_call = i2c_bus_notify }; 194 + 195 + static int __init match_acpi_device_ids(struct device *dev, const void *data) 196 + { 197 + return acpi_match_device(data, dev) ? 1 : 0; 198 + } 199 + 200 + static int __init dell_lis3lv02d_init(void) 201 + { 202 + const struct dmi_system_id *lis3lv02d_dmi_id; 203 + struct device *dev; 204 + int err; 205 + 206 + /* 207 + * First check for a matching platform_device. This protects against 208 + * SMO88xx ACPI fwnodes which actually do have an I2C resource, which 209 + * will already have an i2c_client instantiated (not a platform_device). 210 + */ 211 + dev = bus_find_device(&platform_bus_type, NULL, smo8800_ids, match_acpi_device_ids); 212 + if (!dev) { 213 + pr_debug("No SMO88xx platform-device found\n"); 214 + return 0; 215 + } 216 + put_device(dev); 217 + 218 + lis3lv02d_dmi_id = dmi_first_match(lis3lv02d_devices); 219 + if (!lis3lv02d_dmi_id && !probe_i2c_addr) { 220 + pr_warn("accelerometer is present on SMBus but its address is unknown, skipping registration\n"); 221 + pr_info("Pass dell_lis3lv02d.probe_i2c_addr=1 on the kernel command line to probe, this may be dangerous!\n"); 222 + return 0; 223 + } 224 + 225 + if (lis3lv02d_dmi_id) 226 + i2c_addr = (long)lis3lv02d_dmi_id->driver_data; 227 + 228 + /* 229 + * Register i2c-bus notifier + queue initial scan for lis3lv02d 230 + * i2c_client instantiation. 231 + */ 232 + err = bus_register_notifier(&i2c_bus_type, &i2c_nb); 233 + if (err) 234 + return err; 235 + 236 + notifier_registered = true; 237 + 238 + queue_work(system_long_wq, &i2c_work); 239 + return 0; 240 + } 241 + module_init(dell_lis3lv02d_init); 242 + 243 + static void __exit dell_lis3lv02d_module_exit(void) 244 + { 245 + if (!notifier_registered) 246 + return; 247 + 248 + bus_unregister_notifier(&i2c_bus_type, &i2c_nb); 249 + cancel_work_sync(&i2c_work); 250 + i2c_unregister_device(i2c_dev); 251 + } 252 + module_exit(dell_lis3lv02d_module_exit); 253 + 254 + MODULE_DESCRIPTION("lis3lv02d i2c-client instantiation for ACPI SMO88xx devices"); 255 + MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 256 + MODULE_LICENSE("GPL");
+41 -28
drivers/platform/x86/dell/dell-pc.c
··· 18 18 #include <linux/kernel.h> 19 19 #include <linux/module.h> 20 20 #include <linux/platform_profile.h> 21 + #include <linux/platform_device.h> 21 22 #include <linux/slab.h> 22 23 23 24 #include "dell-smbios.h" 25 + 26 + static struct platform_device *platform_device; 27 + static int supported_modes; 24 28 25 29 static const struct dmi_system_id dell_device_table[] __initconst = { 26 30 { ··· 109 105 #define DELL_ACC_SET_FIELD GENMASK(11, 8) 110 106 #define DELL_THERMAL_SUPPORTED GENMASK(3, 0) 111 107 112 - static struct platform_profile_handler *thermal_handler; 113 - 114 108 enum thermal_mode_bits { 115 109 DELL_BALANCED = BIT(0), 116 110 DELL_COOL_BOTTOM = BIT(1), ··· 184 182 return dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT); 185 183 } 186 184 187 - static int thermal_platform_profile_set(struct platform_profile_handler *pprof, 185 + static int thermal_platform_profile_set(struct device *dev, 188 186 enum platform_profile_option profile) 189 187 { 190 188 switch (profile) { ··· 201 199 } 202 200 } 203 201 204 - static int thermal_platform_profile_get(struct platform_profile_handler *pprof, 202 + static int thermal_platform_profile_get(struct device *dev, 205 203 enum platform_profile_option *profile) 206 204 { 207 205 int ret; ··· 230 228 return 0; 231 229 } 232 230 231 + static int thermal_platform_profile_probe(void *drvdata, unsigned long *choices) 232 + { 233 + if (supported_modes & DELL_QUIET) 234 + set_bit(PLATFORM_PROFILE_QUIET, choices); 235 + if (supported_modes & DELL_COOL_BOTTOM) 236 + set_bit(PLATFORM_PROFILE_COOL, choices); 237 + if (supported_modes & DELL_BALANCED) 238 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 239 + if (supported_modes & DELL_PERFORMANCE) 240 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 241 + 242 + return 0; 243 + } 244 + 245 + static const struct platform_profile_ops dell_pc_platform_profile_ops = { 246 + .probe = thermal_platform_profile_probe, 247 + .profile_get = thermal_platform_profile_get, 248 + .profile_set = thermal_platform_profile_set, 249 + }; 250 + 233 251 static int thermal_init(void) 234 252 { 253 + struct device *ppdev; 235 254 int ret; 236 - int supported_modes; 237 255 238 256 /* If thermal commands are not supported, exit without error */ 239 257 if (!dell_smbios_class_is_supported(CLASS_INFO)) ··· 266 244 if (!supported_modes) 267 245 return 0; 268 246 269 - thermal_handler = kzalloc(sizeof(*thermal_handler), GFP_KERNEL); 270 - if (!thermal_handler) 271 - return -ENOMEM; 272 - thermal_handler->profile_get = thermal_platform_profile_get; 273 - thermal_handler->profile_set = thermal_platform_profile_set; 247 + platform_device = platform_device_register_simple("dell-pc", PLATFORM_DEVID_NONE, NULL, 0); 248 + if (IS_ERR(platform_device)) 249 + return PTR_ERR(platform_device); 274 250 275 - if (supported_modes & DELL_QUIET) 276 - set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices); 277 - if (supported_modes & DELL_COOL_BOTTOM) 278 - set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices); 279 - if (supported_modes & DELL_BALANCED) 280 - set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices); 281 - if (supported_modes & DELL_PERFORMANCE) 282 - set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices); 283 - 284 - /* Clean up if failed */ 285 - ret = platform_profile_register(thermal_handler); 286 - if (ret) { 287 - kfree(thermal_handler); 288 - thermal_handler = NULL; 251 + ppdev = devm_platform_profile_register(&platform_device->dev, "dell-pc", 252 + NULL, &dell_pc_platform_profile_ops); 253 + if (IS_ERR(ppdev)) { 254 + ret = PTR_ERR(ppdev); 255 + goto cleanup_platform_device; 289 256 } 257 + 258 + return 0; 259 + 260 + cleanup_platform_device: 261 + platform_device_unregister(platform_device); 290 262 291 263 return ret; 292 264 } 293 265 294 266 static void thermal_cleanup(void) 295 267 { 296 - if (thermal_handler) { 297 - platform_profile_remove(); 298 - kfree(thermal_handler); 299 - } 268 + platform_device_unregister(platform_device); 300 269 } 301 270 302 271 static int __init dell_init(void)
+27
drivers/platform/x86/dell/dell-smo8800-ids.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * ACPI SMO88XX lis3lv02d freefall / accelerometer device-ids. 4 + * 5 + * Copyright (C) 2012 Sonal Santan <sonal.santan@gmail.com> 6 + * Copyright (C) 2014 Pali Rohár <pali@kernel.org> 7 + */ 8 + #ifndef _DELL_SMO8800_IDS_H_ 9 + #define _DELL_SMO8800_IDS_H_ 10 + 11 + #include <linux/mod_devicetable.h> 12 + #include <linux/module.h> 13 + 14 + static const struct acpi_device_id smo8800_ids[] = { 15 + { "SMO8800" }, 16 + { "SMO8801" }, 17 + { "SMO8810" }, 18 + { "SMO8811" }, 19 + { "SMO8820" }, 20 + { "SMO8821" }, 21 + { "SMO8830" }, 22 + { "SMO8831" }, 23 + { } 24 + }; 25 + MODULE_DEVICE_TABLE(acpi, smo8800_ids); 26 + 27 + #endif
+1 -15
drivers/platform/x86/dell/dell-smo8800.c
··· 14 14 #include <linux/interrupt.h> 15 15 #include <linux/kernel.h> 16 16 #include <linux/miscdevice.h> 17 - #include <linux/mod_devicetable.h> 18 17 #include <linux/module.h> 19 18 #include <linux/platform_device.h> 20 19 #include <linux/uaccess.h> 20 + #include "dell-smo8800-ids.h" 21 21 22 22 struct smo8800_device { 23 23 u32 irq; /* acpi device irq */ ··· 162 162 misc_deregister(&smo8800->miscdev); 163 163 dev_dbg(&device->dev, "device /dev/freefall unregistered\n"); 164 164 } 165 - 166 - /* NOTE: Keep this list in sync with drivers/i2c/busses/i2c-i801.c */ 167 - static const struct acpi_device_id smo8800_ids[] = { 168 - { "SMO8800", 0 }, 169 - { "SMO8801", 0 }, 170 - { "SMO8810", 0 }, 171 - { "SMO8811", 0 }, 172 - { "SMO8820", 0 }, 173 - { "SMO8821", 0 }, 174 - { "SMO8830", 0 }, 175 - { "SMO8831", 0 }, 176 - { "", 0 }, 177 - }; 178 - MODULE_DEVICE_TABLE(acpi, smo8800_ids); 179 165 180 166 static struct platform_driver smo8800_driver = { 181 167 .probe = smo8800_probe,
+1 -1
drivers/platform/x86/dell/dell-uart-backlight.c
··· 159 159 160 160 set_power[0] = DELL_SOF(SET_CMD_LEN); 161 161 set_power[1] = CMD_SET_BL_POWER; 162 - set_power[2] = (power == FB_BLANK_UNBLANK) ? 1 : 0; 162 + set_power[2] = (power == BACKLIGHT_POWER_ON) ? 1 : 0; 163 163 set_power[3] = dell_uart_checksum(set_power, 3); 164 164 165 165 ret = dell_uart_bl_command(dell_bl, set_power, SET_CMD_LEN, resp, SET_RESP_LEN);
+4 -13
drivers/platform/x86/dell/dell-wmi-sysman/sysman.c
··· 25 25 /* reset bios to defaults */ 26 26 static const char * const reset_types[] = {"builtinsafe", "lastknowngood", "factory", "custom"}; 27 27 static int reset_option = -1; 28 - static const struct class *fw_attr_class; 29 28 30 29 31 30 /** ··· 540 541 goto err_exit_bios_attr_pass_interface; 541 542 } 542 543 543 - ret = fw_attributes_class_get(&fw_attr_class); 544 - if (ret) 545 - goto err_exit_bios_attr_pass_interface; 546 - 547 - wmi_priv.class_dev = device_create(fw_attr_class, NULL, MKDEV(0, 0), 544 + wmi_priv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), 548 545 NULL, "%s", DRIVER_NAME); 549 546 if (IS_ERR(wmi_priv.class_dev)) { 550 547 ret = PTR_ERR(wmi_priv.class_dev); 551 - goto err_unregister_class; 548 + goto err_exit_bios_attr_pass_interface; 552 549 } 553 550 554 551 wmi_priv.main_dir_kset = kset_create_and_add("attributes", NULL, ··· 597 602 release_attributes_data(); 598 603 599 604 err_destroy_classdev: 600 - device_destroy(fw_attr_class, MKDEV(0, 0)); 601 - 602 - err_unregister_class: 603 - fw_attributes_class_put(); 605 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 604 606 605 607 err_exit_bios_attr_pass_interface: 606 608 exit_bios_attr_pass_interface(); ··· 611 619 static void __exit sysman_exit(void) 612 620 { 613 621 release_attributes_data(); 614 - device_destroy(fw_attr_class, MKDEV(0, 0)); 615 - fw_attributes_class_put(); 622 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 616 623 exit_bios_attr_set_interface(); 617 624 exit_bios_attr_pass_interface(); 618 625 }
+10 -10
drivers/platform/x86/dell/dell_rbu.c
··· 475 475 } 476 476 477 477 static ssize_t data_read(struct file *filp, struct kobject *kobj, 478 - struct bin_attribute *bin_attr, 478 + const struct bin_attribute *bin_attr, 479 479 char *buffer, loff_t pos, size_t count) 480 480 { 481 481 ssize_t ret_count = 0; ··· 492 492 spin_unlock(&rbu_data.lock); 493 493 return ret_count; 494 494 } 495 - static BIN_ATTR_RO(data, 0); 495 + static const BIN_ATTR_RO(data, 0); 496 496 497 497 static void callbackfn_rbu(const struct firmware *fw, void *context) 498 498 { ··· 530 530 } 531 531 532 532 static ssize_t image_type_read(struct file *filp, struct kobject *kobj, 533 - struct bin_attribute *bin_attr, 533 + const struct bin_attribute *bin_attr, 534 534 char *buffer, loff_t pos, size_t count) 535 535 { 536 536 int size = 0; ··· 540 540 } 541 541 542 542 static ssize_t image_type_write(struct file *filp, struct kobject *kobj, 543 - struct bin_attribute *bin_attr, 543 + const struct bin_attribute *bin_attr, 544 544 char *buffer, loff_t pos, size_t count) 545 545 { 546 546 int rc = count; ··· 597 597 598 598 return rc; 599 599 } 600 - static BIN_ATTR_RW(image_type, 0); 600 + static const BIN_ATTR_RW(image_type, 0); 601 601 602 602 static ssize_t packet_size_read(struct file *filp, struct kobject *kobj, 603 - struct bin_attribute *bin_attr, 603 + const struct bin_attribute *bin_attr, 604 604 char *buffer, loff_t pos, size_t count) 605 605 { 606 606 int size = 0; ··· 613 613 } 614 614 615 615 static ssize_t packet_size_write(struct file *filp, struct kobject *kobj, 616 - struct bin_attribute *bin_attr, 616 + const struct bin_attribute *bin_attr, 617 617 char *buffer, loff_t pos, size_t count) 618 618 { 619 619 unsigned long temp; ··· 626 626 spin_unlock(&rbu_data.lock); 627 627 return count; 628 628 } 629 - static BIN_ATTR_RW(packet_size, 0); 629 + static const BIN_ATTR_RW(packet_size, 0); 630 630 631 - static struct bin_attribute *rbu_bin_attrs[] = { 631 + static const struct bin_attribute *const rbu_bin_attrs[] = { 632 632 &bin_attr_data, 633 633 &bin_attr_image_type, 634 634 &bin_attr_packet_size, ··· 636 636 }; 637 637 638 638 static const struct attribute_group rbu_group = { 639 - .bin_attrs = rbu_bin_attrs, 639 + .bin_attrs_new = rbu_bin_attrs, 640 640 }; 641 641 642 642 static int __init dcdrbu_init(void)
+8 -34
drivers/platform/x86/firmware_attributes_class.c
··· 2 2 3 3 /* Firmware attributes class helper module */ 4 4 5 - #include <linux/mutex.h> 6 - #include <linux/device/class.h> 7 5 #include <linux/module.h> 8 6 #include "firmware_attributes_class.h" 9 7 10 - static DEFINE_MUTEX(fw_attr_lock); 11 - static int fw_attr_inuse; 12 - 13 - static const struct class firmware_attributes_class = { 8 + const struct class firmware_attributes_class = { 14 9 .name = "firmware-attributes", 15 10 }; 11 + EXPORT_SYMBOL_GPL(firmware_attributes_class); 16 12 17 - int fw_attributes_class_get(const struct class **fw_attr_class) 13 + static __init int fw_attributes_class_init(void) 18 14 { 19 - int err; 20 - 21 - mutex_lock(&fw_attr_lock); 22 - if (!fw_attr_inuse) { /*first time class is being used*/ 23 - err = class_register(&firmware_attributes_class); 24 - if (err) { 25 - mutex_unlock(&fw_attr_lock); 26 - return err; 27 - } 28 - } 29 - fw_attr_inuse++; 30 - *fw_attr_class = &firmware_attributes_class; 31 - mutex_unlock(&fw_attr_lock); 32 - return 0; 15 + return class_register(&firmware_attributes_class); 33 16 } 34 - EXPORT_SYMBOL_GPL(fw_attributes_class_get); 17 + module_init(fw_attributes_class_init); 35 18 36 - int fw_attributes_class_put(void) 19 + static __exit void fw_attributes_class_exit(void) 37 20 { 38 - mutex_lock(&fw_attr_lock); 39 - if (!fw_attr_inuse) { 40 - mutex_unlock(&fw_attr_lock); 41 - return -EINVAL; 42 - } 43 - fw_attr_inuse--; 44 - if (!fw_attr_inuse) /* No more consumers */ 45 - class_unregister(&firmware_attributes_class); 46 - mutex_unlock(&fw_attr_lock); 47 - return 0; 21 + class_unregister(&firmware_attributes_class); 48 22 } 49 - EXPORT_SYMBOL_GPL(fw_attributes_class_put); 23 + module_exit(fw_attributes_class_exit); 50 24 51 25 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); 52 26 MODULE_DESCRIPTION("Firmware attributes class helper module");
+3 -2
drivers/platform/x86/firmware_attributes_class.h
··· 5 5 #ifndef FW_ATTR_CLASS_H 6 6 #define FW_ATTR_CLASS_H 7 7 8 - int fw_attributes_class_get(const struct class **fw_attr_class); 9 - int fw_attributes_class_put(void); 8 + #include <linux/device/class.h> 9 + 10 + extern const struct class firmware_attributes_class; 10 11 11 12 #endif /* FW_ATTR_CLASS_H */
+4 -4
drivers/platform/x86/fujitsu-laptop.c
··· 505 505 return -ENOMEM; 506 506 507 507 fujitsu_bl = priv; 508 - strcpy(acpi_device_name(device), ACPI_FUJITSU_BL_DEVICE_NAME); 509 - strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); 508 + strscpy(acpi_device_name(device), ACPI_FUJITSU_BL_DEVICE_NAME); 509 + strscpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); 510 510 device->driver_data = priv; 511 511 512 512 pr_info("ACPI: %s [%s]\n", ··· 891 891 WARN_ONCE(fext, "More than one FUJ02E3 ACPI device was found. Driver may not work as intended."); 892 892 fext = device; 893 893 894 - strcpy(acpi_device_name(device), ACPI_FUJITSU_LAPTOP_DEVICE_NAME); 895 - strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); 894 + strscpy(acpi_device_name(device), ACPI_FUJITSU_LAPTOP_DEVICE_NAME); 895 + strscpy(acpi_device_class(device), ACPI_FUJITSU_CLASS); 896 896 device->driver_data = priv; 897 897 898 898 /* kfifo */
+3 -11
drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
··· 24 24 .mutex = __MUTEX_INITIALIZER(bioscfg_drv.mutex), 25 25 }; 26 26 27 - static const struct class *fw_attr_class; 28 - 29 27 ssize_t display_name_language_code_show(struct kobject *kobj, 30 28 struct kobj_attribute *attr, 31 29 char *buf) ··· 970 972 if (ret) 971 973 return ret; 972 974 973 - ret = fw_attributes_class_get(&fw_attr_class); 974 - if (ret) 975 - goto err_unregister_class; 976 - 977 - bioscfg_drv.class_dev = device_create(fw_attr_class, NULL, MKDEV(0, 0), 975 + bioscfg_drv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), 978 976 NULL, "%s", DRIVER_NAME); 979 977 if (IS_ERR(bioscfg_drv.class_dev)) { 980 978 ret = PTR_ERR(bioscfg_drv.class_dev); ··· 1037 1043 release_attributes_data(); 1038 1044 1039 1045 err_destroy_classdev: 1040 - device_destroy(fw_attr_class, MKDEV(0, 0)); 1046 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 1041 1047 1042 1048 err_unregister_class: 1043 - fw_attributes_class_put(); 1044 1049 hp_exit_attr_set_interface(); 1045 1050 1046 1051 return ret; ··· 1048 1055 static void __exit hp_exit(void) 1049 1056 { 1050 1057 release_attributes_data(); 1051 - device_destroy(fw_attr_class, MKDEV(0, 0)); 1058 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 1052 1059 1053 - fw_attributes_class_put(); 1054 1060 hp_exit_attr_set_interface(); 1055 1061 } 1056 1062
+407 -42
drivers/platform/x86/hp/hp-wmi.c
··· 45 45 #define HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET 0x63 46 46 #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95 47 47 48 + #define HP_FAN_SPEED_AUTOMATIC 0x00 49 + #define HP_POWER_LIMIT_DEFAULT 0x00 50 + #define HP_POWER_LIMIT_NO_CHANGE 0xFF 51 + 48 52 #define ACPI_AC_CLASS "ac_adapter" 49 53 50 54 #define zero_if_sup(tmp) (zero_insize_support?0:sizeof(tmp)) // use when zero insize is required ··· 87 83 "8BAD", "8A42", "8A15" 88 84 }; 89 85 90 - /* DMI Board names of Victus laptops */ 86 + /* DMI Board names of Victus 16-d1xxx laptops */ 91 87 static const char * const victus_thermal_profile_boards[] = { 92 88 "8A25" 89 + }; 90 + 91 + /* DMI Board names of Victus 16-s1000 laptops */ 92 + static const char * const victus_s_thermal_profile_boards[] = { 93 + "8C9C" 93 94 }; 94 95 95 96 enum hp_wmi_radio { ··· 156 147 HPWMI_THERMAL_PROFILE_QUERY = 0x4c, 157 148 }; 158 149 150 + struct victus_power_limits { 151 + u8 pl1; 152 + u8 pl2; 153 + u8 pl4; 154 + u8 cpu_gpu_concurrent_limit; 155 + }; 156 + 157 + struct victus_gpu_power_modes { 158 + u8 ctgp_enable; 159 + u8 ppab_enable; 160 + u8 dstate; 161 + u8 gpu_slowdown_temp; 162 + }; 163 + 159 164 enum hp_wmi_gm_commandtype { 160 - HPWMI_FAN_SPEED_GET_QUERY = 0x11, 161 - HPWMI_SET_PERFORMANCE_MODE = 0x1A, 162 - HPWMI_FAN_SPEED_MAX_GET_QUERY = 0x26, 163 - HPWMI_FAN_SPEED_MAX_SET_QUERY = 0x27, 164 - HPWMI_GET_SYSTEM_DESIGN_DATA = 0x28, 165 + HPWMI_FAN_SPEED_GET_QUERY = 0x11, 166 + HPWMI_SET_PERFORMANCE_MODE = 0x1A, 167 + HPWMI_FAN_SPEED_MAX_GET_QUERY = 0x26, 168 + HPWMI_FAN_SPEED_MAX_SET_QUERY = 0x27, 169 + HPWMI_GET_SYSTEM_DESIGN_DATA = 0x28, 170 + HPWMI_FAN_COUNT_GET_QUERY = 0x10, 171 + HPWMI_GET_GPU_THERMAL_MODES_QUERY = 0x21, 172 + HPWMI_SET_GPU_THERMAL_MODES_QUERY = 0x22, 173 + HPWMI_SET_POWER_LIMITS_QUERY = 0x29, 174 + HPWMI_VICTUS_S_FAN_SPEED_GET_QUERY = 0x2D, 175 + HPWMI_FAN_SPEED_SET_QUERY = 0x2E, 165 176 }; 166 177 167 178 enum hp_wmi_command { ··· 238 209 HP_VICTUS_THERMAL_PROFILE_DEFAULT = 0x00, 239 210 HP_VICTUS_THERMAL_PROFILE_PERFORMANCE = 0x01, 240 211 HP_VICTUS_THERMAL_PROFILE_QUIET = 0x03, 212 + }; 213 + 214 + enum hp_thermal_profile_victus_s { 215 + HP_VICTUS_S_THERMAL_PROFILE_DEFAULT = 0x00, 216 + HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE = 0x01, 241 217 }; 242 218 243 219 enum hp_thermal_profile { ··· 307 273 static struct input_dev *hp_wmi_input_dev; 308 274 static struct input_dev *camera_shutter_input_dev; 309 275 static struct platform_device *hp_wmi_platform_dev; 310 - static struct platform_profile_handler platform_profile_handler; 276 + static struct device *platform_profile_device; 311 277 static struct notifier_block platform_power_source_nb; 312 278 static enum platform_profile_option active_platform_profile; 313 279 static bool platform_profile_support; ··· 445 411 return ret; 446 412 } 447 413 414 + /* 415 + * Calling this hp_wmi_get_fan_count_userdefine_trigger function also enables 416 + * and/or maintains the laptop in user defined thermal and fan states, instead 417 + * of using a fallback state. After a 120 seconds timeout however, the laptop 418 + * goes back to its fallback state. 419 + */ 420 + static int hp_wmi_get_fan_count_userdefine_trigger(void) 421 + { 422 + u8 fan_data[4] = {}; 423 + int ret; 424 + 425 + ret = hp_wmi_perform_query(HPWMI_FAN_COUNT_GET_QUERY, HPWMI_GM, 426 + &fan_data, sizeof(u8), 427 + sizeof(fan_data)); 428 + if (ret != 0) 429 + return -EINVAL; 430 + 431 + return fan_data[0]; /* Others bytes aren't providing fan count */ 432 + } 433 + 448 434 static int hp_wmi_get_fan_speed(int fan) 449 435 { 450 436 u8 fsh, fsl; ··· 481 427 fsl = fan_data[3]; 482 428 483 429 return (fsh << 8) | fsl; 430 + } 431 + 432 + static int hp_wmi_get_fan_speed_victus_s(int fan) 433 + { 434 + u8 fan_data[128] = {}; 435 + int ret; 436 + 437 + if (fan < 0 || fan >= sizeof(fan_data)) 438 + return -EINVAL; 439 + 440 + ret = hp_wmi_perform_query(HPWMI_VICTUS_S_FAN_SPEED_GET_QUERY, 441 + HPWMI_GM, &fan_data, sizeof(u8), 442 + sizeof(fan_data)); 443 + if (ret != 0) 444 + return -EINVAL; 445 + 446 + return fan_data[fan] * 100; 484 447 } 485 448 486 449 static int hp_wmi_read_int(int query) ··· 626 555 return ret < 0 ? ret : -EINVAL; 627 556 628 557 return enabled; 558 + } 559 + 560 + static int hp_wmi_fan_speed_reset(void) 561 + { 562 + u8 fan_speed[2] = { HP_FAN_SPEED_AUTOMATIC, HP_FAN_SPEED_AUTOMATIC }; 563 + int ret; 564 + 565 + ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_SET_QUERY, HPWMI_GM, 566 + &fan_speed, sizeof(fan_speed), 0); 567 + 568 + return ret; 569 + } 570 + 571 + static int hp_wmi_fan_speed_max_reset(void) 572 + { 573 + int ret; 574 + 575 + ret = hp_wmi_fan_speed_max_set(0); 576 + if (ret) 577 + return ret; 578 + 579 + /* Disabling max fan speed on Victus s1xxx laptops needs a 2nd step: */ 580 + ret = hp_wmi_fan_speed_reset(); 581 + return ret; 629 582 } 630 583 631 584 static int hp_wmi_fan_speed_max_get(void) ··· 1316 1221 return 0; 1317 1222 } 1318 1223 1319 - static int platform_profile_omen_get(struct platform_profile_handler *pprof, 1224 + static int platform_profile_omen_get(struct device *dev, 1320 1225 enum platform_profile_option *profile) 1321 1226 { 1322 1227 /* ··· 1413 1318 return 0; 1414 1319 } 1415 1320 1416 - static int platform_profile_omen_set(struct platform_profile_handler *pprof, 1321 + static int platform_profile_omen_set(struct device *dev, 1417 1322 enum platform_profile_option profile) 1418 1323 { 1419 1324 int err; ··· 1440 1345 sizeof(thermal_profile), 0); 1441 1346 } 1442 1347 1443 - static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof, 1348 + static int hp_wmi_platform_profile_get(struct device *dev, 1444 1349 enum platform_profile_option *profile) 1445 1350 { 1446 1351 int tp; ··· 1469 1374 return 0; 1470 1375 } 1471 1376 1472 - static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof, 1377 + static int hp_wmi_platform_profile_set(struct device *dev, 1473 1378 enum platform_profile_option profile) 1474 1379 { 1475 1380 int err, tp; ··· 1535 1440 return 0; 1536 1441 } 1537 1442 1538 - static int platform_profile_victus_get(struct platform_profile_handler *pprof, 1443 + static int platform_profile_victus_get(struct device *dev, 1539 1444 enum platform_profile_option *profile) 1540 1445 { 1541 1446 /* Same behaviour as platform_profile_omen_get */ 1542 - return platform_profile_omen_get(pprof, profile); 1447 + return platform_profile_omen_get(dev, profile); 1543 1448 } 1544 1449 1545 1450 static int platform_profile_victus_set_ec(enum platform_profile_option profile) ··· 1567 1472 return 0; 1568 1473 } 1569 1474 1570 - static int platform_profile_victus_set(struct platform_profile_handler *pprof, 1475 + static bool is_victus_s_thermal_profile(void) 1476 + { 1477 + const char *board_name; 1478 + 1479 + board_name = dmi_get_system_info(DMI_BOARD_NAME); 1480 + if (!board_name) 1481 + return false; 1482 + 1483 + return match_string(victus_s_thermal_profile_boards, 1484 + ARRAY_SIZE(victus_s_thermal_profile_boards), 1485 + board_name) >= 0; 1486 + } 1487 + 1488 + static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable, 1489 + bool *ppab_enable, 1490 + u8 *dstate, 1491 + u8 *gpu_slowdown_temp) 1492 + { 1493 + struct victus_gpu_power_modes gpu_power_modes; 1494 + int ret; 1495 + 1496 + ret = hp_wmi_perform_query(HPWMI_GET_GPU_THERMAL_MODES_QUERY, HPWMI_GM, 1497 + &gpu_power_modes, sizeof(gpu_power_modes), 1498 + sizeof(gpu_power_modes)); 1499 + if (ret == 0) { 1500 + *ctgp_enable = gpu_power_modes.ctgp_enable ? true : false; 1501 + *ppab_enable = gpu_power_modes.ppab_enable ? true : false; 1502 + *dstate = gpu_power_modes.dstate; 1503 + *gpu_slowdown_temp = gpu_power_modes.gpu_slowdown_temp; 1504 + } 1505 + 1506 + return ret; 1507 + } 1508 + 1509 + static int victus_s_gpu_thermal_profile_set(bool ctgp_enable, 1510 + bool ppab_enable, 1511 + u8 dstate) 1512 + { 1513 + struct victus_gpu_power_modes gpu_power_modes; 1514 + int ret; 1515 + 1516 + bool current_ctgp_state, current_ppab_state; 1517 + u8 current_dstate, current_gpu_slowdown_temp; 1518 + 1519 + /* Retrieving GPU slowdown temperature, in order to keep it unchanged */ 1520 + ret = victus_s_gpu_thermal_profile_get(&current_ctgp_state, 1521 + &current_ppab_state, 1522 + &current_dstate, 1523 + &current_gpu_slowdown_temp); 1524 + if (ret < 0) { 1525 + pr_warn("GPU modes not updated, unable to get slowdown temp\n"); 1526 + return ret; 1527 + } 1528 + 1529 + gpu_power_modes.ctgp_enable = ctgp_enable ? 0x01 : 0x00; 1530 + gpu_power_modes.ppab_enable = ppab_enable ? 0x01 : 0x00; 1531 + gpu_power_modes.dstate = dstate; 1532 + gpu_power_modes.gpu_slowdown_temp = current_gpu_slowdown_temp; 1533 + 1534 + 1535 + ret = hp_wmi_perform_query(HPWMI_SET_GPU_THERMAL_MODES_QUERY, HPWMI_GM, 1536 + &gpu_power_modes, sizeof(gpu_power_modes), 0); 1537 + 1538 + return ret; 1539 + } 1540 + 1541 + /* Note: HP_POWER_LIMIT_DEFAULT can be used to restore default PL1 and PL2 */ 1542 + static int victus_s_set_cpu_pl1_pl2(u8 pl1, u8 pl2) 1543 + { 1544 + struct victus_power_limits power_limits; 1545 + int ret; 1546 + 1547 + /* We need to know both PL1 and PL2 values in order to check them */ 1548 + if (pl1 == HP_POWER_LIMIT_NO_CHANGE || pl2 == HP_POWER_LIMIT_NO_CHANGE) 1549 + return -EINVAL; 1550 + 1551 + /* PL2 is not supposed to be lower than PL1 */ 1552 + if (pl2 < pl1) 1553 + return -EINVAL; 1554 + 1555 + power_limits.pl1 = pl1; 1556 + power_limits.pl2 = pl2; 1557 + power_limits.pl4 = HP_POWER_LIMIT_NO_CHANGE; 1558 + power_limits.cpu_gpu_concurrent_limit = HP_POWER_LIMIT_NO_CHANGE; 1559 + 1560 + ret = hp_wmi_perform_query(HPWMI_SET_POWER_LIMITS_QUERY, HPWMI_GM, 1561 + &power_limits, sizeof(power_limits), 0); 1562 + 1563 + return ret; 1564 + } 1565 + 1566 + static int platform_profile_victus_s_set_ec(enum platform_profile_option profile) 1567 + { 1568 + bool gpu_ctgp_enable, gpu_ppab_enable; 1569 + u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */ 1570 + int err, tp; 1571 + 1572 + switch (profile) { 1573 + case PLATFORM_PROFILE_PERFORMANCE: 1574 + tp = HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE; 1575 + gpu_ctgp_enable = true; 1576 + gpu_ppab_enable = true; 1577 + gpu_dstate = 1; 1578 + break; 1579 + case PLATFORM_PROFILE_BALANCED: 1580 + tp = HP_VICTUS_S_THERMAL_PROFILE_DEFAULT; 1581 + gpu_ctgp_enable = false; 1582 + gpu_ppab_enable = true; 1583 + gpu_dstate = 1; 1584 + break; 1585 + case PLATFORM_PROFILE_LOW_POWER: 1586 + tp = HP_VICTUS_S_THERMAL_PROFILE_DEFAULT; 1587 + gpu_ctgp_enable = false; 1588 + gpu_ppab_enable = false; 1589 + gpu_dstate = 1; 1590 + break; 1591 + default: 1592 + return -EOPNOTSUPP; 1593 + } 1594 + 1595 + hp_wmi_get_fan_count_userdefine_trigger(); 1596 + 1597 + err = omen_thermal_profile_set(tp); 1598 + if (err < 0) { 1599 + pr_err("Failed to set platform profile %d: %d\n", profile, err); 1600 + return err; 1601 + } 1602 + 1603 + err = victus_s_gpu_thermal_profile_set(gpu_ctgp_enable, 1604 + gpu_ppab_enable, 1605 + gpu_dstate); 1606 + if (err < 0) { 1607 + pr_err("Failed to set GPU profile %d: %d\n", profile, err); 1608 + return err; 1609 + } 1610 + 1611 + return 0; 1612 + } 1613 + 1614 + static int platform_profile_victus_s_set(struct device *dev, 1615 + enum platform_profile_option profile) 1616 + { 1617 + int err; 1618 + 1619 + guard(mutex)(&active_platform_profile_lock); 1620 + 1621 + err = platform_profile_victus_s_set_ec(profile); 1622 + if (err < 0) 1623 + return err; 1624 + 1625 + active_platform_profile = profile; 1626 + 1627 + return 0; 1628 + } 1629 + 1630 + static int platform_profile_victus_set(struct device *dev, 1571 1631 enum platform_profile_option profile) 1572 1632 { 1573 1633 int err; ··· 1734 1484 return err; 1735 1485 1736 1486 active_platform_profile = profile; 1487 + 1488 + return 0; 1489 + } 1490 + 1491 + static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices) 1492 + { 1493 + if (is_omen_thermal_profile()) { 1494 + set_bit(PLATFORM_PROFILE_COOL, choices); 1495 + } else if (is_victus_thermal_profile()) { 1496 + set_bit(PLATFORM_PROFILE_QUIET, choices); 1497 + } else if (is_victus_s_thermal_profile()) { 1498 + /* Adding an equivalent to HP Omen software ECO mode: */ 1499 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 1500 + } else { 1501 + set_bit(PLATFORM_PROFILE_QUIET, choices); 1502 + set_bit(PLATFORM_PROFILE_COOL, choices); 1503 + } 1504 + 1505 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 1506 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1737 1507 1738 1508 return 0; 1739 1509 } ··· 1815 1545 return NOTIFY_OK; 1816 1546 } 1817 1547 1548 + static int victus_s_powersource_event(struct notifier_block *nb, 1549 + unsigned long value, 1550 + void *data) 1551 + { 1552 + struct acpi_bus_event *event_entry = data; 1553 + int err; 1554 + 1555 + if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0) 1556 + return NOTIFY_DONE; 1557 + 1558 + pr_debug("Received power source device event\n"); 1559 + 1560 + /* 1561 + * Switching to battery power source while Performance mode is active 1562 + * needs manual triggering of CPU power limits. Same goes when switching 1563 + * to AC power source while Performance mode is active. Other modes 1564 + * however are automatically behaving without any manual action. 1565 + * Seen on HP 16-s1034nf (board 8C9C) with F.11 and F.13 BIOS versions. 1566 + */ 1567 + 1568 + if (active_platform_profile == PLATFORM_PROFILE_PERFORMANCE) { 1569 + pr_debug("Triggering CPU PL1/PL2 actualization\n"); 1570 + err = victus_s_set_cpu_pl1_pl2(HP_POWER_LIMIT_DEFAULT, 1571 + HP_POWER_LIMIT_DEFAULT); 1572 + if (err) 1573 + pr_warn("Failed to actualize power limits: %d\n", err); 1574 + 1575 + return NOTIFY_DONE; 1576 + } 1577 + 1578 + return NOTIFY_OK; 1579 + } 1580 + 1818 1581 static int omen_register_powersource_event_handler(void) 1819 1582 { 1820 1583 int err; ··· 1863 1560 return 0; 1864 1561 } 1865 1562 1563 + static int victus_s_register_powersource_event_handler(void) 1564 + { 1565 + int err; 1566 + 1567 + platform_power_source_nb.notifier_call = victus_s_powersource_event; 1568 + err = register_acpi_notifier(&platform_power_source_nb); 1569 + if (err < 0) { 1570 + pr_warn("Failed to install ACPI power source notify handler\n"); 1571 + return err; 1572 + } 1573 + 1574 + return 0; 1575 + } 1576 + 1866 1577 static inline void omen_unregister_powersource_event_handler(void) 1867 1578 { 1868 1579 unregister_acpi_notifier(&platform_power_source_nb); 1869 1580 } 1870 1581 1871 - static int thermal_profile_setup(void) 1582 + static inline void victus_s_unregister_powersource_event_handler(void) 1872 1583 { 1584 + unregister_acpi_notifier(&platform_power_source_nb); 1585 + } 1586 + 1587 + static const struct platform_profile_ops platform_profile_omen_ops = { 1588 + .probe = hp_wmi_platform_profile_probe, 1589 + .profile_get = platform_profile_omen_get, 1590 + .profile_set = platform_profile_omen_set, 1591 + }; 1592 + 1593 + static const struct platform_profile_ops platform_profile_victus_ops = { 1594 + .probe = hp_wmi_platform_profile_probe, 1595 + .profile_get = platform_profile_victus_get, 1596 + .profile_set = platform_profile_victus_set, 1597 + }; 1598 + 1599 + static const struct platform_profile_ops platform_profile_victus_s_ops = { 1600 + .probe = hp_wmi_platform_profile_probe, 1601 + .profile_get = platform_profile_omen_get, 1602 + .profile_set = platform_profile_victus_s_set, 1603 + }; 1604 + 1605 + static const struct platform_profile_ops hp_wmi_platform_profile_ops = { 1606 + .probe = hp_wmi_platform_profile_probe, 1607 + .profile_get = hp_wmi_platform_profile_get, 1608 + .profile_set = hp_wmi_platform_profile_set, 1609 + }; 1610 + 1611 + static int thermal_profile_setup(struct platform_device *device) 1612 + { 1613 + const struct platform_profile_ops *ops; 1873 1614 int err, tp; 1874 1615 1875 1616 if (is_omen_thermal_profile()) { ··· 1929 1582 if (err < 0) 1930 1583 return err; 1931 1584 1932 - platform_profile_handler.profile_get = platform_profile_omen_get; 1933 - platform_profile_handler.profile_set = platform_profile_omen_set; 1934 - 1935 - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); 1585 + ops = &platform_profile_omen_ops; 1936 1586 } else if (is_victus_thermal_profile()) { 1937 1587 err = platform_profile_victus_get_ec(&active_platform_profile); 1938 1588 if (err < 0) ··· 1943 1599 if (err < 0) 1944 1600 return err; 1945 1601 1946 - platform_profile_handler.profile_get = platform_profile_victus_get; 1947 - platform_profile_handler.profile_set = platform_profile_victus_set; 1602 + ops = &platform_profile_victus_ops; 1603 + } else if (is_victus_s_thermal_profile()) { 1604 + /* 1605 + * Being unable to retrieve laptop's current thermal profile, 1606 + * during this setup, we set it to Balanced by default. 1607 + */ 1608 + active_platform_profile = PLATFORM_PROFILE_BALANCED; 1948 1609 1949 - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); 1610 + err = platform_profile_victus_s_set_ec(active_platform_profile); 1611 + if (err < 0) 1612 + return err; 1613 + 1614 + ops = &platform_profile_victus_s_ops; 1950 1615 } else { 1951 1616 tp = thermal_profile_get(); 1952 1617 ··· 1970 1617 if (err) 1971 1618 return err; 1972 1619 1973 - platform_profile_handler.profile_get = hp_wmi_platform_profile_get; 1974 - platform_profile_handler.profile_set = hp_wmi_platform_profile_set; 1975 - 1976 - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); 1977 - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); 1620 + ops = &hp_wmi_platform_profile_ops; 1978 1621 } 1979 1622 1980 - set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices); 1981 - set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices); 1623 + platform_profile_device = devm_platform_profile_register(&device->dev, "hp-wmi", 1624 + NULL, ops); 1625 + if (IS_ERR(platform_profile_device)) 1626 + return PTR_ERR(platform_profile_device); 1982 1627 1983 - err = platform_profile_register(&platform_profile_handler); 1984 - if (err) 1985 - return err; 1986 - 1628 + pr_info("Registered as platform profile handler\n"); 1987 1629 platform_profile_support = true; 1988 1630 1989 1631 return 0; ··· 2011 1663 if (err < 0) 2012 1664 return err; 2013 1665 2014 - thermal_profile_setup(); 1666 + thermal_profile_setup(device); 2015 1667 2016 1668 return 0; 2017 1669 } ··· 2037 1689 rfkill_unregister(wwan_rfkill); 2038 1690 rfkill_destroy(wwan_rfkill); 2039 1691 } 2040 - 2041 - if (platform_profile_support) 2042 - platform_profile_remove(); 2043 1692 } 2044 1693 2045 1694 static int hp_wmi_resume_handler(struct device *device) ··· 2104 1759 case hwmon_pwm: 2105 1760 return 0644; 2106 1761 case hwmon_fan: 2107 - if (hp_wmi_get_fan_speed(channel) >= 0) 2108 - return 0444; 1762 + if (is_victus_s_thermal_profile()) { 1763 + if (hp_wmi_get_fan_speed_victus_s(channel) >= 0) 1764 + return 0444; 1765 + } else { 1766 + if (hp_wmi_get_fan_speed(channel) >= 0) 1767 + return 0444; 1768 + } 2109 1769 break; 2110 1770 default: 2111 1771 return 0; ··· 2126 1776 2127 1777 switch (type) { 2128 1778 case hwmon_fan: 2129 - ret = hp_wmi_get_fan_speed(channel); 2130 - 1779 + if (is_victus_s_thermal_profile()) 1780 + ret = hp_wmi_get_fan_speed_victus_s(channel); 1781 + else 1782 + ret = hp_wmi_get_fan_speed(channel); 2131 1783 if (ret < 0) 2132 1784 return ret; 2133 1785 *val = ret; ··· 2162 1810 case hwmon_pwm: 2163 1811 switch (val) { 2164 1812 case 0: 1813 + if (is_victus_s_thermal_profile()) 1814 + hp_wmi_get_fan_count_userdefine_trigger(); 2165 1815 /* 0 is no fan speed control (max), which is 1 for us */ 2166 1816 return hp_wmi_fan_speed_max_set(1); 2167 1817 case 2: 2168 1818 /* 2 is automatic speed control, which is 0 for us */ 2169 - return hp_wmi_fan_speed_max_set(0); 1819 + if (is_victus_s_thermal_profile()) { 1820 + hp_wmi_get_fan_count_userdefine_trigger(); 1821 + return hp_wmi_fan_speed_max_reset(); 1822 + } else 1823 + return hp_wmi_fan_speed_max_set(0); 2170 1824 default: 2171 1825 /* we don't support manual fan speed control */ 2172 1826 return -EINVAL; ··· 2251 1893 err = omen_register_powersource_event_handler(); 2252 1894 if (err) 2253 1895 goto err_unregister_device; 1896 + } else if (is_victus_s_thermal_profile()) { 1897 + err = victus_s_register_powersource_event_handler(); 1898 + if (err) 1899 + goto err_unregister_device; 2254 1900 } 2255 1901 2256 1902 return 0; ··· 2273 1911 { 2274 1912 if (is_omen_thermal_profile() || is_victus_thermal_profile()) 2275 1913 omen_unregister_powersource_event_handler(); 1914 + 1915 + if (is_victus_s_thermal_profile()) 1916 + victus_s_unregister_powersource_event_handler(); 2276 1917 2277 1918 if (wmi_has_guid(HPWMI_EVENT_GUID)) 2278 1919 hp_wmi_input_destroy();
+2 -2
drivers/platform/x86/hp/hp_accel.c
··· 267 267 }; 268 268 269 269 static bool hp_accel_i8042_filter(unsigned char data, unsigned char str, 270 - struct serio *port) 270 + struct serio *port, void *context) 271 271 { 272 272 static bool extended; 273 273 ··· 326 326 /* filter to remove HPQ6000 accelerometer data 327 327 * from keyboard bus stream */ 328 328 if (strstr(dev_name(&device->dev), "HPQ6000")) 329 - i8042_install_filter(hp_accel_i8042_filter); 329 + i8042_install_filter(hp_accel_i8042_filter, NULL); 330 330 331 331 INIT_WORK(&hpled_led.work, delayed_set_status_worker); 332 332 ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+27 -16
drivers/platform/x86/ideapad-laptop.c
··· 142 142 143 143 struct ideapad_dytc_priv { 144 144 enum platform_profile_option current_profile; 145 - struct platform_profile_handler pprof; 145 + struct device *ppdev; /* platform profile device */ 146 146 struct mutex mutex; /* protects the DYTC interface */ 147 147 struct ideapad_private *priv; 148 148 }; ··· 933 933 * dytc_profile_get: Function to register with platform_profile 934 934 * handler. Returns current platform profile. 935 935 */ 936 - static int dytc_profile_get(struct platform_profile_handler *pprof, 936 + static int dytc_profile_get(struct device *dev, 937 937 enum platform_profile_option *profile) 938 938 { 939 - struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof); 939 + struct ideapad_dytc_priv *dytc = dev_get_drvdata(dev); 940 940 941 941 *profile = dytc->current_profile; 942 942 return 0; ··· 986 986 * dytc_profile_set: Function to register with platform_profile 987 987 * handler. Sets current platform profile. 988 988 */ 989 - static int dytc_profile_set(struct platform_profile_handler *pprof, 989 + static int dytc_profile_set(struct device *dev, 990 990 enum platform_profile_option profile) 991 991 { 992 - struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof); 992 + struct ideapad_dytc_priv *dytc = dev_get_drvdata(dev); 993 993 struct ideapad_private *priv = dytc->priv; 994 994 unsigned long output; 995 995 int err; ··· 1023 1023 return -EINTR; 1024 1024 } 1025 1025 1026 + static int dytc_profile_probe(void *drvdata, unsigned long *choices) 1027 + { 1028 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 1029 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 1030 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1031 + 1032 + return 0; 1033 + } 1034 + 1026 1035 static void dytc_profile_refresh(struct ideapad_private *priv) 1027 1036 { 1028 1037 enum platform_profile_option profile; ··· 1050 1041 1051 1042 if (profile != priv->dytc->current_profile) { 1052 1043 priv->dytc->current_profile = profile; 1053 - platform_profile_notify(); 1044 + platform_profile_notify(priv->dytc->ppdev); 1054 1045 } 1055 1046 } 1056 1047 ··· 1070 1061 } 1071 1062 }, 1072 1063 {} 1064 + }; 1065 + 1066 + static const struct platform_profile_ops dytc_profile_ops = { 1067 + .probe = dytc_profile_probe, 1068 + .profile_get = dytc_profile_get, 1069 + .profile_set = dytc_profile_set, 1073 1070 }; 1074 1071 1075 1072 static int ideapad_dytc_profile_init(struct ideapad_private *priv) ··· 1118 1103 mutex_init(&priv->dytc->mutex); 1119 1104 1120 1105 priv->dytc->priv = priv; 1121 - priv->dytc->pprof.profile_get = dytc_profile_get; 1122 - priv->dytc->pprof.profile_set = dytc_profile_set; 1123 - 1124 - /* Setup supported modes */ 1125 - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices); 1126 - set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices); 1127 - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices); 1128 1106 1129 1107 /* Create platform_profile structure and register */ 1130 - err = platform_profile_register(&priv->dytc->pprof); 1131 - if (err) 1108 + priv->dytc->ppdev = devm_platform_profile_register(&priv->platform_device->dev, 1109 + "ideapad-laptop", &priv->dytc, 1110 + &dytc_profile_ops); 1111 + if (IS_ERR(priv->dytc->ppdev)) { 1112 + err = PTR_ERR(priv->dytc->ppdev); 1132 1113 goto pp_reg_failed; 1114 + } 1133 1115 1134 1116 /* Ensure initial values are correct */ 1135 1117 dytc_profile_refresh(priv); ··· 1146 1134 if (!priv->dytc) 1147 1135 return; 1148 1136 1149 - platform_profile_remove(); 1150 1137 mutex_destroy(&priv->dytc->mutex); 1151 1138 kfree(priv->dytc); 1152 1139
+23 -20
drivers/platform/x86/inspur_platform_profile.c
··· 32 32 33 33 struct inspur_wmi_priv { 34 34 struct wmi_device *wdev; 35 - struct platform_profile_handler handler; 35 + struct device *ppdev; 36 36 }; 37 37 38 38 static int inspur_wmi_perform_query(struct wmi_device *wdev, ··· 84 84 * 0x0: No Error 85 85 * 0x1: Error 86 86 */ 87 - static int inspur_platform_profile_set(struct platform_profile_handler *pprof, 87 + static int inspur_platform_profile_set(struct device *dev, 88 88 enum platform_profile_option profile) 89 89 { 90 - struct inspur_wmi_priv *priv = container_of(pprof, struct inspur_wmi_priv, 91 - handler); 90 + struct inspur_wmi_priv *priv = dev_get_drvdata(dev); 92 91 u8 ret_code[4] = {0, 0, 0, 0}; 93 92 int ret; 94 93 ··· 131 132 * 0x1: Performance Mode 132 133 * 0x2: Power Saver Mode 133 134 */ 134 - static int inspur_platform_profile_get(struct platform_profile_handler *pprof, 135 + static int inspur_platform_profile_get(struct device *dev, 135 136 enum platform_profile_option *profile) 136 137 { 137 - struct inspur_wmi_priv *priv = container_of(pprof, struct inspur_wmi_priv, 138 - handler); 138 + struct inspur_wmi_priv *priv = dev_get_drvdata(dev); 139 139 u8 ret_code[4] = {0, 0, 0, 0}; 140 140 int ret; 141 141 ··· 164 166 return 0; 165 167 } 166 168 169 + static int inspur_platform_profile_probe(void *drvdata, unsigned long *choices) 170 + { 171 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 172 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 173 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 174 + 175 + return 0; 176 + } 177 + 178 + static const struct platform_profile_ops inspur_platform_profile_ops = { 179 + .probe = inspur_platform_profile_probe, 180 + .profile_get = inspur_platform_profile_get, 181 + .profile_set = inspur_platform_profile_set, 182 + }; 183 + 167 184 static int inspur_wmi_probe(struct wmi_device *wdev, const void *context) 168 185 { 169 186 struct inspur_wmi_priv *priv; ··· 190 177 priv->wdev = wdev; 191 178 dev_set_drvdata(&wdev->dev, priv); 192 179 193 - priv->handler.profile_get = inspur_platform_profile_get; 194 - priv->handler.profile_set = inspur_platform_profile_set; 180 + priv->ppdev = devm_platform_profile_register(&wdev->dev, "inspur-wmi", priv, 181 + &inspur_platform_profile_ops); 195 182 196 - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices); 197 - set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices); 198 - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices); 199 - 200 - return platform_profile_register(&priv->handler); 201 - } 202 - 203 - static void inspur_wmi_remove(struct wmi_device *wdev) 204 - { 205 - platform_profile_remove(); 183 + return PTR_ERR_OR_ZERO(priv->ppdev); 206 184 } 207 185 208 186 static const struct wmi_device_id inspur_wmi_id_table[] = { ··· 210 206 }, 211 207 .id_table = inspur_wmi_id_table, 212 208 .probe = inspur_wmi_probe, 213 - .remove = inspur_wmi_remove, 214 209 .no_singleton = true, 215 210 }; 216 211
+1
drivers/platform/x86/intel/Kconfig
··· 83 83 config INTEL_BYTCRC_PWRSRC 84 84 tristate "Intel Bay Trail Crystal Cove power source driver" 85 85 depends on INTEL_SOC_PMIC 86 + depends on POWER_SUPPLY 86 87 help 87 88 This option adds a power source driver for Crystal Cove PMICs 88 89 on Intel Bay Trail devices.
+77 -2
drivers/platform/x86/intel/bytcrc_pwrsrc.c
··· 8 8 * Copyright (C) 2013 Intel Corporation 9 9 */ 10 10 11 + #include <linux/array_size.h> 12 + #include <linux/bits.h> 11 13 #include <linux/debugfs.h> 14 + #include <linux/interrupt.h> 12 15 #include <linux/mfd/intel_soc_pmic.h> 13 16 #include <linux/module.h> 14 17 #include <linux/platform_device.h> 18 + #include <linux/power_supply.h> 19 + #include <linux/property.h> 15 20 #include <linux/regmap.h> 16 21 22 + #define CRYSTALCOVE_PWRSRC_IRQ 0x03 17 23 #define CRYSTALCOVE_SPWRSRC_REG 0x1E 24 + #define CRYSTALCOVE_SPWRSRC_USB BIT(0) 25 + #define CRYSTALCOVE_SPWRSRC_DC BIT(1) 26 + #define CRYSTALCOVE_SPWRSRC_BATTERY BIT(2) 18 27 #define CRYSTALCOVE_RESETSRC0_REG 0x20 19 28 #define CRYSTALCOVE_RESETSRC1_REG 0x21 20 29 #define CRYSTALCOVE_WAKESRC_REG 0x22 ··· 31 22 struct crc_pwrsrc_data { 32 23 struct regmap *regmap; 33 24 struct dentry *debug_dentry; 25 + struct power_supply *psy; 34 26 unsigned int resetsrc0; 35 27 unsigned int resetsrc1; 36 28 unsigned int wakesrc; ··· 128 118 return regmap_write(data->regmap, reg, *val); 129 119 } 130 120 121 + static irqreturn_t crc_pwrsrc_irq_handler(int irq, void *_data) 122 + { 123 + struct crc_pwrsrc_data *data = _data; 124 + unsigned int irq_mask; 125 + 126 + if (regmap_read(data->regmap, CRYSTALCOVE_PWRSRC_IRQ, &irq_mask)) 127 + return IRQ_NONE; 128 + 129 + regmap_write(data->regmap, CRYSTALCOVE_PWRSRC_IRQ, irq_mask); 130 + 131 + power_supply_changed(data->psy); 132 + return IRQ_HANDLED; 133 + } 134 + 135 + static int crc_pwrsrc_psy_get_property(struct power_supply *psy, 136 + enum power_supply_property psp, 137 + union power_supply_propval *val) 138 + { 139 + struct crc_pwrsrc_data *data = power_supply_get_drvdata(psy); 140 + unsigned int pwrsrc; 141 + int ret; 142 + 143 + if (psp != POWER_SUPPLY_PROP_ONLINE) 144 + return -EINVAL; 145 + 146 + ret = regmap_read(data->regmap, CRYSTALCOVE_SPWRSRC_REG, &pwrsrc); 147 + if (ret) 148 + return ret; 149 + 150 + val->intval = !!(pwrsrc & (CRYSTALCOVE_SPWRSRC_USB | 151 + CRYSTALCOVE_SPWRSRC_DC)); 152 + return 0; 153 + } 154 + 155 + static const enum power_supply_property crc_pwrsrc_psy_props[] = { 156 + POWER_SUPPLY_PROP_ONLINE, 157 + }; 158 + 159 + static const struct power_supply_desc crc_pwrsrc_psy_desc = { 160 + .name = "crystal_cove_pwrsrc", 161 + .type = POWER_SUPPLY_TYPE_MAINS, 162 + .properties = crc_pwrsrc_psy_props, 163 + .num_properties = ARRAY_SIZE(crc_pwrsrc_psy_props), 164 + .get_property = crc_pwrsrc_psy_get_property, 165 + }; 166 + 131 167 static int crc_pwrsrc_probe(struct platform_device *pdev) 132 168 { 133 169 struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); 170 + struct device *dev = &pdev->dev; 134 171 struct crc_pwrsrc_data *data; 135 - int ret; 172 + int irq, ret; 136 173 137 - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 174 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 138 175 if (!data) 139 176 return -ENOMEM; 140 177 ··· 205 148 ret = crc_pwrsrc_read_and_clear(data, CRYSTALCOVE_WAKESRC_REG, &data->wakesrc); 206 149 if (ret) 207 150 return ret; 151 + 152 + if (device_property_read_bool(dev->parent, "linux,register-pwrsrc-power_supply")) { 153 + struct power_supply_config psy_cfg = { .drv_data = data }; 154 + 155 + irq = platform_get_irq(pdev, 0); 156 + if (irq < 0) 157 + return irq; 158 + 159 + data->psy = devm_power_supply_register(dev, &crc_pwrsrc_psy_desc, &psy_cfg); 160 + if (IS_ERR(data->psy)) 161 + return dev_err_probe(dev, PTR_ERR(data->psy), "registering power-supply\n"); 162 + 163 + ret = devm_request_threaded_irq(dev, irq, NULL, 164 + crc_pwrsrc_irq_handler, 165 + IRQF_ONESHOT, KBUILD_MODNAME, data); 166 + if (ret) 167 + return dev_err_probe(dev, ret, "requesting IRQ\n"); 168 + } 208 169 209 170 data->debug_dentry = debugfs_create_dir(KBUILD_MODNAME, NULL); 210 171 debugfs_create_file("pwrsrc", 0444, data->debug_dentry, data, &pwrsrc_fops);
+12 -2
drivers/platform/x86/intel/int0002_vgpio.c
··· 83 83 84 84 static void int0002_irq_unmask(struct irq_data *data) 85 85 { 86 + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); 87 + irq_hw_number_t hwirq = irqd_to_hwirq(data); 86 88 u32 gpe_en_reg; 89 + 90 + gpiochip_enable_irq(gc, hwirq); 87 91 88 92 gpe_en_reg = inl(GPE0A_EN_PORT); 89 93 gpe_en_reg |= GPE0A_PME_B0_EN_BIT; ··· 96 92 97 93 static void int0002_irq_mask(struct irq_data *data) 98 94 { 95 + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); 96 + irq_hw_number_t hwirq = irqd_to_hwirq(data); 99 97 u32 gpe_en_reg; 100 98 101 99 gpe_en_reg = inl(GPE0A_EN_PORT); 102 100 gpe_en_reg &= ~GPE0A_PME_B0_EN_BIT; 103 101 outl(gpe_en_reg, GPE0A_EN_PORT); 102 + 103 + gpiochip_disable_irq(gc, hwirq); 104 104 } 105 105 106 106 static int int0002_irq_set_wake(struct irq_data *data, unsigned int on) ··· 148 140 return (gpe_sts_reg & GPE0A_PME_B0_STS_BIT); 149 141 } 150 142 151 - static struct irq_chip int0002_irqchip = { 143 + static const struct irq_chip int0002_irqchip = { 152 144 .name = DRV_NAME, 153 145 .irq_ack = int0002_irq_ack, 154 146 .irq_mask = int0002_irq_mask, 155 147 .irq_unmask = int0002_irq_unmask, 156 148 .irq_set_wake = int0002_irq_set_wake, 149 + .flags = IRQCHIP_IMMUTABLE, 150 + GPIOCHIP_IRQ_RESOURCE_HELPERS, 157 151 }; 158 152 159 153 static void int0002_init_irq_valid_mask(struct gpio_chip *chip, ··· 213 203 } 214 204 215 205 girq = &chip->irq; 216 - girq->chip = &int0002_irqchip; 206 + gpio_irq_chip_set_chip(girq, &int0002_irqchip); 217 207 /* This let us handle the parent IRQ in the driver */ 218 208 girq->parent_handler = NULL; 219 209 girq->num_parents = 0;
+2
drivers/platform/x86/intel/int3472/common.c
··· 70 70 return -ENODEV; 71 71 } 72 72 73 + dev_dbg(dev, "Sensor name %s\n", acpi_dev_name(sensor)); 74 + 73 75 *name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT, 74 76 acpi_dev_name(sensor)); 75 77 if (!*name_ret)
+14 -10
drivers/platform/x86/intel/int3472/discrete.c
··· 178 178 * to create clocks and regulators via the usual frameworks. 179 179 * 180 180 * Return: 181 - * * 1 - To continue the loop 182 - * * 0 - When all resources found are handled properly. 183 - * * -EINVAL - If the resource is not a GPIO IO resource 184 - * * -ENODEV - If the resource has no corresponding _DSM entry 185 - * * -Other - Errors propagated from one of the sub-functions. 181 + * * 1 - Continue the loop without adding a copy of the resource to 182 + * * the list passed to acpi_dev_get_resources() 183 + * * 0 - Continue the loop after adding a copy of the resource to 184 + * * the list passed to acpi_dev_get_resources() 185 + * * -errno - Error, break loop 186 186 */ 187 187 static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, 188 188 void *data) ··· 220 220 int3472_get_func_and_polarity(type, &func, &polarity); 221 221 222 222 pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); 223 - if (pin != agpio->pin_table[0]) 224 - dev_warn(int3472->dev, "%s %s pin number mismatch _DSM %d resource %d\n", 225 - func, agpio->resource_source.string_ptr, pin, 226 - agpio->pin_table[0]); 223 + /* Pin field is not really used under Windows and wraps around at 8 bits */ 224 + if (pin != (agpio->pin_table[0] & 0xff)) 225 + dev_dbg(int3472->dev, FW_BUG "%s %s pin number mismatch _DSM %d resource %d\n", 226 + func, agpio->resource_source.string_ptr, pin, agpio->pin_table[0]); 227 227 228 228 active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); 229 229 if (!active_value) ··· 289 289 if (ret < 0) 290 290 return dev_err_probe(int3472->dev, ret, err_msg); 291 291 292 - return ret; 292 + /* Tell acpi_dev_get_resources() to not make a copy of the resource */ 293 + return 1; 293 294 } 294 295 295 296 static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) ··· 336 335 struct int3472_discrete_device *int3472; 337 336 struct int3472_cldb cldb; 338 337 int ret; 338 + 339 + if (!adev) 340 + return -ENODEV; 339 341 340 342 ret = skl_int3472_fill_cldb(adev, &cldb); 341 343 if (ret) {
+3
drivers/platform/x86/intel/int3472/tps68470.c
··· 152 152 int ret; 153 153 int i; 154 154 155 + if (!adev) 156 + return -ENODEV; 157 + 155 158 n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata); 156 159 if (n_consumers < 0) 157 160 return n_consumers;
+1 -1
drivers/platform/x86/intel/plr_tpmi.c
··· 262 262 struct resource *res; 263 263 struct tpmi_plr *plr; 264 264 void __iomem *base; 265 - char name[16]; 265 + char name[17]; 266 266 int err; 267 267 268 268 plat_info = tpmi_get_platform_data(auxdev);
+2 -2
drivers/platform/x86/intel/pmt/class.c
··· 81 81 */ 82 82 static ssize_t 83 83 intel_pmt_read(struct file *filp, struct kobject *kobj, 84 - struct bin_attribute *attr, char *buf, loff_t off, 84 + const struct bin_attribute *attr, char *buf, loff_t off, 85 85 size_t count) 86 86 { 87 87 struct intel_pmt_entry *entry = container_of(attr, ··· 308 308 entry->pmt_bin_attr.attr.name = ns->name; 309 309 entry->pmt_bin_attr.attr.mode = 0440; 310 310 entry->pmt_bin_attr.mmap = intel_pmt_mmap; 311 - entry->pmt_bin_attr.read = intel_pmt_read; 311 + entry->pmt_bin_attr.read_new = intel_pmt_read; 312 312 entry->pmt_bin_attr.size = entry->size; 313 313 314 314 ret = sysfs_create_bin_file(&dev->kobj, &entry->pmt_bin_attr);
-33
drivers/platform/x86/intel/punit_ipc.c
··· 131 131 } 132 132 133 133 /** 134 - * intel_punit_ipc_simple_command() - Simple IPC command 135 - * @cmd: IPC command code. 136 - * @para1: First 8bit parameter, set 0 if not used. 137 - * @para2: Second 8bit parameter, set 0 if not used. 138 - * 139 - * Send a IPC command to P-Unit when there is no data transaction 140 - * 141 - * Return: IPC error code or 0 on success. 142 - */ 143 - int intel_punit_ipc_simple_command(int cmd, int para1, int para2) 144 - { 145 - IPC_DEV *ipcdev = punit_ipcdev; 146 - IPC_TYPE type; 147 - u32 val; 148 - int ret; 149 - 150 - mutex_lock(&ipcdev->lock); 151 - 152 - reinit_completion(&ipcdev->cmd_complete); 153 - type = (cmd & IPC_PUNIT_CMD_TYPE_MASK) >> IPC_TYPE_OFFSET; 154 - 155 - val = cmd & ~IPC_PUNIT_CMD_TYPE_MASK; 156 - val |= CMD_RUN | para2 << CMD_PARA2_SHIFT | para1 << CMD_PARA1_SHIFT; 157 - ipc_write_cmd(ipcdev, type, val); 158 - ret = intel_punit_ipc_check_status(ipcdev, type); 159 - 160 - mutex_unlock(&ipcdev->lock); 161 - 162 - return ret; 163 - } 164 - EXPORT_SYMBOL(intel_punit_ipc_simple_command); 165 - 166 - /** 167 134 * intel_punit_ipc_command() - IPC command with data and pointers 168 135 * @cmd: IPC command code. 169 136 * @para1: First 8bit parameter, set 0 if not used.
+17 -17
drivers/platform/x86/intel/sdsi.c
··· 398 398 } 399 399 400 400 static ssize_t provision_akc_write(struct file *filp, struct kobject *kobj, 401 - struct bin_attribute *attr, char *buf, loff_t off, 402 - size_t count) 401 + const struct bin_attribute *attr, char *buf, 402 + loff_t off, size_t count) 403 403 { 404 404 struct device *dev = kobj_to_dev(kobj); 405 405 struct sdsi_priv *priv = dev_get_drvdata(dev); ··· 409 409 410 410 return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_AKC); 411 411 } 412 - static BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG); 412 + static const BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG); 413 413 414 414 static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj, 415 - struct bin_attribute *attr, char *buf, loff_t off, 416 - size_t count) 415 + const struct bin_attribute *attr, char *buf, 416 + loff_t off, size_t count) 417 417 { 418 418 struct device *dev = kobj_to_dev(kobj); 419 419 struct sdsi_priv *priv = dev_get_drvdata(dev); ··· 423 423 424 424 return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_CAP); 425 425 } 426 - static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG); 426 + static const BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG); 427 427 428 428 static ssize_t 429 429 certificate_read(u64 command, u64 control_flags, struct sdsi_priv *priv, ··· 469 469 470 470 static ssize_t 471 471 state_certificate_read(struct file *filp, struct kobject *kobj, 472 - struct bin_attribute *attr, char *buf, loff_t off, 472 + const struct bin_attribute *attr, char *buf, loff_t off, 473 473 size_t count) 474 474 { 475 475 struct device *dev = kobj_to_dev(kobj); ··· 477 477 478 478 return certificate_read(SDSI_CMD_READ_STATE, 0, priv, buf, off, count); 479 479 } 480 - static BIN_ATTR_ADMIN_RO(state_certificate, SDSI_SIZE_READ_MSG); 480 + static const BIN_ATTR_ADMIN_RO(state_certificate, SDSI_SIZE_READ_MSG); 481 481 482 482 static ssize_t 483 483 meter_certificate_read(struct file *filp, struct kobject *kobj, 484 - struct bin_attribute *attr, char *buf, loff_t off, 484 + const struct bin_attribute *attr, char *buf, loff_t off, 485 485 size_t count) 486 486 { 487 487 struct device *dev = kobj_to_dev(kobj); ··· 489 489 490 490 return certificate_read(SDSI_CMD_READ_METER, 0, priv, buf, off, count); 491 491 } 492 - static BIN_ATTR_ADMIN_RO(meter_certificate, SDSI_SIZE_READ_MSG); 492 + static const BIN_ATTR_ADMIN_RO(meter_certificate, SDSI_SIZE_READ_MSG); 493 493 494 494 static ssize_t 495 495 meter_current_read(struct file *filp, struct kobject *kobj, 496 - struct bin_attribute *attr, char *buf, loff_t off, 496 + const struct bin_attribute *attr, char *buf, loff_t off, 497 497 size_t count) 498 498 { 499 499 struct device *dev = kobj_to_dev(kobj); ··· 502 502 return certificate_read(SDSI_CMD_READ_METER, CTRL_METER_ENABLE_DRAM, 503 503 priv, buf, off, count); 504 504 } 505 - static BIN_ATTR_ADMIN_RO(meter_current, SDSI_SIZE_READ_MSG); 505 + static const BIN_ATTR_ADMIN_RO(meter_current, SDSI_SIZE_READ_MSG); 506 506 507 507 static ssize_t registers_read(struct file *filp, struct kobject *kobj, 508 - struct bin_attribute *attr, char *buf, loff_t off, 509 - size_t count) 508 + const struct bin_attribute *attr, char *buf, 509 + loff_t off, size_t count) 510 510 { 511 511 struct device *dev = kobj_to_dev(kobj); 512 512 struct sdsi_priv *priv = dev_get_drvdata(dev); ··· 528 528 529 529 return count; 530 530 } 531 - static BIN_ATTR_ADMIN_RO(registers, SDSI_SIZE_REGS); 531 + static const BIN_ATTR_ADMIN_RO(registers, SDSI_SIZE_REGS); 532 532 533 - static struct bin_attribute *sdsi_bin_attrs[] = { 533 + static const struct bin_attribute *const sdsi_bin_attrs[] = { 534 534 &bin_attr_registers, 535 535 &bin_attr_state_certificate, 536 536 &bin_attr_meter_certificate, ··· 576 576 577 577 static const struct attribute_group sdsi_group = { 578 578 .attrs = sdsi_attrs, 579 - .bin_attrs = sdsi_bin_attrs, 579 + .bin_attrs_new = sdsi_bin_attrs, 580 580 .is_bin_visible = sdsi_battr_is_visible, 581 581 }; 582 582 __ATTRIBUTE_GROUPS(sdsi);
+44 -25
drivers/platform/x86/lenovo-wmi-camera.c
··· 13 13 #include <linux/module.h> 14 14 #include <linux/mutex.h> 15 15 #include <linux/wmi.h> 16 + #include <linux/cleanup.h> 16 17 17 18 #define WMI_LENOVO_CAMERABUTTON_EVENT_GUID "50C76F1F-D8E4-D895-0A3D-62F4EA400013" 18 19 ··· 27 26 SW_CAMERA_ON = 1, 28 27 }; 29 28 29 + static int camera_shutter_input_setup(struct wmi_device *wdev, u8 camera_mode) 30 + { 31 + struct lenovo_wmi_priv *priv = dev_get_drvdata(&wdev->dev); 32 + int err; 33 + 34 + priv->idev = input_allocate_device(); 35 + if (!priv->idev) 36 + return -ENOMEM; 37 + 38 + priv->idev->name = "Lenovo WMI Camera Button"; 39 + priv->idev->phys = "wmi/input0"; 40 + priv->idev->id.bustype = BUS_HOST; 41 + priv->idev->dev.parent = &wdev->dev; 42 + 43 + input_set_capability(priv->idev, EV_SW, SW_CAMERA_LENS_COVER); 44 + 45 + input_report_switch(priv->idev, SW_CAMERA_LENS_COVER, 46 + camera_mode == SW_CAMERA_ON ? 0 : 1); 47 + input_sync(priv->idev); 48 + 49 + err = input_register_device(priv->idev); 50 + if (err) { 51 + input_free_device(priv->idev); 52 + priv->idev = NULL; 53 + } 54 + 55 + return err; 56 + } 57 + 30 58 static void lenovo_wmi_notify(struct wmi_device *wdev, union acpi_object *obj) 31 59 { 32 60 struct lenovo_wmi_priv *priv = dev_get_drvdata(&wdev->dev); 33 - unsigned int keycode; 34 61 u8 camera_mode; 35 62 36 63 if (obj->type != ACPI_TYPE_BUFFER) { ··· 82 53 return; 83 54 } 84 55 85 - mutex_lock(&priv->notify_lock); 56 + guard(mutex)(&priv->notify_lock); 86 57 87 - keycode = camera_mode == SW_CAMERA_ON ? 88 - KEY_CAMERA_ACCESS_ENABLE : KEY_CAMERA_ACCESS_DISABLE; 89 - input_report_key(priv->idev, keycode, 1); 90 - input_sync(priv->idev); 91 - input_report_key(priv->idev, keycode, 0); 92 - input_sync(priv->idev); 58 + if (!priv->idev) { 59 + if (camera_shutter_input_setup(wdev, camera_mode)) 60 + dev_warn(&wdev->dev, "Failed to register input device\n"); 61 + return; 62 + } 93 63 94 - mutex_unlock(&priv->notify_lock); 64 + if (camera_mode == SW_CAMERA_ON) 65 + input_report_switch(priv->idev, SW_CAMERA_LENS_COVER, 0); 66 + else 67 + input_report_switch(priv->idev, SW_CAMERA_LENS_COVER, 1); 68 + input_sync(priv->idev); 95 69 } 96 70 97 71 static int lenovo_wmi_probe(struct wmi_device *wdev, const void *context) 98 72 { 99 73 struct lenovo_wmi_priv *priv; 100 - int ret; 101 74 102 75 priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); 103 76 if (!priv) 104 77 return -ENOMEM; 105 78 106 79 dev_set_drvdata(&wdev->dev, priv); 107 - 108 - priv->idev = devm_input_allocate_device(&wdev->dev); 109 - if (!priv->idev) 110 - return -ENOMEM; 111 - 112 - priv->idev->name = "Lenovo WMI Camera Button"; 113 - priv->idev->phys = "wmi/input0"; 114 - priv->idev->id.bustype = BUS_HOST; 115 - priv->idev->dev.parent = &wdev->dev; 116 - input_set_capability(priv->idev, EV_KEY, KEY_CAMERA_ACCESS_ENABLE); 117 - input_set_capability(priv->idev, EV_KEY, KEY_CAMERA_ACCESS_DISABLE); 118 - 119 - ret = input_register_device(priv->idev); 120 - if (ret) 121 - return ret; 122 80 123 81 mutex_init(&priv->notify_lock); 124 82 ··· 115 99 static void lenovo_wmi_remove(struct wmi_device *wdev) 116 100 { 117 101 struct lenovo_wmi_priv *priv = dev_get_drvdata(&wdev->dev); 102 + 103 + if (priv->idev) 104 + input_unregister_device(priv->idev); 118 105 119 106 mutex_destroy(&priv->notify_lock); 120 107 }
+3 -3
drivers/platform/x86/msi-laptop.c
··· 806 806 } 807 807 static DECLARE_DELAYED_WORK(msi_touchpad_dwork, msi_send_touchpad_key); 808 808 809 - static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, 810 - struct serio *port) 809 + static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, struct serio *port, 810 + void *context) 811 811 { 812 812 static bool extended; 813 813 ··· 996 996 if (result) 997 997 goto fail_input; 998 998 999 - result = i8042_install_filter(msi_laptop_i8042_filter); 999 + result = i8042_install_filter(msi_laptop_i8042_filter, NULL); 1000 1000 if (result) { 1001 1001 pr_err("Unable to install key filter\n"); 1002 1002 goto fail_filter;
+2 -2
drivers/platform/x86/panasonic-laptop.c
··· 260 260 * keypress events over the PS/2 kbd interface, filter these out. 261 261 */ 262 262 static bool panasonic_i8042_filter(unsigned char data, unsigned char str, 263 - struct serio *port) 263 + struct serio *port, void *context) 264 264 { 265 265 static bool extended; 266 266 ··· 1100 1100 pcc->platform = NULL; 1101 1101 } 1102 1102 1103 - i8042_install_filter(panasonic_i8042_filter); 1103 + i8042_install_filter(panasonic_i8042_filter, NULL); 1104 1104 return 0; 1105 1105 1106 1106 out_platform:
-1
drivers/platform/x86/quickstart.c
··· 20 20 #include <linux/module.h> 21 21 #include <linux/mutex.h> 22 22 #include <linux/platform_device.h> 23 - #include <linux/pm_wakeup.h> 24 23 #include <linux/printk.h> 25 24 #include <linux/slab.h> 26 25 #include <linux/sysfs.h>
+34 -26
drivers/platform/x86/serdev_helpers.h
··· 22 22 #include <linux/string.h> 23 23 24 24 static inline struct device * 25 - get_serdev_controller(const char *serial_ctrl_hid, 26 - const char *serial_ctrl_uid, 27 - int serial_ctrl_port, 28 - const char *serdev_ctrl_name) 25 + get_serdev_controller_from_parent(struct device *ctrl_dev, 26 + int serial_ctrl_port, 27 + const char *serdev_ctrl_name) 29 28 { 30 - struct device *ctrl_dev, *child; 31 - struct acpi_device *ctrl_adev; 29 + struct device *child; 32 30 char name[32]; 33 31 int i; 34 - 35 - ctrl_adev = acpi_dev_get_first_match_dev(serial_ctrl_hid, serial_ctrl_uid, -1); 36 - if (!ctrl_adev) { 37 - pr_err("error could not get %s/%s serial-ctrl adev\n", 38 - serial_ctrl_hid, serial_ctrl_uid); 39 - return ERR_PTR(-ENODEV); 40 - } 41 - 42 - /* get_first_physical_node() returns a weak ref */ 43 - ctrl_dev = get_device(acpi_get_first_physical_node(ctrl_adev)); 44 - if (!ctrl_dev) { 45 - pr_err("error could not get %s/%s serial-ctrl physical node\n", 46 - serial_ctrl_hid, serial_ctrl_uid); 47 - ctrl_dev = ERR_PTR(-ENODEV); 48 - goto put_ctrl_adev; 49 - } 50 32 51 33 /* Walk host -> uart-ctrl -> port -> serdev-ctrl */ 52 34 for (i = 0; i < 3; i++) { ··· 49 67 put_device(ctrl_dev); 50 68 if (!child) { 51 69 pr_err("error could not find '%s' device\n", name); 52 - ctrl_dev = ERR_PTR(-ENODEV); 53 - goto put_ctrl_adev; 70 + return ERR_PTR(-ENODEV); 54 71 } 55 72 56 73 ctrl_dev = child; 57 74 } 58 75 59 - put_ctrl_adev: 60 - acpi_dev_put(ctrl_adev); 61 76 return ctrl_dev; 77 + } 78 + 79 + static inline struct device * 80 + get_serdev_controller(const char *serial_ctrl_hid, 81 + const char *serial_ctrl_uid, 82 + int serial_ctrl_port, 83 + const char *serdev_ctrl_name) 84 + { 85 + struct acpi_device *adev; 86 + struct device *parent; 87 + 88 + adev = acpi_dev_get_first_match_dev(serial_ctrl_hid, serial_ctrl_uid, -1); 89 + if (!adev) { 90 + pr_err("error could not get %s/%s serial-ctrl adev\n", 91 + serial_ctrl_hid, serial_ctrl_uid ?: "*"); 92 + return ERR_PTR(-ENODEV); 93 + } 94 + 95 + /* get_first_physical_node() returns a weak ref */ 96 + parent = get_device(acpi_get_first_physical_node(adev)); 97 + acpi_dev_put(adev); 98 + if (!parent) { 99 + pr_err("error could not get %s/%s serial-ctrl physical node\n", 100 + serial_ctrl_hid, serial_ctrl_uid ?: "*"); 101 + return ERR_PTR(-ENODEV); 102 + } 103 + 104 + /* This puts our reference on parent and returns a ref on the ctrl */ 105 + return get_serdev_controller_from_parent(parent, serial_ctrl_port, serdev_ctrl_name); 62 106 }
+3 -10
drivers/platform/x86/think-lmi.c
··· 194 194 [TLMI_LEVEL_MASTER] = "master", 195 195 }; 196 196 static struct think_lmi tlmi_priv; 197 - static const struct class *fw_attr_class; 198 197 static DEFINE_MUTEX(tlmi_mutex); 199 198 200 199 static inline struct tlmi_pwd_setting *to_tlmi_pwd_setting(struct kobject *kobj) ··· 1445 1446 { 1446 1447 int i, ret; 1447 1448 1448 - ret = fw_attributes_class_get(&fw_attr_class); 1449 - if (ret) 1450 - return ret; 1451 - 1452 - tlmi_priv.class_dev = device_create(fw_attr_class, NULL, MKDEV(0, 0), 1449 + tlmi_priv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), 1453 1450 NULL, "%s", "thinklmi"); 1454 1451 if (IS_ERR(tlmi_priv.class_dev)) { 1455 1452 ret = PTR_ERR(tlmi_priv.class_dev); ··· 1558 1563 fail_create_attr: 1559 1564 tlmi_release_attr(); 1560 1565 fail_device_created: 1561 - device_destroy(fw_attr_class, MKDEV(0, 0)); 1566 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 1562 1567 fail_class_created: 1563 - fw_attributes_class_put(); 1564 1568 return ret; 1565 1569 } 1566 1570 ··· 1782 1788 static void tlmi_remove(struct wmi_device *wdev) 1783 1789 { 1784 1790 tlmi_release_attr(); 1785 - device_destroy(fw_attr_class, MKDEV(0, 0)); 1786 - fw_attributes_class_put(); 1791 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 1787 1792 } 1788 1793 1789 1794 static int tlmi_probe(struct wmi_device *wdev, const void *context)
+24 -22
drivers/platform/x86/thinkpad_acpi.c
··· 963 963 static struct platform_device *tpacpi_pdev; 964 964 static struct platform_device *tpacpi_sensors_pdev; 965 965 static struct device *tpacpi_hwmon; 966 + static struct device *tpacpi_pprof; 966 967 static struct input_dev *tpacpi_inputdev; 967 968 static struct mutex tpacpi_inputdev_send_mutex; 968 969 static LIST_HEAD(tpacpi_all_drivers); ··· 3276 3275 * scancodes to preserve uAPI compatibility, see tpacpi_input_send_key(). 3277 3276 */ 3278 3277 { KE_KEY, 0x131d, { KEY_VENDOR } }, /* System debug info, similar to old ThinkPad key */ 3278 + { KE_KEY, 0x1320, { KEY_LINK_PHONE } }, 3279 3279 { KE_KEY, TP_HKEY_EV_TRACK_DOUBLETAP /* 0x8036 */, { KEY_PROG4 } }, 3280 3280 { KE_END } 3281 3281 }; ··· 10417 10415 * dytc_profile_get: Function to register with platform_profile 10418 10416 * handler. Returns current platform profile. 10419 10417 */ 10420 - static int dytc_profile_get(struct platform_profile_handler *pprof, 10418 + static int dytc_profile_get(struct device *dev, 10421 10419 enum platform_profile_option *profile) 10422 10420 { 10423 10421 *profile = dytc_current_profile; ··· 10492 10490 * dytc_profile_set: Function to register with platform_profile 10493 10491 * handler. Sets current platform profile. 10494 10492 */ 10495 - static int dytc_profile_set(struct platform_profile_handler *pprof, 10493 + static int dytc_profile_set(struct device *dev, 10496 10494 enum platform_profile_option profile) 10497 10495 { 10498 10496 int perfmode; ··· 10541 10539 return err; 10542 10540 } 10543 10541 10542 + static int dytc_profile_probe(void *drvdata, unsigned long *choices) 10543 + { 10544 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 10545 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 10546 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 10547 + 10548 + return 0; 10549 + } 10550 + 10551 + static const struct platform_profile_ops dytc_profile_ops = { 10552 + .probe = dytc_profile_probe, 10553 + .profile_get = dytc_profile_get, 10554 + .profile_set = dytc_profile_set, 10555 + }; 10556 + 10544 10557 static void dytc_profile_refresh(void) 10545 10558 { 10546 10559 enum platform_profile_option profile; ··· 10584 10567 err = convert_dytc_to_profile(funcmode, perfmode, &profile); 10585 10568 if (!err && profile != dytc_current_profile) { 10586 10569 dytc_current_profile = profile; 10587 - platform_profile_notify(); 10570 + platform_profile_notify(tpacpi_pprof); 10588 10571 } 10589 10572 } 10590 - 10591 - static struct platform_profile_handler dytc_profile = { 10592 - .profile_get = dytc_profile_get, 10593 - .profile_set = dytc_profile_set, 10594 - }; 10595 10573 10596 10574 static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) 10597 10575 { 10598 10576 int err, output; 10599 - 10600 - /* Setup supported modes */ 10601 - set_bit(PLATFORM_PROFILE_LOW_POWER, dytc_profile.choices); 10602 - set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices); 10603 - set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices); 10604 10577 10605 10578 err = dytc_command(DYTC_CMD_QUERY, &output); 10606 10579 if (err) ··· 10646 10639 "DYTC version %d: thermal mode available\n", dytc_version); 10647 10640 10648 10641 /* Create platform_profile structure and register */ 10649 - err = platform_profile_register(&dytc_profile); 10642 + tpacpi_pprof = devm_platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi", 10643 + NULL, &dytc_profile_ops); 10650 10644 /* 10651 10645 * If for some reason platform_profiles aren't enabled 10652 10646 * don't quit terminally. 10653 10647 */ 10654 - if (err) 10648 + if (IS_ERR(tpacpi_pprof)) 10655 10649 return -ENODEV; 10656 10650 10657 10651 /* Ensure initial values are correct */ ··· 10665 10657 return 0; 10666 10658 } 10667 10659 10668 - static void dytc_profile_exit(void) 10669 - { 10670 - platform_profile_remove(); 10671 - } 10672 - 10673 10660 static struct ibm_struct dytc_profile_driver_data = { 10674 10661 .name = "dytc-profile", 10675 - .exit = dytc_profile_exit, 10676 10662 }; 10677 10663 10678 10664 /************************************************************************* ··· 11683 11681 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) { 11684 11682 if (strlen(val) > sizeof(ibms_init[i].param) - 1) 11685 11683 return -ENOSPC; 11686 - strcpy(ibms_init[i].param, val); 11684 + strscpy(ibms_init[i].param, val); 11687 11685 return 0; 11688 11686 } 11689 11687 }
+2 -2
drivers/platform/x86/toshiba_acpi.c
··· 2755 2755 } 2756 2756 2757 2757 static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, 2758 - struct serio *port) 2758 + struct serio *port, void *context) 2759 2759 { 2760 2760 if (str & I8042_STR_AUXDATA) 2761 2761 return false; ··· 2915 2915 if (ec_handle && acpi_has_method(ec_handle, "NTFY")) { 2916 2916 INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work); 2917 2917 2918 - error = i8042_install_filter(toshiba_acpi_i8042_filter); 2918 + error = i8042_install_filter(toshiba_acpi_i8042_filter, NULL); 2919 2919 if (error) { 2920 2920 pr_err("Error installing key filter\n"); 2921 2921 goto err_free_dev;
+39 -38
drivers/platform/x86/wmi-bmof.c
··· 20 20 21 21 #define WMI_BMOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910" 22 22 23 - struct bmof_priv { 24 - union acpi_object *bmofdata; 25 - struct bin_attribute bmof_bin_attr; 26 - }; 27 - 28 - static ssize_t read_bmof(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, 23 + static ssize_t bmof_read(struct file *filp, struct kobject *kobj, const struct bin_attribute *attr, 29 24 char *buf, loff_t off, size_t count) 30 25 { 31 - struct bmof_priv *priv = container_of(attr, struct bmof_priv, bmof_bin_attr); 26 + struct device *dev = kobj_to_dev(kobj); 27 + union acpi_object *obj = dev_get_drvdata(dev); 32 28 33 - return memory_read_from_buffer(buf, count, &off, priv->bmofdata->buffer.pointer, 34 - priv->bmofdata->buffer.length); 29 + return memory_read_from_buffer(buf, count, &off, obj->buffer.pointer, obj->buffer.length); 35 30 } 31 + 32 + static const BIN_ATTR_ADMIN_RO(bmof, 0); 33 + 34 + static const struct bin_attribute * const bmof_attrs[] = { 35 + &bin_attr_bmof, 36 + NULL 37 + }; 38 + 39 + static size_t bmof_bin_size(struct kobject *kobj, const struct bin_attribute *attr, int n) 40 + { 41 + struct device *dev = kobj_to_dev(kobj); 42 + union acpi_object *obj = dev_get_drvdata(dev); 43 + 44 + return obj->buffer.length; 45 + } 46 + 47 + static const struct attribute_group bmof_group = { 48 + .bin_size = bmof_bin_size, 49 + .bin_attrs_new = bmof_attrs, 50 + }; 51 + 52 + static const struct attribute_group *bmof_groups[] = { 53 + &bmof_group, 54 + NULL 55 + }; 36 56 37 57 static int wmi_bmof_probe(struct wmi_device *wdev, const void *context) 38 58 { 39 - struct bmof_priv *priv; 40 - int ret; 59 + union acpi_object *obj; 41 60 42 - priv = devm_kzalloc(&wdev->dev, sizeof(struct bmof_priv), GFP_KERNEL); 43 - if (!priv) 44 - return -ENOMEM; 45 - 46 - dev_set_drvdata(&wdev->dev, priv); 47 - 48 - priv->bmofdata = wmidev_block_query(wdev, 0); 49 - if (!priv->bmofdata) { 61 + obj = wmidev_block_query(wdev, 0); 62 + if (!obj) { 50 63 dev_err(&wdev->dev, "failed to read Binary MOF\n"); 51 64 return -EIO; 52 65 } 53 66 54 - if (priv->bmofdata->type != ACPI_TYPE_BUFFER) { 67 + if (obj->type != ACPI_TYPE_BUFFER) { 55 68 dev_err(&wdev->dev, "Binary MOF is not a buffer\n"); 56 - ret = -EIO; 57 - goto err_free; 69 + kfree(obj); 70 + return -EIO; 58 71 } 59 72 60 - sysfs_bin_attr_init(&priv->bmof_bin_attr); 61 - priv->bmof_bin_attr.attr.name = "bmof"; 62 - priv->bmof_bin_attr.attr.mode = 0400; 63 - priv->bmof_bin_attr.read = read_bmof; 64 - priv->bmof_bin_attr.size = priv->bmofdata->buffer.length; 65 - 66 - ret = device_create_bin_file(&wdev->dev, &priv->bmof_bin_attr); 67 - if (ret) 68 - goto err_free; 73 + dev_set_drvdata(&wdev->dev, obj); 69 74 70 75 return 0; 71 - 72 - err_free: 73 - kfree(priv->bmofdata); 74 - return ret; 75 76 } 76 77 77 78 static void wmi_bmof_remove(struct wmi_device *wdev) 78 79 { 79 - struct bmof_priv *priv = dev_get_drvdata(&wdev->dev); 80 + union acpi_object *obj = dev_get_drvdata(&wdev->dev); 80 81 81 - device_remove_bin_file(&wdev->dev, &priv->bmof_bin_attr); 82 - kfree(priv->bmofdata); 82 + kfree(obj); 83 83 } 84 84 85 85 static const struct wmi_device_id wmi_bmof_id_table[] = { ··· 90 90 static struct wmi_driver wmi_bmof_driver = { 91 91 .driver = { 92 92 .name = "wmi-bmof", 93 + .dev_groups = bmof_groups, 93 94 }, 94 95 .probe = wmi_bmof_probe, 95 96 .remove = wmi_bmof_remove,
+1 -1
drivers/platform/x86/x86-android-tablets/Makefile
··· 3 3 # X86 Android tablet support Makefile 4 4 # 5 5 6 + obj-$(CONFIG_X86_ANDROID_TABLETS) += vexia_atla10_ec.o 6 7 obj-$(CONFIG_X86_ANDROID_TABLETS) += x86-android-tablets.o 7 - 8 8 x86-android-tablets-y := core.o dmi.o shared-psy-info.o \ 9 9 asus.o lenovo.o other.o
+2 -2
drivers/platform/x86/x86-android-tablets/asus.c
··· 145 145 146 146 static const struct x86_serdev_info asus_me176c_serdevs[] __initconst = { 147 147 { 148 - .ctrl_hid = "80860F0A", 149 - .ctrl_uid = "2", 148 + .ctrl.acpi.hid = "80860F0A", 149 + .ctrl.acpi.uid = "2", 150 150 .ctrl_devname = "serial0", 151 151 .serdev_hid = "BCM2E3A", 152 152 },
+24 -7
drivers/platform/x86/x86-android-tablets/core.c
··· 157 157 static const struct software_node *bat_swnode; 158 158 static void (*exit_handler)(void); 159 159 160 - static struct i2c_adapter * 160 + static __init struct i2c_adapter * 161 161 get_i2c_adap_by_handle(const struct x86_i2c_client_info *client_info) 162 162 { 163 163 acpi_handle handle; ··· 177 177 return dev->parent == data; 178 178 } 179 179 180 - static struct i2c_adapter * 180 + static __init struct i2c_adapter * 181 181 get_i2c_adap_by_pci_parent(const struct x86_i2c_client_info *client_info) 182 182 { 183 183 struct i2c_adapter *adap = NULL; ··· 212 212 if (board_info.irq < 0) 213 213 return board_info.irq; 214 214 215 - if (dev_info->use_pci_devname) 215 + if (dev_info->use_pci) 216 216 adap = get_i2c_adap_by_pci_parent(client_info); 217 217 else 218 218 adap = get_i2c_adap_by_handle(client_info); ··· 271 271 return 0; 272 272 } 273 273 274 - static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx) 274 + static __init struct device * 275 + get_serdev_controller_by_pci_parent(const struct x86_serdev_info *info) 275 276 { 277 + struct pci_dev *pdev; 278 + 279 + pdev = pci_get_domain_bus_and_slot(0, 0, info->ctrl.pci.devfn); 280 + if (!pdev) 281 + return ERR_PTR(-EPROBE_DEFER); 282 + 283 + /* This puts our reference on pdev and returns a ref on the ctrl */ 284 + return get_serdev_controller_from_parent(&pdev->dev, 0, info->ctrl_devname); 285 + } 286 + 287 + static __init int x86_instantiate_serdev(const struct x86_dev_info *dev_info, int idx) 288 + { 289 + const struct x86_serdev_info *info = &dev_info->serdev_info[idx]; 276 290 struct acpi_device *serdev_adev; 277 291 struct serdev_device *serdev; 278 292 struct device *ctrl_dev; 279 293 int ret = -ENODEV; 280 294 281 - ctrl_dev = get_serdev_controller(info->ctrl_hid, info->ctrl_uid, 0, 282 - info->ctrl_devname); 295 + if (dev_info->use_pci) 296 + ctrl_dev = get_serdev_controller_by_pci_parent(info); 297 + else 298 + ctrl_dev = get_serdev_controller(info->ctrl.acpi.hid, info->ctrl.acpi.uid, 299 + 0, info->ctrl_devname); 283 300 if (IS_ERR(ctrl_dev)) 284 301 return PTR_ERR(ctrl_dev); 285 302 ··· 463 446 464 447 serdev_count = dev_info->serdev_count; 465 448 for (i = 0; i < serdev_count; i++) { 466 - ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i); 449 + ret = x86_instantiate_serdev(dev_info, i); 467 450 if (ret < 0) { 468 451 x86_android_tablet_remove(pdev); 469 452 return ret;
+4 -4
drivers/platform/x86/x86-android-tablets/lenovo.c
··· 178 178 */ 179 179 static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = { 180 180 { 181 - .ctrl_hid = "8086228A", 182 - .ctrl_uid = "1", 181 + .ctrl.acpi.hid = "8086228A", 182 + .ctrl.acpi.uid = "1", 183 183 .ctrl_devname = "serial0", 184 184 .serdev_hid = "BCM2E1A", 185 185 }, ··· 601 601 .num_consumer_supplies = 1, 602 602 }; 603 603 604 - struct bq24190_platform_data lenovo_yoga_tab2_1380_bq24190_pdata = { 604 + static struct bq24190_platform_data lenovo_yoga_tab2_1380_bq24190_pdata = { 605 605 .regulator_init_data = &lenovo_yoga_tab2_1380_bq24190_vbus_init_data, 606 606 }; 607 607 ··· 726 726 }, 727 727 }; 728 728 729 - const char * const lenovo_yoga_tab2_1380_modules[] __initconst = { 729 + static const char * const lenovo_yoga_tab2_1380_modules[] __initconst = { 730 730 "bq24190_charger", /* For the Vbus regulator for lc824206xa */ 731 731 NULL 732 732 };
+13 -3
drivers/platform/x86/x86-android-tablets/other.c
··· 602 602 * Vexia EDU ATLA 10 tablet, Android 4.2 / 4.4 + Guadalinex Ubuntu tablet 603 603 * distributed to schools in the Spanish Andalucía region. 604 604 */ 605 - const char * const crystal_cove_pwrsrc_psy[] = { "crystal_cove_pwrsrc" }; 605 + static const char * const crystal_cove_pwrsrc_psy[] = { "crystal_cove_pwrsrc" }; 606 606 607 607 static const struct property_entry vexia_edu_atla10_ulpmc_props[] = { 608 608 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", crystal_cove_pwrsrc_psy), 609 609 { } 610 610 }; 611 611 612 - const struct software_node vexia_edu_atla10_ulpmc_node = { 612 + static const struct software_node vexia_edu_atla10_ulpmc_node = { 613 613 .properties = vexia_edu_atla10_ulpmc_props, 614 614 }; 615 615 ··· 715 715 } 716 716 }; 717 717 718 + static const struct x86_serdev_info vexia_edu_atla10_serdevs[] __initconst = { 719 + { 720 + .ctrl.pci.devfn = PCI_DEVFN(0x1e, 3), 721 + .ctrl_devname = "serial0", 722 + .serdev_hid = "OBDA8723", 723 + }, 724 + }; 725 + 718 726 static struct gpiod_lookup_table vexia_edu_atla10_ft5416_gpios = { 719 727 .dev_id = "i2c-FTSC1000", 720 728 .table = { ··· 763 755 const struct x86_dev_info vexia_edu_atla10_info __initconst = { 764 756 .i2c_client_info = vexia_edu_atla10_i2c_clients, 765 757 .i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_i2c_clients), 758 + .serdev_info = vexia_edu_atla10_serdevs, 759 + .serdev_count = ARRAY_SIZE(vexia_edu_atla10_serdevs), 766 760 .gpiod_lookup_tables = vexia_edu_atla10_gpios, 767 761 .init = vexia_edu_atla10_init, 768 - .use_pci_devname = true, 762 + .use_pci = true, 769 763 }; 770 764 771 765 /*
+261
drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * power_supply class (battery) driver for the I2C attached embedded controller 4 + * found on Vexia EDU ATLA 10 (9V version) tablets. 5 + * 6 + * This is based on the ACPI Battery device in the DSDT which should work 7 + * expect that it expects the I2C controller to be enumerated as an ACPI 8 + * device and the tablet's BIOS enumerates all LPSS devices as PCI devices 9 + * (and changing the LPSS BIOS settings from PCI -> ACPI does not work). 10 + * 11 + * Copyright (c) 2024 Hans de Goede <hansg@kernel.org> 12 + */ 13 + 14 + #include <linux/bits.h> 15 + #include <linux/devm-helpers.h> 16 + #include <linux/err.h> 17 + #include <linux/i2c.h> 18 + #include <linux/module.h> 19 + #include <linux/power_supply.h> 20 + #include <linux/types.h> 21 + #include <linux/workqueue.h> 22 + 23 + #include <asm/byteorder.h> 24 + 25 + /* State field uses ACPI Battery spec status bits */ 26 + #define ACPI_BATTERY_STATE_DISCHARGING BIT(0) 27 + #define ACPI_BATTERY_STATE_CHARGING BIT(1) 28 + 29 + #define ATLA10_EC_BATTERY_STATE_COMMAND 0x87 30 + #define ATLA10_EC_BATTERY_INFO_COMMAND 0x88 31 + 32 + /* From broken ACPI battery device in DSDT */ 33 + #define ATLA10_EC_VOLTAGE_MIN_DESIGN_uV 3750000 34 + 35 + /* Update data every 5 seconds */ 36 + #define UPDATE_INTERVAL_JIFFIES (5 * HZ) 37 + 38 + struct atla10_ec_battery_state { 39 + u8 status; /* Using ACPI Battery spec status bits */ 40 + u8 capacity; /* Percent */ 41 + __le16 charge_now_mAh; 42 + __le16 voltage_now_mV; 43 + __le16 current_now_mA; 44 + __le16 charge_full_mAh; 45 + __le16 temp; /* centi degrees Celsius */ 46 + } __packed; 47 + 48 + struct atla10_ec_battery_info { 49 + __le16 charge_full_design_mAh; 50 + __le16 voltage_now_mV; /* Should be design voltage, but is not ? */ 51 + __le16 charge_full_design2_mAh; 52 + } __packed; 53 + 54 + struct atla10_ec_data { 55 + struct i2c_client *client; 56 + struct power_supply *psy; 57 + struct delayed_work work; 58 + struct mutex update_lock; 59 + struct atla10_ec_battery_info info; 60 + struct atla10_ec_battery_state state; 61 + bool valid; /* true if state is valid */ 62 + unsigned long last_update; /* In jiffies */ 63 + }; 64 + 65 + static int atla10_ec_cmd(struct atla10_ec_data *data, u8 cmd, u8 len, u8 *values) 66 + { 67 + struct device *dev = &data->client->dev; 68 + u8 buf[I2C_SMBUS_BLOCK_MAX]; 69 + int ret; 70 + 71 + ret = i2c_smbus_read_block_data(data->client, cmd, buf); 72 + if (ret != len) { 73 + dev_err(dev, "I2C command 0x%02x error: %d\n", cmd, ret); 74 + return -EIO; 75 + } 76 + 77 + memcpy(values, buf, len); 78 + return 0; 79 + } 80 + 81 + static int atla10_ec_update(struct atla10_ec_data *data) 82 + { 83 + int ret; 84 + 85 + if (data->valid && time_before(jiffies, data->last_update + UPDATE_INTERVAL_JIFFIES)) 86 + return 0; 87 + 88 + ret = atla10_ec_cmd(data, ATLA10_EC_BATTERY_STATE_COMMAND, 89 + sizeof(data->state), (u8 *)&data->state); 90 + if (ret) 91 + return ret; 92 + 93 + data->last_update = jiffies; 94 + data->valid = true; 95 + return 0; 96 + } 97 + 98 + static int atla10_ec_psy_get_property(struct power_supply *psy, 99 + enum power_supply_property psp, 100 + union power_supply_propval *val) 101 + { 102 + struct atla10_ec_data *data = power_supply_get_drvdata(psy); 103 + int charge_now_mAh, charge_full_mAh, ret; 104 + 105 + guard(mutex)(&data->update_lock); 106 + 107 + ret = atla10_ec_update(data); 108 + if (ret) 109 + return ret; 110 + 111 + switch (psp) { 112 + case POWER_SUPPLY_PROP_STATUS: 113 + if (data->state.status & ACPI_BATTERY_STATE_DISCHARGING) 114 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 115 + else if (data->state.status & ACPI_BATTERY_STATE_CHARGING) 116 + val->intval = POWER_SUPPLY_STATUS_CHARGING; 117 + else if (data->state.capacity == 100) 118 + val->intval = POWER_SUPPLY_STATUS_FULL; 119 + else 120 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 121 + break; 122 + case POWER_SUPPLY_PROP_CAPACITY: 123 + val->intval = data->state.capacity; 124 + break; 125 + case POWER_SUPPLY_PROP_CHARGE_NOW: 126 + /* 127 + * The EC has a bug where it reports charge-full-design as 128 + * charge-now when the battery is full. Clamp charge-now to 129 + * charge-full to workaround this. 130 + */ 131 + charge_now_mAh = le16_to_cpu(data->state.charge_now_mAh); 132 + charge_full_mAh = le16_to_cpu(data->state.charge_full_mAh); 133 + val->intval = min(charge_now_mAh, charge_full_mAh) * 1000; 134 + break; 135 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 136 + val->intval = le16_to_cpu(data->state.voltage_now_mV) * 1000; 137 + break; 138 + case POWER_SUPPLY_PROP_CURRENT_NOW: 139 + val->intval = le16_to_cpu(data->state.current_now_mA) * 1000; 140 + /* 141 + * Documentation/ABI/testing/sysfs-class-power specifies 142 + * negative current for discharging. 143 + */ 144 + if (data->state.status & ACPI_BATTERY_STATE_DISCHARGING) 145 + val->intval = -val->intval; 146 + break; 147 + case POWER_SUPPLY_PROP_CHARGE_FULL: 148 + val->intval = le16_to_cpu(data->state.charge_full_mAh) * 1000; 149 + break; 150 + case POWER_SUPPLY_PROP_TEMP: 151 + val->intval = le16_to_cpu(data->state.temp) / 10; 152 + break; 153 + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 154 + val->intval = le16_to_cpu(data->info.charge_full_design_mAh) * 1000; 155 + break; 156 + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 157 + val->intval = ATLA10_EC_VOLTAGE_MIN_DESIGN_uV; 158 + break; 159 + case POWER_SUPPLY_PROP_PRESENT: 160 + val->intval = 1; 161 + break; 162 + case POWER_SUPPLY_PROP_TECHNOLOGY: 163 + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; 164 + break; 165 + default: 166 + return -EINVAL; 167 + } 168 + 169 + return 0; 170 + } 171 + 172 + static void atla10_ec_external_power_changed_work(struct work_struct *work) 173 + { 174 + struct atla10_ec_data *data = container_of(work, struct atla10_ec_data, work.work); 175 + 176 + dev_dbg(&data->client->dev, "External power changed\n"); 177 + data->valid = false; 178 + power_supply_changed(data->psy); 179 + } 180 + 181 + static void atla10_ec_external_power_changed(struct power_supply *psy) 182 + { 183 + struct atla10_ec_data *data = power_supply_get_drvdata(psy); 184 + 185 + /* After charger plug in/out wait 0.5s for things to stabilize */ 186 + mod_delayed_work(system_wq, &data->work, HZ / 2); 187 + } 188 + 189 + static const enum power_supply_property atla10_ec_psy_props[] = { 190 + POWER_SUPPLY_PROP_STATUS, 191 + POWER_SUPPLY_PROP_CAPACITY, 192 + POWER_SUPPLY_PROP_CHARGE_NOW, 193 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 194 + POWER_SUPPLY_PROP_CURRENT_NOW, 195 + POWER_SUPPLY_PROP_CHARGE_FULL, 196 + POWER_SUPPLY_PROP_TEMP, 197 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 198 + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 199 + POWER_SUPPLY_PROP_PRESENT, 200 + POWER_SUPPLY_PROP_TECHNOLOGY, 201 + }; 202 + 203 + static const struct power_supply_desc atla10_ec_psy_desc = { 204 + .name = "atla10_ec_battery", 205 + .type = POWER_SUPPLY_TYPE_BATTERY, 206 + .properties = atla10_ec_psy_props, 207 + .num_properties = ARRAY_SIZE(atla10_ec_psy_props), 208 + .get_property = atla10_ec_psy_get_property, 209 + .external_power_changed = atla10_ec_external_power_changed, 210 + }; 211 + 212 + static int atla10_ec_probe(struct i2c_client *client) 213 + { 214 + struct power_supply_config psy_cfg = { }; 215 + struct device *dev = &client->dev; 216 + struct atla10_ec_data *data; 217 + int ret; 218 + 219 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 220 + if (!data) 221 + return -ENOMEM; 222 + 223 + psy_cfg.drv_data = data; 224 + data->client = client; 225 + 226 + ret = devm_mutex_init(dev, &data->update_lock); 227 + if (ret) 228 + return ret; 229 + 230 + ret = devm_delayed_work_autocancel(dev, &data->work, 231 + atla10_ec_external_power_changed_work); 232 + if (ret) 233 + return ret; 234 + 235 + ret = atla10_ec_cmd(data, ATLA10_EC_BATTERY_INFO_COMMAND, 236 + sizeof(data->info), (u8 *)&data->info); 237 + if (ret) 238 + return ret; 239 + 240 + data->psy = devm_power_supply_register(dev, &atla10_ec_psy_desc, &psy_cfg); 241 + return PTR_ERR_OR_ZERO(data->psy); 242 + } 243 + 244 + static const struct i2c_device_id atla10_ec_id_table[] = { 245 + { "vexia_atla10_ec" }, 246 + { } 247 + }; 248 + MODULE_DEVICE_TABLE(i2c, atla10_ec_id_table); 249 + 250 + static struct i2c_driver atla10_ec_driver = { 251 + .driver = { 252 + .name = "vexia_atla10_ec", 253 + }, 254 + .probe = atla10_ec_probe, 255 + .id_table = atla10_ec_id_table, 256 + }; 257 + module_i2c_driver(atla10_ec_driver); 258 + 259 + MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 260 + MODULE_DESCRIPTION("Battery driver for Vexia EDU ATLA 10 tablet EC"); 261 + MODULE_LICENSE("GPL");
+10 -3
drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
··· 57 57 }; 58 58 59 59 struct x86_serdev_info { 60 - const char *ctrl_hid; 61 - const char *ctrl_uid; 60 + union { 61 + struct { 62 + const char *hid; 63 + const char *uid; 64 + } acpi; 65 + struct { 66 + unsigned int devfn; 67 + } pci; 68 + } ctrl; 62 69 const char *ctrl_devname; 63 70 /* 64 71 * ATM the serdev core only supports of or ACPI matching; and so far all ··· 98 91 int gpio_button_count; 99 92 int (*init)(struct device *dev); 100 93 void (*exit)(void); 101 - bool use_pci_devname; 94 + bool use_pci; 102 95 }; 103 96 104 97 int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
+15
include/linux/amd-pmf-io.h
··· 18 18 * enum sfh_message_type - Query the SFH message type 19 19 * @MT_HPD: Message ID to know the Human presence info from MP2 FW 20 20 * @MT_ALS: Message ID to know the Ambient light info from MP2 FW 21 + * @MT_SRA: Message ID to know the SRA data from MP2 FW 21 22 */ 22 23 enum sfh_message_type { 23 24 MT_HPD, 24 25 MT_ALS, 26 + MT_SRA, 25 27 }; 26 28 27 29 /** ··· 42 40 * struct amd_sfh_info - get HPD sensor info from MP2 FW 43 41 * @ambient_light: Populates the ambient light information 44 42 * @user_present: Populates the user presence information 43 + * @platform_type: Operating modes (clamshell, flat, tent, etc.) 44 + * @laptop_placement: Device states (ontable, onlap, outbag) 45 45 */ 46 46 struct amd_sfh_info { 47 47 u32 ambient_light; 48 48 u8 user_present; 49 + u32 platform_type; 50 + u32 laptop_placement; 51 + }; 52 + 53 + enum laptop_placement { 54 + LP_UNKNOWN = 0, 55 + ON_TABLE, 56 + ON_LAP_MOTION, 57 + IN_BAG, 58 + OUT_OF_BAG, 59 + LP_UNDEFINED, 49 60 }; 50 61 51 62 int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
+20 -8
include/linux/i8042.h
··· 54 54 55 55 struct serio; 56 56 57 + /** 58 + * typedef i8042_filter_t - i8042 filter callback 59 + * @data: Data received by the i8042 controller 60 + * @str: Status register of the i8042 controller 61 + * @serio: Serio of the i8042 controller 62 + * @context: Context pointer associated with this callback 63 + * 64 + * This represents a i8042 filter callback which can be used with i8042_install_filter() 65 + * and i8042_remove_filter() to filter the i8042 input for platform-specific key codes. 66 + * 67 + * Context: Interrupt context. 68 + * Returns: true if the data should be filtered out, false if otherwise. 69 + */ 70 + typedef bool (*i8042_filter_t)(unsigned char data, unsigned char str, struct serio *serio, 71 + void *context); 72 + 57 73 #if defined(CONFIG_SERIO_I8042) || defined(CONFIG_SERIO_I8042_MODULE) 58 74 59 75 void i8042_lock_chip(void); 60 76 void i8042_unlock_chip(void); 61 77 int i8042_command(unsigned char *param, int command); 62 - int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, 63 - struct serio *serio)); 64 - int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, 65 - struct serio *serio)); 78 + int i8042_install_filter(i8042_filter_t filter, void *context); 79 + int i8042_remove_filter(i8042_filter_t filter); 66 80 67 81 #else 68 82 ··· 93 79 return -ENODEV; 94 80 } 95 81 96 - static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, 97 - struct serio *serio)) 82 + static inline int i8042_install_filter(i8042_filter_t filter, void *context) 98 83 { 99 84 return -ENODEV; 100 85 } 101 86 102 - static inline int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, 103 - struct serio *serio)) 87 + static inline int i8042_remove_filter(i8042_filter_t filter) 104 88 { 105 89 return -ENODEV; 106 90 }
+24 -9
include/linux/platform_profile.h
··· 9 9 #ifndef _PLATFORM_PROFILE_H_ 10 10 #define _PLATFORM_PROFILE_H_ 11 11 12 + #include <linux/device.h> 12 13 #include <linux/bitops.h> 13 14 14 15 /* ··· 24 23 PLATFORM_PROFILE_BALANCED, 25 24 PLATFORM_PROFILE_BALANCED_PERFORMANCE, 26 25 PLATFORM_PROFILE_PERFORMANCE, 26 + PLATFORM_PROFILE_CUSTOM, 27 27 PLATFORM_PROFILE_LAST, /*must always be last */ 28 28 }; 29 29 30 - struct platform_profile_handler { 31 - unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 32 - int (*profile_get)(struct platform_profile_handler *pprof, 33 - enum platform_profile_option *profile); 34 - int (*profile_set)(struct platform_profile_handler *pprof, 35 - enum platform_profile_option profile); 30 + /** 31 + * struct platform_profile_ops - platform profile operations 32 + * @probe: Callback to setup choices available to the new class device. These 33 + * choices will only be enforced when setting a new profile, not when 34 + * getting the current one. 35 + * @profile_get: Callback that will be called when showing the current platform 36 + * profile in sysfs. 37 + * @profile_set: Callback that will be called when storing a new platform 38 + * profile in sysfs. 39 + */ 40 + struct platform_profile_ops { 41 + int (*probe)(void *drvdata, unsigned long *choices); 42 + int (*profile_get)(struct device *dev, enum platform_profile_option *profile); 43 + int (*profile_set)(struct device *dev, enum platform_profile_option profile); 36 44 }; 37 45 38 - int platform_profile_register(struct platform_profile_handler *pprof); 39 - int platform_profile_remove(void); 46 + struct device *platform_profile_register(struct device *dev, const char *name, 47 + void *drvdata, 48 + const struct platform_profile_ops *ops); 49 + int platform_profile_remove(struct device *dev); 50 + struct device *devm_platform_profile_register(struct device *dev, const char *name, 51 + void *drvdata, 52 + const struct platform_profile_ops *ops); 40 53 int platform_profile_cycle(void); 41 - void platform_profile_notify(void); 54 + void platform_profile_notify(struct device *dev); 42 55 43 56 #endif /*_PLATFORM_PROFILE_H_*/
+1
include/uapi/linux/input-event-codes.h
··· 519 519 #define KEY_NOTIFICATION_CENTER 0x1bc /* Show/hide the notification center */ 520 520 #define KEY_PICKUP_PHONE 0x1bd /* Answer incoming call */ 521 521 #define KEY_HANGUP_PHONE 0x1be /* Decline incoming call */ 522 + #define KEY_LINK_PHONE 0x1bf /* AL Phone Syncing */ 522 523 523 524 #define KEY_DEL_EOL 0x1c0 524 525 #define KEY_DEL_EOS 0x1c1
+1 -1
tools/power/x86/intel-speed-select/isst-config.c
··· 16 16 int arg; 17 17 }; 18 18 19 - static const char *version_str = "v1.20"; 19 + static const char *version_str = "v1.21"; 20 20 21 21 static const int supported_api_ver = 3; 22 22 static struct isst_if_platform_info isst_platform_info;
+1 -1
tools/power/x86/intel-speed-select/isst-core-tpmi.c
··· 329 329 return 0; 330 330 } 331 331 332 - static int tpmi_get_get_trl(struct isst_id *id, int level, int config_index, 332 + static int tpmi_get_get_trl(struct isst_id *id, int config_index, int level, 333 333 int *trl) 334 334 { 335 335 struct isst_pkg_ctdp_level_info ctdp_level;