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.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver updates from Ilpo Järvinen:

- amd/pmf:
- Add support for adjusting PMF PPT and PPT APU thresholds
- Extend custom BIOS inputs for more policies
- Update ta_pmf_action structure to the latest PMF TA

- arm64:
- thinkpad-t14s-ec: Add EC driver for ThinkPad T14s Gen6 Snapdragon

- int3472:
- Increase handshake GPIO delay

- intel/pmc:
- SSRAM support for Lunar Lake and Panther Lake
- Support reading substate requirements data from S0ix blockers
(for platforms starting from Panther Lake)
- Wildcat Lake support

- intel-uncore-freq:
- Solve duplicate sysfs entry warnings
- Present unique domain ID per package

- portwell-ec:
- Support suspend/resume
- Add hwmon support for voltage and temperature

- redmi-wmi:
- Add WMI driver for Redmibook keyboard

- think-lmi:
- Certificate support for ThinkCenter

- x86-android-tables + others:
- Convert away from legacy GPIO APIs

- x86-android-tables:
- Add support for Acer A1-840 tablet
- Fix modules list for Lenovo devices
- Stop using EPROBE_DEFER

- Miscellaneous cleanups / refactoring / improvements

* tag 'platform-drivers-x86-v6.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (63 commits)
platform/x86: pcengines-apuv2: Use static device properties
platform/x86: meraki-mx100: Use static device properties
platform/x86: barco-p50-gpio: use software nodes for gpio-leds/keys
platform/x86: x86-android-tablets: Stop using EPROBE_DEFER
platform/x86: x86-android-tablets: Fix modules lists for Lenovo devices
platform/x86: x86-android-tablets: Simplify lenovo_yoga_tab2_830_1050_exit()
platform/x86: x86-android-tablets: Add support for Acer A1-840 tablet
platform/x86: x86-android-tablets: Move Acer info to its own file
platform/x86: x86-android-tablets: Update my email address
platform/x86: x86-android-tablets: Simplify node-group [un]registration
platform/x86: x86-android-tablets: use swnode_group instead of manual registering
platform/x86: x86-android-tablets: replace bat_swnode with swnode_group
platform/x86: x86-android-tablets: convert gpio_keys devices to GPIO references
platform/x86: x86-android-tablets: remove support for GPIO lookup tables
platform/x86: x86-android-tablets: convert Yoga Tab2 fast charger to GPIO references
platform/x86: x86-android-tablets: convert HID-I2C devices to GPIO references
platform/x86: x86-android-tablets: convert wm1502 devices to GPIO references
platform/x86: x86-android-tablets: convert int3496 devices to GPIO references
platform/x86: x86-android-tablets: convert EDT devices to GPIO references
platform/x86: x86-android-tablets: convert Novatek devices to GPIO references
...

+3390 -892
+50
Documentation/devicetree/bindings/embedded-controller/lenovo,thinkpad-t14s-ec.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/embedded-controller/lenovo,thinkpad-t14s-ec.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Lenovo Thinkpad T14s Embedded Controller 8 + 9 + maintainers: 10 + - Sebastian Reichel <sre@kernel.org> 11 + 12 + description: 13 + The Qualcomm Snapdragon-based Lenovo Thinkpad T14s has an Embedded Controller 14 + (EC) which handles things such as keyboard backlight, LEDs or non-standard 15 + keys. 16 + 17 + properties: 18 + compatible: 19 + const: lenovo,thinkpad-t14s-ec 20 + 21 + reg: 22 + const: 0x28 23 + 24 + interrupts: 25 + maxItems: 1 26 + 27 + wakeup-source: true 28 + 29 + required: 30 + - compatible 31 + - reg 32 + - interrupts 33 + 34 + additionalProperties: false 35 + 36 + examples: 37 + - |+ 38 + #include <dt-bindings/interrupt-controller/irq.h> 39 + i2c { 40 + #address-cells = <1>; 41 + #size-cells = <0>; 42 + 43 + embedded-controller@28 { 44 + compatible = "lenovo,thinkpad-t14s-ec"; 45 + reg = <0x28>; 46 + interrupts-extended = <&tlmm 66 IRQ_TYPE_LEVEL_LOW>; 47 + wakeup-source; 48 + }; 49 + }; 50 + ...
+12
MAINTAINERS
··· 21605 21605 T: git https://github.com/pkshih/rtw.git 21606 21606 F: drivers/net/wireless/realtek/rtw89/ 21607 21607 21608 + REDMIBOOK WMI DRIVERS 21609 + M: Gladyshev Ilya <foxido@foxido.dev> 21610 + L: platform-driver-x86@vger.kernel.org 21611 + S: Maintained 21612 + F: drivers/platform/x86/redmi-wmi.c 21613 + 21608 21614 REDPINE WIRELESS DRIVER 21609 21615 L: linux-wireless@vger.kernel.org 21610 21616 S: Orphan ··· 25459 25453 W: http://thinkwiki.org/wiki/Ibm-acpi 25460 25454 T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git 25461 25455 F: drivers/platform/x86/lenovo/thinkpad_acpi.c 25456 + 25457 + THINKPAD T14S EMBEDDED CONTROLLER DRIVER 25458 + M: Sebastian Reichel <sre@kernel.org> 25459 + S: Maintained 25460 + F: Documentation/devicetree/bindings/embedded-controller/lenovo,thinkpad-t14s-ec.yaml 25461 + F: drivers/platform/arm64/lenovo-thinkpad-t14s.c 25462 25462 25463 25463 THINKPAD LMI DRIVER 25464 25464 M: Mark Pearson <mpearson-lenovo@squebb.ca>
+24
arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi
··· 887 887 }; 888 888 }; 889 889 890 + &i2c6 { 891 + clock-frequency = <400000>; 892 + 893 + status = "okay"; 894 + 895 + embedded-controller@28 { 896 + compatible = "lenovo,thinkpad-t14s-ec"; 897 + reg = <0x28>; 898 + 899 + interrupts-extended = <&tlmm 66 IRQ_TYPE_LEVEL_LOW>; 900 + 901 + pinctrl-0 = <&ec_int_n_default>; 902 + pinctrl-names = "default"; 903 + 904 + wakeup-source; 905 + }; 906 + }; 907 + 890 908 &i2c7 { 891 909 clock-frequency = <400000>; 892 910 ··· 1286 1268 <44 4>, /* SPI (TPM) */ 1287 1269 <72 2>, /* Secure EC I2C connection (?) */ 1288 1270 <238 1>; /* UFS Reset */ 1271 + 1272 + ec_int_n_default: ec-int-n-state { 1273 + pins = "gpio66"; 1274 + function = "gpio"; 1275 + bias-disable; 1276 + }; 1289 1277 1290 1278 eusb3_reset_n: eusb3-reset-n-state { 1291 1279 pins = "gpio6";
+20
drivers/platform/arm64/Kconfig
··· 70 70 71 71 Say M or Y here to include this support. 72 72 73 + config EC_LENOVO_THINKPAD_T14S 74 + tristate "Lenovo Thinkpad T14s Embedded Controller driver" 75 + depends on ARCH_QCOM || COMPILE_TEST 76 + depends on I2C 77 + depends on INPUT 78 + select INPUT_SPARSEKMAP 79 + select LEDS_CLASS 80 + select NEW_LEDS 81 + select SND_CTL_LED if SND 82 + help 83 + Driver for the Embedded Controller in the Qualcomm Snapdragon-based 84 + Lenovo Thinkpad T14s, which provides access to keyboard backlight 85 + and status LEDs. 86 + 87 + This driver provides support for the mentioned laptop where this 88 + information is not properly exposed via the standard Qualcomm 89 + devices. 90 + 91 + Say M or Y here to include this support. 92 + 73 93 endif # ARM64_PLATFORM_DEVICES
+1
drivers/platform/arm64/Makefile
··· 8 8 obj-$(CONFIG_EC_ACER_ASPIRE1) += acer-aspire1-ec.o 9 9 obj-$(CONFIG_EC_HUAWEI_GAOKUN) += huawei-gaokun-ec.o 10 10 obj-$(CONFIG_EC_LENOVO_YOGA_C630) += lenovo-yoga-c630.o 11 + obj-$(CONFIG_EC_LENOVO_THINKPAD_T14S) += lenovo-thinkpad-t14s.o
+616
drivers/platform/arm64/lenovo-thinkpad-t14s.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2025, Sebastian Reichel 4 + */ 5 + 6 + #include <linux/bitfield.h> 7 + #include <linux/bits.h> 8 + #include <linux/cleanup.h> 9 + #include <linux/container_of.h> 10 + #include <linux/device.h> 11 + #include <linux/delay.h> 12 + #include <linux/dev_printk.h> 13 + #include <linux/err.h> 14 + #include <linux/i2c.h> 15 + #include <linux/input.h> 16 + #include <linux/input/sparse-keymap.h> 17 + #include <linux/interrupt.h> 18 + #include <linux/leds.h> 19 + #include <linux/lockdep.h> 20 + #include <linux/module.h> 21 + #include <linux/regmap.h> 22 + #include <linux/slab.h> 23 + 24 + #define T14S_EC_CMD_ECRD 0x02 25 + #define T14S_EC_CMD_ECWR 0x03 26 + #define T14S_EC_CMD_EVT 0xf0 27 + 28 + #define T14S_EC_REG_LED 0x0c 29 + #define T14S_EC_REG_KBD_BL1 0x0d 30 + #define T14S_EC_REG_KBD_BL2 0xe1 31 + #define T14S_EC_KBD_BL1_MASK GENMASK_U8(7, 6) 32 + #define T14S_EC_KBD_BL2_MASK GENMASK_U8(3, 2) 33 + #define T14S_EC_REG_AUD 0x30 34 + #define T14S_EC_MIC_MUTE_LED BIT(5) 35 + #define T14S_EC_SPK_MUTE_LED BIT(6) 36 + 37 + #define T14S_EC_EVT_NONE 0x00 38 + #define T14S_EC_EVT_KEY_FN_4 0x13 39 + #define T14S_EC_EVT_KEY_FN_F7 0x16 40 + #define T14S_EC_EVT_KEY_FN_SPACE 0x1f 41 + #define T14S_EC_EVT_KEY_TP_DOUBLE_TAP 0x20 42 + #define T14S_EC_EVT_AC_CONNECTED 0x26 43 + #define T14S_EC_EVT_AC_DISCONNECTED 0x27 44 + #define T14S_EC_EVT_KEY_POWER 0x28 45 + #define T14S_EC_EVT_LID_OPEN 0x2a 46 + #define T14S_EC_EVT_LID_CLOSED 0x2b 47 + #define T14S_EC_EVT_THERMAL_TZ40 0x5c 48 + #define T14S_EC_EVT_THERMAL_TZ42 0x5d 49 + #define T14S_EC_EVT_THERMAL_TZ39 0x5e 50 + #define T14S_EC_EVT_KEY_FN_F12 0x62 51 + #define T14S_EC_EVT_KEY_FN_TAB 0x63 52 + #define T14S_EC_EVT_KEY_FN_F8 0x64 53 + #define T14S_EC_EVT_KEY_FN_F10 0x65 54 + #define T14S_EC_EVT_KEY_FN_F4 0x6a 55 + #define T14S_EC_EVT_KEY_FN_D 0x6b 56 + #define T14S_EC_EVT_KEY_FN_T 0x6c 57 + #define T14S_EC_EVT_KEY_FN_H 0x6d 58 + #define T14S_EC_EVT_KEY_FN_M 0x6e 59 + #define T14S_EC_EVT_KEY_FN_L 0x6f 60 + #define T14S_EC_EVT_KEY_FN_RIGHT_SHIFT 0x71 61 + #define T14S_EC_EVT_KEY_FN_ESC 0x74 62 + #define T14S_EC_EVT_KEY_FN_N 0x79 63 + #define T14S_EC_EVT_KEY_FN_F11 0x7a 64 + #define T14S_EC_EVT_KEY_FN_G 0x7e 65 + 66 + /* Hardware LED blink rate is 1 Hz (500ms off, 500ms on) */ 67 + #define T14S_EC_BLINK_RATE_ON_OFF_MS 500 68 + 69 + /* 70 + * Add a virtual offset on all key event codes for sparse keymap handling, 71 + * since the sparse keymap infrastructure does not map some raw key event 72 + * codes used by the EC. For example 0x16 (T14S_EC_EVT_KEY_FN_F7) is mapped 73 + * to KEY_MUTE if no offset is applied. 74 + */ 75 + #define T14S_EC_KEY_EVT_OFFSET 0x1000 76 + #define T14S_EC_KEY_ENTRY(key, value) \ 77 + { KE_KEY, T14S_EC_KEY_EVT_OFFSET + T14S_EC_EVT_KEY_##key, { value } } 78 + 79 + enum t14s_ec_led_status_t { 80 + T14S_EC_LED_OFF = 0x00, 81 + T14S_EC_LED_ON = 0x80, 82 + T14S_EC_LED_BLINK = 0xc0, 83 + }; 84 + 85 + struct t14s_ec_led_classdev { 86 + struct led_classdev led_classdev; 87 + int led; 88 + enum t14s_ec_led_status_t cache; 89 + struct t14s_ec *ec; 90 + }; 91 + 92 + struct t14s_ec { 93 + struct regmap *regmap; 94 + struct device *dev; 95 + struct t14s_ec_led_classdev led_pwr_btn; 96 + struct t14s_ec_led_classdev led_chrg_orange; 97 + struct t14s_ec_led_classdev led_chrg_white; 98 + struct t14s_ec_led_classdev led_lid_logo_dot; 99 + struct led_classdev kbd_backlight; 100 + struct led_classdev led_mic_mute; 101 + struct led_classdev led_spk_mute; 102 + struct input_dev *inputdev; 103 + }; 104 + 105 + static const struct regmap_config t14s_ec_regmap_config = { 106 + .reg_bits = 8, 107 + .val_bits = 8, 108 + .max_register = 0xff, 109 + }; 110 + 111 + static int t14s_ec_write(void *context, unsigned int reg, 112 + unsigned int val) 113 + { 114 + struct t14s_ec *ec = context; 115 + struct i2c_client *client = to_i2c_client(ec->dev); 116 + u8 buf[5] = {T14S_EC_CMD_ECWR, reg, 0x00, 0x01, val}; 117 + int ret; 118 + 119 + ret = i2c_master_send(client, buf, sizeof(buf)); 120 + if (ret < 0) 121 + return ret; 122 + 123 + return 0; 124 + } 125 + 126 + static int t14s_ec_read(void *context, unsigned int reg, 127 + unsigned int *val) 128 + { 129 + struct t14s_ec *ec = context; 130 + struct i2c_client *client = to_i2c_client(ec->dev); 131 + u8 buf[4] = {T14S_EC_CMD_ECRD, reg, 0x00, 0x01}; 132 + struct i2c_msg request, response; 133 + u8 result; 134 + int ret; 135 + 136 + request.addr = client->addr; 137 + request.flags = I2C_M_STOP; 138 + request.len = sizeof(buf); 139 + request.buf = buf; 140 + response.addr = client->addr; 141 + response.flags = I2C_M_RD; 142 + response.len = 1; 143 + response.buf = &result; 144 + 145 + i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT); 146 + 147 + ret = __i2c_transfer(client->adapter, &request, 1); 148 + if (ret < 0) 149 + goto out; 150 + 151 + ret = __i2c_transfer(client->adapter, &response, 1); 152 + if (ret < 0) 153 + goto out; 154 + 155 + *val = result; 156 + ret = 0; 157 + 158 + out: 159 + i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); 160 + return ret; 161 + } 162 + 163 + static const struct regmap_bus t14s_ec_regmap_bus = { 164 + .reg_write = t14s_ec_write, 165 + .reg_read = t14s_ec_read, 166 + }; 167 + 168 + static int t14s_ec_read_evt(struct t14s_ec *ec, u8 *val) 169 + { 170 + struct i2c_client *client = to_i2c_client(ec->dev); 171 + u8 buf[4] = {T14S_EC_CMD_EVT, 0x00, 0x00, 0x01}; 172 + struct i2c_msg request, response; 173 + int ret; 174 + 175 + request.addr = client->addr; 176 + request.flags = I2C_M_STOP; 177 + request.len = sizeof(buf); 178 + request.buf = buf; 179 + response.addr = client->addr; 180 + response.flags = I2C_M_RD; 181 + response.len = 1; 182 + response.buf = val; 183 + 184 + i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT); 185 + 186 + ret = __i2c_transfer(client->adapter, &request, 1); 187 + if (ret < 0) 188 + goto out; 189 + 190 + ret = __i2c_transfer(client->adapter, &response, 1); 191 + if (ret < 0) 192 + goto out; 193 + 194 + ret = 0; 195 + 196 + out: 197 + i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); 198 + return ret; 199 + } 200 + 201 + static int t14s_led_set_status(struct t14s_ec *ec, 202 + struct t14s_ec_led_classdev *led, 203 + const enum t14s_ec_led_status_t ledstatus) 204 + { 205 + int ret; 206 + 207 + ret = regmap_write(ec->regmap, T14S_EC_REG_LED, 208 + led->led | ledstatus); 209 + if (ret < 0) 210 + return ret; 211 + 212 + led->cache = ledstatus; 213 + return 0; 214 + } 215 + 216 + static int t14s_led_brightness_set(struct led_classdev *led_cdev, 217 + enum led_brightness brightness) 218 + { 219 + struct t14s_ec_led_classdev *led = container_of(led_cdev, 220 + struct t14s_ec_led_classdev, led_classdev); 221 + enum t14s_ec_led_status_t new_state; 222 + 223 + if (brightness == LED_OFF) 224 + new_state = T14S_EC_LED_OFF; 225 + else if (led->cache == T14S_EC_LED_BLINK) 226 + new_state = T14S_EC_LED_BLINK; 227 + else 228 + new_state = T14S_EC_LED_ON; 229 + 230 + return t14s_led_set_status(led->ec, led, new_state); 231 + } 232 + 233 + static int t14s_led_blink_set(struct led_classdev *led_cdev, 234 + unsigned long *delay_on, 235 + unsigned long *delay_off) 236 + { 237 + struct t14s_ec_led_classdev *led = container_of(led_cdev, 238 + struct t14s_ec_led_classdev, led_classdev); 239 + 240 + if (*delay_on == 0 && *delay_off == 0) { 241 + /* Userspace does not provide a blink rate; we can choose it */ 242 + *delay_on = T14S_EC_BLINK_RATE_ON_OFF_MS; 243 + *delay_off = T14S_EC_BLINK_RATE_ON_OFF_MS; 244 + } else if ((*delay_on != T14S_EC_BLINK_RATE_ON_OFF_MS) || 245 + (*delay_off != T14S_EC_BLINK_RATE_ON_OFF_MS)) 246 + return -EINVAL; 247 + 248 + return t14s_led_set_status(led->ec, led, T14S_EC_LED_BLINK); 249 + } 250 + 251 + static int t14s_init_led(struct t14s_ec *ec, struct t14s_ec_led_classdev *led, 252 + u8 id, const char *name) 253 + { 254 + led->led_classdev.name = name; 255 + led->led_classdev.flags = LED_RETAIN_AT_SHUTDOWN; 256 + led->led_classdev.max_brightness = 1; 257 + led->led_classdev.brightness_set_blocking = t14s_led_brightness_set; 258 + led->led_classdev.blink_set = t14s_led_blink_set; 259 + led->ec = ec; 260 + led->led = id; 261 + 262 + return devm_led_classdev_register(ec->dev, &led->led_classdev); 263 + } 264 + 265 + static int t14s_leds_probe(struct t14s_ec *ec) 266 + { 267 + int ret; 268 + 269 + ret = t14s_init_led(ec, &ec->led_pwr_btn, 0, "platform::power"); 270 + if (ret) 271 + return ret; 272 + 273 + ret = t14s_init_led(ec, &ec->led_chrg_orange, 1, 274 + "platform:amber:battery-charging"); 275 + if (ret) 276 + return ret; 277 + 278 + ret = t14s_init_led(ec, &ec->led_chrg_white, 2, 279 + "platform:white:battery-full"); 280 + if (ret) 281 + return ret; 282 + 283 + ret = t14s_init_led(ec, &ec->led_lid_logo_dot, 10, 284 + "platform::lid_logo_dot"); 285 + if (ret) 286 + return ret; 287 + 288 + return 0; 289 + } 290 + 291 + static int t14s_kbd_bl_set(struct led_classdev *led_cdev, 292 + enum led_brightness brightness) 293 + { 294 + struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 295 + kbd_backlight); 296 + int ret; 297 + u8 val; 298 + 299 + val = FIELD_PREP(T14S_EC_KBD_BL1_MASK, brightness); 300 + ret = regmap_update_bits(ec->regmap, T14S_EC_REG_KBD_BL1, 301 + T14S_EC_KBD_BL1_MASK, val); 302 + if (ret < 0) 303 + return ret; 304 + 305 + val = FIELD_PREP(T14S_EC_KBD_BL2_MASK, brightness); 306 + ret = regmap_update_bits(ec->regmap, T14S_EC_REG_KBD_BL2, 307 + T14S_EC_KBD_BL2_MASK, val); 308 + if (ret < 0) 309 + return ret; 310 + 311 + return 0; 312 + } 313 + 314 + static enum led_brightness t14s_kbd_bl_get(struct led_classdev *led_cdev) 315 + { 316 + struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 317 + kbd_backlight); 318 + unsigned int val; 319 + int ret; 320 + 321 + ret = regmap_read(ec->regmap, T14S_EC_REG_KBD_BL1, &val); 322 + if (ret < 0) 323 + return ret; 324 + 325 + return FIELD_GET(T14S_EC_KBD_BL1_MASK, val); 326 + } 327 + 328 + static void t14s_kbd_bl_update(struct t14s_ec *ec) 329 + { 330 + enum led_brightness brightness = t14s_kbd_bl_get(&ec->kbd_backlight); 331 + 332 + led_classdev_notify_brightness_hw_changed(&ec->kbd_backlight, brightness); 333 + } 334 + 335 + static int t14s_kbd_backlight_probe(struct t14s_ec *ec) 336 + { 337 + ec->kbd_backlight.name = "platform::kbd_backlight"; 338 + ec->kbd_backlight.flags = LED_BRIGHT_HW_CHANGED; 339 + ec->kbd_backlight.max_brightness = 2; 340 + ec->kbd_backlight.brightness_set_blocking = t14s_kbd_bl_set; 341 + ec->kbd_backlight.brightness_get = t14s_kbd_bl_get; 342 + 343 + return devm_led_classdev_register(ec->dev, &ec->kbd_backlight); 344 + } 345 + 346 + static enum led_brightness t14s_audio_led_get(struct t14s_ec *ec, u8 led_bit) 347 + { 348 + unsigned int val; 349 + int ret; 350 + 351 + ret = regmap_read(ec->regmap, T14S_EC_REG_AUD, &val); 352 + if (ret < 0) 353 + return ret; 354 + 355 + return !!(val & led_bit) ? LED_ON : LED_OFF; 356 + } 357 + 358 + static enum led_brightness t14s_audio_led_set(struct t14s_ec *ec, 359 + u8 led_mask, 360 + enum led_brightness brightness) 361 + { 362 + return regmap_assign_bits(ec->regmap, T14S_EC_REG_AUD, led_mask, brightness > 0); 363 + } 364 + 365 + static enum led_brightness t14s_mic_mute_led_get(struct led_classdev *led_cdev) 366 + { 367 + struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 368 + led_mic_mute); 369 + 370 + return t14s_audio_led_get(ec, T14S_EC_MIC_MUTE_LED); 371 + } 372 + 373 + static int t14s_mic_mute_led_set(struct led_classdev *led_cdev, 374 + enum led_brightness brightness) 375 + { 376 + struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 377 + led_mic_mute); 378 + 379 + return t14s_audio_led_set(ec, T14S_EC_MIC_MUTE_LED, brightness); 380 + } 381 + 382 + static enum led_brightness t14s_spk_mute_led_get(struct led_classdev *led_cdev) 383 + { 384 + struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 385 + led_spk_mute); 386 + 387 + return t14s_audio_led_get(ec, T14S_EC_SPK_MUTE_LED); 388 + } 389 + 390 + static int t14s_spk_mute_led_set(struct led_classdev *led_cdev, 391 + enum led_brightness brightness) 392 + { 393 + struct t14s_ec *ec = container_of(led_cdev, struct t14s_ec, 394 + led_spk_mute); 395 + 396 + return t14s_audio_led_set(ec, T14S_EC_SPK_MUTE_LED, brightness); 397 + } 398 + 399 + static int t14s_kbd_audio_led_probe(struct t14s_ec *ec) 400 + { 401 + int ret; 402 + 403 + ec->led_mic_mute.name = "platform::micmute"; 404 + ec->led_mic_mute.max_brightness = 1; 405 + ec->led_mic_mute.default_trigger = "audio-micmute"; 406 + ec->led_mic_mute.brightness_set_blocking = t14s_mic_mute_led_set; 407 + ec->led_mic_mute.brightness_get = t14s_mic_mute_led_get; 408 + 409 + ec->led_spk_mute.name = "platform::mute"; 410 + ec->led_spk_mute.max_brightness = 1; 411 + ec->led_spk_mute.default_trigger = "audio-mute"; 412 + ec->led_spk_mute.brightness_set_blocking = t14s_spk_mute_led_set; 413 + ec->led_spk_mute.brightness_get = t14s_spk_mute_led_get; 414 + 415 + ret = devm_led_classdev_register(ec->dev, &ec->led_mic_mute); 416 + if (ret) 417 + return ret; 418 + 419 + return devm_led_classdev_register(ec->dev, &ec->led_spk_mute); 420 + } 421 + 422 + static const struct key_entry t14s_keymap[] = { 423 + T14S_EC_KEY_ENTRY(FN_4, KEY_SLEEP), 424 + T14S_EC_KEY_ENTRY(FN_N, KEY_VENDOR), 425 + T14S_EC_KEY_ENTRY(FN_F4, KEY_MICMUTE), 426 + T14S_EC_KEY_ENTRY(FN_F7, KEY_SWITCHVIDEOMODE), 427 + T14S_EC_KEY_ENTRY(FN_F8, KEY_PERFORMANCE), 428 + T14S_EC_KEY_ENTRY(FN_F10, KEY_SELECTIVE_SCREENSHOT), 429 + T14S_EC_KEY_ENTRY(FN_F11, KEY_LINK_PHONE), 430 + T14S_EC_KEY_ENTRY(FN_F12, KEY_BOOKMARKS), 431 + T14S_EC_KEY_ENTRY(FN_SPACE, KEY_KBDILLUMTOGGLE), 432 + T14S_EC_KEY_ENTRY(FN_ESC, KEY_FN_ESC), 433 + T14S_EC_KEY_ENTRY(FN_TAB, KEY_ZOOM), 434 + T14S_EC_KEY_ENTRY(FN_RIGHT_SHIFT, KEY_FN_RIGHT_SHIFT), 435 + T14S_EC_KEY_ENTRY(TP_DOUBLE_TAP, KEY_PROG4), 436 + { KE_END } 437 + }; 438 + 439 + static int t14s_input_probe(struct t14s_ec *ec) 440 + { 441 + int ret; 442 + 443 + ec->inputdev = devm_input_allocate_device(ec->dev); 444 + if (!ec->inputdev) 445 + return -ENOMEM; 446 + 447 + ec->inputdev->name = "ThinkPad Extra Buttons"; 448 + ec->inputdev->phys = "thinkpad/input0"; 449 + ec->inputdev->id.bustype = BUS_HOST; 450 + ec->inputdev->dev.parent = ec->dev; 451 + 452 + ret = sparse_keymap_setup(ec->inputdev, t14s_keymap, NULL); 453 + if (ret) 454 + return ret; 455 + 456 + return input_register_device(ec->inputdev); 457 + } 458 + 459 + static irqreturn_t t14s_ec_irq_handler(int irq, void *data) 460 + { 461 + struct t14s_ec *ec = data; 462 + int ret; 463 + u8 val; 464 + 465 + ret = t14s_ec_read_evt(ec, &val); 466 + if (ret < 0) { 467 + dev_err(ec->dev, "Failed to read event\n"); 468 + return IRQ_HANDLED; 469 + } 470 + 471 + switch (val) { 472 + case T14S_EC_EVT_NONE: 473 + break; 474 + case T14S_EC_EVT_KEY_FN_SPACE: 475 + t14s_kbd_bl_update(ec); 476 + fallthrough; 477 + case T14S_EC_EVT_KEY_FN_F4: 478 + case T14S_EC_EVT_KEY_FN_F7: 479 + case T14S_EC_EVT_KEY_FN_4: 480 + case T14S_EC_EVT_KEY_FN_F8: 481 + case T14S_EC_EVT_KEY_FN_F12: 482 + case T14S_EC_EVT_KEY_FN_TAB: 483 + case T14S_EC_EVT_KEY_FN_F10: 484 + case T14S_EC_EVT_KEY_FN_N: 485 + case T14S_EC_EVT_KEY_FN_F11: 486 + case T14S_EC_EVT_KEY_FN_ESC: 487 + case T14S_EC_EVT_KEY_FN_RIGHT_SHIFT: 488 + case T14S_EC_EVT_KEY_TP_DOUBLE_TAP: 489 + sparse_keymap_report_event(ec->inputdev, 490 + T14S_EC_KEY_EVT_OFFSET + val, 1, true); 491 + break; 492 + case T14S_EC_EVT_AC_CONNECTED: 493 + dev_dbg(ec->dev, "AC connected\n"); 494 + break; 495 + case T14S_EC_EVT_AC_DISCONNECTED: 496 + dev_dbg(ec->dev, "AC disconnected\n"); 497 + break; 498 + case T14S_EC_EVT_KEY_POWER: 499 + dev_dbg(ec->dev, "power button\n"); 500 + break; 501 + case T14S_EC_EVT_LID_OPEN: 502 + dev_dbg(ec->dev, "LID open\n"); 503 + break; 504 + case T14S_EC_EVT_LID_CLOSED: 505 + dev_dbg(ec->dev, "LID closed\n"); 506 + break; 507 + case T14S_EC_EVT_THERMAL_TZ40: 508 + dev_dbg(ec->dev, "Thermal Zone 40 Status Change Event (CPU/GPU)\n"); 509 + break; 510 + case T14S_EC_EVT_THERMAL_TZ42: 511 + dev_dbg(ec->dev, "Thermal Zone 42 Status Change Event (Battery)\n"); 512 + break; 513 + case T14S_EC_EVT_THERMAL_TZ39: 514 + dev_dbg(ec->dev, "Thermal Zone 39 Status Change Event (CPU/GPU)\n"); 515 + break; 516 + case T14S_EC_EVT_KEY_FN_G: 517 + dev_dbg(ec->dev, "FN + G - toggle double-tapping\n"); 518 + break; 519 + case T14S_EC_EVT_KEY_FN_L: 520 + dev_dbg(ec->dev, "FN + L - low performance mode\n"); 521 + break; 522 + case T14S_EC_EVT_KEY_FN_M: 523 + dev_dbg(ec->dev, "FN + M - medium performance mode\n"); 524 + break; 525 + case T14S_EC_EVT_KEY_FN_H: 526 + dev_dbg(ec->dev, "FN + H - high performance mode\n"); 527 + break; 528 + case T14S_EC_EVT_KEY_FN_T: 529 + dev_dbg(ec->dev, "FN + T - toggle intelligent cooling mode\n"); 530 + break; 531 + case T14S_EC_EVT_KEY_FN_D: 532 + dev_dbg(ec->dev, "FN + D - toggle privacy guard mode\n"); 533 + break; 534 + default: 535 + dev_info(ec->dev, "Unknown EC event: 0x%02x\n", val); 536 + break; 537 + } 538 + 539 + return IRQ_HANDLED; 540 + } 541 + 542 + static int t14s_ec_probe(struct i2c_client *client) 543 + { 544 + struct device *dev = &client->dev; 545 + struct t14s_ec *ec; 546 + int ret; 547 + 548 + ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL); 549 + if (!ec) 550 + return -ENOMEM; 551 + 552 + ec->dev = dev; 553 + 554 + ec->regmap = devm_regmap_init(dev, &t14s_ec_regmap_bus, 555 + ec, &t14s_ec_regmap_config); 556 + if (IS_ERR(ec->regmap)) 557 + return dev_err_probe(dev, PTR_ERR(ec->regmap), 558 + "Failed to init regmap\n"); 559 + 560 + ret = devm_request_threaded_irq(dev, client->irq, NULL, 561 + t14s_ec_irq_handler, 562 + IRQF_ONESHOT, dev_name(dev), ec); 563 + if (ret < 0) 564 + return dev_err_probe(dev, ret, "Failed to get IRQ\n"); 565 + 566 + ret = t14s_leds_probe(ec); 567 + if (ret < 0) 568 + return ret; 569 + 570 + ret = t14s_kbd_backlight_probe(ec); 571 + if (ret < 0) 572 + return ret; 573 + 574 + ret = t14s_kbd_audio_led_probe(ec); 575 + if (ret < 0) 576 + return ret; 577 + 578 + ret = t14s_input_probe(ec); 579 + if (ret < 0) 580 + return ret; 581 + 582 + /* 583 + * Disable wakeup support by default, because the driver currently does 584 + * not support masking any events and the laptop should not wake up when 585 + * the LID is closed. 586 + */ 587 + device_wakeup_disable(dev); 588 + 589 + return 0; 590 + } 591 + 592 + static const struct of_device_id t14s_ec_of_match[] = { 593 + { .compatible = "lenovo,thinkpad-t14s-ec" }, 594 + {} 595 + }; 596 + MODULE_DEVICE_TABLE(of, t14s_ec_of_match); 597 + 598 + static const struct i2c_device_id t14s_ec_i2c_id_table[] = { 599 + { "thinkpad-t14s-ec", }, 600 + {} 601 + }; 602 + MODULE_DEVICE_TABLE(i2c, t14s_ec_i2c_id_table); 603 + 604 + static struct i2c_driver t14s_ec_i2c_driver = { 605 + .driver = { 606 + .name = "thinkpad-t14s-ec", 607 + .of_match_table = t14s_ec_of_match, 608 + }, 609 + .probe = t14s_ec_probe, 610 + .id_table = t14s_ec_i2c_id_table, 611 + }; 612 + module_i2c_driver(t14s_ec_i2c_driver); 613 + 614 + MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); 615 + MODULE_DESCRIPTION("Lenovo Thinkpad T14s Embedded Controller"); 616 + MODULE_LICENSE("GPL");
+12
drivers/platform/x86/Kconfig
··· 118 118 To compile this driver as a module, choose M here: the module will 119 119 be called xiaomi-wmi. 120 120 121 + config REDMI_WMI 122 + tristate "Redmibook WMI key driver" 123 + depends on ACPI_WMI 124 + depends on INPUT 125 + select INPUT_SPARSEKMAP 126 + help 127 + Say Y here if you want support for WMI-based hotkey events on 128 + Xiaomi Redmibook devices. 129 + 130 + To compile this driver as a module, choose M here: the module will 131 + be called redmi-wmi. 132 + 121 133 config GIGABYTE_WMI 122 134 tristate "Gigabyte WMI temperature driver" 123 135 depends on ACPI_WMI
+1
drivers/platform/x86/Makefile
··· 13 13 obj-$(CONFIG_MXM_WMI) += mxm-wmi.o 14 14 obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o 15 15 obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o 16 + obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o 16 17 obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o 17 18 18 19 # Acer
+2 -2
drivers/platform/x86/amd/hsmp/acpi.c
··· 495 495 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 496 496 ret = hsmp_get_tbl_dram_base(sock_ind); 497 497 if (ret) 498 - dev_err(dev, "Failed to init metric table\n"); 498 + dev_info(dev, "Failed to init metric table\n"); 499 499 } 500 500 501 501 ret = hsmp_create_sensor(dev, sock_ind); 502 502 if (ret) 503 - dev_err(dev, "Failed to register HSMP sensors with hwmon\n"); 503 + dev_info(dev, "Failed to register HSMP sensors with hwmon\n"); 504 504 505 505 dev_set_drvdata(dev, &hsmp_pdev->sock[sock_ind]); 506 506
+2 -2
drivers/platform/x86/amd/hsmp/plat.c
··· 189 189 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 190 190 ret = hsmp_get_tbl_dram_base(i); 191 191 if (ret) 192 - dev_err(dev, "Failed to init metric table\n"); 192 + dev_info(dev, "Failed to init metric table\n"); 193 193 } 194 194 195 195 /* Register with hwmon interface for reporting power */ 196 196 ret = hsmp_create_sensor(dev, i); 197 197 if (ret) 198 - dev_err(dev, "Failed to register HSMP sensors with hwmon\n"); 198 + dev_info(dev, "Failed to register HSMP sensors with hwmon\n"); 199 199 } 200 200 201 201 return 0;
+81 -6
drivers/platform/x86/amd/pmf/acpi.c
··· 161 161 return !!(pdev->supported_func & BIT(index - 1)); 162 162 } 163 163 164 + int is_apmf_bios_input_notifications_supported(struct amd_pmf_dev *pdev) 165 + { 166 + return !!(pdev->notifications & CUSTOM_BIOS_INPUT_BITS); 167 + } 168 + 164 169 int apts_get_static_slider_granular_v2(struct amd_pmf_dev *pdev, 165 170 struct amd_pmf_apts_granular_output *data, u32 apts_idx) 166 171 { ··· 320 315 return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, req, sizeof(*req)); 321 316 } 322 317 318 + int apmf_get_sbios_requests_v1(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v1 *req) 319 + { 320 + return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, req, sizeof(*req)); 321 + } 322 + 323 323 int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req) 324 324 { 325 325 return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, 326 326 req, sizeof(*req)); 327 + } 328 + 329 + static void amd_pmf_handle_early_preq(struct amd_pmf_dev *pdev) 330 + { 331 + if (!pdev->cb_flag) 332 + return; 333 + 334 + amd_pmf_invoke_cmd_enact(pdev); 335 + pdev->cb_flag = false; 327 336 } 328 337 329 338 static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data) ··· 348 329 guard(mutex)(&pmf_dev->cb_mutex); 349 330 350 331 ret = apmf_get_sbios_requests_v2(pmf_dev, &pmf_dev->req); 351 - if (ret) 332 + if (ret) { 352 333 dev_err(pmf_dev->dev, "Failed to get v2 SBIOS requests: %d\n", ret); 334 + return; 335 + } 336 + 337 + dev_dbg(pmf_dev->dev, "Pending request (preq): 0x%x\n", pmf_dev->req.pending_req); 338 + 339 + amd_pmf_handle_early_preq(pmf_dev); 340 + } 341 + 342 + static void apmf_event_handler_v1(acpi_handle handle, u32 event, void *data) 343 + { 344 + struct amd_pmf_dev *pmf_dev = data; 345 + int ret; 346 + 347 + guard(mutex)(&pmf_dev->cb_mutex); 348 + 349 + ret = apmf_get_sbios_requests_v1(pmf_dev, &pmf_dev->req1); 350 + if (ret) { 351 + dev_err(pmf_dev->dev, "Failed to get v1 SBIOS requests: %d\n", ret); 352 + return; 353 + } 354 + 355 + dev_dbg(pmf_dev->dev, "Pending request (preq1): 0x%x\n", pmf_dev->req1.pending_req); 356 + 357 + amd_pmf_handle_early_preq(pmf_dev); 353 358 } 354 359 355 360 static void apmf_event_handler(acpi_handle handle, u32 event, void *data) ··· 428 385 429 386 pdev->pmf_if_version = output.version; 430 387 388 + pdev->notifications = output.notification_mask; 431 389 return 0; 432 390 } 433 391 ··· 465 421 return apmf_if_call_store_buffer(pdev, APMF_FUNC_DYN_SLIDER_DC, data, sizeof(*data)); 466 422 } 467 423 424 + static apmf_event_handler_t apmf_event_handlers[] = { 425 + [PMF_IF_V1] = apmf_event_handler_v1, 426 + [PMF_IF_V2] = apmf_event_handler_v2, 427 + }; 428 + 468 429 int apmf_install_handler(struct amd_pmf_dev *pmf_dev) 469 430 { 470 431 acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev); ··· 489 440 apmf_event_handler(ahandle, 0, pmf_dev); 490 441 } 491 442 492 - if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) { 443 + if (!pmf_dev->smart_pc_enabled) 444 + return -EINVAL; 445 + 446 + switch (pmf_dev->pmf_if_version) { 447 + case PMF_IF_V1: 448 + if (!is_apmf_bios_input_notifications_supported(pmf_dev)) 449 + break; 450 + fallthrough; 451 + case PMF_IF_V2: 493 452 status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY, 494 - apmf_event_handler_v2, pmf_dev); 453 + apmf_event_handlers[pmf_dev->pmf_if_version], pmf_dev); 495 454 if (ACPI_FAILURE(status)) { 496 - dev_err(pmf_dev->dev, "failed to install notify handler for custom BIOS inputs\n"); 455 + dev_err(pmf_dev->dev, 456 + "failed to install notify handler v%d for custom BIOS inputs\n", 457 + pmf_dev->pmf_if_version); 497 458 return -ENODEV; 498 459 } 460 + break; 461 + default: 462 + break; 499 463 } 500 464 501 465 return 0; ··· 562 500 is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS)) 563 501 acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler); 564 502 565 - if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) 566 - acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler_v2); 503 + if (!pmf_dev->smart_pc_enabled) 504 + return; 505 + 506 + switch (pmf_dev->pmf_if_version) { 507 + case PMF_IF_V1: 508 + if (!is_apmf_bios_input_notifications_supported(pmf_dev)) 509 + break; 510 + fallthrough; 511 + case PMF_IF_V2: 512 + acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, 513 + apmf_event_handlers[pmf_dev->pmf_if_version]); 514 + break; 515 + default: 516 + break; 517 + } 567 518 } 568 519 569 520 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
+68 -9
drivers/platform/x86/amd/pmf/pmf.h
··· 93 93 #define PMF_POLICY_BIOS_OUTPUT_1 10 94 94 #define PMF_POLICY_BIOS_OUTPUT_2 11 95 95 #define PMF_POLICY_P3T 38 96 + #define PMF_POLICY_PMF_PPT 54 97 + #define PMF_POLICY_PMF_PPT_APU_ONLY 55 96 98 #define PMF_POLICY_BIOS_OUTPUT_3 57 97 99 #define PMF_POLICY_BIOS_OUTPUT_4 58 98 100 #define PMF_POLICY_BIOS_OUTPUT_5 59 ··· 118 116 #define PMF_IF_V2 2 119 117 120 118 #define APTS_MAX_STATES 16 119 + #define CUSTOM_BIOS_INPUT_BITS GENMASK(16, 7) 120 + 121 + typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data); 121 122 122 123 /* APTS PMF BIOS Interface */ 123 124 struct amd_pmf_apts_output { ··· 187 182 u32 stt_min_limit; 188 183 u8 skin_temp_apu; 189 184 u8 skin_temp_hs2; 185 + } __packed; 186 + 187 + /* As per APMF spec 1.3 */ 188 + struct apmf_sbios_req_v1 { 189 + u16 size; 190 + u32 pending_req; 191 + u8 rsvd; 192 + u8 cql_event; 193 + u8 amt_event; 194 + u32 fppt; 195 + u32 sppt; 196 + u32 sppt_apu_only; 197 + u32 spl; 198 + u32 stt_min_limit; 199 + u8 skin_temp_apu; 200 + u8 skin_temp_hs2; 201 + u8 enable_cnqf; 202 + u32 custom_policy[10]; 190 203 } __packed; 191 204 192 205 struct apmf_sbios_req_v2 { ··· 354 331 POWER_MODE_V2_MAX, 355 332 }; 356 333 334 + struct pmf_bios_inputs_prev { 335 + u32 custom_bios_inputs[10]; 336 + }; 337 + 357 338 struct amd_pmf_dev { 358 339 void __iomem *regbase; 359 340 void __iomem *smu_virt_addr; ··· 402 375 struct resource *res; 403 376 struct apmf_sbios_req_v2 req; /* To get custom bios pending request */ 404 377 struct mutex cb_mutex; 378 + u32 notifications; 379 + struct apmf_sbios_req_v1 req1; 380 + struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */ 381 + bool cb_flag; /* To handle first custom BIOS input */ 405 382 }; 406 383 407 384 struct apmf_sps_prop_granular_v2 { ··· 652 621 TA_MAX, 653 622 }; 654 623 655 - enum apmf_smartpc_custom_bios_inputs { 656 - APMF_SMARTPC_CUSTOM_BIOS_INPUT1, 657 - APMF_SMARTPC_CUSTOM_BIOS_INPUT2, 624 + struct amd_pmf_pb_bitmap { 625 + const char *name; 626 + u32 bit_mask; 658 627 }; 659 628 660 - enum apmf_preq_smartpc { 661 - NOTIFY_CUSTOM_BIOS_INPUT1 = 5, 662 - NOTIFY_CUSTOM_BIOS_INPUT2, 629 + static const struct amd_pmf_pb_bitmap custom_bios_inputs[] __used = { 630 + {"NOTIFY_CUSTOM_BIOS_INPUT1", BIT(5)}, 631 + {"NOTIFY_CUSTOM_BIOS_INPUT2", BIT(6)}, 632 + {"NOTIFY_CUSTOM_BIOS_INPUT3", BIT(7)}, 633 + {"NOTIFY_CUSTOM_BIOS_INPUT4", BIT(8)}, 634 + {"NOTIFY_CUSTOM_BIOS_INPUT5", BIT(9)}, 635 + {"NOTIFY_CUSTOM_BIOS_INPUT6", BIT(10)}, 636 + {"NOTIFY_CUSTOM_BIOS_INPUT7", BIT(11)}, 637 + {"NOTIFY_CUSTOM_BIOS_INPUT8", BIT(12)}, 638 + {"NOTIFY_CUSTOM_BIOS_INPUT9", BIT(13)}, 639 + {"NOTIFY_CUSTOM_BIOS_INPUT10", BIT(14)}, 640 + }; 641 + 642 + static const struct amd_pmf_pb_bitmap custom_bios_inputs_v1[] __used = { 643 + {"NOTIFY_CUSTOM_BIOS_INPUT1", BIT(7)}, 644 + {"NOTIFY_CUSTOM_BIOS_INPUT2", BIT(8)}, 645 + {"NOTIFY_CUSTOM_BIOS_INPUT3", BIT(9)}, 646 + {"NOTIFY_CUSTOM_BIOS_INPUT4", BIT(10)}, 647 + {"NOTIFY_CUSTOM_BIOS_INPUT5", BIT(11)}, 648 + {"NOTIFY_CUSTOM_BIOS_INPUT6", BIT(12)}, 649 + {"NOTIFY_CUSTOM_BIOS_INPUT7", BIT(13)}, 650 + {"NOTIFY_CUSTOM_BIOS_INPUT8", BIT(14)}, 651 + {"NOTIFY_CUSTOM_BIOS_INPUT9", BIT(15)}, 652 + {"NOTIFY_CUSTOM_BIOS_INPUT10", BIT(16)}, 663 653 }; 664 654 665 655 enum platform_type { ··· 729 677 u32 stt_skintemp_apu; /* in C */ 730 678 u32 stt_skintemp_hs2; /* in C */ 731 679 u32 p3t_limit; /* in mW */ 680 + u32 pmf_ppt; /* in mW */ 681 + u32 pmf_ppt_apu_only; /* in mW */ 732 682 }; 733 683 734 684 /* Input conditions */ ··· 740 686 u32 power_slider; 741 687 u32 lid_state; 742 688 bool user_present; 743 - u32 bios_input1; 744 - u32 bios_input2; 689 + u32 bios_input_1[2]; 745 690 u32 monitor_count; 746 691 u32 rsvd2[2]; 747 692 u32 bat_design; ··· 764 711 u32 workload_type; 765 712 u32 display_type; 766 713 u32 display_state; 767 - u32 rsvd5[150]; 714 + u32 rsvd5_1[17]; 715 + u32 bios_input_2[8]; 716 + u32 rsvd5[125]; 768 717 }; 769 718 770 719 struct ta_pmf_load_policy_table { ··· 792 737 struct ta_pmf_action { 793 738 u32 action_index; 794 739 u32 value; 740 + u32 spl_arg; 795 741 }; 796 742 797 743 /* Output actions from TA */ ··· 834 778 int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev, bool alloc_buffer); 835 779 int amd_pmf_notify_sbios_heartbeat_event_v2(struct amd_pmf_dev *dev, u8 flag); 836 780 u32 fixp_q88_fromint(u32 val); 781 + int is_apmf_bios_input_notifications_supported(struct amd_pmf_dev *pdev); 837 782 838 783 /* SPS Layer */ 839 784 int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf); ··· 862 805 void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev); 863 806 void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms); 864 807 int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req); 808 + int apmf_get_sbios_requests_v1(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v1 *req); 865 809 int apmf_get_sbios_requests_v2(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v2 *req); 866 810 867 811 void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event); ··· 886 828 /* Smart PC - TA interfaces */ 887 829 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); 888 830 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); 831 + int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev); 889 832 890 833 #endif /* PMF_H */
+71 -9
drivers/platform/x86/amd/pmf/spc.c
··· 70 70 } 71 71 } 72 72 73 + static u32 amd_pmf_get_ta_custom_bios_inputs(struct ta_pmf_enact_table *in, int index) 74 + { 75 + switch (index) { 76 + case 0 ... 1: 77 + return in->ev_info.bios_input_1[index]; 78 + case 2 ... 9: 79 + return in->ev_info.bios_input_2[index - 2]; 80 + default: 81 + return 0; 82 + } 83 + } 84 + 73 85 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) 74 86 { 87 + int i; 88 + 75 89 dev_dbg(dev->dev, "==== TA inputs START ====\n"); 76 90 dev_dbg(dev->dev, "Slider State: %s\n", ta_slider_as_str(in->ev_info.power_slider)); 77 91 dev_dbg(dev->dev, "Power Source: %s\n", amd_pmf_source_as_str(in->ev_info.power_source)); ··· 104 90 dev_dbg(dev->dev, "Platform type: %s\n", platform_type_as_str(in->ev_info.platform_type)); 105 91 dev_dbg(dev->dev, "Laptop placement: %s\n", 106 92 laptop_placement_as_str(in->ev_info.device_state)); 107 - dev_dbg(dev->dev, "Custom BIOS input1: %u\n", in->ev_info.bios_input1); 108 - dev_dbg(dev->dev, "Custom BIOS input2: %u\n", in->ev_info.bios_input2); 93 + for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) 94 + dev_dbg(dev->dev, "Custom BIOS input%d: %u\n", i + 1, 95 + amd_pmf_get_ta_custom_bios_inputs(in, i)); 109 96 dev_dbg(dev->dev, "==== TA inputs END ====\n"); 110 97 } 111 98 #else 112 99 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {} 113 100 #endif 114 101 102 + /* 103 + * This helper function sets the appropriate BIOS input value in the TA enact 104 + * table based on the provided index. We need this approach because the custom 105 + * BIOS input array is not continuous, due to the existing TA structure layout. 106 + */ 107 + static void amd_pmf_set_ta_custom_bios_input(struct ta_pmf_enact_table *in, int index, u32 value) 108 + { 109 + switch (index) { 110 + case 0 ... 1: 111 + in->ev_info.bios_input_1[index] = value; 112 + break; 113 + case 2 ... 9: 114 + in->ev_info.bios_input_2[index - 2] = value; 115 + break; 116 + default: 117 + return; 118 + } 119 + } 120 + 121 + static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, u32 pending_req, 122 + const struct amd_pmf_pb_bitmap *inputs, 123 + const u32 *custom_policy, struct ta_pmf_enact_table *in) 124 + { 125 + unsigned int i; 126 + 127 + for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) { 128 + if (!(pending_req & inputs[i].bit_mask)) 129 + continue; 130 + amd_pmf_set_ta_custom_bios_input(in, i, custom_policy[i]); 131 + pdev->cb_prev.custom_bios_inputs[i] = custom_policy[i]; 132 + dev_dbg(pdev->dev, "Custom BIOS Input[%d]: %u\n", i, custom_policy[i]); 133 + } 134 + } 135 + 115 136 static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev, 116 137 struct ta_pmf_enact_table *in) 117 138 { 118 - if (!pdev->req.pending_req) 139 + unsigned int i; 140 + 141 + for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) 142 + amd_pmf_set_ta_custom_bios_input(in, i, pdev->cb_prev.custom_bios_inputs[i]); 143 + 144 + if (!(pdev->req.pending_req || pdev->req1.pending_req)) 119 145 return; 120 146 121 - switch (pdev->req.pending_req) { 122 - case BIT(NOTIFY_CUSTOM_BIOS_INPUT1): 123 - in->ev_info.bios_input1 = pdev->req.custom_policy[APMF_SMARTPC_CUSTOM_BIOS_INPUT1]; 147 + if (!pdev->smart_pc_enabled) 148 + return; 149 + 150 + switch (pdev->pmf_if_version) { 151 + case PMF_IF_V1: 152 + if (!is_apmf_bios_input_notifications_supported(pdev)) 153 + return; 154 + amd_pmf_update_bios_inputs(pdev, pdev->req1.pending_req, custom_bios_inputs_v1, 155 + pdev->req1.custom_policy, in); 124 156 break; 125 - case BIT(NOTIFY_CUSTOM_BIOS_INPUT2): 126 - in->ev_info.bios_input2 = pdev->req.custom_policy[APMF_SMARTPC_CUSTOM_BIOS_INPUT2]; 157 + case PMF_IF_V2: 158 + amd_pmf_update_bios_inputs(pdev, pdev->req.pending_req, custom_bios_inputs, 159 + pdev->req.custom_policy, in); 127 160 break; 128 161 default: 129 - dev_dbg(pdev->dev, "Invalid preq for BIOS input: 0x%x\n", pdev->req.pending_req); 162 + break; 130 163 } 131 164 132 165 /* Clear pending requests after handling */ 133 166 memset(&pdev->req, 0, sizeof(pdev->req)); 167 + memset(&pdev->req1, 0, sizeof(pdev->req1)); 134 168 } 135 169 136 170 static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in)
+1 -1
drivers/platform/x86/amd/pmf/sps.c
··· 283 283 284 284 bool is_pprof_balanced(struct amd_pmf_dev *pmf) 285 285 { 286 - return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false; 286 + return pmf->current_profile == PLATFORM_PROFILE_BALANCED; 287 287 } 288 288 289 289 static int amd_pmf_profile_get(struct device *dev,
+20 -2
drivers/platform/x86/amd/pmf/tee-if.c
··· 147 147 } 148 148 break; 149 149 150 + case PMF_POLICY_PMF_PPT: 151 + if (dev->prev_data->pmf_ppt != val) { 152 + amd_pmf_send_cmd(dev, SET_PMF_PPT, false, val, NULL); 153 + dev_dbg(dev->dev, "update PMF PPT: %u\n", val); 154 + dev->prev_data->pmf_ppt = val; 155 + } 156 + break; 157 + 158 + case PMF_POLICY_PMF_PPT_APU_ONLY: 159 + if (dev->prev_data->pmf_ppt_apu_only != val) { 160 + amd_pmf_send_cmd(dev, SET_PMF_PPT_APU_ONLY, false, val, NULL); 161 + dev_dbg(dev->dev, "update PMF PPT APU ONLY: %u\n", val); 162 + dev->prev_data->pmf_ppt_apu_only = val; 163 + } 164 + break; 165 + 150 166 case PMF_POLICY_SYSTEM_STATE: 151 167 switch (val) { 152 168 case 0: ··· 225 209 } 226 210 } 227 211 228 - static int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev) 212 + int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev) 229 213 { 230 214 struct ta_pmf_shared_memory *ta_sm = NULL; 231 215 struct ta_pmf_enact_result *out = NULL; ··· 577 561 ret = amd_pmf_start_policy_engine(dev); 578 562 dev_dbg(dev->dev, "start policy engine ret: %d\n", ret); 579 563 status = ret == TA_PMF_TYPE_SUCCESS; 580 - if (status) 564 + if (status) { 565 + dev->cb_flag = true; 581 566 break; 567 + } 582 568 amd_pmf_tee_deinit(dev); 583 569 } 584 570
+62 -42
drivers/platform/x86/barco-p50-gpio.c
··· 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 12 13 13 #include <linux/delay.h> 14 + #include <linux/dev_printk.h> 14 15 #include <linux/dmi.h> 15 16 #include <linux/err.h> 16 17 #include <linux/io.h> ··· 19 18 #include <linux/leds.h> 20 19 #include <linux/module.h> 21 20 #include <linux/platform_device.h> 22 - #include <linux/gpio_keys.h> 23 21 #include <linux/gpio/driver.h> 24 22 #include <linux/gpio/machine.h> 25 - #include <linux/input.h> 23 + #include <linux/gpio/property.h> 24 + #include <linux/input-event-codes.h> 25 + #include <linux/property.h> 26 26 27 27 28 28 #define DRIVER_NAME "barco-p50-gpio" ··· 80 78 [P50_GPIO_LINE_BTN] = "identify-button", 81 79 }; 82 80 83 - 84 - static struct gpiod_lookup_table p50_gpio_led_table = { 85 - .dev_id = "leds-gpio", 86 - .table = { 87 - GPIO_LOOKUP_IDX(DRIVER_NAME, P50_GPIO_LINE_LED, NULL, 0, GPIO_ACTIVE_HIGH), 88 - {} 89 - } 81 + static const struct software_node gpiochip_node = { 82 + .name = DRIVER_NAME, 90 83 }; 91 84 92 85 /* GPIO LEDs */ 93 - static struct gpio_led leds[] = { 94 - { .name = "identify" } 86 + static const struct software_node gpio_leds_node = { 87 + .name = "gpio-leds-identify", 95 88 }; 96 89 97 - static struct gpio_led_platform_data leds_pdata = { 98 - .num_leds = ARRAY_SIZE(leds), 99 - .leds = leds, 90 + static const struct property_entry identify_led_props[] = { 91 + PROPERTY_ENTRY_GPIO("gpios", &gpiochip_node, P50_GPIO_LINE_LED, GPIO_ACTIVE_HIGH), 92 + { } 93 + }; 94 + 95 + static const struct software_node identify_led_node = { 96 + .parent = &gpio_leds_node, 97 + .name = "identify", 98 + .properties = identify_led_props, 100 99 }; 101 100 102 101 /* GPIO keyboard */ 103 - static struct gpio_keys_button buttons[] = { 104 - { 105 - .code = KEY_VENDOR, 106 - .gpio = P50_GPIO_LINE_BTN, 107 - .active_low = 1, 108 - .type = EV_KEY, 109 - .value = 1, 110 - }, 102 + static const struct property_entry gpio_keys_props[] = { 103 + PROPERTY_ENTRY_STRING("label", "identify"), 104 + PROPERTY_ENTRY_U32("poll-interval", 100), 105 + { } 111 106 }; 112 107 113 - static struct gpio_keys_platform_data keys_pdata = { 114 - .buttons = buttons, 115 - .nbuttons = ARRAY_SIZE(buttons), 116 - .poll_interval = 100, 117 - .rep = 0, 118 - .name = "identify", 108 + static const struct software_node gpio_keys_node = { 109 + .name = "gpio-keys-identify", 110 + .properties = gpio_keys_props, 119 111 }; 120 112 113 + static struct property_entry vendor_key_props[] = { 114 + PROPERTY_ENTRY_U32("linux,code", KEY_VENDOR), 115 + PROPERTY_ENTRY_GPIO("gpios", &gpiochip_node, P50_GPIO_LINE_BTN, GPIO_ACTIVE_LOW), 116 + { } 117 + }; 118 + 119 + static const struct software_node vendor_key_node = { 120 + .parent = &gpio_keys_node, 121 + .properties = vendor_key_props, 122 + }; 123 + 124 + static const struct software_node *p50_swnodes[] = { 125 + &gpiochip_node, 126 + &gpio_leds_node, 127 + &identify_led_node, 128 + &gpio_keys_node, 129 + &vendor_key_node, 130 + NULL 131 + }; 121 132 122 133 /* low level access routines */ 123 134 ··· 300 285 301 286 static int p50_gpio_probe(struct platform_device *pdev) 302 287 { 288 + struct platform_device_info key_info = { 289 + .name = "gpio-keys-polled", 290 + .id = PLATFORM_DEVID_NONE, 291 + .parent = &pdev->dev, 292 + }; 293 + struct platform_device_info led_info = { 294 + .name = "leds-gpio", 295 + .id = PLATFORM_DEVID_NONE, 296 + .parent = &pdev->dev, 297 + }; 303 298 struct p50_gpio *p50; 304 299 struct resource *res; 305 300 int ret; ··· 364 339 return ret; 365 340 } 366 341 367 - gpiod_add_lookup_table(&p50_gpio_led_table); 342 + ret = software_node_register_node_group(p50_swnodes); 343 + if (ret) 344 + return dev_err_probe(&pdev->dev, ret, "failed to register software nodes"); 368 345 369 - p50->leds_pdev = platform_device_register_data(&pdev->dev, 370 - "leds-gpio", PLATFORM_DEVID_NONE, &leds_pdata, sizeof(leds_pdata)); 371 - 346 + led_info.fwnode = software_node_fwnode(&gpio_leds_node); 347 + p50->leds_pdev = platform_device_register_full(&led_info); 372 348 if (IS_ERR(p50->leds_pdev)) { 373 349 ret = PTR_ERR(p50->leds_pdev); 374 350 dev_err(&pdev->dev, "Could not register leds-gpio: %d\n", ret); 375 351 goto err_leds; 376 352 } 377 353 378 - /* gpio-keys-polled uses old-style gpio interface, pass the right identifier */ 379 - buttons[0].gpio += p50->gc.base; 380 - 381 - p50->keys_pdev = 382 - platform_device_register_data(&pdev->dev, "gpio-keys-polled", 383 - PLATFORM_DEVID_NONE, 384 - &keys_pdata, sizeof(keys_pdata)); 385 - 354 + key_info.fwnode = software_node_fwnode(&gpio_keys_node); 355 + p50->keys_pdev = platform_device_register_full(&key_info); 386 356 if (IS_ERR(p50->keys_pdev)) { 387 357 ret = PTR_ERR(p50->keys_pdev); 388 358 dev_err(&pdev->dev, "Could not register gpio-keys-polled: %d\n", ret); ··· 389 369 err_keys: 390 370 platform_device_unregister(p50->leds_pdev); 391 371 err_leds: 392 - gpiod_remove_lookup_table(&p50_gpio_led_table); 372 + software_node_unregister_node_group(p50_swnodes); 393 373 394 374 return ret; 395 375 } ··· 401 381 platform_device_unregister(p50->keys_pdev); 402 382 platform_device_unregister(p50->leds_pdev); 403 383 404 - gpiod_remove_lookup_table(&p50_gpio_led_table); 384 + software_node_unregister_node_group(p50_swnodes); 405 385 } 406 386 407 387 static struct platform_driver p50_gpio_driver = {
+5 -3
drivers/platform/x86/dell/dell_rbu.c
··· 232 232 done = 1; 233 233 } 234 234 235 - if ((rc = create_packet(temp, packet_length))) 235 + rc = create_packet(temp, packet_length); 236 + if (rc) 236 237 return rc; 237 238 238 239 pr_debug("%p:%td\n", temp, (end - temp)); ··· 277 276 return bytes_copied; 278 277 } 279 278 280 - static int packet_read_list(char *data, size_t * pread_length) 279 + static int packet_read_list(char *data, size_t *pread_length) 281 280 { 282 281 struct packet_data *newpacket; 283 282 int temp_count = 0; ··· 446 445 bytes_left = rbu_data.imagesize - pos; 447 446 data_length = min(bytes_left, count); 448 447 449 - if ((retval = packet_read_list(ptempBuf, &data_length)) < 0) 448 + retval = packet_read_list(ptempBuf, &data_length); 449 + if (retval < 0) 450 450 goto read_rbu_data_exit; 451 451 452 452 if ((pos + count) > rbu_data.imagesize) {
+38 -20
drivers/platform/x86/intel/int3472/discrete.c
··· 129 129 * @hid: The ACPI HID of the device without the instance number e.g. INT347E 130 130 * @type_from: The GPIO type from ACPI ?SDT 131 131 * @type_to: The assigned GPIO type, typically same as @type_from 132 + * @enable_time_us: Enable time in usec for GPIOs mapped to regulators 132 133 * @con_id: The name of the GPIO for the device 133 134 * @polarity_low: GPIO_ACTIVE_LOW true if the @polarity_low is true, 134 135 * GPIO_ACTIVE_HIGH otherwise ··· 139 138 u8 type_from; 140 139 u8 type_to; 141 140 bool polarity_low; 141 + unsigned int enable_time_us; 142 142 const char *con_id; 143 143 }; 144 144 145 145 static const struct int3472_gpio_map int3472_gpio_map[] = { 146 - /* mt9m114 designs declare a powerdown pin which controls the regulators */ 147 - { "INT33F0", INT3472_GPIO_TYPE_POWERDOWN, INT3472_GPIO_TYPE_POWER_ENABLE, false, "vdd" }, 148 - /* ov7251 driver / DT-bindings expect "enable" as con_id for reset */ 149 - { "INT347E", INT3472_GPIO_TYPE_RESET, INT3472_GPIO_TYPE_RESET, false, "enable" }, 146 + { /* mt9m114 designs declare a powerdown pin which controls the regulators */ 147 + .hid = "INT33F0", 148 + .type_from = INT3472_GPIO_TYPE_POWERDOWN, 149 + .type_to = INT3472_GPIO_TYPE_POWER_ENABLE, 150 + .con_id = "vdd", 151 + .enable_time_us = GPIO_REGULATOR_ENABLE_TIME, 152 + }, 153 + { /* ov7251 driver / DT-bindings expect "enable" as con_id for reset */ 154 + .hid = "INT347E", 155 + .type_from = INT3472_GPIO_TYPE_RESET, 156 + .type_to = INT3472_GPIO_TYPE_RESET, 157 + .con_id = "enable", 158 + }, 159 + { /* ov08x40's handshake pin needs a 45 ms delay on some HP laptops */ 160 + .hid = "OVTI08F4", 161 + .type_from = INT3472_GPIO_TYPE_HANDSHAKE, 162 + .type_to = INT3472_GPIO_TYPE_HANDSHAKE, 163 + .con_id = "dvdd", 164 + .enable_time_us = 45 * USEC_PER_MSEC, 165 + }, 150 166 }; 151 167 152 168 static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3472, u8 *type, 153 - const char **con_id, unsigned long *gpio_flags) 169 + const char **con_id, unsigned long *gpio_flags, 170 + unsigned int *enable_time_us) 154 171 { 155 172 struct acpi_device *adev = int3472->sensor; 156 173 unsigned int i; ··· 192 173 *gpio_flags = int3472_gpio_map[i].polarity_low ? 193 174 GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH; 194 175 *con_id = int3472_gpio_map[i].con_id; 176 + *enable_time_us = int3472_gpio_map[i].enable_time_us; 195 177 return; 196 178 } 179 + 180 + *enable_time_us = GPIO_REGULATOR_ENABLE_TIME; 197 181 198 182 switch (*type) { 199 183 case INT3472_GPIO_TYPE_RESET: ··· 226 204 case INT3472_GPIO_TYPE_HANDSHAKE: 227 205 *con_id = "dvdd"; 228 206 *gpio_flags = GPIO_ACTIVE_HIGH; 207 + /* Setups using a handshake pin need 25 ms enable delay */ 208 + *enable_time_us = 25 * USEC_PER_MSEC; 229 209 break; 230 210 default: 231 211 *con_id = "unknown"; ··· 273 249 void *data) 274 250 { 275 251 struct int3472_discrete_device *int3472 = data; 252 + const char *second_sensor = NULL; 276 253 struct acpi_resource_gpio *agpio; 254 + unsigned int enable_time_us; 277 255 u8 active_value, pin, type; 256 + unsigned long gpio_flags; 278 257 union acpi_object *obj; 279 258 struct gpio_desc *gpio; 280 259 const char *err_msg; 281 260 const char *con_id; 282 - unsigned long gpio_flags; 283 261 int ret; 284 262 285 263 if (!acpi_gpio_get_io_resource(ares, &agpio)) ··· 304 278 305 279 type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value); 306 280 307 - int3472_get_con_id_and_polarity(int3472, &type, &con_id, &gpio_flags); 281 + int3472_get_con_id_and_polarity(int3472, &type, &con_id, &gpio_flags, &enable_time_us); 308 282 309 283 pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); 310 284 /* Pin field is not really used under Windows and wraps around at 8 bits */ ··· 354 328 355 329 break; 356 330 case INT3472_GPIO_TYPE_POWER_ENABLE: 357 - ret = skl_int3472_register_regulator(int3472, gpio, 358 - GPIO_REGULATOR_ENABLE_TIME, 359 - con_id, 360 - int3472->quirks.avdd_second_sensor); 361 - if (ret) 362 - err_msg = "Failed to map power-enable to sensor\n"; 363 - 364 - break; 331 + second_sensor = int3472->quirks.avdd_second_sensor; 332 + fallthrough; 365 333 case INT3472_GPIO_TYPE_HANDSHAKE: 366 - /* Setups using a handshake pin need 25 ms enable delay */ 367 - ret = skl_int3472_register_regulator(int3472, gpio, 368 - 25 * USEC_PER_MSEC, 369 - con_id, NULL); 334 + ret = skl_int3472_register_regulator(int3472, gpio, enable_time_us, 335 + con_id, second_sensor); 370 336 if (ret) 371 - err_msg = "Failed to map handshake to sensor\n"; 337 + err_msg = "Failed to register regulator\n"; 372 338 373 339 break; 374 340 default: /* Never reached */
+1 -1
drivers/platform/x86/intel/pmc/Makefile
··· 4 4 # 5 5 6 6 intel_pmc_core-y := core.o spt.o cnp.o icl.o \ 7 - tgl.o adl.o mtl.o arl.o lnl.o ptl.o 7 + tgl.o adl.o mtl.o arl.o lnl.o ptl.o wcl.o 8 8 obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o 9 9 intel_pmc_core_pltdrv-y := pltdrv.o 10 10 obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o
+4
drivers/platform/x86/intel/pmc/arl.c
··· 725 725 .dmu_guid = ARL_PMT_DMU_GUID, 726 726 .regmap_list = arl_pmc_info_list, 727 727 .map = &arl_socs_reg_map, 728 + .sub_req_show = &pmc_core_substate_req_regs_fops, 728 729 .suspend = cnl_suspend, 729 730 .resume = arl_resume, 730 731 .init = arl_core_init, 732 + .sub_req = pmc_core_pmt_get_lpm_req, 731 733 }; 732 734 733 735 struct pmc_dev_info arl_h_pmc_dev = { ··· 737 735 .dmu_guid = ARL_PMT_DMU_GUID, 738 736 .regmap_list = arl_pmc_info_list, 739 737 .map = &mtl_socm_reg_map, 738 + .sub_req_show = &pmc_core_substate_req_regs_fops, 740 739 .suspend = cnl_suspend, 741 740 .resume = arl_h_resume, 742 741 .init = arl_h_core_init, 742 + .sub_req = pmc_core_pmt_get_lpm_req, 743 743 };
+151 -40
drivers/platform/x86/intel/pmc/core.c
··· 11 11 12 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 13 14 + enum header_type { 15 + HEADER_STATUS, 16 + HEADER_VALUE, 17 + }; 18 + 14 19 #include <linux/bitfield.h> 15 20 #include <linux/debugfs.h> 16 21 #include <linux/delay.h> ··· 833 828 } 834 829 DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_l_sts_regs); 835 830 836 - static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index) 831 + static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, 832 + enum header_type type) 837 833 { 838 834 struct pmc_dev *pmcdev = s->private; 839 835 int mode; 840 836 841 - seq_printf(s, "%30s |", "Element"); 837 + seq_printf(s, "%40s |", "Element"); 842 838 pmc_for_each_mode(mode, pmcdev) 843 839 seq_printf(s, " %9s |", pmc_lpm_modes[mode]); 844 840 845 - seq_printf(s, " %9s |", "Status"); 846 - seq_printf(s, " %11s |\n", "Live Status"); 841 + if (type == HEADER_STATUS) { 842 + seq_printf(s, " %9s |", "Status"); 843 + seq_printf(s, " %11s |\n", "Live Status"); 844 + } else { 845 + seq_printf(s, " %9s |\n", "Value"); 846 + } 847 847 } 848 + 849 + static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) 850 + { 851 + struct pmc_dev *pmcdev = s->private; 852 + unsigned int pmc_idx; 853 + 854 + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); pmc_idx++) { 855 + const struct pmc_bit_map **maps; 856 + unsigned int arr_size, r_idx; 857 + u32 offset, counter; 858 + u32 *lpm_req_regs; 859 + struct pmc *pmc; 860 + 861 + pmc = pmcdev->pmcs[pmc_idx]; 862 + if (!pmc || !pmc->lpm_req_regs) 863 + continue; 864 + 865 + lpm_req_regs = pmc->lpm_req_regs; 866 + maps = pmc->map->s0ix_blocker_maps; 867 + offset = pmc->map->s0ix_blocker_offset; 868 + arr_size = pmc_core_lpm_get_arr_size(maps); 869 + 870 + /* Display the header */ 871 + pmc_core_substate_req_header_show(s, pmc_idx, HEADER_VALUE); 872 + 873 + for (r_idx = 0; r_idx < arr_size; r_idx++) { 874 + const struct pmc_bit_map *map; 875 + 876 + for (map = maps[r_idx]; map->name; map++) { 877 + int mode; 878 + 879 + if (!map->blk) 880 + continue; 881 + 882 + counter = pmc_core_reg_read(pmc, offset); 883 + seq_printf(s, "pmc%u: %34s |", pmc_idx, map->name); 884 + pmc_for_each_mode(mode, pmcdev) { 885 + bool required = *lpm_req_regs & BIT(mode); 886 + 887 + seq_printf(s, " %9s |", required ? "Required" : " "); 888 + } 889 + seq_printf(s, " %9u |\n", counter); 890 + offset += map->blk * S0IX_BLK_SIZE; 891 + lpm_req_regs++; 892 + } 893 + } 894 + } 895 + return 0; 896 + } 897 + 898 + static int pmc_core_substate_blk_req_open(struct inode *inode, struct file *file) 899 + { 900 + return single_open(file, pmc_core_substate_blk_req_show, inode->i_private); 901 + } 902 + 903 + const struct file_operations pmc_core_substate_blk_req_fops = { 904 + .owner = THIS_MODULE, 905 + .open = pmc_core_substate_blk_req_open, 906 + .read = seq_read, 907 + .llseek = seq_lseek, 908 + .release = single_release, 909 + }; 848 910 849 911 static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) 850 912 { ··· 944 872 continue; 945 873 946 874 /* Display the header */ 947 - pmc_core_substate_req_header_show(s, pmc_index); 875 + pmc_core_substate_req_header_show(s, pmc_index, HEADER_STATUS); 948 876 949 877 /* Loop over maps */ 950 878 for (mp = 0; mp < num_maps; mp++) { ··· 982 910 } 983 911 984 912 /* Display the element name in the first column */ 985 - seq_printf(s, "pmc%d: %26s |", pmc_index, map[i].name); 913 + seq_printf(s, "pmc%d: %34s |", pmc_index, map[i].name); 986 914 987 915 /* Loop over the enabled states and display if required */ 988 916 pmc_for_each_mode(mode, pmcdev) { ··· 1003 931 } 1004 932 return 0; 1005 933 } 1006 - DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs); 934 + 935 + static int pmc_core_substate_req_regs_open(struct inode *inode, struct file *file) 936 + { 937 + return single_open(file, pmc_core_substate_req_regs_show, inode->i_private); 938 + } 939 + 940 + const struct file_operations pmc_core_substate_req_regs_fops = { 941 + .owner = THIS_MODULE, 942 + .open = pmc_core_substate_req_regs_open, 943 + .read = seq_read, 944 + .llseek = seq_lseek, 945 + .release = single_release, 946 + }; 1007 947 1008 948 static unsigned int pmc_core_get_crystal_freq(void) 1009 949 { ··· 1244 1160 for (mode = 0; mode < LPM_MAX_NUM_MODES; mode++) 1245 1161 pri_order[mode_order[mode]] = mode; 1246 1162 else 1247 - dev_warn(&pmcdev->pdev->dev, 1163 + dev_dbg(&pmcdev->pdev->dev, 1248 1164 "Assuming a default substate order for this platform\n"); 1249 1165 1250 1166 /* ··· 1348 1264 debugfs_remove_recursive(pmcdev->dbgfs_dir); 1349 1265 } 1350 1266 1351 - static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) 1267 + static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) 1352 1268 { 1353 1269 struct pmc *primary_pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 1354 1270 struct dentry *dir; ··· 1415 1331 if (primary_pmc->lpm_req_regs) { 1416 1332 debugfs_create_file("substate_requirements", 0444, 1417 1333 pmcdev->dbgfs_dir, pmcdev, 1418 - &pmc_core_substate_req_regs_fops); 1334 + pmc_dev_info->sub_req_show); 1419 1335 } 1420 1336 1421 1337 if (primary_pmc->map->pson_residency_offset && pmc_core_is_pson_residency_enabled(pmcdev)) { ··· 1483 1399 * +----+---------------------------------------------------------+ 1484 1400 * 1485 1401 */ 1486 - static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct pci_dev *pcidev) 1402 + int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct telem_endpoint *ep) 1487 1403 { 1488 - struct telem_endpoint *ep; 1489 1404 const u8 *lpm_indices; 1490 1405 int num_maps, mode_offset = 0; 1491 1406 int ret, mode; 1492 1407 int lpm_size; 1493 - u32 guid; 1494 1408 1495 1409 lpm_indices = pmc->map->lpm_reg_index; 1496 1410 num_maps = pmc->map->lpm_num_maps; 1497 1411 lpm_size = LPM_MAX_NUM_MODES * num_maps; 1498 1412 1499 - guid = pmc_core_find_guid(pmcdev->regmap_list, pmc->map); 1500 - if (!guid) 1501 - return -ENXIO; 1502 - 1503 - ep = pmt_telem_find_and_register_endpoint(pcidev, guid, 0); 1504 - if (IS_ERR(ep)) { 1505 - dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %pe", ep); 1506 - return -EPROBE_DEFER; 1507 - } 1508 - 1509 1413 pmc->lpm_req_regs = devm_kzalloc(&pmcdev->pdev->dev, 1510 1414 lpm_size * sizeof(u32), 1511 1415 GFP_KERNEL); 1512 - if (!pmc->lpm_req_regs) { 1513 - ret = -ENOMEM; 1514 - goto unregister_ep; 1515 - } 1416 + if (!pmc->lpm_req_regs) 1417 + return -ENOMEM; 1516 1418 1517 1419 mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; 1518 1420 pmc_for_each_mode(mode, pmcdev) { ··· 1512 1442 if (ret) { 1513 1443 dev_err(&pmcdev->pdev->dev, 1514 1444 "couldn't read Low Power Mode requirements: %d\n", ret); 1515 - goto unregister_ep; 1445 + return ret; 1516 1446 } 1517 1447 ++req_offset; 1518 1448 } 1519 1449 mode_offset += LPM_REG_COUNT + LPM_MODE_OFFSET; 1520 1450 } 1521 - 1522 - unregister_ep: 1523 - pmt_telem_unregister_endpoint(ep); 1524 - 1525 1451 return ret; 1526 1452 } 1527 1453 1528 - static int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev, int func) 1454 + int pmc_core_pmt_get_blk_sub_req(struct pmc_dev *pmcdev, struct pmc *pmc, 1455 + struct telem_endpoint *ep) 1529 1456 { 1530 - struct pci_dev *pcidev __free(pci_dev_put) = NULL; 1531 - unsigned int i; 1457 + u32 num_blocker, sample_offset; 1458 + unsigned int index; 1459 + u32 *req_offset; 1532 1460 int ret; 1533 1461 1534 - pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, func)); 1462 + num_blocker = pmc->map->num_s0ix_blocker; 1463 + sample_offset = pmc->map->blocker_req_offset; 1464 + 1465 + pmc->lpm_req_regs = devm_kcalloc(&pmcdev->pdev->dev, num_blocker, 1466 + sizeof(u32), GFP_KERNEL); 1467 + if (!pmc->lpm_req_regs) 1468 + return -ENOMEM; 1469 + 1470 + req_offset = pmc->lpm_req_regs; 1471 + for (index = 0; index < num_blocker; index++, req_offset++) { 1472 + ret = pmt_telem_read32(ep, index + sample_offset, req_offset, 1); 1473 + if (ret) { 1474 + dev_err(&pmcdev->pdev->dev, 1475 + "couldn't read Low Power Mode requirements: %d\n", ret); 1476 + return ret; 1477 + } 1478 + } 1479 + return 0; 1480 + } 1481 + 1482 + static int pmc_core_get_telem_info(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) 1483 + { 1484 + struct pci_dev *pcidev __free(pci_dev_put) = NULL; 1485 + struct telem_endpoint *ep; 1486 + unsigned int i; 1487 + u32 guid; 1488 + int ret; 1489 + 1490 + pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, pmc_dev_info->pci_func)); 1535 1491 if (!pcidev) 1536 1492 return -ENODEV; 1537 1493 1538 1494 for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { 1539 - if (!pmcdev->pmcs[i]) 1495 + struct pmc *pmc; 1496 + 1497 + pmc = pmcdev->pmcs[i]; 1498 + if (!pmc) 1540 1499 continue; 1541 1500 1542 - ret = pmc_core_get_lpm_req(pmcdev, pmcdev->pmcs[i], pcidev); 1501 + guid = pmc_core_find_guid(pmcdev->regmap_list, pmc->map); 1502 + if (!guid) 1503 + return -ENXIO; 1504 + 1505 + ep = pmt_telem_find_and_register_endpoint(pcidev, guid, 0); 1506 + if (IS_ERR(ep)) { 1507 + dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %pe", ep); 1508 + return -EPROBE_DEFER; 1509 + } 1510 + 1511 + ret = pmc_dev_info->sub_req(pmcdev, pmc, ep); 1512 + pmt_telem_unregister_endpoint(ep); 1543 1513 if (ret) 1544 1514 return ret; 1545 1515 } ··· 1693 1583 pmc_core_punit_pmt_init(pmcdev, pmc_dev_info->dmu_guid); 1694 1584 1695 1585 if (ssram) { 1696 - ret = pmc_core_ssram_get_lpm_reqs(pmcdev, pmc_dev_info->pci_func); 1586 + ret = pmc_core_get_telem_info(pmcdev, pmc_dev_info); 1697 1587 if (ret) 1698 1588 goto unmap_regbase; 1699 1589 } ··· 1742 1632 X86_MATCH_VFM(INTEL_ARROWLAKE_U, &arl_h_pmc_dev), 1743 1633 X86_MATCH_VFM(INTEL_LUNARLAKE_M, &lnl_pmc_dev), 1744 1634 X86_MATCH_VFM(INTEL_PANTHERLAKE_L, &ptl_pmc_dev), 1635 + X86_MATCH_VFM(INTEL_WILDCATLAKE_L, &wcl_pmc_dev), 1745 1636 {} 1746 1637 }; 1747 1638 ··· 1869 1758 pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(primary_pmc); 1870 1759 pmc_core_do_dmi_quirks(primary_pmc); 1871 1760 1872 - pmc_core_dbgfs_register(pmcdev); 1761 + pmc_core_dbgfs_register(pmcdev, pmc_dev_info); 1873 1762 pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) * 1874 1763 pmc_core_adjust_slp_s0_step(primary_pmc, 1)); 1875 1764
+27
drivers/platform/x86/intel/pmc/core.h
··· 297 297 #define PTL_PMC_LTR_CUR_ASLT 0x1C28 298 298 #define PTL_PMC_LTR_CUR_PLT 0x1C2C 299 299 #define PTL_PCD_PMC_MMIO_REG_LEN 0x31A8 300 + #define PTL_NUM_S0IX_BLOCKER 106 301 + #define PTL_BLK_REQ_OFFSET 55 302 + 303 + /* Wildcat Lake */ 304 + #define WCL_PMC_LTR_RESERVED 0x1B64 305 + #define WCL_PCD_PMC_MMIO_REG_LEN 0x3178 300 306 301 307 /* SSRAM PMC Device ID */ 302 308 /* LNL */ ··· 311 305 /* PTL */ 312 306 #define PMC_DEVID_PTL_PCDH 0xe37f 313 307 #define PMC_DEVID_PTL_PCDP 0xe47f 308 + 309 + /* WCL */ 310 + #define PMC_DEVID_WCL_PCDN 0x4d7f 314 311 315 312 /* ARL */ 316 313 #define PMC_DEVID_ARL_SOCM 0x777f ··· 353 344 * @pm_read_disable_bit: Bit index to read PMC_READ_DISABLE 354 345 * @slps0_dbg_offset: PWRMBASE offset to SLP_S0_DEBUG_REG* 355 346 * @s0ix_blocker_offset PWRMBASE offset to S0ix blocker counter 347 + * @num_s0ix_blocker: Number of S0ix blockers 348 + * @blocker_req_offset: Telemetry offset to S0ix blocker low power mode substate requirement table 356 349 * 357 350 * Each PCH has unique set of register offsets and bit indexes. This structure 358 351 * captures them to have a common implementation. ··· 380 369 const u32 ltr_ignore_max; 381 370 const u32 pm_vric1_offset; 382 371 const u32 s0ix_blocker_offset; 372 + const u32 num_s0ix_blocker; 373 + const u32 blocker_req_offset; 383 374 /* Low Power Mode registers */ 384 375 const int lpm_num_maps; 385 376 const int lpm_num_modes; ··· 487 474 * SSRAM support. 488 475 * @map: Pointer to a pmc_reg_map struct that contains platform 489 476 * specific attributes of the primary PMC 477 + * @sub_req_show: File operations to show substate requirements 490 478 * @suspend: Function to perform platform specific suspend 491 479 * @resume: Function to perform platform specific resume 492 480 * @init: Function to perform platform specific init action 481 + * @sub_req: Function to achieve low power mode substate requirements 493 482 */ 494 483 struct pmc_dev_info { 495 484 u8 pci_func; 496 485 u32 dmu_guid; 497 486 struct pmc_info *regmap_list; 498 487 const struct pmc_reg_map *map; 488 + const struct file_operations *sub_req_show; 499 489 void (*suspend)(struct pmc_dev *pmcdev); 500 490 int (*resume)(struct pmc_dev *pmcdev); 501 491 int (*init)(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info); 492 + int (*sub_req)(struct pmc_dev *pmcdev, struct pmc *pmc, struct telem_endpoint *ep); 502 493 }; 503 494 504 495 extern const struct pmc_bit_map msr_map[]; ··· 522 505 extern const struct pmc_bit_map mtl_socm_signal_status_map[]; 523 506 extern const struct pmc_reg_map mtl_socm_reg_map; 524 507 extern const struct pmc_reg_map mtl_ioep_reg_map; 508 + extern const struct pmc_bit_map ptl_pcdp_clocksource_status_map[]; 509 + extern const struct pmc_bit_map ptl_pcdp_vnn_req_status_3_map[]; 510 + extern const struct pmc_bit_map ptl_pcdp_signal_status_map[]; 525 511 526 512 void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); 527 513 int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); ··· 548 528 extern struct pmc_dev_info arl_h_pmc_dev; 549 529 extern struct pmc_dev_info lnl_pmc_dev; 550 530 extern struct pmc_dev_info ptl_pmc_dev; 531 + extern struct pmc_dev_info wcl_pmc_dev; 551 532 552 533 void cnl_suspend(struct pmc_dev *pmcdev); 553 534 int cnl_resume(struct pmc_dev *pmcdev); 535 + int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct telem_endpoint *ep); 536 + int pmc_core_pmt_get_blk_sub_req(struct pmc_dev *pmcdev, struct pmc *pmc, 537 + struct telem_endpoint *ep); 538 + 539 + extern const struct file_operations pmc_core_substate_req_regs_fops; 540 + extern const struct file_operations pmc_core_substate_blk_req_fops; 554 541 555 542 #define pmc_for_each_mode(mode, pmcdev) \ 556 543 for (unsigned int __i = 0, __cond; \
+18
drivers/platform/x86/intel/pmc/lnl.c
··· 13 13 14 14 #include "core.h" 15 15 16 + #define SOCM_LPM_REQ_GUID 0x15099748 17 + 18 + static const u8 LNL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20}; 19 + 16 20 static const struct pmc_bit_map lnl_ltr_show_map[] = { 17 21 {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, 18 22 {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, ··· 532 528 .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, 533 529 .s0ix_blocker_maps = lnl_blk_maps, 534 530 .s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET, 531 + .lpm_reg_index = LNL_LPM_REG_INDEX, 532 + }; 533 + 534 + static struct pmc_info lnl_pmc_info_list[] = { 535 + { 536 + .guid = SOCM_LPM_REQ_GUID, 537 + .devid = PMC_DEVID_LNL_SOCM, 538 + .map = &lnl_socm_reg_map, 539 + }, 540 + {} 535 541 }; 536 542 537 543 #define LNL_NPU_PCI_DEV 0x643e ··· 571 557 } 572 558 573 559 struct pmc_dev_info lnl_pmc_dev = { 560 + .pci_func = 2, 561 + .regmap_list = lnl_pmc_info_list, 574 562 .map = &lnl_socm_reg_map, 563 + .sub_req_show = &pmc_core_substate_req_regs_fops, 575 564 .suspend = cnl_suspend, 576 565 .resume = lnl_resume, 577 566 .init = lnl_core_init, 567 + .sub_req = pmc_core_pmt_get_lpm_req, 578 568 };
+2
drivers/platform/x86/intel/pmc/mtl.c
··· 997 997 .dmu_guid = MTL_PMT_DMU_GUID, 998 998 .regmap_list = mtl_pmc_info_list, 999 999 .map = &mtl_socm_reg_map, 1000 + .sub_req_show = &pmc_core_substate_req_regs_fops, 1000 1001 .suspend = cnl_suspend, 1001 1002 .resume = mtl_resume, 1002 1003 .init = mtl_core_init, 1004 + .sub_req = pmc_core_pmt_get_lpm_req, 1003 1005 };
+34 -3
drivers/platform/x86/intel/pmc/ptl.c
··· 10 10 11 11 #include "core.h" 12 12 13 + /* PMC SSRAM PMT Telemetry GUIDS */ 14 + #define PCDP_LPM_REQ_GUID 0x47179370 15 + 16 + /* 17 + * Die Mapping to Product. 18 + * Product PCDDie 19 + * PTL-H PCD-H 20 + * PTL-P PCD-P 21 + * PTL-U PCD-P 22 + */ 23 + 13 24 static const struct pmc_bit_map ptl_pcdp_pfear_map[] = { 14 25 {"PMC_0", BIT(0)}, 15 26 {"FUSE_OSSE", BIT(1)}, ··· 173 162 {} 174 163 }; 175 164 176 - static const struct pmc_bit_map ptl_pcdp_clocksource_status_map[] = { 165 + const struct pmc_bit_map ptl_pcdp_clocksource_status_map[] = { 177 166 {"AON2_OFF_STS", BIT(0), 1}, 178 167 {"AON3_OFF_STS", BIT(1), 0}, 179 168 {"AON4_OFF_STS", BIT(2), 1}, ··· 393 382 {} 394 383 }; 395 384 396 - static const struct pmc_bit_map ptl_pcdp_vnn_req_status_3_map[] = { 385 + const struct pmc_bit_map ptl_pcdp_vnn_req_status_3_map[] = { 397 386 {"DTS0_VNN_REQ_STS", BIT(7), 0}, 398 387 {"GPIOCOM5_VNN_REQ_STS", BIT(11), 1}, 399 388 {} ··· 432 421 {} 433 422 }; 434 423 435 - static const struct pmc_bit_map ptl_pcdp_signal_status_map[] = { 424 + const struct pmc_bit_map ptl_pcdp_signal_status_map[] = { 436 425 {"LSX_Wake0_STS", BIT(0), 0}, 437 426 {"LSX_Wake1_STS", BIT(1), 0}, 438 427 {"LSX_Wake2_STS", BIT(2), 0}, ··· 526 515 .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, 527 516 .s0ix_blocker_maps = ptl_pcdp_blk_maps, 528 517 .s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET, 518 + .num_s0ix_blocker = PTL_NUM_S0IX_BLOCKER, 519 + .blocker_req_offset = PTL_BLK_REQ_OFFSET, 520 + }; 521 + 522 + static struct pmc_info ptl_pmc_info_list[] = { 523 + { 524 + .guid = PCDP_LPM_REQ_GUID, 525 + .devid = PMC_DEVID_PTL_PCDH, 526 + .map = &ptl_pcdp_reg_map, 527 + }, 528 + { 529 + .guid = PCDP_LPM_REQ_GUID, 530 + .devid = PMC_DEVID_PTL_PCDP, 531 + .map = &ptl_pcdp_reg_map, 532 + }, 533 + {} 529 534 }; 530 535 531 536 #define PTL_NPU_PCI_DEV 0xb03e ··· 570 543 } 571 544 572 545 struct pmc_dev_info ptl_pmc_dev = { 546 + .pci_func = 2, 547 + .regmap_list = ptl_pmc_info_list, 573 548 .map = &ptl_pcdp_reg_map, 549 + .sub_req_show = &pmc_core_substate_blk_req_fops, 574 550 .suspend = cnl_suspend, 575 551 .resume = ptl_resume, 576 552 .init = ptl_core_init, 553 + .sub_req = pmc_core_pmt_get_blk_sub_req, 577 554 };
+1
drivers/platform/x86/intel/pmc/ssram_telemetry.c
··· 190 190 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_LNL_SOCM) }, 191 191 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDH) }, 192 192 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDP) }, 193 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_WCL_PCDN) }, 193 194 { } 194 195 }; 195 196 MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids);
+2 -2
drivers/platform/x86/intel/pmc/tgl.c
··· 273 273 274 274 addr = (u32 *)out_obj->buffer.pointer; 275 275 276 - lpm_req_regs = devm_kzalloc(&pdev->dev, lpm_size * sizeof(u32), 277 - GFP_KERNEL); 276 + lpm_req_regs = devm_kcalloc(&pdev->dev, lpm_size, sizeof(u32), 277 + GFP_KERNEL); 278 278 if (!lpm_req_regs) 279 279 goto free_acpi_obj; 280 280
+486
drivers/platform/x86/intel/pmc/wcl.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * This file contains platform specific structure definitions 4 + * and init function used by Wildcat Lake PCH. 5 + * 6 + * Copyright (c) 2025, Intel Corporation. 7 + */ 8 + 9 + #include <linux/bits.h> 10 + #include <linux/pci.h> 11 + 12 + #include "core.h" 13 + 14 + static const struct pmc_bit_map wcl_pcdn_pfear_map[] = { 15 + {"PMC_0", BIT(0)}, 16 + {"FUSE_OSSE", BIT(1)}, 17 + {"ESPISPI", BIT(2)}, 18 + {"XHCI", BIT(3)}, 19 + {"SPA", BIT(4)}, 20 + {"RSVD", BIT(5)}, 21 + {"MPFPW2", BIT(6)}, 22 + {"GBE", BIT(7)}, 23 + 24 + {"SBR16B21", BIT(0)}, 25 + {"SBR16B5", BIT(1)}, 26 + {"SBR8B1", BIT(2)}, 27 + {"SBR8B0", BIT(3)}, 28 + {"P2SB0", BIT(4)}, 29 + {"D2D_DISP_1", BIT(5)}, 30 + {"LPSS", BIT(6)}, 31 + {"LPC", BIT(7)}, 32 + 33 + {"SMB", BIT(0)}, 34 + {"ISH", BIT(1)}, 35 + {"DBG_SBR16B", BIT(2)}, 36 + {"NPK_0", BIT(3)}, 37 + {"D2D_NOC_1", BIT(4)}, 38 + {"FIA_P", BIT(5)}, 39 + {"FUSE", BIT(6)}, 40 + {"DBG_PSF", BIT(7)}, 41 + 42 + {"DISP_PGA1", BIT(0)}, 43 + {"XDCI", BIT(1)}, 44 + {"EXI", BIT(2)}, 45 + {"CSE", BIT(3)}, 46 + {"KVMCC", BIT(4)}, 47 + {"PMT", BIT(5)}, 48 + {"CLINK", BIT(6)}, 49 + {"PTIO", BIT(7)}, 50 + 51 + {"USBR0", BIT(0)}, 52 + {"SBR16B22", BIT(1)}, 53 + {"SMT1", BIT(2)}, 54 + {"MPFPW1", BIT(3)}, 55 + {"SMS2", BIT(4)}, 56 + {"SMS1", BIT(5)}, 57 + {"CSMERTC", BIT(6)}, 58 + {"CSMEPSF", BIT(7)}, 59 + 60 + {"D2D_NOC_0", BIT(0)}, 61 + {"ESE", BIT(1)}, 62 + {"FIACPCB_P", BIT(2)}, 63 + {"RSVD", BIT(3)}, 64 + {"SBR8B2", BIT(4)}, 65 + {"OSSE_SMT1", BIT(5)}, 66 + {"D2D_DISP", BIT(6)}, 67 + {"P2SB1", BIT(7)}, 68 + 69 + {"U3FPW1", BIT(0)}, 70 + {"SBR16B3", BIT(1)}, 71 + {"PSF4", BIT(2)}, 72 + {"CNVI", BIT(3)}, 73 + {"UFSX2", BIT(4)}, 74 + {"ENDBG", BIT(5)}, 75 + {"DBC", BIT(6)}, 76 + {"SBRG", BIT(7)}, 77 + 78 + {"RSVD", BIT(0)}, 79 + {"NPK1", BIT(1)}, 80 + {"SBR16B7", BIT(2)}, 81 + {"SBR16B4", BIT(3)}, 82 + {"FIA_XG", BIT(4)}, 83 + {"PSF6", BIT(5)}, 84 + {"UFSPW1", BIT(6)}, 85 + {"FIA_U", BIT(7)}, 86 + 87 + {"PSF8", BIT(0)}, 88 + {"PSF0", BIT(1)}, 89 + {"RSVD", BIT(2)}, 90 + {"FIACPCB_U", BIT(3)}, 91 + {"TAM", BIT(4)}, 92 + {"SBR16B0", BIT(5)}, 93 + {"TBTLSX", BIT(6)}, 94 + {"THC0", BIT(7)}, 95 + 96 + {"THC1", BIT(0)}, 97 + {"PMC_1", BIT(1)}, 98 + {"FIACPCB_XG", BIT(2)}, 99 + {"TCSS", BIT(3)}, 100 + {"DISP_PGA", BIT(4)}, 101 + {"SBR16B20", BIT(5)}, 102 + {"SBR8B20", BIT(6)}, 103 + {"DBG_SBR", BIT(7)}, 104 + 105 + {"SPC", BIT(0)}, 106 + {"ACE_0", BIT(1)}, 107 + {"ACE_1", BIT(2)}, 108 + {"ACE_2", BIT(3)}, 109 + {"ACE_3", BIT(4)}, 110 + {"ACE_4", BIT(5)}, 111 + {"ACE_5", BIT(6)}, 112 + {"ACE_6", BIT(7)}, 113 + 114 + {"ACE_7", BIT(0)}, 115 + {"ACE_8", BIT(1)}, 116 + {"ACE_9", BIT(2)}, 117 + {"ACE_10", BIT(3)}, 118 + {"SBR16B2", BIT(4)}, 119 + {"SBR8B4", BIT(5)}, 120 + {"OSSE", BIT(6)}, 121 + {"SBR16B1", BIT(7)}, 122 + {} 123 + }; 124 + 125 + static const struct pmc_bit_map *ext_wcl_pcdn_pfear_map[] = { 126 + wcl_pcdn_pfear_map, 127 + NULL 128 + }; 129 + 130 + static const struct pmc_bit_map wcl_pcdn_ltr_show_map[] = { 131 + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, 132 + {"RSVD", WCL_PMC_LTR_RESERVED}, 133 + {"SATA", CNP_PMC_LTR_SATA}, 134 + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, 135 + {"XHCI", CNP_PMC_LTR_XHCI}, 136 + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, 137 + {"ME", CNP_PMC_LTR_ME}, 138 + {"SATA1", CNP_PMC_LTR_EVA}, 139 + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, 140 + {"HD_AUDIO", CNP_PMC_LTR_AZ}, 141 + {"CNV", CNP_PMC_LTR_CNV}, 142 + {"LPSS", CNP_PMC_LTR_LPSS}, 143 + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, 144 + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, 145 + {"SATA2", PTL_PMC_LTR_SATA2}, 146 + {"ESPI", CNP_PMC_LTR_ESPI}, 147 + {"SCC", CNP_PMC_LTR_SCC}, 148 + {"ISH", CNP_PMC_LTR_ISH}, 149 + {"UFSX2", CNP_PMC_LTR_UFSX2}, 150 + {"EMMC", CNP_PMC_LTR_EMMC}, 151 + {"WIGIG", ICL_PMC_LTR_WIGIG}, 152 + {"THC0", TGL_PMC_LTR_THC0}, 153 + {"THC1", TGL_PMC_LTR_THC1}, 154 + {"SOUTHPORT_G", MTL_PMC_LTR_SPG}, 155 + {"ESE", MTL_PMC_LTR_ESE}, 156 + {"IOE_PMC", MTL_PMC_LTR_IOE_PMC}, 157 + {"DMI3", ARL_PMC_LTR_DMI3}, 158 + {"OSSE", LNL_PMC_LTR_OSSE}, 159 + 160 + /* Below two cannot be used for LTR_IGNORE */ 161 + {"CURRENT_PLATFORM", PTL_PMC_LTR_CUR_PLT}, 162 + {"AGGREGATED_SYSTEM", PTL_PMC_LTR_CUR_ASLT}, 163 + {} 164 + }; 165 + 166 + static const struct pmc_bit_map wcl_pcdn_power_gating_status_0_map[] = { 167 + {"PMC_PGD0_PG_STS", BIT(0), 0}, 168 + {"FUSE_OSSE_PGD0_PG_STS", BIT(1), 0}, 169 + {"ESPISPI_PGD0_PG_STS", BIT(2), 0}, 170 + {"XHCI_PGD0_PG_STS", BIT(3), 1}, 171 + {"SPA_PGD0_PG_STS", BIT(4), 1}, 172 + {"RSVD_5", BIT(5), 0}, 173 + {"MPFPW2_PGD0_PG_STS", BIT(6), 0}, 174 + {"GBE_PGD0_PG_STS", BIT(7), 1}, 175 + {"SBR16B21_PGD0_PG_STS", BIT(8), 0}, 176 + {"SBR16B5_PGD0_PG_STS", BIT(9), 0}, 177 + {"SBR8B1_PGD0_PG_STS", BIT(10), 0}, 178 + {"SBR8B0_PGD0_PG_STS", BIT(11), 0}, 179 + {"P2SB0_PG_STS", BIT(12), 1}, 180 + {"D2D_DISP_PGD1_PG_STS", BIT(13), 0}, 181 + {"LPSS_PGD0_PG_STS", BIT(14), 1}, 182 + {"LPC_PGD0_PG_STS", BIT(15), 0}, 183 + {"SMB_PGD0_PG_STS", BIT(16), 0}, 184 + {"ISH_PGD0_PG_STS", BIT(17), 0}, 185 + {"DBG_SBR16B_PGD0_PG_STS", BIT(18), 0}, 186 + {"NPK_PGD0_PG_STS", BIT(19), 0}, 187 + {"D2D_NOC_PGD1_PG_STS", BIT(20), 0}, 188 + {"FIA_P_PGD0_PG_STS", BIT(21), 0}, 189 + {"FUSE_PGD0_PG_STS", BIT(22), 0}, 190 + {"DBG_PSF_PGD0_PG_STS", BIT(23), 0}, 191 + {"DISP_PGA1_PGD0_PG_STS", BIT(24), 0}, 192 + {"XDCI_PGD0_PG_STS", BIT(25), 1}, 193 + {"EXI_PGD0_PG_STS", BIT(26), 0}, 194 + {"CSE_PGD0_PG_STS", BIT(27), 1}, 195 + {"KVMCC_PGD0_PG_STS", BIT(28), 1}, 196 + {"PMT_PGD0_PG_STS", BIT(29), 1}, 197 + {"CLINK_PGD0_PG_STS", BIT(30), 1}, 198 + {"PTIO_PGD0_PG_STS", BIT(31), 1}, 199 + {} 200 + }; 201 + 202 + static const struct pmc_bit_map wcl_pcdn_power_gating_status_1_map[] = { 203 + {"USBR0_PGD0_PG_STS", BIT(0), 1}, 204 + {"SBR16B22_PGD0_PG_STS", BIT(1), 0}, 205 + {"SMT1_PGD0_PG_STS", BIT(2), 1}, 206 + {"MPFPW1_PGD0_PG_STS", BIT(3), 0}, 207 + {"SMS2_PGD0_PG_STS", BIT(4), 1}, 208 + {"SMS1_PGD0_PG_STS", BIT(5), 1}, 209 + {"CSMERTC_PGD0_PG_STS", BIT(6), 0}, 210 + {"CSMEPSF_PGD0_PG_STS", BIT(7), 0}, 211 + {"D2D_NOC_PGD0_PG_STS", BIT(8), 0}, 212 + {"ESE_PGD0_PG_STS", BIT(9), 1}, 213 + {"FIACPCB_P_PGD0_PG_STS", BIT(10), 0}, 214 + {"SBR8B2_PGD0_PG_STS", BIT(12), 0}, 215 + {"OSSE_SMT1_PGD0_PG_STS", BIT(13), 1}, 216 + {"D2D_DISP_PGD0_PG_STS", BIT(14), 0}, 217 + {"P2SB1_PGD0_PG_STS", BIT(15), 1}, 218 + {"U3FPW1_PGD0_PG_STS", BIT(16), 0}, 219 + {"SBR16B3_PGD0_PG_STS", BIT(17), 0}, 220 + {"PSF4_PGD0_PG_STS", BIT(18), 0}, 221 + {"CNVI_PGD0_PG_STS", BIT(19), 0}, 222 + {"UFSX2_PGD0_PG_STS", BIT(20), 1}, 223 + {"ENDBG_PGD0_PG_STS", BIT(21), 0}, 224 + {"DBC_PGD0_PG_STS", BIT(22), 0}, 225 + {"SBRG_PGD0_PG_STS", BIT(23), 0}, 226 + {"NPK_PGD1_PG_STS", BIT(25), 0}, 227 + {"SBR16B7_PGD0_PG_STS", BIT(26), 0}, 228 + {"SBR16B4_PGD0_PG_STS", BIT(27), 0}, 229 + {"FIA_XG_PSF_PGD0_PG_STS", BIT(28), 0}, 230 + {"PSF6_PGD0_PG_STS", BIT(29), 0}, 231 + {"UFSPW1_PGD0_PG_STS", BIT(30), 0}, 232 + {"FIA_U_PGD0_PG_STS", BIT(31), 0}, 233 + {} 234 + }; 235 + 236 + static const struct pmc_bit_map wcl_pcdn_power_gating_status_2_map[] = { 237 + {"PSF8_PGD0_PG_STS", BIT(0), 0}, 238 + {"PSF0_PGD0_PG_STS", BIT(1), 0}, 239 + {"FIACPCB_U_PGD0_PG_STS", BIT(3), 0}, 240 + {"TAM_PGD0_PG_STS", BIT(4), 1}, 241 + {"SBR16B0_PGD0_PG_STS", BIT(5), 0}, 242 + {"TBTLSX_PGD0_PG_STS", BIT(6), 1}, 243 + {"THC0_PGD0_PG_STS", BIT(7), 1}, 244 + {"THC1_PGD0_PG_STS", BIT(8), 1}, 245 + {"PMC_PGD1_PG_STS", BIT(9), 0}, 246 + {"FIACPCB_XG_PGD0_PG_STS", BIT(10), 0}, 247 + {"TCSS_PGD0_PG_STS", BIT(11), 0}, 248 + {"DISP_PGA_PGD0_PG_STS", BIT(12), 0}, 249 + {"SBR8B4_PGD0_PG_STS", BIT(13), 0}, 250 + {"SBR8B20_PGD0_PG_STS", BIT(14), 0}, 251 + {"DBG_PGD0_PG_STS", BIT(15), 0}, 252 + {"SPC_PGD0_PG_STS", BIT(16), 1}, 253 + {"ACE_PGD0_PG_STS", BIT(17), 0}, 254 + {"ACE_PGD1_PG_STS", BIT(18), 0}, 255 + {"ACE_PGD2_PG_STS", BIT(19), 0}, 256 + {"ACE_PGD3_PG_STS", BIT(20), 0}, 257 + {"ACE_PGD4_PG_STS", BIT(21), 0}, 258 + {"ACE_PGD5_PG_STS", BIT(22), 0}, 259 + {"ACE_PGD6_PG_STS", BIT(23), 0}, 260 + {"ACE_PGD7_PG_STS", BIT(24), 0}, 261 + {"ACE_PGD8_PG_STS", BIT(25), 0}, 262 + {"ACE_PGD9_PG_STS", BIT(26), 0}, 263 + {"ACE_PGD10_PG_STS", BIT(27), 0}, 264 + {"SBR16B2_PG_PGD0_PG_STS", BIT(28), 0}, 265 + {"SBR16B20_PGD0_PG_STS", BIT(29), 0}, 266 + {"OSSE_PGD0_PG_STS", BIT(30), 1}, 267 + {"SBR16B1_PGD0_PG_STS", BIT(31), 0}, 268 + {} 269 + }; 270 + 271 + static const struct pmc_bit_map wcl_pcdn_d3_status_0_map[] = { 272 + {"LPSS_D3_STS", BIT(3), 1}, 273 + {"XDCI_D3_STS", BIT(4), 1}, 274 + {"XHCI_D3_STS", BIT(5), 1}, 275 + {"SPA_D3_STS", BIT(12), 0}, 276 + {"SPC_D3_STS", BIT(14), 0}, 277 + {"OSSE_D3_STS", BIT(15), 0}, 278 + {"ESPISPI_D3_STS", BIT(18), 0}, 279 + {"PSTH_D3_STS", BIT(21), 0}, 280 + {} 281 + }; 282 + 283 + static const struct pmc_bit_map wcl_pcdn_d3_status_1_map[] = { 284 + {"OSSE_SMT1_D3_STS", BIT(16), 0}, 285 + {"GBE_D3_STS", BIT(19), 0}, 286 + {"ITSS_D3_STS", BIT(23), 0}, 287 + {"CNVI_D3_STS", BIT(27), 0}, 288 + {"UFSX2_D3_STS", BIT(28), 0}, 289 + {} 290 + }; 291 + 292 + static const struct pmc_bit_map wcl_pcdn_d3_status_2_map[] = { 293 + {"CSMERTC_D3_STS", BIT(1), 0}, 294 + {"ESE_D3_STS", BIT(2), 0}, 295 + {"CSE_D3_STS", BIT(4), 0}, 296 + {"KVMCC_D3_STS", BIT(5), 0}, 297 + {"USBR0_D3_STS", BIT(6), 0}, 298 + {"ISH_D3_STS", BIT(7), 0}, 299 + {"SMT1_D3_STS", BIT(8), 0}, 300 + {"SMT2_D3_STS", BIT(9), 0}, 301 + {"SMT3_D3_STS", BIT(10), 0}, 302 + {"CLINK_D3_STS", BIT(14), 0}, 303 + {"PTIO_D3_STS", BIT(16), 0}, 304 + {"PMT_D3_STS", BIT(17), 0}, 305 + {"SMS1_D3_STS", BIT(18), 0}, 306 + {"SMS2_D3_STS", BIT(19), 0}, 307 + {"OSSE_SMT2_D3_STS", BIT(22), 0}, 308 + {} 309 + }; 310 + 311 + static const struct pmc_bit_map wcl_pcdn_d3_status_3_map[] = { 312 + {"THC0_D3_STS", BIT(14), 1}, 313 + {"THC1_D3_STS", BIT(15), 1}, 314 + {"OSSE_SMT3_D3_STS", BIT(16), 0}, 315 + {"ACE_D3_STS", BIT(23), 0}, 316 + {} 317 + }; 318 + 319 + static const struct pmc_bit_map wcl_pcdn_vnn_req_status_0_map[] = { 320 + {"LPSS_VNN_REQ_STS", BIT(3), 1}, 321 + {"OSSE_VNN_REQ_STS", BIT(15), 1}, 322 + {"ESPISPI_VNN_REQ_STS", BIT(18), 1}, 323 + {} 324 + }; 325 + 326 + static const struct pmc_bit_map wcl_pcdn_vnn_req_status_1_map[] = { 327 + {"NPK_VNN_REQ_STS", BIT(4), 1}, 328 + {"DFXAGG_VNN_REQ_STS", BIT(8), 0}, 329 + {"EXI_VNN_REQ_STS", BIT(9), 1}, 330 + {"OSSE_SMT1_VNN_REQ_STS", BIT(16), 1}, 331 + {"P2D_VNN_REQ_STS", BIT(18), 1}, 332 + {"GBE_VNN_REQ_STS", BIT(19), 1}, 333 + {"SMB_VNN_REQ_STS", BIT(25), 1}, 334 + {"LPC_VNN_REQ_STS", BIT(26), 0}, 335 + {} 336 + }; 337 + 338 + static const struct pmc_bit_map wcl_pcdn_vnn_req_status_2_map[] = { 339 + {"CSMERTC_VNN_REQ_STS", BIT(1), 1}, 340 + {"ESE_VNN_REQ_STS", BIT(2), 1}, 341 + {"CSE_VNN_REQ_STS", BIT(4), 1}, 342 + {"ISH_VNN_REQ_STS", BIT(7), 1}, 343 + {"SMT1_VNN_REQ_STS", BIT(8), 1}, 344 + {"CLINK_VNN_REQ_STS", BIT(14), 1}, 345 + {"SMS1_VNN_REQ_STS", BIT(18), 1}, 346 + {"SMS2_VNN_REQ_STS", BIT(19), 1}, 347 + {"GPIOCOM4_VNN_REQ_STS", BIT(20), 1}, 348 + {"GPIOCOM3_VNN_REQ_STS", BIT(21), 1}, 349 + {"GPIOCOM1_VNN_REQ_STS", BIT(23), 1}, 350 + {"GPIOCOM0_VNN_REQ_STS", BIT(24), 1}, 351 + {"DISP_SHIM_VNN_REQ_STS", BIT(31), 1}, 352 + {} 353 + }; 354 + 355 + static const struct pmc_bit_map wcl_pcdn_vnn_misc_status_map[] = { 356 + {"CPU_C10_REQ_STS", BIT(0), 0}, 357 + {"TS_OFF_REQ_STS", BIT(1), 0}, 358 + {"PNDE_MET_REQ_STS", BIT(2), 1}, 359 + {"FW_THROTTLE_ALLOWED_REQ_STS", BIT(4), 0}, 360 + {"VNN_SOC_REQ_STS", BIT(6), 1}, 361 + {"ISH_VNNAON_REQ_STS", BIT(7), 0}, 362 + {"D2D_NOC_CFI_QACTIVE_REQ_STS", BIT(8), 1}, 363 + {"D2D_NOC_GPSB_QACTIVE_REQ_STS", BIT(9), 1}, 364 + {"PLT_GREATER_REQ_STS", BIT(11), 1}, 365 + {"ALL_SBR_IDLE_REQ_STS", BIT(12), 0}, 366 + {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13), 0}, 367 + {"PM_SYNC_STATES_REQ_STS", BIT(14), 0}, 368 + {"EA_REQ_STS", BIT(15), 0}, 369 + {"MPHY_CORE_OFF_REQ_STS", BIT(16), 0}, 370 + {"BRK_EV_EN_REQ_STS", BIT(17), 0}, 371 + {"AUTO_DEMO_EN_REQ_STS", BIT(18), 0}, 372 + {"ITSS_CLK_SRC_REQ_STS", BIT(19), 1}, 373 + {"ARC_IDLE_REQ_STS", BIT(21), 0}, 374 + {"FIA_DEEP_PM_REQ_STS", BIT(23), 0}, 375 + {"XDCI_ATTACHED_REQ_STS", BIT(24), 1}, 376 + {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25), 0}, 377 + {"D2D_DISP_DDI_QACTIVE_REQ_STS", BIT(26), 1}, 378 + {"PRE_WAKE0_REQ_STS", BIT(27), 1}, 379 + {"PRE_WAKE1_REQ_STS", BIT(28), 1}, 380 + {"PRE_WAKE2_REQ_STS", BIT(29), 1}, 381 + {} 382 + }; 383 + 384 + static const struct pmc_bit_map wcl_pcdn_rsc_status_map[] = { 385 + {"Memory", 0, 1}, 386 + {"PSF0", 0, 1}, 387 + {"PSF6", 0, 1}, 388 + {"PSF8", 0, 1}, 389 + {"SAF_CFI_LINK", 0, 1}, 390 + {"SB", 0, 1}, 391 + {} 392 + }; 393 + 394 + static const struct pmc_bit_map *wcl_pcdn_lpm_maps[] = { 395 + ptl_pcdp_clocksource_status_map, 396 + wcl_pcdn_power_gating_status_0_map, 397 + wcl_pcdn_power_gating_status_1_map, 398 + wcl_pcdn_power_gating_status_2_map, 399 + wcl_pcdn_d3_status_0_map, 400 + wcl_pcdn_d3_status_1_map, 401 + wcl_pcdn_d3_status_2_map, 402 + wcl_pcdn_d3_status_3_map, 403 + wcl_pcdn_vnn_req_status_0_map, 404 + wcl_pcdn_vnn_req_status_1_map, 405 + wcl_pcdn_vnn_req_status_2_map, 406 + ptl_pcdp_vnn_req_status_3_map, 407 + wcl_pcdn_vnn_misc_status_map, 408 + ptl_pcdp_signal_status_map, 409 + NULL 410 + }; 411 + 412 + static const struct pmc_bit_map *wcl_pcdn_blk_maps[] = { 413 + wcl_pcdn_power_gating_status_0_map, 414 + wcl_pcdn_power_gating_status_1_map, 415 + wcl_pcdn_power_gating_status_2_map, 416 + wcl_pcdn_rsc_status_map, 417 + wcl_pcdn_vnn_req_status_0_map, 418 + wcl_pcdn_vnn_req_status_1_map, 419 + wcl_pcdn_vnn_req_status_2_map, 420 + ptl_pcdp_vnn_req_status_3_map, 421 + wcl_pcdn_d3_status_0_map, 422 + wcl_pcdn_d3_status_1_map, 423 + wcl_pcdn_d3_status_2_map, 424 + wcl_pcdn_d3_status_3_map, 425 + ptl_pcdp_clocksource_status_map, 426 + wcl_pcdn_vnn_misc_status_map, 427 + ptl_pcdp_signal_status_map, 428 + NULL 429 + }; 430 + 431 + static const struct pmc_reg_map wcl_pcdn_reg_map = { 432 + .pfear_sts = ext_wcl_pcdn_pfear_map, 433 + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, 434 + .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, 435 + .ltr_show_sts = wcl_pcdn_ltr_show_map, 436 + .msr_sts = msr_map, 437 + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, 438 + .regmap_length = WCL_PCD_PMC_MMIO_REG_LEN, 439 + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, 440 + .ppfear_buckets = LNL_PPFEAR_NUM_ENTRIES, 441 + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, 442 + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, 443 + .lpm_num_maps = PTL_LPM_NUM_MAPS, 444 + .ltr_ignore_max = LNL_NUM_IP_IGN_ALLOWED, 445 + .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, 446 + .etr3_offset = ETR3_OFFSET, 447 + .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET, 448 + .lpm_priority_offset = MTL_LPM_PRI_OFFSET, 449 + .lpm_en_offset = MTL_LPM_EN_OFFSET, 450 + .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, 451 + .lpm_sts = wcl_pcdn_lpm_maps, 452 + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, 453 + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, 454 + .s0ix_blocker_maps = wcl_pcdn_blk_maps, 455 + .s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET, 456 + }; 457 + 458 + #define WCL_NPU_PCI_DEV 0xfd3e 459 + 460 + /* 461 + * Set power state of select devices that do not have drivers to D3 462 + * so that they do not block Package C entry. 463 + */ 464 + static void wcl_d3_fixup(void) 465 + { 466 + pmc_core_set_device_d3(WCL_NPU_PCI_DEV); 467 + } 468 + 469 + static int wcl_resume(struct pmc_dev *pmcdev) 470 + { 471 + wcl_d3_fixup(); 472 + return cnl_resume(pmcdev); 473 + } 474 + 475 + static int wcl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) 476 + { 477 + wcl_d3_fixup(); 478 + return generic_core_init(pmcdev, pmc_dev_info); 479 + } 480 + 481 + struct pmc_dev_info wcl_pmc_dev = { 482 + .map = &wcl_pcdn_reg_map, 483 + .suspend = cnl_suspend, 484 + .resume = wcl_resume, 485 + .init = wcl_core_init, 486 + };
+74 -2
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
··· 374 374 cluster_info->uncore_data.agent_type_mask = FIELD_GET(UNCORE_AGENT_TYPES, status); 375 375 } 376 376 377 + #define MAX_PARTITIONS 2 378 + 379 + /* IO domain ID start index for a partition */ 380 + static u8 io_die_start[MAX_PARTITIONS]; 381 + 382 + /* Next IO domain ID index after the current partition IO die IDs */ 383 + static u8 io_die_index_next; 384 + 385 + /* Lock to protect io_die_start, io_die_index_next */ 386 + static DEFINE_MUTEX(domain_lock); 387 + 388 + static void set_domain_id(int id, int num_resources, 389 + struct oobmsm_plat_info *plat_info, 390 + struct tpmi_uncore_cluster_info *cluster_info) 391 + { 392 + u8 part_io_index, cdie_range, pkg_io_index, max_dies; 393 + 394 + if (plat_info->partition >= MAX_PARTITIONS) { 395 + cluster_info->uncore_data.domain_id = id; 396 + return; 397 + } 398 + 399 + if (cluster_info->uncore_data.agent_type_mask & AGENT_TYPE_CORE) { 400 + cluster_info->uncore_data.domain_id = cluster_info->cdie_id; 401 + return; 402 + } 403 + 404 + /* Unlikely but cdie_mask may have holes, so take range */ 405 + cdie_range = fls(plat_info->cdie_mask) - ffs(plat_info->cdie_mask) + 1; 406 + max_dies = topology_max_dies_per_package(); 407 + 408 + /* 409 + * If the CPU doesn't enumerate dies, then use current cdie range 410 + * as the max. 411 + */ 412 + if (cdie_range > max_dies) 413 + max_dies = cdie_range; 414 + 415 + guard(mutex)(&domain_lock); 416 + 417 + if (!io_die_index_next) 418 + io_die_index_next = max_dies; 419 + 420 + if (!io_die_start[plat_info->partition]) { 421 + io_die_start[plat_info->partition] = io_die_index_next; 422 + /* 423 + * number of IO dies = num_resources - cdie_range. Hence 424 + * next partition io_die_index_next is set after IO dies 425 + * in the current partition. 426 + */ 427 + io_die_index_next += (num_resources - cdie_range); 428 + } 429 + 430 + /* 431 + * Index from IO die start within the partition: 432 + * This is the first valid domain after the cdies. 433 + * For example the current resource index 5 and cdies end at 434 + * index 3 (cdie_cnt = 4). Then the IO only index 5 - 4 = 1. 435 + */ 436 + part_io_index = id - cdie_range; 437 + 438 + /* 439 + * Add to the IO die start index for this partition in this package 440 + * to make unique in the package. 441 + */ 442 + pkg_io_index = io_die_start[plat_info->partition] + part_io_index; 443 + 444 + /* Assign this to domain ID */ 445 + cluster_info->uncore_data.domain_id = pkg_io_index; 446 + } 447 + 377 448 /* Callback for sysfs read for TPMI uncore values. Called under mutex locks. */ 378 449 static int uncore_read(struct uncore_data *data, unsigned int *value, enum uncore_index index) 379 450 { ··· 681 610 cluster_info->uncore_data.package_id = pkg; 682 611 /* There are no dies like Cascade Lake */ 683 612 cluster_info->uncore_data.die_id = 0; 684 - cluster_info->uncore_data.domain_id = i; 685 613 cluster_info->uncore_data.cluster_id = j; 686 614 687 615 set_cdie_id(i, cluster_info, plat_info); 616 + 617 + set_domain_id(i, num_resources, plat_info, cluster_info); 688 618 689 619 cluster_info->uncore_root = tpmi_uncore; 690 620 ··· 710 638 711 639 auxiliary_set_drvdata(auxdev, tpmi_uncore); 712 640 713 - if (topology_max_dies_per_package() > 1) 641 + if (topology_max_dies_per_package() > 1 || plat_info->partition) 714 642 return 0; 715 643 716 644 tpmi_uncore->root_cluster.root_domain = true;
+79 -15
drivers/platform/x86/lenovo/think-lmi.c
··· 119 119 * You must reboot the computer before the changes will take effect. 120 120 */ 121 121 #define LENOVO_SET_BIOS_CERT_GUID "26861C9F-47E9-44C4-BD8B-DFE7FA2610FE" 122 + #define LENOVO_TC_SET_BIOS_CERT_GUID "955aaf7d-8bc4-4f04-90aa-97469512f167" 122 123 123 124 /* 124 125 * Name: UpdateBiosCert ··· 129 128 * You must reboot the computer before the changes will take effect. 130 129 */ 131 130 #define LENOVO_UPDATE_BIOS_CERT_GUID "9AA3180A-9750-41F7-B9F7-D5D3B1BAC3CE" 131 + #define LENOVO_TC_UPDATE_BIOS_CERT_GUID "5f5bbbb2-c72f-4fb8-8129-228eef4fdbed" 132 132 133 133 /* 134 134 * Name: ClearBiosCert ··· 139 137 * You must reboot the computer before the changes will take effect. 140 138 */ 141 139 #define LENOVO_CLEAR_BIOS_CERT_GUID "B2BC39A7-78DD-4D71-B059-A510DEC44890" 140 + #define LENOVO_TC_CLEAR_BIOS_CERT_GUID "97849cb6-cb44-42d1-a750-26a596a9eec4" 141 + 142 142 /* 143 143 * Name: CertToPassword 144 144 * Description: Switch from certificate to password authentication. ··· 149 145 * You must reboot the computer before the changes will take effect. 150 146 */ 151 147 #define LENOVO_CERT_TO_PASSWORD_GUID "0DE8590D-5510-4044-9621-77C227F5A70D" 148 + #define LENOVO_TC_CERT_TO_PASSWORD_GUID "ef65480d-38c9-420d-b700-ab3d6c8ebaca" 152 149 153 150 /* 154 151 * Name: SetBiosSettingCert ··· 158 153 * Format: "Item,Value,Signature" 159 154 */ 160 155 #define LENOVO_SET_BIOS_SETTING_CERT_GUID "34A008CC-D205-4B62-9E67-31DFA8B90003" 156 + #define LENOVO_TC_SET_BIOS_SETTING_CERT_GUID "19ecba3b-b318-4192-a89b-43d94bc60cea" 161 157 162 158 /* 163 159 * Name: SaveBiosSettingCert ··· 167 161 * Format: "Signature" 168 162 */ 169 163 #define LENOVO_SAVE_BIOS_SETTING_CERT_GUID "C050FB9D-DF5F-4606-B066-9EFC401B2551" 164 + #define LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID "0afaf46f-7cca-450a-b455-a826a0bf1af5" 170 165 171 166 /* 172 167 * Name: CertThumbprint ··· 184 177 #define TLMI_CERT_SVC BIT(7) /* Admin Certificate Based */ 185 178 #define TLMI_CERT_SMC BIT(8) /* System Certificate Based */ 186 179 180 + static const struct tlmi_cert_guids thinkpad_cert_guid = { 181 + .thumbprint = LENOVO_CERT_THUMBPRINT_GUID, 182 + .set_bios_setting = LENOVO_SET_BIOS_SETTING_CERT_GUID, 183 + .save_bios_setting = LENOVO_SAVE_BIOS_SETTING_CERT_GUID, 184 + .cert_to_password = LENOVO_CERT_TO_PASSWORD_GUID, 185 + .clear_bios_cert = LENOVO_CLEAR_BIOS_CERT_GUID, 186 + .update_bios_cert = LENOVO_UPDATE_BIOS_CERT_GUID, 187 + .set_bios_cert = LENOVO_SET_BIOS_CERT_GUID, 188 + }; 189 + 190 + static const struct tlmi_cert_guids thinkcenter_cert_guid = { 191 + .thumbprint = NULL, 192 + .set_bios_setting = LENOVO_TC_SET_BIOS_SETTING_CERT_GUID, 193 + .save_bios_setting = LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID, 194 + .cert_to_password = LENOVO_TC_CERT_TO_PASSWORD_GUID, 195 + .clear_bios_cert = LENOVO_TC_CLEAR_BIOS_CERT_GUID, 196 + .update_bios_cert = LENOVO_TC_UPDATE_BIOS_CERT_GUID, 197 + .set_bios_cert = LENOVO_TC_SET_BIOS_CERT_GUID, 198 + }; 199 + 187 200 static const struct tlmi_err_codes tlmi_errs[] = { 188 201 {"Success", 0}, 202 + {"Set Certificate operation was successful.", 0}, 189 203 {"Not Supported", -EOPNOTSUPP}, 190 204 {"Invalid Parameter", -EINVAL}, 191 205 {"Access Denied", -EACCES}, 192 206 {"System Busy", -EBUSY}, 207 + {"Set Certificate operation failed with status:Invalid Parameter.", -EINVAL}, 208 + {"Set Certificate operation failed with status:Invalid certificate type.", -EINVAL}, 209 + {"Set Certificate operation failed with status:Invalid password format.", -EINVAL}, 210 + {"Set Certificate operation failed with status:Password retry count exceeded.", -EACCES}, 211 + {"Set Certificate operation failed with status:Password Invalid.", -EACCES}, 212 + {"Set Certificate operation failed with status:Operation aborted.", -EBUSY}, 213 + {"Set Certificate operation failed with status:No free slots to write.", -ENOSPC}, 214 + {"Set Certificate operation failed with status:Certificate not found.", -EEXIST}, 215 + {"Set Certificate operation failed with status:Internal error.", -EFAULT}, 216 + {"Set Certificate operation failed with status:Certificate too large.", -EFBIG}, 193 217 }; 194 218 195 219 static const char * const encoding_options[] = { ··· 706 668 const union acpi_object *obj; 707 669 acpi_status status; 708 670 709 - status = wmi_evaluate_method(LENOVO_CERT_THUMBPRINT_GUID, 0, 0, &input, &output); 671 + if (!tlmi_priv.cert_guid->thumbprint) 672 + return -EOPNOTSUPP; 673 + 674 + status = wmi_evaluate_method(tlmi_priv.cert_guid->thumbprint, 0, 0, &input, &output); 710 675 if (ACPI_FAILURE(status)) { 711 676 kfree(output.pointer); 712 677 return -EIO; ··· 792 751 kfree_sensitive(passwd); 793 752 return -ENOMEM; 794 753 } 795 - ret = tlmi_simple_call(LENOVO_CERT_TO_PASSWORD_GUID, auth_str); 754 + ret = tlmi_simple_call(tlmi_priv.cert_guid->cert_to_password, auth_str); 796 755 kfree(auth_str); 797 756 kfree_sensitive(passwd); 798 757 ··· 815 774 char *auth_str, *new_cert; 816 775 const char *serial; 817 776 char *signature; 818 - char *guid; 777 + const char *guid; 819 778 int ret; 820 779 821 780 if (!capable(CAP_SYS_ADMIN)) ··· 838 797 if (!auth_str) 839 798 return -ENOMEM; 840 799 841 - ret = tlmi_simple_call(LENOVO_CLEAR_BIOS_CERT_GUID, auth_str); 800 + ret = tlmi_simple_call(tlmi_priv.cert_guid->clear_bios_cert, auth_str); 842 801 kfree(auth_str); 843 802 844 803 return ret ?: count; ··· 875 834 kfree(new_cert); 876 835 return -EACCES; 877 836 } 878 - guid = LENOVO_UPDATE_BIOS_CERT_GUID; 837 + guid = tlmi_priv.cert_guid->update_bios_cert; 879 838 /* Format: 'Certificate,Signature' */ 880 839 auth_str = cert_command(setting, new_cert, signature); 881 840 } else { ··· 886 845 kfree(new_cert); 887 846 return -EACCES; 888 847 } 889 - guid = LENOVO_SET_BIOS_CERT_GUID; 890 - /* Format: 'Certificate, password' */ 891 - auth_str = cert_command(setting, new_cert, setting->password); 848 + guid = tlmi_priv.cert_guid->set_bios_cert; 849 + if (tlmi_priv.thinkcenter_mode) { 850 + /* Format: 'Certificate, password, encoding, kbdlang' */ 851 + auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s,%s", new_cert, 852 + setting->password, 853 + encoding_options[setting->encoding], 854 + setting->kbdlang); 855 + } else { 856 + /* Format: 'Certificate, password' */ 857 + auth_str = cert_command(setting, new_cert, setting->password); 858 + } 892 859 } 893 860 kfree(new_cert); 894 861 if (!auth_str) ··· 1120 1071 goto out; 1121 1072 } 1122 1073 1123 - ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTING_CERT_GUID, set_str); 1074 + ret = tlmi_simple_call(tlmi_priv.cert_guid->set_bios_setting, set_str); 1124 1075 if (ret) 1125 1076 goto out; 1126 1077 if (tlmi_priv.save_mode == TLMI_SAVE_BULK) 1127 1078 tlmi_priv.save_required = true; 1128 1079 else 1129 - ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID, 1080 + ret = tlmi_simple_call(tlmi_priv.cert_guid->save_bios_setting, 1130 1081 tlmi_priv.pwd_admin->save_signature); 1131 1082 } else if (tlmi_priv.opcode_support) { 1132 1083 /* ··· 1331 1282 ret = -EINVAL; 1332 1283 goto out; 1333 1284 } 1334 - ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID, 1285 + ret = tlmi_simple_call(tlmi_priv.cert_guid->save_bios_setting, 1335 1286 tlmi_priv.pwd_admin->save_signature); 1336 1287 if (ret) 1337 1288 goto out; ··· 1632 1583 wmi_has_guid(LENOVO_SAVE_BIOS_SETTING_CERT_GUID)) 1633 1584 tlmi_priv.certificate_support = true; 1634 1585 1586 + /* ThinkCenter uses different GUIDs for certificate support */ 1587 + if (wmi_has_guid(LENOVO_TC_SET_BIOS_CERT_GUID) && 1588 + wmi_has_guid(LENOVO_TC_SET_BIOS_SETTING_CERT_GUID) && 1589 + wmi_has_guid(LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID)) { 1590 + tlmi_priv.certificate_support = true; 1591 + tlmi_priv.thinkcenter_mode = true; 1592 + pr_info("ThinkCenter modified support being used\n"); 1593 + } 1594 + 1635 1595 /* 1636 1596 * Try to find the number of valid settings of this machine 1637 1597 * and use it to create sysfs attributes. ··· 1786 1728 } 1787 1729 1788 1730 if (tlmi_priv.certificate_support) { 1789 - tlmi_priv.pwd_admin->cert_installed = 1790 - tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SVC; 1791 - tlmi_priv.pwd_system->cert_installed = 1792 - tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SMC; 1731 + if (tlmi_priv.thinkcenter_mode) { 1732 + tlmi_priv.cert_guid = &thinkcenter_cert_guid; 1733 + tlmi_priv.pwd_admin->cert_installed = tlmi_priv.pwdcfg.core.password_mode; 1734 + } else { 1735 + tlmi_priv.cert_guid = &thinkpad_cert_guid; 1736 + tlmi_priv.pwd_admin->cert_installed = 1737 + tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SVC; 1738 + tlmi_priv.pwd_system->cert_installed = 1739 + tlmi_priv.pwdcfg.core.password_state & TLMI_CERT_SMC; 1740 + } 1793 1741 } 1794 1742 return 0; 1795 1743
+14
drivers/platform/x86/lenovo/think-lmi.h
··· 41 41 TLMI_SAVE_SAVE, 42 42 }; 43 43 44 + /* GUIDs can differ between platforms */ 45 + struct tlmi_cert_guids { 46 + const char *thumbprint; 47 + const char *set_bios_setting; 48 + const char *save_bios_setting; 49 + const char *cert_to_password; 50 + const char *clear_bios_cert; 51 + const char *update_bios_cert; 52 + const char *set_bios_cert; 53 + }; 54 + 44 55 /* password configuration details */ 45 56 #define TLMI_PWDCFG_MODE_LEGACY 0 46 57 #define TLMI_PWDCFG_MODE_PASSWORD 1 ··· 120 109 enum save_mode save_mode; 121 110 bool save_required; 122 111 bool reboot_required; 112 + bool thinkcenter_mode; 123 113 124 114 struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT]; 125 115 struct device *class_dev; ··· 133 121 struct tlmi_pwd_setting *pwd_system; 134 122 struct tlmi_pwd_setting *pwd_hdd; 135 123 struct tlmi_pwd_setting *pwd_nvme; 124 + 125 + const struct tlmi_cert_guids *cert_guid; 136 126 }; 137 127 138 128 #endif /* !_THINK_LMI_H_ */
+1 -1
drivers/platform/x86/lenovo/wmi-capdata01.c
··· 93 93 continue; 94 94 memcpy(output, &list->data[idx], sizeof(list->data[idx])); 95 95 return 0; 96 - }; 96 + } 97 97 98 98 return -EINVAL; 99 99 }
+5
drivers/platform/x86/lenovo/yoga-tab2-pro-1380-fastcharger.c
··· 255 255 if (!serdev) 256 256 return -ENOMEM; 257 257 258 + /* Propagate pdev-fwnode set by x86-android-tablets to serdev */ 259 + device_set_node(&serdev->dev, dev_fwnode(&pdev->dev)); 260 + /* The fwnode is a managed node, so it will be auto-put on serdev_device_put() */ 261 + fwnode_handle_get(dev_fwnode(&serdev->dev)); 262 + 258 263 ret = serdev_device_add(serdev); 259 264 if (ret) { 260 265 serdev_device_put(serdev);
+262 -142
drivers/platform/x86/meraki-mx100.c
··· 15 15 16 16 #include <linux/dmi.h> 17 17 #include <linux/err.h> 18 - #include <linux/gpio_keys.h> 19 18 #include <linux/gpio/machine.h> 20 - #include <linux/input.h> 19 + #include <linux/gpio/property.h> 20 + #include <linux/input-event-codes.h> 21 21 #include <linux/io.h> 22 22 #include <linux/kernel.h> 23 - #include <linux/leds.h> 24 23 #include <linux/module.h> 25 24 #include <linux/platform_device.h> 25 + #include <linux/property.h> 26 26 27 27 #define TINK_GPIO_DRIVER_NAME "gpio_ich" 28 28 29 + static const struct software_node gpio_ich_node = { 30 + .name = TINK_GPIO_DRIVER_NAME, 31 + }; 32 + 29 33 /* LEDs */ 30 - static const struct gpio_led tink_leds[] = { 31 - { 32 - .name = "mx100:green:internet", 33 - .default_trigger = "default-on", 34 - }, 35 - { 36 - .name = "mx100:green:lan2", 37 - }, 38 - { 39 - .name = "mx100:green:lan3", 40 - }, 41 - { 42 - .name = "mx100:green:lan4", 43 - }, 44 - { 45 - .name = "mx100:green:lan5", 46 - }, 47 - { 48 - .name = "mx100:green:lan6", 49 - }, 50 - { 51 - .name = "mx100:green:lan7", 52 - }, 53 - { 54 - .name = "mx100:green:lan8", 55 - }, 56 - { 57 - .name = "mx100:green:lan9", 58 - }, 59 - { 60 - .name = "mx100:green:lan10", 61 - }, 62 - { 63 - .name = "mx100:green:lan11", 64 - }, 65 - { 66 - .name = "mx100:green:ha", 67 - }, 68 - { 69 - .name = "mx100:orange:ha", 70 - }, 71 - { 72 - .name = "mx100:green:usb", 73 - }, 74 - { 75 - .name = "mx100:orange:usb", 76 - }, 34 + static const struct software_node tink_gpio_leds_node = { 35 + .name = "meraki-mx100-leds", 77 36 }; 78 37 79 - static const struct gpio_led_platform_data tink_leds_pdata = { 80 - .num_leds = ARRAY_SIZE(tink_leds), 81 - .leds = tink_leds, 38 + static const struct property_entry tink_internet_led_props[] = { 39 + PROPERTY_ENTRY_STRING("label", "mx100:green:internet"), 40 + PROPERTY_ENTRY_STRING("linux,default-trigger", "default-on"), 41 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 11, GPIO_ACTIVE_LOW), 42 + { } 82 43 }; 83 44 84 - static struct gpiod_lookup_table tink_leds_table = { 85 - .dev_id = "leds-gpio", 86 - .table = { 87 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 11, 88 - NULL, 0, GPIO_ACTIVE_LOW), 89 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 18, 90 - NULL, 1, GPIO_ACTIVE_HIGH), 91 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 20, 92 - NULL, 2, GPIO_ACTIVE_HIGH), 93 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 22, 94 - NULL, 3, GPIO_ACTIVE_HIGH), 95 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 23, 96 - NULL, 4, GPIO_ACTIVE_HIGH), 97 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 32, 98 - NULL, 5, GPIO_ACTIVE_HIGH), 99 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 34, 100 - NULL, 6, GPIO_ACTIVE_HIGH), 101 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 35, 102 - NULL, 7, GPIO_ACTIVE_HIGH), 103 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 36, 104 - NULL, 8, GPIO_ACTIVE_HIGH), 105 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 37, 106 - NULL, 9, GPIO_ACTIVE_HIGH), 107 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 48, 108 - NULL, 10, GPIO_ACTIVE_HIGH), 109 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 16, 110 - NULL, 11, GPIO_ACTIVE_LOW), 111 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 7, 112 - NULL, 12, GPIO_ACTIVE_LOW), 113 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 21, 114 - NULL, 13, GPIO_ACTIVE_LOW), 115 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 19, 116 - NULL, 14, GPIO_ACTIVE_LOW), 117 - {} /* Terminating entry */ 118 - } 45 + static const struct software_node tink_internet_led_node = { 46 + .name = "internet-led", 47 + .parent = &tink_gpio_leds_node, 48 + .properties = tink_internet_led_props, 49 + }; 50 + 51 + static const struct property_entry tink_lan2_led_props[] = { 52 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan2"), 53 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 18, GPIO_ACTIVE_HIGH), 54 + { } 55 + }; 56 + 57 + static const struct software_node tink_lan2_led_node = { 58 + .name = "lan2-led", 59 + .parent = &tink_gpio_leds_node, 60 + .properties = tink_lan2_led_props, 61 + }; 62 + 63 + static const struct property_entry tink_lan3_led_props[] = { 64 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan3"), 65 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 20, GPIO_ACTIVE_HIGH), 66 + { } 67 + }; 68 + 69 + static const struct software_node tink_lan3_led_node = { 70 + .name = "lan3-led", 71 + .parent = &tink_gpio_leds_node, 72 + .properties = tink_lan3_led_props, 73 + }; 74 + 75 + static const struct property_entry tink_lan4_led_props[] = { 76 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan4"), 77 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 22, GPIO_ACTIVE_HIGH), 78 + { } 79 + }; 80 + 81 + static const struct software_node tink_lan4_led_node = { 82 + .name = "lan4-led", 83 + .parent = &tink_gpio_leds_node, 84 + .properties = tink_lan4_led_props, 85 + }; 86 + 87 + static const struct property_entry tink_lan5_led_props[] = { 88 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan5"), 89 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 23, GPIO_ACTIVE_HIGH), 90 + { } 91 + }; 92 + 93 + static const struct software_node tink_lan5_led_node = { 94 + .name = "lan5-led", 95 + .parent = &tink_gpio_leds_node, 96 + .properties = tink_lan5_led_props, 97 + }; 98 + 99 + static const struct property_entry tink_lan6_led_props[] = { 100 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan6"), 101 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 32, GPIO_ACTIVE_HIGH), 102 + { } 103 + }; 104 + 105 + static const struct software_node tink_lan6_led_node = { 106 + .name = "lan6-led", 107 + .parent = &tink_gpio_leds_node, 108 + .properties = tink_lan6_led_props, 109 + }; 110 + 111 + static const struct property_entry tink_lan7_led_props[] = { 112 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan7"), 113 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 34, GPIO_ACTIVE_HIGH), 114 + { } 115 + }; 116 + 117 + static const struct software_node tink_lan7_led_node = { 118 + .name = "lan7-led", 119 + .parent = &tink_gpio_leds_node, 120 + .properties = tink_lan7_led_props, 121 + }; 122 + 123 + static const struct property_entry tink_lan8_led_props[] = { 124 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan8"), 125 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 35, GPIO_ACTIVE_HIGH), 126 + { } 127 + }; 128 + 129 + static const struct software_node tink_lan8_led_node = { 130 + .name = "lan8-led", 131 + .parent = &tink_gpio_leds_node, 132 + .properties = tink_lan8_led_props, 133 + }; 134 + 135 + static const struct property_entry tink_lan9_led_props[] = { 136 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan9"), 137 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 36, GPIO_ACTIVE_HIGH), 138 + { } 139 + }; 140 + 141 + static const struct software_node tink_lan9_led_node = { 142 + .name = "lan9-led", 143 + .parent = &tink_gpio_leds_node, 144 + .properties = tink_lan9_led_props, 145 + }; 146 + 147 + static const struct property_entry tink_lan10_led_props[] = { 148 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan10"), 149 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 37, GPIO_ACTIVE_HIGH), 150 + { } 151 + }; 152 + 153 + static const struct software_node tink_lan10_led_node = { 154 + .name = "lan10-led", 155 + .parent = &tink_gpio_leds_node, 156 + .properties = tink_lan10_led_props, 157 + }; 158 + 159 + static const struct property_entry tink_lan11_led_props[] = { 160 + PROPERTY_ENTRY_STRING("label", "mx100:green:lan11"), 161 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 48, GPIO_ACTIVE_HIGH), 162 + { } 163 + }; 164 + 165 + static const struct software_node tink_lan11_led_node = { 166 + .name = "lan11-led", 167 + .parent = &tink_gpio_leds_node, 168 + .properties = tink_lan11_led_props, 169 + }; 170 + 171 + static const struct property_entry tink_ha_green_led_props[] = { 172 + PROPERTY_ENTRY_STRING("label", "mx100:green:ha"), 173 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 16, GPIO_ACTIVE_LOW), 174 + { } 175 + }; 176 + 177 + static const struct software_node tink_ha_green_led_node = { 178 + .name = "ha-green-led", 179 + .parent = &tink_gpio_leds_node, 180 + .properties = tink_ha_green_led_props, 181 + }; 182 + 183 + static const struct property_entry tink_ha_orange_led_props[] = { 184 + PROPERTY_ENTRY_STRING("label", "mx100:orange:ha"), 185 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 7, GPIO_ACTIVE_LOW), 186 + { } 187 + }; 188 + 189 + static const struct software_node tink_ha_orange_led_node = { 190 + .name = "ha-orange-led", 191 + .parent = &tink_gpio_leds_node, 192 + .properties = tink_ha_orange_led_props, 193 + }; 194 + 195 + static const struct property_entry tink_usb_green_led_props[] = { 196 + PROPERTY_ENTRY_STRING("label", "mx100:green:usb"), 197 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 21, GPIO_ACTIVE_LOW), 198 + { } 199 + }; 200 + 201 + static const struct software_node tink_usb_green_led_node = { 202 + .name = "usb-green-led", 203 + .parent = &tink_gpio_leds_node, 204 + .properties = tink_usb_green_led_props, 205 + }; 206 + 207 + static const struct property_entry tink_usb_orange_led_props[] = { 208 + PROPERTY_ENTRY_STRING("label", "mx100:orange:usb"), 209 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 19, GPIO_ACTIVE_LOW), 210 + { } 211 + }; 212 + 213 + static const struct software_node tink_usb_orange_led_node = { 214 + .name = "usb-orange-led", 215 + .parent = &tink_gpio_leds_node, 216 + .properties = tink_usb_orange_led_props, 119 217 }; 120 218 121 219 /* Reset Button */ 122 - static struct gpio_keys_button tink_buttons[] = { 123 - { 124 - .desc = "Reset", 125 - .type = EV_KEY, 126 - .code = KEY_RESTART, 127 - .active_low = 1, 128 - .debounce_interval = 100, 129 - }, 220 + static const struct property_entry tink_gpio_keys_props[] = { 221 + PROPERTY_ENTRY_U32("poll-interval", 20), 222 + { } 130 223 }; 131 224 132 - static const struct gpio_keys_platform_data tink_buttons_pdata = { 133 - .buttons = tink_buttons, 134 - .nbuttons = ARRAY_SIZE(tink_buttons), 135 - .poll_interval = 20, 136 - .rep = 0, 137 - .name = "mx100-keys", 225 + static const struct software_node tink_gpio_keys_node = { 226 + .name = "mx100-keys", 227 + .properties = tink_gpio_keys_props, 138 228 }; 139 229 140 - static struct gpiod_lookup_table tink_keys_table = { 141 - .dev_id = "gpio-keys-polled", 142 - .table = { 143 - GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 60, 144 - NULL, 0, GPIO_ACTIVE_LOW), 145 - {} /* Terminating entry */ 146 - } 230 + static const struct property_entry tink_reset_key_props[] = { 231 + PROPERTY_ENTRY_U32("linux,code", KEY_RESTART), 232 + PROPERTY_ENTRY_STRING("label", "Reset"), 233 + PROPERTY_ENTRY_GPIO("gpios", &gpio_ich_node, 60, GPIO_ACTIVE_LOW), 234 + PROPERTY_ENTRY_U32("linux,input-type", EV_KEY), 235 + PROPERTY_ENTRY_U32("debounce-interval", 100), 236 + { } 237 + }; 238 + 239 + static const struct software_node tink_reset_key_node = { 240 + .name = "reset", 241 + .parent = &tink_gpio_keys_node, 242 + .properties = tink_reset_key_props, 243 + }; 244 + 245 + static const struct software_node *tink_swnodes[] = { 246 + &gpio_ich_node, 247 + /* LEDs nodes */ 248 + &tink_gpio_leds_node, 249 + &tink_internet_led_node, 250 + &tink_lan2_led_node, 251 + &tink_lan3_led_node, 252 + &tink_lan4_led_node, 253 + &tink_lan5_led_node, 254 + &tink_lan6_led_node, 255 + &tink_lan7_led_node, 256 + &tink_lan8_led_node, 257 + &tink_lan9_led_node, 258 + &tink_lan10_led_node, 259 + &tink_lan11_led_node, 260 + &tink_ha_green_led_node, 261 + &tink_ha_orange_led_node, 262 + &tink_usb_green_led_node, 263 + &tink_usb_orange_led_node, 264 + /* Keys nodes */ 265 + &tink_gpio_keys_node, 266 + &tink_reset_key_node, 267 + NULL 147 268 }; 148 269 149 270 /* Board setup */ ··· 282 161 static struct platform_device *tink_leds_pdev; 283 162 static struct platform_device *tink_keys_pdev; 284 163 285 - static struct platform_device * __init tink_create_dev( 286 - const char *name, const void *pdata, size_t sz) 287 - { 288 - struct platform_device *pdev; 289 - 290 - pdev = platform_device_register_data(NULL, 291 - name, PLATFORM_DEVID_NONE, pdata, sz); 292 - if (IS_ERR(pdev)) 293 - pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev)); 294 - 295 - return pdev; 296 - } 297 - 298 164 static int __init tink_board_init(void) 299 165 { 300 - int ret; 166 + struct platform_device_info keys_info = { 167 + .name = "gpio-keys-polled", 168 + .id = PLATFORM_DEVID_NONE, 169 + }; 170 + struct platform_device_info leds_info = { 171 + .name = "leds-gpio", 172 + .id = PLATFORM_DEVID_NONE, 173 + }; 174 + int err; 301 175 302 176 if (!dmi_first_match(tink_systems)) 303 177 return -ENODEV; ··· 304 188 */ 305 189 outl(inl(0x530) | BIT(28), 0x530); 306 190 307 - gpiod_add_lookup_table(&tink_leds_table); 308 - gpiod_add_lookup_table(&tink_keys_table); 309 - 310 - tink_leds_pdev = tink_create_dev("leds-gpio", 311 - &tink_leds_pdata, sizeof(tink_leds_pdata)); 312 - if (IS_ERR(tink_leds_pdev)) { 313 - ret = PTR_ERR(tink_leds_pdev); 314 - goto err; 191 + err = software_node_register_node_group(tink_swnodes); 192 + if (err) { 193 + pr_err("failed to register software nodes: %d\n", err); 194 + return err; 315 195 } 316 196 317 - tink_keys_pdev = tink_create_dev("gpio-keys-polled", 318 - &tink_buttons_pdata, sizeof(tink_buttons_pdata)); 197 + leds_info.fwnode = software_node_fwnode(&tink_gpio_leds_node); 198 + tink_leds_pdev = platform_device_register_full(&leds_info); 199 + if (IS_ERR(tink_leds_pdev)) { 200 + err = PTR_ERR(tink_leds_pdev); 201 + pr_err("failed to create LED device: %d\n", err); 202 + goto err_unregister_swnodes; 203 + } 204 + 205 + keys_info.fwnode = software_node_fwnode(&tink_gpio_keys_node); 206 + tink_keys_pdev = platform_device_register_full(&keys_info); 319 207 if (IS_ERR(tink_keys_pdev)) { 320 - ret = PTR_ERR(tink_keys_pdev); 321 - platform_device_unregister(tink_leds_pdev); 322 - goto err; 208 + err = PTR_ERR(tink_keys_pdev); 209 + pr_err("failed to create key device: %d\n", err); 210 + goto err_unregister_leds; 323 211 } 324 212 325 213 return 0; 326 214 327 - err: 328 - gpiod_remove_lookup_table(&tink_keys_table); 329 - gpiod_remove_lookup_table(&tink_leds_table); 330 - return ret; 215 + err_unregister_leds: 216 + platform_device_unregister(tink_leds_pdev); 217 + err_unregister_swnodes: 218 + software_node_unregister_node_group(tink_swnodes); 219 + return err; 331 220 } 332 221 module_init(tink_board_init); 333 222 ··· 340 219 { 341 220 platform_device_unregister(tink_keys_pdev); 342 221 platform_device_unregister(tink_leds_pdev); 343 - gpiod_remove_lookup_table(&tink_keys_table); 344 - gpiod_remove_lookup_table(&tink_leds_table); 222 + software_node_unregister_node_group(tink_swnodes); 345 223 } 346 224 module_exit(tink_board_exit); 347 225
+120 -76
drivers/platform/x86/pcengines-apuv2.c
··· 12 12 13 13 #include <linux/dmi.h> 14 14 #include <linux/err.h> 15 + #include <linux/gpio/machine.h> 16 + #include <linux/gpio/property.h> 17 + #include <linux/input-event-codes.h> 15 18 #include <linux/kernel.h> 16 - #include <linux/leds.h> 17 19 #include <linux/module.h> 18 20 #include <linux/platform_device.h> 19 - #include <linux/gpio_keys.h> 20 - #include <linux/gpio/machine.h> 21 - #include <linux/input.h> 21 + #include <linux/property.h> 22 22 #include <linux/platform_data/gpio/gpio-amd-fch.h> 23 23 24 24 /* ··· 72 72 .gpio_names = apu2_gpio_names, 73 73 }; 74 74 75 + static const struct software_node apu2_gpiochip_node = { 76 + .name = AMD_FCH_GPIO_DRIVER_NAME, 77 + }; 78 + 75 79 /* GPIO LEDs device */ 76 - 77 - static const struct gpio_led apu2_leds[] = { 78 - { .name = "apu:green:1" }, 79 - { .name = "apu:green:2" }, 80 - { .name = "apu:green:3" }, 80 + static const struct software_node apu2_leds_node = { 81 + .name = "apu2-leds", 81 82 }; 82 83 83 - static const struct gpio_led_platform_data apu2_leds_pdata = { 84 - .num_leds = ARRAY_SIZE(apu2_leds), 85 - .leds = apu2_leds, 84 + static const struct property_entry apu2_led1_props[] = { 85 + PROPERTY_ENTRY_STRING("label", "apu:green:1"), 86 + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, 87 + APU2_GPIO_LINE_LED1, GPIO_ACTIVE_LOW), 88 + { } 86 89 }; 87 90 88 - static struct gpiod_lookup_table gpios_led_table = { 89 - .dev_id = "leds-gpio", 90 - .table = { 91 - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED1, 92 - NULL, 0, GPIO_ACTIVE_LOW), 93 - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED2, 94 - NULL, 1, GPIO_ACTIVE_LOW), 95 - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3, 96 - NULL, 2, GPIO_ACTIVE_LOW), 97 - {} /* Terminating entry */ 98 - } 91 + static const struct software_node apu2_led1_swnode = { 92 + .name = "led-1", 93 + .parent = &apu2_leds_node, 94 + .properties = apu2_led1_props, 95 + }; 96 + 97 + static const struct property_entry apu2_led2_props[] = { 98 + PROPERTY_ENTRY_STRING("label", "apu:green:2"), 99 + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, 100 + APU2_GPIO_LINE_LED2, GPIO_ACTIVE_LOW), 101 + { } 102 + }; 103 + 104 + static const struct software_node apu2_led2_swnode = { 105 + .name = "led-2", 106 + .parent = &apu2_leds_node, 107 + .properties = apu2_led2_props, 108 + }; 109 + 110 + static const struct property_entry apu2_led3_props[] = { 111 + PROPERTY_ENTRY_STRING("label", "apu:green:3"), 112 + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, 113 + APU2_GPIO_LINE_LED3, GPIO_ACTIVE_LOW), 114 + { } 115 + }; 116 + 117 + static const struct software_node apu2_led3_swnode = { 118 + .name = "led-3", 119 + .parent = &apu2_leds_node, 120 + .properties = apu2_led3_props, 99 121 }; 100 122 101 123 /* GPIO keyboard device */ 102 - 103 - static struct gpio_keys_button apu2_keys_buttons[] = { 104 - { 105 - .code = KEY_RESTART, 106 - .active_low = 1, 107 - .desc = "front button", 108 - .type = EV_KEY, 109 - .debounce_interval = 10, 110 - .value = 1, 111 - }, 124 + static const struct property_entry apu2_keys_props[] = { 125 + PROPERTY_ENTRY_U32("poll-interval", 100), 126 + { } 112 127 }; 113 128 114 - static const struct gpio_keys_platform_data apu2_keys_pdata = { 115 - .buttons = apu2_keys_buttons, 116 - .nbuttons = ARRAY_SIZE(apu2_keys_buttons), 117 - .poll_interval = 100, 118 - .rep = 0, 119 - .name = "apu2-keys", 129 + static const struct software_node apu2_keys_node = { 130 + .name = "apu2-keys", 131 + .properties = apu2_keys_props, 120 132 }; 121 133 122 - static struct gpiod_lookup_table gpios_key_table = { 123 - .dev_id = "gpio-keys-polled", 124 - .table = { 125 - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW, 126 - NULL, 0, GPIO_ACTIVE_LOW), 127 - {} /* Terminating entry */ 128 - } 134 + static const struct property_entry apu2_front_button_props[] = { 135 + PROPERTY_ENTRY_STRING("label", "front button"), 136 + PROPERTY_ENTRY_U32("linux,code", KEY_RESTART), 137 + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, 138 + APU2_GPIO_LINE_MODESW, GPIO_ACTIVE_LOW), 139 + PROPERTY_ENTRY_U32("debounce-interval", 10), 140 + { } 141 + }; 142 + 143 + static const struct software_node apu2_front_button_swnode = { 144 + .name = "front-button", 145 + .parent = &apu2_keys_node, 146 + .properties = apu2_front_button_props, 147 + }; 148 + 149 + static const struct software_node *apu2_swnodes[] = { 150 + &apu2_gpiochip_node, 151 + /* LEDs nodes */ 152 + &apu2_leds_node, 153 + &apu2_led1_swnode, 154 + &apu2_led2_swnode, 155 + &apu2_led3_swnode, 156 + /* Keys nodes */ 157 + &apu2_keys_node, 158 + &apu2_front_button_swnode, 159 + NULL 129 160 }; 130 161 131 162 /* Board setup */ ··· 253 222 static struct platform_device *apu_leds_pdev; 254 223 static struct platform_device *apu_keys_pdev; 255 224 256 - static struct platform_device * __init apu_create_pdev( 257 - const char *name, 258 - const void *pdata, 259 - size_t sz) 225 + static struct platform_device * __init apu_create_pdev(const char *name, 226 + const void *data, size_t size, 227 + const struct software_node *swnode) 260 228 { 229 + struct platform_device_info pdev_info = { 230 + .name = name, 231 + .id = PLATFORM_DEVID_NONE, 232 + .data = data, 233 + .size_data = size, 234 + .fwnode = software_node_fwnode(swnode), 235 + }; 261 236 struct platform_device *pdev; 237 + int err; 262 238 263 - pdev = platform_device_register_resndata(NULL, 264 - name, 265 - PLATFORM_DEVID_NONE, 266 - NULL, 267 - 0, 268 - pdata, 269 - sz); 239 + pdev = platform_device_register_full(&pdev_info); 270 240 271 - if (IS_ERR(pdev)) 272 - pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev)); 241 + err = PTR_ERR_OR_ZERO(pdev); 242 + if (err) 243 + pr_err("failed registering %s: %d\n", name, err); 273 244 274 245 return pdev; 275 246 } ··· 279 246 static int __init apu_board_init(void) 280 247 { 281 248 const struct dmi_system_id *id; 249 + int err; 282 250 283 251 id = dmi_first_match(apu_gpio_dmi_table); 284 252 if (!id) { ··· 287 253 return -ENODEV; 288 254 } 289 255 290 - gpiod_add_lookup_table(&gpios_led_table); 291 - gpiod_add_lookup_table(&gpios_key_table); 256 + err = software_node_register_node_group(apu2_swnodes); 257 + if (err) { 258 + pr_err("failed to register software nodes: %d\n", err); 259 + return err; 260 + } 292 261 293 - apu_gpio_pdev = apu_create_pdev( 294 - AMD_FCH_GPIO_DRIVER_NAME, 295 - id->driver_data, 296 - sizeof(struct amd_fch_gpio_pdata)); 262 + apu_gpio_pdev = apu_create_pdev(AMD_FCH_GPIO_DRIVER_NAME, 263 + id->driver_data, sizeof(struct amd_fch_gpio_pdata), NULL); 264 + err = PTR_ERR_OR_ZERO(apu_gpio_pdev); 265 + if (err) 266 + goto err_unregister_swnodes; 297 267 298 - apu_leds_pdev = apu_create_pdev( 299 - "leds-gpio", 300 - &apu2_leds_pdata, 301 - sizeof(apu2_leds_pdata)); 268 + apu_leds_pdev = apu_create_pdev("leds-gpio", NULL, 0, &apu2_leds_node); 269 + err = PTR_ERR_OR_ZERO(apu_leds_pdev); 270 + if (err) 271 + goto err_unregister_gpio; 302 272 303 - apu_keys_pdev = apu_create_pdev( 304 - "gpio-keys-polled", 305 - &apu2_keys_pdata, 306 - sizeof(apu2_keys_pdata)); 273 + apu_keys_pdev = apu_create_pdev("gpio-keys-polled", NULL, 0, &apu2_keys_node); 274 + err = PTR_ERR_OR_ZERO(apu_keys_pdev); 275 + if (err) 276 + goto err_unregister_leds; 307 277 308 278 return 0; 279 + 280 + err_unregister_leds: 281 + platform_device_unregister(apu_leds_pdev); 282 + err_unregister_gpio: 283 + platform_device_unregister(apu_gpio_pdev); 284 + err_unregister_swnodes: 285 + software_node_unregister_node_group(apu2_swnodes); 286 + return err; 309 287 } 310 288 311 289 static void __exit apu_board_exit(void) 312 290 { 313 - gpiod_remove_lookup_table(&gpios_led_table); 314 - gpiod_remove_lookup_table(&gpios_key_table); 315 - 316 291 platform_device_unregister(apu_keys_pdev); 317 292 platform_device_unregister(apu_leds_pdev); 318 293 platform_device_unregister(apu_gpio_pdev); 294 + software_node_unregister_node_group(apu2_swnodes); 319 295 } 320 296 321 297 module_init(apu_board_init);
+181 -13
drivers/platform/x86/portwell-ec.c
··· 5 5 * Tested on: 6 6 * - Portwell NANO-6064 7 7 * 8 - * This driver provides support for GPIO and Watchdog Timer 9 - * functionalities of the Portwell boards with ITE embedded controller (EC). 8 + * This driver supports Portwell boards with an ITE embedded controller (EC). 10 9 * The EC is accessed through I/O ports and provides: 10 + * - Temperature and voltage readings (hwmon) 11 11 * - 8 GPIO pins for control and monitoring 12 12 * - Hardware watchdog with 1-15300 second timeout range 13 13 * 14 - * It integrates with the Linux GPIO and Watchdog subsystems, allowing 15 - * userspace interaction with EC GPIO pins and watchdog control, 16 - * ensuring system stability and configurability. 14 + * It integrates with the Linux hwmon, GPIO and Watchdog subsystems. 17 15 * 18 16 * (C) Copyright 2025 Portwell, Inc. 19 17 * Author: Yen-Chi Huang (jesse.huang@portwell.com.tw) ··· 20 22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 21 23 22 24 #include <linux/acpi.h> 25 + #include <linux/bits.h> 23 26 #include <linux/bitfield.h> 24 27 #include <linux/dmi.h> 25 28 #include <linux/gpio/driver.h> 29 + #include <linux/hwmon.h> 26 30 #include <linux/init.h> 27 31 #include <linux/io.h> 28 32 #include <linux/ioport.h> 29 33 #include <linux/module.h> 30 34 #include <linux/platform_device.h> 35 + #include <linux/pm.h> 31 36 #include <linux/sizes.h> 32 37 #include <linux/string.h> 38 + #include <linux/units.h> 33 39 #include <linux/watchdog.h> 34 40 35 41 #define PORTWELL_EC_IOSPACE 0xe300 ··· 42 40 #define PORTWELL_GPIO_PINS 8 43 41 #define PORTWELL_GPIO_DIR_REG 0x2b 44 42 #define PORTWELL_GPIO_VAL_REG 0x2c 43 + 44 + #define PORTWELL_HWMON_TEMP_NUM 3 45 + #define PORTWELL_HWMON_VOLT_NUM 5 45 46 46 47 #define PORTWELL_WDT_EC_CONFIG_ADDR 0x06 47 48 #define PORTWELL_WDT_CONFIG_ENABLE 0x1 ··· 57 52 #define PORTWELL_EC_FW_VENDOR_LENGTH 3 58 53 #define PORTWELL_EC_FW_VENDOR_NAME "PWG" 59 54 55 + #define PORTWELL_EC_ADC_MAX 1023 56 + 60 57 static bool force; 61 58 module_param(force, bool, 0444); 62 59 MODULE_PARM_DESC(force, "Force loading EC driver without checking DMI boardname"); 60 + 61 + /* A sensor's metadata (label, scale, and register) */ 62 + struct pwec_sensor_prop { 63 + const char *label; 64 + u8 reg; 65 + u32 scale; 66 + }; 67 + 68 + /* Master configuration with properties for all possible sensors */ 69 + static const struct { 70 + const struct pwec_sensor_prop temp_props[PORTWELL_HWMON_TEMP_NUM]; 71 + const struct pwec_sensor_prop in_props[PORTWELL_HWMON_VOLT_NUM]; 72 + } pwec_master_data = { 73 + .temp_props = { 74 + { "CPU Temperature", 0x00, 0 }, 75 + { "System Temperature", 0x02, 0 }, 76 + { "Aux Temperature", 0x04, 0 }, 77 + }, 78 + .in_props = { 79 + { "Vcore", 0x20, 3000 }, 80 + { "3.3V", 0x22, 6000 }, 81 + { "5V", 0x24, 9600 }, 82 + { "12V", 0x30, 19800 }, 83 + { "VDIMM", 0x32, 3000 }, 84 + }, 85 + }; 86 + 87 + struct pwec_board_info { 88 + u32 temp_mask; /* bit N = temperature channel N */ 89 + u32 in_mask; /* bit N = voltage channel N */ 90 + }; 91 + 92 + static const struct pwec_board_info pwec_board_info_default = { 93 + .temp_mask = GENMASK(PORTWELL_HWMON_TEMP_NUM - 1, 0), 94 + .in_mask = GENMASK(PORTWELL_HWMON_VOLT_NUM - 1, 0), 95 + }; 96 + 97 + static const struct pwec_board_info pwec_board_info_nano = { 98 + .temp_mask = BIT(0) | BIT(1), 99 + .in_mask = GENMASK(4, 0), 100 + }; 63 101 64 102 static const struct dmi_system_id pwec_dmi_table[] = { 65 103 { ··· 110 62 .matches = { 111 63 DMI_MATCH(DMI_BOARD_NAME, "NANO-6064"), 112 64 }, 65 + .driver_data = (void *)&pwec_board_info_nano, 113 66 }, 114 67 { } 115 68 }; ··· 126 77 static u8 pwec_read(u8 address) 127 78 { 128 79 return inb(PORTWELL_EC_IOSPACE + address); 80 + } 81 + 82 + /* Ensure consistent 16-bit read across potential MSB rollover. */ 83 + static u16 pwec_read16_stable(u8 lsb_reg) 84 + { 85 + u8 lsb, msb, old_msb; 86 + 87 + do { 88 + old_msb = pwec_read(lsb_reg + 1); 89 + lsb = pwec_read(lsb_reg); 90 + msb = pwec_read(lsb_reg + 1); 91 + } while (msb != old_msb); 92 + 93 + return (msb << 8) | lsb; 129 94 } 130 95 131 96 /* GPIO functions */ ··· 267 204 .max_timeout = PORTWELL_WDT_EC_MAX_COUNT_SECOND, 268 205 }; 269 206 207 + /* HWMON functions */ 208 + 209 + static umode_t pwec_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type, 210 + u32 attr, int channel) 211 + { 212 + const struct pwec_board_info *info = drvdata; 213 + 214 + switch (type) { 215 + case hwmon_temp: 216 + return (info->temp_mask & BIT(channel)) ? 0444 : 0; 217 + case hwmon_in: 218 + return (info->in_mask & BIT(channel)) ? 0444 : 0; 219 + default: 220 + return 0; 221 + } 222 + } 223 + 224 + static int pwec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 225 + u32 attr, int channel, long *val) 226 + { 227 + u16 tmp16; 228 + 229 + switch (type) { 230 + case hwmon_temp: 231 + *val = pwec_read(pwec_master_data.temp_props[channel].reg) * MILLIDEGREE_PER_DEGREE; 232 + return 0; 233 + case hwmon_in: 234 + tmp16 = pwec_read16_stable(pwec_master_data.in_props[channel].reg); 235 + *val = (tmp16 * pwec_master_data.in_props[channel].scale) / PORTWELL_EC_ADC_MAX; 236 + return 0; 237 + default: 238 + return -EOPNOTSUPP; 239 + } 240 + } 241 + 242 + static int pwec_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, 243 + u32 attr, int channel, const char **str) 244 + { 245 + switch (type) { 246 + case hwmon_temp: 247 + *str = pwec_master_data.temp_props[channel].label; 248 + return 0; 249 + case hwmon_in: 250 + *str = pwec_master_data.in_props[channel].label; 251 + return 0; 252 + default: 253 + return -EOPNOTSUPP; 254 + } 255 + } 256 + 257 + static const struct hwmon_channel_info *pwec_hwmon_info[] = { 258 + HWMON_CHANNEL_INFO(temp, 259 + HWMON_T_INPUT | HWMON_T_LABEL, 260 + HWMON_T_INPUT | HWMON_T_LABEL, 261 + HWMON_T_INPUT | HWMON_T_LABEL), 262 + HWMON_CHANNEL_INFO(in, 263 + HWMON_I_INPUT | HWMON_I_LABEL, 264 + HWMON_I_INPUT | HWMON_I_LABEL, 265 + HWMON_I_INPUT | HWMON_I_LABEL, 266 + HWMON_I_INPUT | HWMON_I_LABEL, 267 + HWMON_I_INPUT | HWMON_I_LABEL), 268 + NULL 269 + }; 270 + 271 + static const struct hwmon_ops pwec_hwmon_ops = { 272 + .is_visible = pwec_hwmon_is_visible, 273 + .read = pwec_hwmon_read, 274 + .read_string = pwec_hwmon_read_string, 275 + }; 276 + 277 + static const struct hwmon_chip_info pwec_chip_info = { 278 + .ops = &pwec_hwmon_ops, 279 + .info = pwec_hwmon_info, 280 + }; 281 + 270 282 static int pwec_firmware_vendor_check(void) 271 283 { 272 284 u8 buf[PORTWELL_EC_FW_VENDOR_LENGTH + 1]; ··· 356 218 357 219 static int pwec_probe(struct platform_device *pdev) 358 220 { 221 + struct device *hwmon_dev; 222 + void *drvdata = dev_get_platdata(&pdev->dev); 359 223 int ret; 360 224 361 225 if (!devm_request_region(&pdev->dev, PORTWELL_EC_IOSPACE, ··· 376 236 return ret; 377 237 } 378 238 379 - ec_wdt_dev.parent = &pdev->dev; 380 - ret = devm_watchdog_register_device(&pdev->dev, &ec_wdt_dev); 381 - if (ret < 0) { 382 - dev_err(&pdev->dev, "failed to register Portwell EC Watchdog\n"); 383 - return ret; 239 + if (IS_REACHABLE(CONFIG_HWMON)) { 240 + hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, 241 + "portwell_ec", drvdata, &pwec_chip_info, NULL); 242 + ret = PTR_ERR_OR_ZERO(hwmon_dev); 243 + if (ret) 244 + return ret; 384 245 } 246 + 247 + ec_wdt_dev.parent = &pdev->dev; 248 + return devm_watchdog_register_device(&pdev->dev, &ec_wdt_dev); 249 + } 250 + 251 + static int pwec_suspend(struct device *dev) 252 + { 253 + if (watchdog_active(&ec_wdt_dev)) 254 + return pwec_wdt_stop(&ec_wdt_dev); 385 255 386 256 return 0; 387 257 } 388 258 259 + static int pwec_resume(struct device *dev) 260 + { 261 + if (watchdog_active(&ec_wdt_dev)) 262 + return pwec_wdt_start(&ec_wdt_dev); 263 + 264 + return 0; 265 + } 266 + 267 + static DEFINE_SIMPLE_DEV_PM_OPS(pwec_dev_pm_ops, pwec_suspend, pwec_resume); 268 + 389 269 static struct platform_driver pwec_driver = { 390 270 .driver = { 391 271 .name = "portwell-ec", 272 + .pm = pm_sleep_ptr(&pwec_dev_pm_ops), 392 273 }, 393 274 .probe = pwec_probe, 394 275 }; ··· 418 257 419 258 static int __init pwec_init(void) 420 259 { 260 + const struct dmi_system_id *match; 261 + const struct pwec_board_info *hwmon_data; 421 262 int ret; 422 263 423 - if (!dmi_check_system(pwec_dmi_table)) { 264 + match = dmi_first_match(pwec_dmi_table); 265 + if (!match) { 424 266 if (!force) 425 267 return -ENODEV; 426 - pr_warn("force load portwell-ec without DMI check\n"); 268 + hwmon_data = &pwec_board_info_default; 269 + pr_warn("force load portwell-ec without DMI check, using full display config\n"); 270 + } else { 271 + hwmon_data = match->driver_data; 427 272 } 428 273 429 274 ret = platform_driver_register(&pwec_driver); 430 275 if (ret) 431 276 return ret; 432 277 433 - pwec_dev = platform_device_register_simple("portwell-ec", -1, NULL, 0); 278 + pwec_dev = platform_device_register_data(NULL, "portwell-ec", PLATFORM_DEVID_NONE, 279 + hwmon_data, sizeof(*hwmon_data)); 434 280 if (IS_ERR(pwec_dev)) { 435 281 platform_driver_unregister(&pwec_driver); 436 282 return PTR_ERR(pwec_dev);
+1 -9
drivers/platform/x86/quickstart.c
··· 154 154 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, quickstart_notify); 155 155 } 156 156 157 - static void quickstart_mutex_destroy(void *data) 158 - { 159 - struct mutex *lock = data; 160 - 161 - mutex_destroy(lock); 162 - } 163 - 164 157 static int quickstart_probe(struct platform_device *pdev) 165 158 { 166 159 struct quickstart_data *data; ··· 172 179 data->dev = &pdev->dev; 173 180 dev_set_drvdata(&pdev->dev, data); 174 181 175 - mutex_init(&data->input_lock); 176 - ret = devm_add_action_or_reset(&pdev->dev, quickstart_mutex_destroy, &data->input_lock); 182 + ret = devm_mutex_init(&pdev->dev, &data->input_lock); 177 183 if (ret < 0) 178 184 return ret; 179 185
+130
drivers/platform/x86/redmi-wmi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* WMI driver for Xiaomi Redmibooks */ 3 + 4 + #include <linux/acpi.h> 5 + #include <linux/bits.h> 6 + #include <linux/device.h> 7 + #include <linux/input.h> 8 + #include <linux/input/sparse-keymap.h> 9 + #include <linux/module.h> 10 + #include <linux/mutex.h> 11 + #include <linux/unaligned.h> 12 + #include <linux/wmi.h> 13 + 14 + #include <uapi/linux/input-event-codes.h> 15 + 16 + #define WMI_REDMIBOOK_KEYBOARD_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF" 17 + 18 + #define AI_KEY_VALUE_MASK BIT(8) 19 + 20 + static const struct key_entry redmi_wmi_keymap[] = { 21 + {KE_KEY, 0x00000201, {KEY_SELECTIVE_SCREENSHOT}}, 22 + {KE_KEY, 0x00000301, {KEY_ALL_APPLICATIONS}}, 23 + {KE_KEY, 0x00001b01, {KEY_SETUP}}, 24 + 25 + /* AI button has code for each position */ 26 + {KE_KEY, 0x00011801, {KEY_ASSISTANT}}, 27 + {KE_KEY, 0x00011901, {KEY_ASSISTANT}}, 28 + 29 + /* Keyboard backlight */ 30 + {KE_IGNORE, 0x00000501, {}}, 31 + {KE_IGNORE, 0x00800501, {}}, 32 + {KE_IGNORE, 0x00050501, {}}, 33 + {KE_IGNORE, 0x000a0501, {}}, 34 + 35 + {KE_END} 36 + }; 37 + 38 + struct redmi_wmi { 39 + struct input_dev *input_dev; 40 + /* Protects the key event sequence */ 41 + struct mutex key_lock; 42 + }; 43 + 44 + static int redmi_wmi_probe(struct wmi_device *wdev, const void *context) 45 + { 46 + struct redmi_wmi *data; 47 + int err; 48 + 49 + /* Init dev */ 50 + data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL); 51 + if (!data) 52 + return -ENOMEM; 53 + 54 + dev_set_drvdata(&wdev->dev, data); 55 + 56 + err = devm_mutex_init(&wdev->dev, &data->key_lock); 57 + if (err) 58 + return err; 59 + 60 + data->input_dev = devm_input_allocate_device(&wdev->dev); 61 + if (!data->input_dev) 62 + return -ENOMEM; 63 + 64 + data->input_dev->name = "Redmibook WMI keys"; 65 + data->input_dev->phys = "wmi/input0"; 66 + 67 + err = sparse_keymap_setup(data->input_dev, redmi_wmi_keymap, NULL); 68 + if (err) 69 + return err; 70 + 71 + return input_register_device(data->input_dev); 72 + } 73 + 74 + static void redmi_wmi_notify(struct wmi_device *wdev, union acpi_object *obj) 75 + { 76 + struct key_entry *entry; 77 + struct redmi_wmi *data = dev_get_drvdata(&wdev->dev); 78 + bool autorelease = true; 79 + u32 payload; 80 + int value = 1; 81 + 82 + if (obj->type != ACPI_TYPE_BUFFER) { 83 + dev_err(&wdev->dev, "Bad response type %u\n", obj->type); 84 + return; 85 + } 86 + 87 + if (obj->buffer.length < 32) { 88 + dev_err(&wdev->dev, "Invalid buffer length %u\n", obj->buffer.length); 89 + return; 90 + } 91 + 92 + payload = get_unaligned_le32(obj->buffer.pointer); 93 + entry = sparse_keymap_entry_from_scancode(data->input_dev, payload); 94 + 95 + if (!entry) { 96 + dev_dbg(&wdev->dev, "Unknown WMI event with payload %u", payload); 97 + return; 98 + } 99 + 100 + /* AI key quirk */ 101 + if (entry->keycode == KEY_ASSISTANT) { 102 + value = !(payload & AI_KEY_VALUE_MASK); 103 + autorelease = false; 104 + } 105 + 106 + guard(mutex)(&data->key_lock); 107 + sparse_keymap_report_entry(data->input_dev, entry, value, autorelease); 108 + } 109 + 110 + static const struct wmi_device_id redmi_wmi_id_table[] = { 111 + { WMI_REDMIBOOK_KEYBOARD_EVENT_GUID, NULL }, 112 + { } 113 + }; 114 + 115 + static struct wmi_driver redmi_wmi_driver = { 116 + .driver = { 117 + .name = "redmi-wmi", 118 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 119 + }, 120 + .id_table = redmi_wmi_id_table, 121 + .probe = redmi_wmi_probe, 122 + .notify = redmi_wmi_notify, 123 + .no_singleton = true, 124 + }; 125 + module_wmi_driver(redmi_wmi_driver); 126 + 127 + MODULE_DEVICE_TABLE(wmi, redmi_wmi_id_table); 128 + MODULE_AUTHOR("Gladyshev Ilya <foxido@foxido.dev>"); 129 + MODULE_DESCRIPTION("Redmibook WMI driver"); 130 + MODULE_LICENSE("GPL");
+1 -1
drivers/platform/x86/x86-android-tablets/Makefile
··· 6 6 obj-$(CONFIG_X86_ANDROID_TABLETS) += vexia_atla10_ec.o 7 7 obj-$(CONFIG_X86_ANDROID_TABLETS) += x86-android-tablets.o 8 8 x86-android-tablets-y := core.o dmi.o shared-psy-info.o \ 9 - asus.o lenovo.o other.o 9 + acer.o asus.o lenovo.o other.o
+247
drivers/platform/x86/x86-android-tablets/acer.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Board info for Acer X86 tablets which ship with Android as the factory image 4 + * and which have broken DSDT tables. The factory kernels shipped on these 5 + * devices typically have a bunch of things hardcoded, rather than specified 6 + * in their DSDT. 7 + * 8 + * Copyright (C) 2021-2025 Hans de Goede <hansg@kernel.org> 9 + */ 10 + 11 + #include <linux/gpio/machine.h> 12 + #include <linux/gpio/property.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/property.h> 15 + 16 + #include "shared-psy-info.h" 17 + #include "x86-android-tablets.h" 18 + 19 + /* Acer Iconia One 8 A1-840 (non FHD version) */ 20 + static const struct property_entry acer_a1_840_bq24190_props[] = { 21 + PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_4v2_battery_node), 22 + PROPERTY_ENTRY_BOOL("omit-battery-class"), 23 + PROPERTY_ENTRY_BOOL("disable-reset"), 24 + { } 25 + }; 26 + 27 + static const struct software_node acer_a1_840_bq24190_node = { 28 + .properties = acer_a1_840_bq24190_props, 29 + }; 30 + 31 + static const struct property_entry acer_a1_840_touchscreen_props[] = { 32 + PROPERTY_ENTRY_U32("touchscreen-size-x", 800), 33 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 34 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_LOW), 35 + { } 36 + }; 37 + 38 + static const struct software_node acer_a1_840_touchscreen_node = { 39 + .properties = acer_a1_840_touchscreen_props, 40 + }; 41 + 42 + static const struct x86_i2c_client_info acer_a1_840_i2c_clients[] __initconst = { 43 + { 44 + /* BQ24297 charger IC */ 45 + .board_info = { 46 + .type = "bq24297", 47 + .addr = 0x6b, 48 + .dev_name = "bq24297", 49 + .swnode = &acer_a1_840_bq24190_node, 50 + .platform_data = &bq24190_pdata, 51 + }, 52 + .adapter_path = "\\_SB_.I2C1", 53 + .irq_data = { 54 + .type = X86_ACPI_IRQ_TYPE_GPIOINT, 55 + .chip = "INT33FC:02", 56 + .index = 2, 57 + .trigger = ACPI_EDGE_SENSITIVE, 58 + .polarity = ACPI_ACTIVE_LOW, 59 + .con_id = "bq24297_irq", 60 + }, 61 + }, { 62 + /* MPU6515 sensors */ 63 + .board_info = { 64 + .type = "mpu6515", 65 + .addr = 0x69, 66 + .dev_name = "mpu6515", 67 + }, 68 + .adapter_path = "\\_SB_.I2C3", 69 + .irq_data = { 70 + .type = X86_ACPI_IRQ_TYPE_APIC, 71 + .index = 0x47, 72 + .trigger = ACPI_EDGE_SENSITIVE, 73 + .polarity = ACPI_ACTIVE_HIGH, 74 + }, 75 + }, { 76 + /* FT5416 touchscreen controller */ 77 + .board_info = { 78 + .type = "edt-ft5x06", 79 + .addr = 0x38, 80 + .dev_name = "ft5416", 81 + .swnode = &acer_a1_840_touchscreen_node, 82 + }, 83 + .adapter_path = "\\_SB_.I2C4", 84 + .irq_data = { 85 + .type = X86_ACPI_IRQ_TYPE_APIC, 86 + .index = 0x45, 87 + .trigger = ACPI_EDGE_SENSITIVE, 88 + .polarity = ACPI_ACTIVE_HIGH, 89 + }, 90 + } 91 + }; 92 + 93 + static const struct property_entry acer_a1_840_int3496_props[] __initconst = { 94 + PROPERTY_ENTRY_GPIO("mux-gpios", &baytrail_gpiochip_nodes[2], 1, GPIO_ACTIVE_HIGH), 95 + PROPERTY_ENTRY_GPIO("id-gpios", &baytrail_gpiochip_nodes[2], 18, GPIO_ACTIVE_HIGH), 96 + { } 97 + }; 98 + 99 + static const struct platform_device_info acer_a1_840_pdevs[] __initconst = { 100 + { 101 + /* For micro USB ID pin handling */ 102 + .name = "intel-int3496", 103 + .id = PLATFORM_DEVID_NONE, 104 + .properties = acer_a1_840_int3496_props, 105 + }, 106 + }; 107 + 108 + /* Properties for the Dollar Cove TI PMIC battery MFD child used as fuel-gauge */ 109 + static const struct property_entry acer_a1_840_fg_props[] = { 110 + PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_4v2_battery_node), 111 + PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", bq24190_psy, 1), 112 + PROPERTY_ENTRY_GPIO("charged-gpios", &baytrail_gpiochip_nodes[2], 10, GPIO_ACTIVE_HIGH), 113 + { } 114 + }; 115 + 116 + static struct device *acer_a1_840_fg_dev; 117 + static struct fwnode_handle *acer_a1_840_fg_node; 118 + 119 + static int __init acer_a1_840_init(struct device *dev) 120 + { 121 + int ret; 122 + 123 + acer_a1_840_fg_dev = bus_find_device_by_name(&platform_bus_type, NULL, "chtdc_ti_battery"); 124 + if (!acer_a1_840_fg_dev) 125 + return dev_err_probe(dev, -EPROBE_DEFER, "getting chtdc_ti_battery dev\n"); 126 + 127 + acer_a1_840_fg_node = fwnode_create_software_node(acer_a1_840_fg_props, NULL); 128 + if (IS_ERR(acer_a1_840_fg_node)) { 129 + ret = PTR_ERR(acer_a1_840_fg_node); 130 + goto err_put; 131 + } 132 + 133 + ret = device_add_software_node(acer_a1_840_fg_dev, 134 + to_software_node(acer_a1_840_fg_node)); 135 + if (ret) 136 + goto err_put; 137 + 138 + return 0; 139 + 140 + err_put: 141 + fwnode_handle_put(acer_a1_840_fg_node); 142 + acer_a1_840_fg_node = NULL; 143 + put_device(acer_a1_840_fg_dev); 144 + acer_a1_840_fg_dev = NULL; 145 + return ret; 146 + } 147 + 148 + static void acer_a1_840_exit(void) 149 + { 150 + device_remove_software_node(acer_a1_840_fg_dev); 151 + /* 152 + * Skip fwnode_handle_put(acer_a1_840_fg_node), instead leak the node. 153 + * The intel_dc_ti_battery driver may still reference the strdup-ed 154 + * "supplied-from" string. This string will be free-ed if the node 155 + * is released. 156 + */ 157 + acer_a1_840_fg_node = NULL; 158 + put_device(acer_a1_840_fg_dev); 159 + acer_a1_840_fg_dev = NULL; 160 + } 161 + 162 + static const char * const acer_a1_840_modules[] __initconst = { 163 + "bq24190_charger", /* For the Vbus regulator for intel-int3496 */ 164 + NULL 165 + }; 166 + 167 + const struct x86_dev_info acer_a1_840_info __initconst = { 168 + .i2c_client_info = acer_a1_840_i2c_clients, 169 + .i2c_client_count = ARRAY_SIZE(acer_a1_840_i2c_clients), 170 + .pdev_info = acer_a1_840_pdevs, 171 + .pdev_count = ARRAY_SIZE(acer_a1_840_pdevs), 172 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 173 + .swnode_group = generic_lipo_4v2_battery_swnodes, 174 + .modules = acer_a1_840_modules, 175 + .init = acer_a1_840_init, 176 + .exit = acer_a1_840_exit, 177 + }; 178 + 179 + /* Acer Iconia One 7 B1-750 has an Android factory image with everything hardcoded */ 180 + static const char * const acer_b1_750_mount_matrix[] = { 181 + "-1", "0", "0", 182 + "0", "1", "0", 183 + "0", "0", "1" 184 + }; 185 + 186 + static const struct property_entry acer_b1_750_bma250e_props[] = { 187 + PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", acer_b1_750_mount_matrix), 188 + { } 189 + }; 190 + 191 + static const struct software_node acer_b1_750_bma250e_node = { 192 + .properties = acer_b1_750_bma250e_props, 193 + }; 194 + 195 + static const struct property_entry acer_b1_750_novatek_props[] = { 196 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_LOW), 197 + { } 198 + }; 199 + 200 + static const struct software_node acer_b1_750_novatek_node = { 201 + .properties = acer_b1_750_novatek_props, 202 + }; 203 + 204 + static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = { 205 + { 206 + /* Novatek NVT-ts touchscreen */ 207 + .board_info = { 208 + .type = "nt11205-ts", 209 + .addr = 0x34, 210 + .dev_name = "NVT-ts", 211 + .swnode = &acer_b1_750_novatek_node, 212 + }, 213 + .adapter_path = "\\_SB_.I2C4", 214 + .irq_data = { 215 + .type = X86_ACPI_IRQ_TYPE_GPIOINT, 216 + .chip = "INT33FC:02", 217 + .index = 3, 218 + .trigger = ACPI_EDGE_SENSITIVE, 219 + .polarity = ACPI_ACTIVE_LOW, 220 + .con_id = "NVT-ts_irq", 221 + }, 222 + }, { 223 + /* BMA250E accelerometer */ 224 + .board_info = { 225 + .type = "bma250e", 226 + .addr = 0x18, 227 + .swnode = &acer_b1_750_bma250e_node, 228 + }, 229 + .adapter_path = "\\_SB_.I2C3", 230 + .irq_data = { 231 + .type = X86_ACPI_IRQ_TYPE_GPIOINT, 232 + .chip = "INT33FC:02", 233 + .index = 25, 234 + .trigger = ACPI_LEVEL_SENSITIVE, 235 + .polarity = ACPI_ACTIVE_HIGH, 236 + .con_id = "bma250e_irq", 237 + }, 238 + }, 239 + }; 240 + 241 + const struct x86_dev_info acer_b1_750_info __initconst = { 242 + .i2c_client_info = acer_b1_750_i2c_clients, 243 + .i2c_client_count = ARRAY_SIZE(acer_b1_750_i2c_clients), 244 + .pdev_info = int3496_pdevs, 245 + .pdev_count = 1, 246 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 247 + };
+58 -50
drivers/platform/x86/x86-android-tablets/asus.c
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 11 11 #include <linux/gpio/machine.h> 12 - #include <linux/input.h> 12 + #include <linux/gpio/property.h> 13 + #include <linux/input-event-codes.h> 13 14 #include <linux/platform_device.h> 14 15 15 16 #include "shared-psy-info.h" 16 17 #include "x86-android-tablets.h" 17 18 18 19 /* Asus ME176C and TF103C tablets shared data */ 19 - static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = { 20 - .dev_id = "intel-int3496", 21 - .table = { 22 - GPIO_LOOKUP("INT33FC:02", 22, "id", GPIO_ACTIVE_HIGH), 23 - { } 20 + static const struct property_entry asus_me176c_tf103c_int3496_props[] __initconst = { 21 + PROPERTY_ENTRY_GPIO("id-gpios", &baytrail_gpiochip_nodes[2], 22, GPIO_ACTIVE_HIGH), 22 + { } 23 + }; 24 + 25 + static const struct platform_device_info asus_me176c_tf103c_pdevs[] __initconst = { 26 + { 27 + /* For micro USB ID pin handling */ 28 + .name = "intel-int3496", 29 + .id = PLATFORM_DEVID_NONE, 30 + .properties = asus_me176c_tf103c_int3496_props, 24 31 }, 25 32 }; 26 33 27 - static const struct x86_gpio_button asus_me176c_tf103c_lid __initconst = { 28 - .button = { 29 - .code = SW_LID, 30 - .active_low = true, 31 - .desc = "lid_sw", 32 - .type = EV_SW, 33 - .wakeup = true, 34 - .debounce_interval = 50, 35 - }, 36 - .chip = "INT33FC:02", 37 - .pin = 12, 34 + static const struct software_node asus_me176c_tf103c_gpio_keys_node = { 35 + .name = "lid_sw", 36 + }; 37 + 38 + static const struct property_entry asus_me176c_tf103c_lid_props[] = { 39 + PROPERTY_ENTRY_U32("linux,input-type", EV_SW), 40 + PROPERTY_ENTRY_U32("linux,code", SW_LID), 41 + PROPERTY_ENTRY_STRING("label", "lid_sw"), 42 + PROPERTY_ENTRY_GPIO("gpios", &baytrail_gpiochip_nodes[2], 12, GPIO_ACTIVE_LOW), 43 + PROPERTY_ENTRY_U32("debounce-interval", 50), 44 + PROPERTY_ENTRY_BOOL("wakeup-source"), 45 + { } 46 + }; 47 + 48 + static const struct software_node asus_me176c_tf103c_lid_node = { 49 + .parent = &asus_me176c_tf103c_gpio_keys_node, 50 + .properties = asus_me176c_tf103c_lid_props, 51 + }; 52 + 53 + static const struct software_node *asus_me176c_tf103c_lid_swnodes[] = { 54 + &asus_me176c_tf103c_gpio_keys_node, 55 + &asus_me176c_tf103c_lid_node, 56 + NULL 38 57 }; 39 58 40 59 /* Asus ME176C tablets have an Android factory image with everything hardcoded */ ··· 94 75 95 76 static const struct software_node asus_me176c_ug3105_node = { 96 77 .properties = asus_me176c_ug3105_props, 78 + }; 79 + 80 + static const struct property_entry asus_me176c_touchscreen_props[] = { 81 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[0], 60, GPIO_ACTIVE_HIGH), 82 + PROPERTY_ENTRY_GPIO("irq-gpios", &baytrail_gpiochip_nodes[2], 28, GPIO_ACTIVE_HIGH), 83 + { } 84 + }; 85 + 86 + static const struct software_node asus_me176c_touchscreen_node = { 87 + .properties = asus_me176c_touchscreen_props, 97 88 }; 98 89 99 90 static const struct x86_i2c_client_info asus_me176c_i2c_clients[] __initconst = { ··· 161 132 .type = "GDIX1001:00", 162 133 .addr = 0x14, 163 134 .dev_name = "goodix_ts", 135 + .swnode = &asus_me176c_touchscreen_node, 164 136 }, 165 137 .adapter_path = "\\_SB_.I2C6", 166 138 .irq_data = { ··· 182 152 }, 183 153 }; 184 154 185 - static struct gpiod_lookup_table asus_me176c_goodix_gpios = { 186 - .dev_id = "i2c-goodix_ts", 187 - .table = { 188 - GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_HIGH), 189 - GPIO_LOOKUP("INT33FC:02", 28, "irq", GPIO_ACTIVE_HIGH), 190 - { } 191 - }, 192 - }; 193 - 194 - static struct gpiod_lookup_table * const asus_me176c_gpios[] = { 195 - &int3496_gpo2_pin22_gpios, 196 - &asus_me176c_goodix_gpios, 197 - NULL 198 - }; 199 - 200 155 const struct x86_dev_info asus_me176c_info __initconst = { 201 156 .i2c_client_info = asus_me176c_i2c_clients, 202 157 .i2c_client_count = ARRAY_SIZE(asus_me176c_i2c_clients), 203 - .pdev_info = int3496_pdevs, 204 - .pdev_count = 1, 158 + .pdev_info = asus_me176c_tf103c_pdevs, 159 + .pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs), 205 160 .serdev_info = asus_me176c_serdevs, 206 161 .serdev_count = ARRAY_SIZE(asus_me176c_serdevs), 207 - .gpio_button = &asus_me176c_tf103c_lid, 208 - .gpio_button_count = 1, 209 - .gpiod_lookup_tables = asus_me176c_gpios, 210 - .bat_swnode = &generic_lipo_hv_4v35_battery_node, 162 + .gpio_button_swnodes = asus_me176c_tf103c_lid_swnodes, 163 + .swnode_group = generic_lipo_hv_4v35_battery_swnodes, 211 164 .modules = bq24190_modules, 165 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 212 166 }; 213 167 214 168 /* Asus TF103C tablets have an Android factory image with everything hardcoded */ ··· 307 293 }, 308 294 }; 309 295 310 - static struct gpiod_lookup_table * const asus_tf103c_gpios[] = { 311 - &int3496_gpo2_pin22_gpios, 312 - NULL 313 - }; 314 - 315 296 const struct x86_dev_info asus_tf103c_info __initconst = { 316 297 .i2c_client_info = asus_tf103c_i2c_clients, 317 298 .i2c_client_count = ARRAY_SIZE(asus_tf103c_i2c_clients), 318 - .pdev_info = int3496_pdevs, 319 - .pdev_count = 1, 320 - .gpio_button = &asus_me176c_tf103c_lid, 321 - .gpio_button_count = 1, 322 - .gpiod_lookup_tables = asus_tf103c_gpios, 323 - .bat_swnode = &generic_lipo_4v2_battery_node, 299 + .pdev_info = asus_me176c_tf103c_pdevs, 300 + .pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs), 301 + .gpio_button_swnodes = asus_me176c_tf103c_lid_swnodes, 302 + .swnode_group = generic_lipo_4v2_battery_swnodes, 324 303 .modules = bq24190_modules, 304 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 325 305 };
+72 -49
drivers/platform/x86/x86-android-tablets/core.c
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ··· 152 152 static struct spi_device **spi_devs; 153 153 static struct platform_device **pdevs; 154 154 static struct serdev_device **serdevs; 155 - static struct gpio_keys_button *buttons; 156 - static struct gpiod_lookup_table * const *gpiod_lookup_tables; 157 - static const struct software_node *bat_swnode; 155 + static const struct software_node **gpio_button_swnodes; 156 + static const struct software_node **swnode_group; 157 + static const struct software_node **gpiochip_node_group; 158 158 static void (*exit_handler)(void); 159 159 160 160 static __init struct i2c_adapter * ··· 265 265 spi_devs[idx] = spi_new_device(controller, &board_info); 266 266 put_device(&controller->dev); 267 267 if (!spi_devs[idx]) 268 - return dev_err_probe(&controller->dev, -ENOMEM, 269 - "creating SPI-device %d\n", idx); 268 + return -ENOMEM; 270 269 271 270 return 0; 272 271 } ··· 276 277 struct pci_dev *pdev; 277 278 278 279 pdev = pci_get_domain_bus_and_slot(0, 0, info->ctrl.pci.devfn); 279 - if (!pdev) 280 - return ERR_PTR(-EPROBE_DEFER); 280 + if (!pdev) { 281 + pr_err("error could not get PCI serdev at devfn 0x%02x\n", info->ctrl.pci.devfn); 282 + return ERR_PTR(-ENODEV); 283 + } 281 284 282 285 /* This puts our reference on pdev and returns a ref on the ctrl */ 283 286 return get_serdev_controller_from_parent(&pdev->dev, 0, info->ctrl_devname); ··· 332 331 return ret; 333 332 } 334 333 334 + const struct software_node baytrail_gpiochip_nodes[] = { 335 + { .name = "INT33FC:00" }, 336 + { .name = "INT33FC:01" }, 337 + { .name = "INT33FC:02" }, 338 + }; 339 + 340 + static const struct software_node *baytrail_gpiochip_node_group[] = { 341 + &baytrail_gpiochip_nodes[0], 342 + &baytrail_gpiochip_nodes[1], 343 + &baytrail_gpiochip_nodes[2], 344 + NULL 345 + }; 346 + 347 + const struct software_node cherryview_gpiochip_nodes[] = { 348 + { .name = "INT33FF:00" }, 349 + { .name = "INT33FF:01" }, 350 + { .name = "INT33FF:02" }, 351 + { .name = "INT33FF:03" }, 352 + }; 353 + 354 + static const struct software_node *cherryview_gpiochip_node_group[] = { 355 + &cherryview_gpiochip_nodes[0], 356 + &cherryview_gpiochip_nodes[1], 357 + &cherryview_gpiochip_nodes[2], 358 + &cherryview_gpiochip_nodes[3], 359 + NULL 360 + }; 361 + 335 362 static void x86_android_tablet_remove(struct platform_device *pdev) 336 363 { 337 364 int i; ··· 375 346 platform_device_unregister(pdevs[i]); 376 347 377 348 kfree(pdevs); 378 - kfree(buttons); 379 349 380 350 for (i = spi_dev_count - 1; i >= 0; i--) 381 351 spi_unregister_device(spi_devs[i]); ··· 389 361 if (exit_handler) 390 362 exit_handler(); 391 363 392 - for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++) 393 - gpiod_remove_lookup_table(gpiod_lookup_tables[i]); 394 - 395 - software_node_unregister(bat_swnode); 364 + software_node_unregister_node_group(gpio_button_swnodes); 365 + software_node_unregister_node_group(swnode_group); 366 + software_node_unregister_node_group(gpiochip_node_group); 396 367 } 397 368 398 369 static __init int x86_android_tablet_probe(struct platform_device *pdev) ··· 415 388 for (i = 0; dev_info->modules && dev_info->modules[i]; i++) 416 389 request_module(dev_info->modules[i]); 417 390 418 - bat_swnode = dev_info->bat_swnode; 419 - if (bat_swnode) { 420 - ret = software_node_register(bat_swnode); 421 - if (ret) 422 - return ret; 391 + switch (dev_info->gpiochip_type) { 392 + case X86_GPIOCHIP_BAYTRAIL: 393 + gpiochip_node_group = baytrail_gpiochip_node_group; 394 + break; 395 + case X86_GPIOCHIP_CHERRYVIEW: 396 + gpiochip_node_group = cherryview_gpiochip_node_group; 397 + break; 398 + case X86_GPIOCHIP_UNSPECIFIED: 399 + gpiochip_node_group = NULL; 400 + break; 423 401 } 424 402 425 - gpiod_lookup_tables = dev_info->gpiod_lookup_tables; 426 - for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++) 427 - gpiod_add_lookup_table(gpiod_lookup_tables[i]); 403 + ret = software_node_register_node_group(gpiochip_node_group); 404 + if (ret) 405 + return ret; 406 + 407 + ret = software_node_register_node_group(dev_info->swnode_group); 408 + if (ret) { 409 + x86_android_tablet_remove(pdev); 410 + return ret; 411 + } 412 + swnode_group = dev_info->swnode_group; 428 413 429 414 if (dev_info->init) { 430 415 ret = dev_info->init(&pdev->dev); ··· 509 470 } 510 471 } 511 472 512 - if (dev_info->gpio_button_count) { 513 - struct gpio_keys_platform_data pdata = { }; 514 - struct gpio_desc *gpiod; 473 + if (dev_info->gpio_button_swnodes) { 474 + struct platform_device_info button_info = { 475 + .name = "gpio-keys", 476 + .id = PLATFORM_DEVID_AUTO, 477 + }; 515 478 516 - buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL); 517 - if (!buttons) { 479 + ret = software_node_register_node_group(dev_info->gpio_button_swnodes); 480 + if (ret < 0) { 518 481 x86_android_tablet_remove(pdev); 519 - return -ENOMEM; 482 + return ret; 520 483 } 521 484 522 - for (i = 0; i < dev_info->gpio_button_count; i++) { 523 - ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip, 524 - dev_info->gpio_button[i].pin, 525 - dev_info->gpio_button[i].button.desc, 526 - false, GPIOD_IN, &gpiod); 527 - if (ret < 0) { 528 - x86_android_tablet_remove(pdev); 529 - return ret; 530 - } 485 + gpio_button_swnodes = dev_info->gpio_button_swnodes; 531 486 532 - buttons[i] = dev_info->gpio_button[i].button; 533 - buttons[i].gpio = desc_to_gpio(gpiod); 534 - /* Release GPIO descriptor so that gpio-keys can request it */ 535 - devm_gpiod_put(&x86_android_tablet_device->dev, gpiod); 536 - } 537 - 538 - pdata.buttons = buttons; 539 - pdata.nbuttons = dev_info->gpio_button_count; 540 - 541 - pdevs[pdev_count] = platform_device_register_data(&pdev->dev, "gpio-keys", 542 - PLATFORM_DEVID_AUTO, 543 - &pdata, sizeof(pdata)); 487 + button_info.fwnode = software_node_fwnode(dev_info->gpio_button_swnodes[0]); 488 + pdevs[pdev_count] = platform_device_register_full(&button_info); 544 489 if (IS_ERR(pdevs[pdev_count])) { 545 490 ret = PTR_ERR(pdevs[pdev_count]); 546 491 x86_android_tablet_remove(pdev); ··· 560 537 } 561 538 module_exit(x86_android_tablet_exit); 562 539 563 - MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 540 + MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 564 541 MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver"); 565 542 MODULE_LICENSE("GPL");
+11 -1
drivers/platform/x86/x86-android-tablets/dmi.c
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 11 11 #include <linux/dmi.h> ··· 16 16 #include "x86-android-tablets.h" 17 17 18 18 const struct dmi_system_id x86_android_tablet_ids[] __initconst = { 19 + { 20 + /* Acer Iconia One 8 A1-840 (non FHD version) */ 21 + .matches = { 22 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 23 + DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"), 24 + /* Above strings are too generic also match BIOS date */ 25 + DMI_MATCH(DMI_BIOS_DATE, "04/01/2014"), 26 + }, 27 + .driver_data = (void *)&acer_a1_840_info, 28 + }, 19 29 { 20 30 /* Acer Iconia One 7 B1-750 */ 21 31 .matches = {
+161 -130
drivers/platform/x86/x86-android-tablets/lenovo.c
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 12 13 13 #include <linux/efi.h> 14 14 #include <linux/gpio/machine.h> 15 + #include <linux/gpio/property.h> 16 + #include <linux/input-event-codes.h> 15 17 #include <linux/mfd/arizona/pdata.h> 16 18 #include <linux/mfd/arizona/registers.h> 17 19 #include <linux/mfd/intel_soc_pmic.h> ··· 61 59 .initial_brightness = 128, 62 60 }; 63 61 62 + static const struct software_node arizona_gpiochip_node = { 63 + .name = "arizona", 64 + }; 65 + 66 + static const struct software_node crystalcove_gpiochip_node = { 67 + .name = "gpio_crystalcove", 68 + }; 69 + 64 70 /* Lenovo Yoga Book X90F / X90L's Android factory image has everything hardcoded */ 71 + 72 + static const struct property_entry lenovo_yb1_x90_goodix_props[] = { 73 + PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[1], 53, GPIO_ACTIVE_HIGH), 74 + PROPERTY_ENTRY_GPIO("irq-gpios", &cherryview_gpiochip_nodes[1], 56, GPIO_ACTIVE_HIGH), 75 + { } 76 + }; 77 + 78 + static const struct software_node lenovo_yb1_x90_goodix_node = { 79 + .properties = lenovo_yb1_x90_goodix_props, 80 + }; 65 81 66 82 static const struct property_entry lenovo_yb1_x90_wacom_props[] = { 67 83 PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001), 68 84 PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150), 85 + PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 82, GPIO_ACTIVE_LOW), 69 86 { } 70 87 }; 71 88 ··· 106 85 PROPERTY_ENTRY_U32("touchscreen-size-y", 1920), 107 86 PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384), 108 87 PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"), 88 + PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 7, GPIO_ACTIVE_LOW), 109 89 { } 110 90 }; 111 91 ··· 130 108 .type = "GDIX1001:00", 131 109 .addr = 0x14, 132 110 .dev_name = "goodix_ts", 111 + .swnode = &lenovo_yb1_x90_goodix_node, 133 112 }, 134 113 .adapter_path = "\\_SB_.PCI0.I2C2", 135 114 .irq_data = { ··· 208 185 }, 209 186 }; 210 187 211 - static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = { 212 - .button = { 213 - .code = SW_LID, 214 - .active_low = true, 215 - .desc = "lid_sw", 216 - .type = EV_SW, 217 - .wakeup = true, 218 - .debounce_interval = 50, 219 - }, 220 - .chip = "INT33FF:02", 221 - .pin = 19, 188 + /* 189 + * Software node attached to gpio-keys device representing the LID and 190 + * serving as a parent to software nodes representing individual keys/buttons 191 + * as required by the device tree binding. 192 + */ 193 + static const struct software_node lenovo_lid_gpio_keys_node = { 194 + .name = "lid_sw", 222 195 }; 223 196 224 - static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = { 225 - .dev_id = "i2c-goodix_ts", 226 - .table = { 227 - GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH), 228 - GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH), 229 - { } 230 - }, 197 + static const struct property_entry lenovo_yb1_x90_lid_props[] = { 198 + PROPERTY_ENTRY_U32("linux,input-type", EV_SW), 199 + PROPERTY_ENTRY_U32("linux,code", SW_LID), 200 + PROPERTY_ENTRY_STRING("label", "lid_sw"), 201 + PROPERTY_ENTRY_GPIO("gpios", &cherryview_gpiochip_nodes[2], 19, GPIO_ACTIVE_LOW), 202 + PROPERTY_ENTRY_U32("debounce-interval", 50), 203 + PROPERTY_ENTRY_BOOL("wakeup-source"), 204 + { } 231 205 }; 232 206 233 - static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = { 234 - .dev_id = "i2c-hideep_ts", 235 - .table = { 236 - GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW), 237 - { } 238 - }, 207 + static const struct software_node lenovo_yb1_x90_lid_node = { 208 + .parent = &lenovo_lid_gpio_keys_node, 209 + .properties = lenovo_yb1_x90_lid_props, 239 210 }; 240 211 241 - static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = { 242 - .dev_id = "i2c-wacom", 243 - .table = { 244 - GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW), 245 - { } 246 - }, 247 - }; 248 - 249 - static struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = { 250 - &lenovo_yb1_x90_hideep_gpios, 251 - &lenovo_yb1_x90_goodix_gpios, 252 - &lenovo_yb1_x90_wacom_gpios, 212 + static const struct software_node *lenovo_yb1_x90_lid_swnodes[] = { 213 + &lenovo_lid_gpio_keys_node, 214 + &lenovo_yb1_x90_lid_node, 253 215 NULL 254 216 }; 255 217 ··· 264 256 .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs), 265 257 .serdev_info = lenovo_yb1_x90_serdevs, 266 258 .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs), 267 - .gpio_button = &lenovo_yb1_x90_lid, 268 - .gpio_button_count = 1, 269 - .gpiod_lookup_tables = lenovo_yb1_x90_gpios, 259 + .gpio_button_swnodes = lenovo_yb1_x90_lid_swnodes, 260 + .gpiochip_type = X86_GPIOCHIP_CHERRYVIEW, 270 261 .init = lenovo_yb1_x90_init, 271 262 }; 272 263 ··· 301 294 .properties = lenovo_yoga_tab2_830_1050_bq24190_props, 302 295 }; 303 296 304 - static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = { 305 - .button = { 306 - .code = SW_LID, 307 - .active_low = true, 308 - .desc = "lid_sw", 309 - .type = EV_SW, 310 - .wakeup = true, 311 - .debounce_interval = 50, 312 - }, 313 - .chip = "INT33FC:02", 314 - .pin = 26, 297 + static const struct property_entry lenovo_yoga_tab2_830_1050_lid_props[] = { 298 + PROPERTY_ENTRY_U32("linux,input-type", EV_SW), 299 + PROPERTY_ENTRY_U32("linux,code", SW_LID), 300 + PROPERTY_ENTRY_STRING("label", "lid_sw"), 301 + PROPERTY_ENTRY_GPIO("gpios", &baytrail_gpiochip_nodes[2], 26, GPIO_ACTIVE_LOW), 302 + PROPERTY_ENTRY_U32("debounce-interval", 50), 303 + PROPERTY_ENTRY_BOOL("wakeup-source"), 304 + { } 305 + }; 306 + 307 + static const struct software_node lenovo_yoga_tab2_830_1050_lid_node = { 308 + .parent = &lenovo_lid_gpio_keys_node, 309 + .properties = lenovo_yoga_tab2_830_1050_lid_props, 310 + }; 311 + 312 + static const struct software_node *lenovo_yoga_tab2_830_1050_lid_swnodes[] = { 313 + &lenovo_lid_gpio_keys_node, 314 + &lenovo_yoga_tab2_830_1050_lid_node, 315 + NULL 315 316 }; 316 317 317 318 /* This gets filled by lenovo_yoga_tab2_830_1050_init() */ ··· 399 384 }, 400 385 }; 401 386 402 - static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = { 403 - .dev_id = "intel-int3496", 404 - .table = { 405 - GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW), 406 - GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH), 407 - { } 387 + static const struct property_entry lenovo_yoga_tab2_830_1050_int3496_props[] __initconst = { 388 + PROPERTY_ENTRY_GPIO("mux-gpios", &baytrail_gpiochip_nodes[2], 1, GPIO_ACTIVE_LOW), 389 + PROPERTY_ENTRY_GPIO("id-gpios", &baytrail_gpiochip_nodes[2], 24, GPIO_ACTIVE_HIGH), 390 + { } 391 + }; 392 + 393 + static const struct platform_device_info lenovo_yoga_tab2_830_1050_pdevs[] __initconst = { 394 + { 395 + /* For micro USB ID pin handling */ 396 + .name = "intel-int3496", 397 + .id = PLATFORM_DEVID_NONE, 398 + .properties = lenovo_yoga_tab2_830_1050_int3496_props, 408 399 }, 409 400 }; 410 401 411 402 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00" 412 403 413 - static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = { 414 - .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, 415 - .table = { 416 - GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH), 417 - GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH), 418 - GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH), 419 - GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW), 420 - { } 421 - }, 404 + static const struct property_entry lenovo_yoga_tab2_830_1050_wm1502_props[] = { 405 + PROPERTY_ENTRY_GPIO("reset-gpios", 406 + &crystalcove_gpiochip_node, 3, GPIO_ACTIVE_HIGH), 407 + PROPERTY_ENTRY_GPIO("wlf,ldoena-gpios", 408 + &baytrail_gpiochip_nodes[1], 23, GPIO_ACTIVE_HIGH), 409 + PROPERTY_ENTRY_GPIO("wlf,spkvdd-ena-gpios", 410 + &arizona_gpiochip_node, 2, GPIO_ACTIVE_HIGH), 411 + PROPERTY_ENTRY_GPIO("wlf,micd-pol-gpios", 412 + &arizona_gpiochip_node, 4, GPIO_ACTIVE_LOW), 413 + { } 422 414 }; 423 415 424 - static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = { 425 - &lenovo_yoga_tab2_830_1050_int3496_gpios, 426 - &lenovo_yoga_tab2_830_1050_codec_gpios, 416 + static const struct software_node lenovo_yoga_tab2_830_1050_wm5102 = { 417 + .properties = lenovo_yoga_tab2_830_1050_wm1502_props, 418 + }; 419 + 420 + static const struct software_node *lenovo_yoga_tab2_830_1050_swnodes[] = { 421 + &crystalcove_gpiochip_node, 422 + &arizona_gpiochip_node, 423 + &lenovo_yoga_tab2_830_1050_wm5102, 424 + &generic_lipo_hv_4v35_battery_node, 427 425 NULL 428 426 }; 429 427 430 428 static int __init lenovo_yoga_tab2_830_1050_init(struct device *dev); 431 429 static void lenovo_yoga_tab2_830_1050_exit(void); 432 430 431 + static const char * const lenovo_yoga_tab2_modules[] __initconst = { 432 + "spi_pxa2xx_platform", /* For the SPI codec device */ 433 + "bq24190_charger", /* For the Vbus regulator for int3496/lc824206xa */ 434 + NULL 435 + }; 436 + 433 437 const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = { 434 438 .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients, 435 439 .i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients), 436 - .pdev_info = int3496_pdevs, 437 - .pdev_count = 1, 438 - .gpio_button = &lenovo_yoga_tab2_830_1050_lid, 439 - .gpio_button_count = 1, 440 - .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios, 441 - .bat_swnode = &generic_lipo_hv_4v35_battery_node, 442 - .modules = bq24190_modules, 440 + .pdev_info = lenovo_yoga_tab2_830_1050_pdevs, 441 + .pdev_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_pdevs), 442 + .gpio_button_swnodes = lenovo_yoga_tab2_830_1050_lid_swnodes, 443 + .swnode_group = lenovo_yoga_tab2_830_1050_swnodes, 444 + .modules = lenovo_yoga_tab2_modules, 445 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 443 446 .init = lenovo_yoga_tab2_830_1050_init, 444 447 .exit = lenovo_yoga_tab2_830_1050_exit, 445 448 }; ··· 514 481 PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk", 515 482 "INT33FC:02", "pmu_clk2_grp", "pmu_clk"); 516 483 484 + static struct device *lenovo_yoga_tab2_830_1050_codec_dev; 517 485 static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl; 518 486 static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler; 519 487 ··· 541 507 goto err_unregister_mappings; 542 508 } 543 509 544 - /* We're done with the codec_dev now */ 545 - put_device(codec_dev); 510 + ret = device_add_software_node(codec_dev, &lenovo_yoga_tab2_830_1050_wm5102); 511 + if (ret) { 512 + ret = dev_err_probe(codec_dev, ret, "adding software node\n"); 513 + goto err_put_pinctrl; 514 + } 546 515 516 + lenovo_yoga_tab2_830_1050_codec_dev = codec_dev; 547 517 lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl; 548 518 return 0; 549 519 520 + err_put_pinctrl: 521 + pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl); 550 522 err_unregister_mappings: 551 523 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 552 524 err_put_device: ··· 600 560 { 601 561 unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler); 602 562 603 - if (lenovo_yoga_tab2_830_1050_codec_pinctrl) { 604 - pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl); 605 - pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 606 - } 563 + device_remove_software_node(lenovo_yoga_tab2_830_1050_codec_dev); 564 + pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl); 565 + pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 566 + put_device(lenovo_yoga_tab2_830_1050_codec_dev); 607 567 } 608 568 609 569 /* ··· 758 718 } 759 719 }; 760 720 721 + static const struct property_entry lenovo_yoga_tab2_1380_fc_props[] __initconst = { 722 + PROPERTY_ENTRY_GPIO("uart3_txd-gpios", &baytrail_gpiochip_nodes[0], 57, GPIO_ACTIVE_HIGH), 723 + PROPERTY_ENTRY_GPIO("uart3_rxd-gpios", &baytrail_gpiochip_nodes[0], 61, GPIO_ACTIVE_HIGH), 724 + { } 725 + }; 726 + 761 727 static const struct platform_device_info lenovo_yoga_tab2_1380_pdevs[] __initconst = { 762 728 { 763 729 /* For the Tablet 2 Pro 1380's custom fast charging driver */ 764 730 .name = "lenovo-yoga-tab2-pro-1380-fastcharger", 765 731 .id = PLATFORM_DEVID_NONE, 732 + .properties = lenovo_yoga_tab2_1380_fc_props, 766 733 }, 767 - }; 768 - 769 - static const char * const lenovo_yoga_tab2_1380_modules[] __initconst = { 770 - "bq24190_charger", /* For the Vbus regulator for lc824206xa */ 771 - NULL 772 734 }; 773 735 774 736 static int __init lenovo_yoga_tab2_1380_init(struct device *dev) ··· 794 752 return 0; 795 753 } 796 754 797 - static struct gpiod_lookup_table lenovo_yoga_tab2_1380_fc_gpios = { 798 - .dev_id = "serial0-0", 799 - .table = { 800 - GPIO_LOOKUP("INT33FC:00", 57, "uart3_txd", GPIO_ACTIVE_HIGH), 801 - GPIO_LOOKUP("INT33FC:00", 61, "uart3_rxd", GPIO_ACTIVE_HIGH), 802 - { } 803 - }, 804 - }; 805 - 806 - static struct gpiod_lookup_table * const lenovo_yoga_tab2_1380_gpios[] = { 807 - &lenovo_yoga_tab2_830_1050_codec_gpios, 808 - &lenovo_yoga_tab2_1380_fc_gpios, 809 - NULL 810 - }; 811 - 812 755 const struct x86_dev_info lenovo_yoga_tab2_1380_info __initconst = { 813 756 .i2c_client_info = lenovo_yoga_tab2_1380_i2c_clients, 814 757 .i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_1380_i2c_clients), 815 758 .pdev_info = lenovo_yoga_tab2_1380_pdevs, 816 759 .pdev_count = ARRAY_SIZE(lenovo_yoga_tab2_1380_pdevs), 817 - .gpio_button = &lenovo_yoga_tab2_830_1050_lid, 818 - .gpio_button_count = 1, 819 - .gpiod_lookup_tables = lenovo_yoga_tab2_1380_gpios, 820 - .bat_swnode = &generic_lipo_hv_4v35_battery_node, 821 - .modules = lenovo_yoga_tab2_1380_modules, 760 + .gpio_button_swnodes = lenovo_yoga_tab2_830_1050_lid_swnodes, 761 + .swnode_group = lenovo_yoga_tab2_830_1050_swnodes, 762 + .modules = lenovo_yoga_tab2_modules, 763 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 822 764 .init = lenovo_yoga_tab2_1380_init, 823 765 .exit = lenovo_yoga_tab2_830_1050_exit, 824 766 }; ··· 850 824 PROPERTY_ENTRY_U32("touchscreen-size-x", 1600), 851 825 PROPERTY_ENTRY_U32("touchscreen-size-y", 2560), 852 826 PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255), 827 + PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 7, GPIO_ACTIVE_LOW), 853 828 { } 854 829 }; 855 830 ··· 985 958 }, 986 959 }; 987 960 961 + static const struct property_entry lenovo_yt3_wm1502_props[] = { 962 + PROPERTY_ENTRY_GPIO("wlf,spkvdd-ena-gpios", 963 + &cherryview_gpiochip_nodes[0], 75, GPIO_ACTIVE_HIGH), 964 + PROPERTY_ENTRY_GPIO("wlf,ldoena-gpios", 965 + &cherryview_gpiochip_nodes[0], 81, GPIO_ACTIVE_HIGH), 966 + PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[0], 82, GPIO_ACTIVE_HIGH), 967 + PROPERTY_ENTRY_GPIO("wlf,micd-pol-gpios", &arizona_gpiochip_node, 2, GPIO_ACTIVE_HIGH), 968 + { } 969 + }; 970 + 971 + static const struct software_node lenovo_yt3_wm5102 = { 972 + .properties = lenovo_yt3_wm1502_props, 973 + .name = "wm5102", 974 + }; 975 + 976 + static const struct software_node *lenovo_yt3_swnodes[] = { 977 + &arizona_gpiochip_node, 978 + &lenovo_yt3_wm5102, 979 + NULL 980 + }; 981 + 988 982 static const struct x86_spi_dev_info lenovo_yt3_spi_devs[] __initconst = { 989 983 { 990 984 /* WM5102 codec */ 991 985 .board_info = { 992 986 .modalias = "wm5102", 993 987 .platform_data = &lenovo_yt3_wm5102_pdata, 988 + .swnode = &lenovo_yt3_wm5102, 994 989 .max_speed_hz = 5000000, 995 990 }, 996 991 .ctrl_path = "\\_SB_.PCI0.SPI1", ··· 1062 1013 return 0; 1063 1014 } 1064 1015 1065 - static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = { 1066 - .dev_id = "i2c-hideep_ts", 1067 - .table = { 1068 - GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW), 1069 - { } 1070 - }, 1071 - }; 1072 - 1073 - static struct gpiod_lookup_table lenovo_yt3_wm5102_gpios = { 1074 - .dev_id = "spi1.0", 1075 - .table = { 1076 - GPIO_LOOKUP("INT33FF:00", 75, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH), 1077 - GPIO_LOOKUP("INT33FF:00", 81, "wlf,ldoena", GPIO_ACTIVE_HIGH), 1078 - GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_HIGH), 1079 - GPIO_LOOKUP("arizona", 2, "wlf,micd-pol", GPIO_ACTIVE_HIGH), 1080 - { } 1081 - }, 1082 - }; 1083 - 1084 - static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = { 1085 - &lenovo_yt3_hideep_gpios, 1086 - &lenovo_yt3_wm5102_gpios, 1016 + static const char * const lenovo_yt3_modules[] __initconst = { 1017 + "spi_pxa2xx_platform", /* For the SPI codec device */ 1087 1018 NULL 1088 1019 }; 1089 1020 ··· 1072 1043 .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients), 1073 1044 .spi_dev_info = lenovo_yt3_spi_devs, 1074 1045 .spi_dev_count = ARRAY_SIZE(lenovo_yt3_spi_devs), 1075 - .gpiod_lookup_tables = lenovo_yt3_gpios, 1046 + .swnode_group = lenovo_yt3_swnodes, 1047 + .modules = lenovo_yt3_modules, 1048 + .gpiochip_type = X86_GPIOCHIP_CHERRYVIEW, 1076 1049 .init = lenovo_yt3_init, 1077 1050 };
+116 -222
drivers/platform/x86/x86-android-tablets/other.c
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 11 11 #include <linux/acpi.h> 12 12 #include <linux/gpio/machine.h> 13 - #include <linux/input.h> 13 + #include <linux/gpio/property.h> 14 + #include <linux/input-event-codes.h> 14 15 #include <linux/leds.h> 15 16 #include <linux/pci.h> 16 17 #include <linux/platform_device.h> ··· 22 21 #include "shared-psy-info.h" 23 22 #include "x86-android-tablets.h" 24 23 25 - /* Acer Iconia One 7 B1-750 has an Android factory image with everything hardcoded */ 26 - static const char * const acer_b1_750_mount_matrix[] = { 27 - "-1", "0", "0", 28 - "0", "1", "0", 29 - "0", "0", "1" 30 - }; 31 - 32 - static const struct property_entry acer_b1_750_bma250e_props[] = { 33 - PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", acer_b1_750_mount_matrix), 34 - { } 35 - }; 36 - 37 - static const struct software_node acer_b1_750_bma250e_node = { 38 - .properties = acer_b1_750_bma250e_props, 39 - }; 40 - 41 - static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = { 42 - { 43 - /* Novatek NVT-ts touchscreen */ 44 - .board_info = { 45 - .type = "nt11205-ts", 46 - .addr = 0x34, 47 - .dev_name = "NVT-ts", 48 - }, 49 - .adapter_path = "\\_SB_.I2C4", 50 - .irq_data = { 51 - .type = X86_ACPI_IRQ_TYPE_GPIOINT, 52 - .chip = "INT33FC:02", 53 - .index = 3, 54 - .trigger = ACPI_EDGE_SENSITIVE, 55 - .polarity = ACPI_ACTIVE_LOW, 56 - .con_id = "NVT-ts_irq", 57 - }, 58 - }, { 59 - /* BMA250E accelerometer */ 60 - .board_info = { 61 - .type = "bma250e", 62 - .addr = 0x18, 63 - .swnode = &acer_b1_750_bma250e_node, 64 - }, 65 - .adapter_path = "\\_SB_.I2C3", 66 - .irq_data = { 67 - .type = X86_ACPI_IRQ_TYPE_GPIOINT, 68 - .chip = "INT33FC:02", 69 - .index = 25, 70 - .trigger = ACPI_LEVEL_SENSITIVE, 71 - .polarity = ACPI_ACTIVE_HIGH, 72 - .con_id = "bma250e_irq", 73 - }, 74 - }, 75 - }; 76 - 77 - static struct gpiod_lookup_table acer_b1_750_nvt_ts_gpios = { 78 - .dev_id = "i2c-NVT-ts", 79 - .table = { 80 - GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_LOW), 81 - { } 82 - }, 83 - }; 84 - 85 - static struct gpiod_lookup_table * const acer_b1_750_gpios[] = { 86 - &acer_b1_750_nvt_ts_gpios, 87 - &int3496_reference_gpios, 88 - NULL 89 - }; 90 - 91 - const struct x86_dev_info acer_b1_750_info __initconst = { 92 - .i2c_client_info = acer_b1_750_i2c_clients, 93 - .i2c_client_count = ARRAY_SIZE(acer_b1_750_i2c_clients), 94 - .pdev_info = int3496_pdevs, 95 - .pdev_count = 1, 96 - .gpiod_lookup_tables = acer_b1_750_gpios, 97 - }; 98 - 99 24 /* 100 25 * Advantech MICA-071 101 26 * This is a standard Windows tablet, but it has an extra "quick launch" button 102 27 * which is not described in the ACPI tables in anyway. 103 28 * Use the x86-android-tablets infra to create a gpio-keys device for this. 104 29 */ 105 - static const struct x86_gpio_button advantech_mica_071_button __initconst = { 106 - .button = { 107 - .code = KEY_PROG1, 108 - .active_low = true, 109 - .desc = "prog1_key", 110 - .type = EV_KEY, 111 - .wakeup = false, 112 - .debounce_interval = 50, 113 - }, 114 - .chip = "INT33FC:00", 115 - .pin = 2, 30 + static const struct software_node advantech_mica_071_gpio_keys_node = { 31 + .name = "prog1_key", 32 + }; 33 + 34 + static const struct property_entry advantech_mica_071_prog1_key_props[] = { 35 + PROPERTY_ENTRY_U32("linux,code", KEY_PROG1), 36 + PROPERTY_ENTRY_STRING("label", "prog1_key"), 37 + PROPERTY_ENTRY_GPIO("gpios", &baytrail_gpiochip_nodes[0], 2, GPIO_ACTIVE_LOW), 38 + PROPERTY_ENTRY_U32("debounce-interval", 50), 39 + { } 40 + }; 41 + 42 + static const struct software_node advantech_mica_071_prog1_key_node = { 43 + .parent = &advantech_mica_071_gpio_keys_node, 44 + .properties = advantech_mica_071_prog1_key_props, 45 + }; 46 + 47 + static const struct software_node *advantech_mica_071_button_swnodes[] = { 48 + &advantech_mica_071_gpio_keys_node, 49 + &advantech_mica_071_prog1_key_node, 50 + NULL 116 51 }; 117 52 118 53 const struct x86_dev_info advantech_mica_071_info __initconst = { 119 - .gpio_button = &advantech_mica_071_button, 120 - .gpio_button_count = 1, 54 + .gpio_button_swnodes = advantech_mica_071_button_swnodes, 55 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 121 56 }; 122 57 123 58 /* ··· 149 212 * in the button row with the power + volume-buttons labeled P and F. 150 213 * Use the x86-android-tablets infra to create a gpio-keys device for these. 151 214 */ 152 - static const struct x86_gpio_button cyberbook_t116_buttons[] __initconst = { 153 - { 154 - .button = { 155 - .code = KEY_PROG1, 156 - .active_low = true, 157 - .desc = "prog1_key", 158 - .type = EV_KEY, 159 - .wakeup = false, 160 - .debounce_interval = 50, 161 - }, 162 - .chip = "INT33FF:00", 163 - .pin = 30, 164 - }, 165 - { 166 - .button = { 167 - .code = KEY_PROG2, 168 - .active_low = true, 169 - .desc = "prog2_key", 170 - .type = EV_KEY, 171 - .wakeup = false, 172 - .debounce_interval = 50, 173 - }, 174 - .chip = "INT33FF:03", 175 - .pin = 48, 176 - }, 215 + static const struct software_node cyberbook_t116_gpio_keys_node = { 216 + .name = "prog_keys", 217 + }; 218 + 219 + static const struct property_entry cyberbook_t116_prog1_key_props[] = { 220 + PROPERTY_ENTRY_U32("linux,code", KEY_PROG1), 221 + PROPERTY_ENTRY_STRING("label", "prog1_key"), 222 + PROPERTY_ENTRY_GPIO("gpios", &cherryview_gpiochip_nodes[0], 30, GPIO_ACTIVE_LOW), 223 + PROPERTY_ENTRY_U32("debounce-interval", 50), 224 + { } 225 + }; 226 + 227 + static const struct software_node cyberbook_t116_prog1_key_node = { 228 + .parent = &cyberbook_t116_gpio_keys_node, 229 + .properties = cyberbook_t116_prog1_key_props, 230 + }; 231 + 232 + static const struct property_entry cyberbook_t116_prog2_key_props[] = { 233 + PROPERTY_ENTRY_U32("linux,code", KEY_PROG2), 234 + PROPERTY_ENTRY_STRING("label", "prog2_key"), 235 + PROPERTY_ENTRY_GPIO("gpios", &cherryview_gpiochip_nodes[3], 48, GPIO_ACTIVE_LOW), 236 + PROPERTY_ENTRY_U32("debounce-interval", 50), 237 + { } 238 + }; 239 + 240 + static const struct software_node cyberbook_t116_prog2_key_node = { 241 + .parent = &cyberbook_t116_gpio_keys_node, 242 + .properties = cyberbook_t116_prog2_key_props, 243 + }; 244 + 245 + static const struct software_node *cyberbook_t116_buttons_swnodes[] = { 246 + &cyberbook_t116_gpio_keys_node, 247 + &cyberbook_t116_prog1_key_node, 248 + &cyberbook_t116_prog2_key_node, 249 + NULL 177 250 }; 178 251 179 252 const struct x86_dev_info cyberbook_t116_info __initconst = { 180 - .gpio_button = cyberbook_t116_buttons, 181 - .gpio_button_count = ARRAY_SIZE(cyberbook_t116_buttons), 253 + .gpio_button_swnodes = cyberbook_t116_buttons_swnodes, 254 + .gpiochip_type = X86_GPIOCHIP_CHERRYVIEW, 182 255 }; 183 256 184 257 #define CZC_EC_EXTRA_PORT 0x68 ··· 244 297 static const struct property_entry medion_lifetab_s10346_touchscreen_props[] = { 245 298 PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 246 299 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 300 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_HIGH), 301 + PROPERTY_ENTRY_GPIO("irq-gpios", &baytrail_gpiochip_nodes[2], 3, GPIO_ACTIVE_HIGH), 247 302 { } 248 303 }; 249 304 ··· 289 340 }, 290 341 }; 291 342 292 - static struct gpiod_lookup_table medion_lifetab_s10346_goodix_gpios = { 293 - .dev_id = "i2c-goodix_ts", 294 - .table = { 295 - GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH), 296 - GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH), 297 - { } 298 - }, 299 - }; 300 - 301 - static struct gpiod_lookup_table * const medion_lifetab_s10346_gpios[] = { 302 - &medion_lifetab_s10346_goodix_gpios, 303 - NULL 304 - }; 305 - 306 343 const struct x86_dev_info medion_lifetab_s10346_info __initconst = { 307 344 .i2c_client_info = medion_lifetab_s10346_i2c_clients, 308 345 .i2c_client_count = ARRAY_SIZE(medion_lifetab_s10346_i2c_clients), 309 - .gpiod_lookup_tables = medion_lifetab_s10346_gpios, 346 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 310 347 }; 311 348 312 349 /* Nextbook Ares 8 (BYT) tablets have an Android factory image with everything hardcoded */ ··· 351 416 }, 352 417 }; 353 418 354 - static struct gpiod_lookup_table * const nextbook_ares8_gpios[] = { 355 - &int3496_reference_gpios, 356 - NULL 357 - }; 358 - 359 419 const struct x86_dev_info nextbook_ares8_info __initconst = { 360 420 .i2c_client_info = nextbook_ares8_i2c_clients, 361 421 .i2c_client_count = ARRAY_SIZE(nextbook_ares8_i2c_clients), 362 422 .pdev_info = int3496_pdevs, 363 423 .pdev_count = 1, 364 - .gpiod_lookup_tables = nextbook_ares8_gpios, 424 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 365 425 }; 366 426 367 427 /* Nextbook Ares 8A (CHT) tablets have an Android factory image with everything hardcoded */ ··· 375 445 .properties = nextbook_ares8a_accel_props, 376 446 }; 377 447 448 + static const struct property_entry nextbook_ares8a_ft5416_props[] = { 449 + PROPERTY_ENTRY_U32("touchscreen-size-x", 800), 450 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 451 + PROPERTY_ENTRY_GPIO("reset-gpios", &cherryview_gpiochip_nodes[1], 25, GPIO_ACTIVE_LOW), 452 + { } 453 + }; 454 + 455 + static const struct software_node nextbook_ares8a_ft5416_node = { 456 + .properties = nextbook_ares8a_ft5416_props, 457 + }; 458 + 378 459 static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initconst = { 379 460 { 380 461 /* Freescale MMA8653FC accelerometer */ ··· 402 461 .type = "edt-ft5x06", 403 462 .addr = 0x38, 404 463 .dev_name = "ft5416", 405 - .swnode = &nextbook_ares8_touchscreen_node, 464 + .swnode = &nextbook_ares8a_ft5416_node, 406 465 }, 407 466 .adapter_path = "\\_SB_.PCI0.I2C6", 408 467 .irq_data = { ··· 416 475 }, 417 476 }; 418 477 419 - static struct gpiod_lookup_table nextbook_ares8a_ft5416_gpios = { 420 - .dev_id = "i2c-ft5416", 421 - .table = { 422 - GPIO_LOOKUP("INT33FF:01", 25, "reset", GPIO_ACTIVE_LOW), 423 - { } 424 - }, 425 - }; 426 - 427 - static struct gpiod_lookup_table * const nextbook_ares8a_gpios[] = { 428 - &nextbook_ares8a_ft5416_gpios, 429 - NULL 430 - }; 431 - 432 478 const struct x86_dev_info nextbook_ares8a_info __initconst = { 433 479 .i2c_client_info = nextbook_ares8a_i2c_clients, 434 480 .i2c_client_count = ARRAY_SIZE(nextbook_ares8a_i2c_clients), 435 - .gpiod_lookup_tables = nextbook_ares8a_gpios, 481 + .gpiochip_type = X86_GPIOCHIP_CHERRYVIEW, 436 482 }; 437 483 438 484 /* ··· 428 500 * This button has a WMI interface, but that is broken. Instead of trying to 429 501 * use the broken WMI interface, instantiate a gpio-keys device for this. 430 502 */ 431 - static const struct x86_gpio_button peaq_c1010_button __initconst = { 432 - .button = { 433 - .code = KEY_SOUND, 434 - .active_low = true, 435 - .desc = "dolby_key", 436 - .type = EV_KEY, 437 - .wakeup = false, 438 - .debounce_interval = 50, 439 - }, 440 - .chip = "INT33FC:00", 441 - .pin = 3, 503 + static const struct software_node peaq_c1010_gpio_keys_node = { 504 + .name = "gpio_keys", 505 + }; 506 + 507 + static const struct property_entry peaq_c1010_dolby_key_props[] = { 508 + PROPERTY_ENTRY_U32("linux,code", KEY_SOUND), 509 + PROPERTY_ENTRY_STRING("label", "dolby_key"), 510 + PROPERTY_ENTRY_GPIO("gpios", &baytrail_gpiochip_nodes[0], 3, GPIO_ACTIVE_LOW), 511 + PROPERTY_ENTRY_U32("debounce-interval", 50), 512 + { } 513 + }; 514 + 515 + static const struct software_node peaq_c1010_dolby_key_node = { 516 + .parent = &peaq_c1010_gpio_keys_node, 517 + .properties = peaq_c1010_dolby_key_props, 518 + }; 519 + 520 + static const struct software_node *peaq_c1010_button_swnodes[] = { 521 + &peaq_c1010_gpio_keys_node, 522 + &peaq_c1010_dolby_key_node, 523 + NULL 442 524 }; 443 525 444 526 const struct x86_dev_info peaq_c1010_info __initconst = { 445 - .gpio_button = &peaq_c1010_button, 446 - .gpio_button_count = 1, 527 + .gpio_button_swnodes = peaq_c1010_button_swnodes, 528 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 447 529 }; 448 530 449 531 /* ··· 481 543 PROPERTY_ENTRY_STRING("firmware-name", "gt912-tm800a550l.fw"), 482 544 PROPERTY_ENTRY_STRING("goodix,config-name", "gt912-tm800a550l.cfg"), 483 545 PROPERTY_ENTRY_U32("goodix,main-clk", 54), 546 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_HIGH), 547 + PROPERTY_ENTRY_GPIO("irq-gpios", &baytrail_gpiochip_nodes[2], 3, GPIO_ACTIVE_HIGH), 484 548 { } 485 549 }; 486 550 ··· 518 578 }, 519 579 }; 520 580 521 - static struct gpiod_lookup_table whitelabel_tm800a550l_goodix_gpios = { 522 - .dev_id = "i2c-goodix_ts", 523 - .table = { 524 - GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH), 525 - GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH), 526 - { } 527 - }, 528 - }; 529 - 530 - static struct gpiod_lookup_table * const whitelabel_tm800a550l_gpios[] = { 531 - &whitelabel_tm800a550l_goodix_gpios, 532 - NULL 533 - }; 534 - 535 581 const struct x86_dev_info whitelabel_tm800a550l_info __initconst = { 536 582 .i2c_client_info = whitelabel_tm800a550l_i2c_clients, 537 583 .i2c_client_count = ARRAY_SIZE(whitelabel_tm800a550l_i2c_clients), 538 - .gpiod_lookup_tables = whitelabel_tm800a550l_gpios, 584 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 539 585 }; 540 586 541 587 /* ··· 531 605 static const struct property_entry vexia_edu_atla10_5v_touchscreen_props[] = { 532 606 PROPERTY_ENTRY_U32("hid-descr-addr", 0x0000), 533 607 PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120), 608 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[1], 26, GPIO_ACTIVE_LOW), 534 609 { } 535 610 }; 536 611 ··· 566 639 } 567 640 }; 568 641 569 - static struct gpiod_lookup_table vexia_edu_atla10_5v_ft5416_gpios = { 570 - .dev_id = "i2c-FTSC1000", 571 - .table = { 572 - GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_LOW), 573 - { } 574 - }, 575 - }; 576 - 577 - static struct gpiod_lookup_table * const vexia_edu_atla10_5v_gpios[] = { 578 - &vexia_edu_atla10_5v_ft5416_gpios, 579 - NULL 580 - }; 581 - 582 642 const struct x86_dev_info vexia_edu_atla10_5v_info __initconst = { 583 643 .i2c_client_info = vexia_edu_atla10_5v_i2c_clients, 584 644 .i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_5v_i2c_clients), 585 - .gpiod_lookup_tables = vexia_edu_atla10_5v_gpios, 645 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 586 646 }; 587 647 588 648 /* ··· 605 691 static const struct property_entry vexia_edu_atla10_9v_touchscreen_props[] = { 606 692 PROPERTY_ENTRY_U32("hid-descr-addr", 0x0000), 607 693 PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120), 694 + PROPERTY_ENTRY_GPIO("reset-gpios", &baytrail_gpiochip_nodes[0], 60, GPIO_ACTIVE_LOW), 608 695 { } 609 696 }; 610 697 ··· 698 783 }, 699 784 }; 700 785 701 - static struct gpiod_lookup_table vexia_edu_atla10_9v_ft5416_gpios = { 702 - .dev_id = "i2c-FTSC1000", 703 - .table = { 704 - GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_LOW), 705 - { } 706 - }, 707 - }; 708 - 709 - static struct gpiod_lookup_table * const vexia_edu_atla10_9v_gpios[] = { 710 - &vexia_edu_atla10_9v_ft5416_gpios, 711 - NULL 712 - }; 713 - 714 786 static int __init vexia_edu_atla10_9v_init(struct device *dev) 715 787 { 716 788 struct pci_dev *pdev; ··· 711 809 712 810 /* Reprobe the SDIO controller to enumerate the now enabled Wifi module */ 713 811 pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x11, 0)); 714 - if (!pdev) 715 - return -EPROBE_DEFER; 812 + if (!pdev) { 813 + pr_warn("Could not get PCI SDIO at devfn 0x%02x\n", PCI_DEVFN(0x11, 0)); 814 + return 0; 815 + } 716 816 717 817 ret = device_reprobe(&pdev->dev); 718 818 if (ret) ··· 729 825 .i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_9v_i2c_clients), 730 826 .serdev_info = vexia_edu_atla10_9v_serdevs, 731 827 .serdev_count = ARRAY_SIZE(vexia_edu_atla10_9v_serdevs), 732 - .gpiod_lookup_tables = vexia_edu_atla10_9v_gpios, 733 828 .init = vexia_edu_atla10_9v_init, 734 829 .use_pci = true, 830 + .gpiochip_type = X86_GPIOCHIP_BAYTRAIL, 735 831 }; 736 832 737 833 /* ··· 827 923 static int __init xiaomi_mipad2_init(struct device *dev) 828 924 { 829 925 struct led_classdev *led_cdev; 830 - int ret; 831 926 832 927 xiaomi_mipad2_led_pwm = devm_pwm_get(dev, "pwm_soc_lpss_2"); 833 928 if (IS_ERR(xiaomi_mipad2_led_pwm)) ··· 843 940 /* Turn LED off during suspend */ 844 941 led_cdev->flags = LED_CORE_SUSPENDRESUME; 845 942 846 - ret = devm_led_classdev_register(dev, led_cdev); 847 - if (ret) 848 - return dev_err_probe(dev, ret, "registering LED\n"); 849 - 850 - return software_node_register_node_group(ktd2026_node_group); 851 - } 852 - 853 - static void xiaomi_mipad2_exit(void) 854 - { 855 - software_node_unregister_node_group(ktd2026_node_group); 943 + return devm_led_classdev_register(dev, led_cdev); 856 944 } 857 945 858 946 /* ··· 878 984 const struct x86_dev_info xiaomi_mipad2_info __initconst = { 879 985 .i2c_client_info = xiaomi_mipad2_i2c_clients, 880 986 .i2c_client_count = ARRAY_SIZE(xiaomi_mipad2_i2c_clients), 987 + .swnode_group = ktd2026_node_group, 881 988 .init = xiaomi_mipad2_init, 882 - .exit = xiaomi_mipad2_exit, 883 989 };
+22 -12
drivers/platform/x86/x86-android-tablets/shared-psy-info.c
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 11 11 #include <linux/gpio/machine.h> 12 + #include <linux/gpio/property.h> 12 13 #include <linux/platform_device.h> 13 14 #include <linux/power/bq24190_charger.h> 14 15 #include <linux/property.h> 15 16 #include <linux/regulator/machine.h> 16 17 17 18 #include "shared-psy-info.h" 19 + #include "x86-android-tablets.h" 18 20 19 21 /* Generic / shared charger / battery settings */ 20 22 const char * const tusb1211_chg_det_psy[] = { "tusb1211-charger-detect" }; ··· 113 111 .properties = generic_lipo_4v2_battery_props, 114 112 }; 115 113 114 + const struct software_node *generic_lipo_4v2_battery_swnodes[] = { 115 + &generic_lipo_4v2_battery_node, 116 + NULL 117 + }; 118 + 116 119 /* LiPo HighVoltage (max 4.35V) settings used by most devs with a HV battery */ 117 120 static const struct property_entry generic_lipo_hv_4v35_battery_props[] = { 118 121 PROPERTY_ENTRY_STRING("compatible", "simple-battery"), ··· 136 129 137 130 const struct software_node generic_lipo_hv_4v35_battery_node = { 138 131 .properties = generic_lipo_hv_4v35_battery_props, 132 + }; 133 + 134 + const struct software_node *generic_lipo_hv_4v35_battery_swnodes[] = { 135 + &generic_lipo_hv_4v35_battery_node, 136 + NULL 139 137 }; 140 138 141 139 /* For enabling the bq24190 5V boost based on id-pin */ ··· 168 156 NULL 169 157 }; 170 158 171 - /* Generic platform device array and GPIO lookup table for micro USB ID pin handling */ 159 + static const struct property_entry int3496_reference_props[] __initconst = { 160 + PROPERTY_ENTRY_GPIO("vbus-gpios", &baytrail_gpiochip_nodes[1], 15, GPIO_ACTIVE_HIGH), 161 + PROPERTY_ENTRY_GPIO("mux-gpios", &baytrail_gpiochip_nodes[2], 1, GPIO_ACTIVE_HIGH), 162 + PROPERTY_ENTRY_GPIO("id-gpios", &baytrail_gpiochip_nodes[2], 18, GPIO_ACTIVE_HIGH), 163 + { } 164 + }; 165 + 166 + /* Generic pdevs array and gpio-lookups for micro USB ID pin handling */ 172 167 const struct platform_device_info int3496_pdevs[] __initconst = { 173 168 { 174 169 /* For micro USB ID pin handling */ 175 170 .name = "intel-int3496", 176 171 .id = PLATFORM_DEVID_NONE, 177 - }, 178 - }; 179 - 180 - struct gpiod_lookup_table int3496_reference_gpios = { 181 - .dev_id = "intel-int3496", 182 - .table = { 183 - GPIO_LOOKUP("INT33FC:01", 15, "vbus", GPIO_ACTIVE_HIGH), 184 - GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_HIGH), 185 - GPIO_LOOKUP("INT33FC:02", 18, "id", GPIO_ACTIVE_HIGH), 186 - { } 172 + .properties = int3496_reference_props, 187 173 }, 188 174 };
+5 -3
drivers/platform/x86/x86-android-tablets/shared-psy-info.h
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 #ifndef __PDX86_SHARED_PSY_INFO_H 11 11 #define __PDX86_SHARED_PSY_INFO_H 12 12 13 13 struct bq24190_platform_data; 14 - struct gpiod_lookup_table; 15 14 struct platform_device_info; 16 15 struct software_node; 17 16 ··· 20 21 21 22 extern const struct software_node fg_bq24190_supply_node; 22 23 extern const struct software_node fg_bq25890_supply_node; 24 + 23 25 extern const struct software_node generic_lipo_4v2_battery_node; 26 + extern const struct software_node *generic_lipo_4v2_battery_swnodes[]; 27 + 24 28 extern const struct software_node generic_lipo_hv_4v35_battery_node; 29 + extern const struct software_node *generic_lipo_hv_4v35_battery_swnodes[]; 25 30 26 31 extern struct bq24190_platform_data bq24190_pdata; 27 32 extern const char * const bq24190_modules[]; 28 33 29 34 extern const struct platform_device_info int3496_pdevs[]; 30 - extern struct gpiod_lookup_table int3496_reference_gpios; 31 35 32 36 #endif
+1 -1
drivers/platform/x86/x86-android-tablets/vexia_atla10_ec.c
··· 256 256 }; 257 257 module_i2c_driver(atla10_ec_driver); 258 258 259 - MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 259 + MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 260 260 MODULE_DESCRIPTION("Battery driver for Vexia EDU ATLA 10 tablet EC"); 261 261 MODULE_LICENSE("GPL");
+15 -13
drivers/platform/x86/x86-android-tablets/x86-android-tablets.h
··· 5 5 * devices typically have a bunch of things hardcoded, rather than specified 6 6 * in their DSDT. 7 7 * 8 - * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 8 + * Copyright (C) 2021-2023 Hans de Goede <hansg@kernel.org> 9 9 */ 10 10 #ifndef __PDX86_X86_ANDROID_TABLETS_H 11 11 #define __PDX86_X86_ANDROID_TABLETS_H 12 12 13 13 #include <linux/gpio/consumer.h> 14 - #include <linux/gpio_keys.h> 15 14 #include <linux/i2c.h> 16 15 #include <linux/irqdomain_defs.h> 17 16 #include <linux/spi/spi.h> 18 17 19 18 struct gpio_desc; 20 - struct gpiod_lookup_table; 21 19 struct platform_device_info; 22 20 struct software_node; 23 21 ··· 28 30 X86_ACPI_IRQ_TYPE_APIC, 29 31 X86_ACPI_IRQ_TYPE_GPIOINT, 30 32 X86_ACPI_IRQ_TYPE_PMIC, 33 + }; 34 + 35 + enum x86_gpiochip_type { 36 + X86_GPIOCHIP_UNSPECIFIED = 0, 37 + X86_GPIOCHIP_BAYTRAIL, 38 + X86_GPIOCHIP_CHERRYVIEW, 31 39 }; 32 40 33 41 struct x86_acpi_irq_data { ··· 80 76 const char *serdev_hid; 81 77 }; 82 78 83 - struct x86_gpio_button { 84 - struct gpio_keys_button button; 85 - const char *chip; 86 - int pin; 87 - }; 88 - 89 79 struct x86_dev_info { 90 80 const char * const *modules; 91 - const struct software_node *bat_swnode; 92 - struct gpiod_lookup_table * const *gpiod_lookup_tables; 81 + const struct software_node **swnode_group; 93 82 const struct x86_i2c_client_info *i2c_client_info; 94 83 const struct x86_spi_dev_info *spi_dev_info; 95 84 const struct platform_device_info *pdev_info; 96 85 const struct x86_serdev_info *serdev_info; 97 - const struct x86_gpio_button *gpio_button; 86 + const struct software_node **gpio_button_swnodes; 98 87 int i2c_client_count; 99 88 int spi_dev_count; 100 89 int pdev_count; 101 90 int serdev_count; 102 - int gpio_button_count; 103 91 int (*init)(struct device *dev); 104 92 void (*exit)(void); 105 93 bool use_pci; 94 + enum x86_gpiochip_type gpiochip_type; 106 95 }; 107 96 108 97 int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, ··· 103 106 struct gpio_desc **desc); 104 107 int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data); 105 108 109 + /* Software nodes representing GPIO chips used by various tablets */ 110 + extern const struct software_node baytrail_gpiochip_nodes[]; 111 + extern const struct software_node cherryview_gpiochip_nodes[]; 112 + 106 113 /* 107 114 * Extern declarations of x86_dev_info structs so there can be a single 108 115 * MODULE_DEVICE_TABLE(dmi, ...), while splitting the board descriptions. 109 116 */ 117 + extern const struct x86_dev_info acer_a1_840_info; 110 118 extern const struct x86_dev_info acer_b1_750_info; 111 119 extern const struct x86_dev_info advantech_mica_071_info; 112 120 extern const struct x86_dev_info asus_me176c_info;
+1 -9
drivers/platform/x86/xiaomi-wmi.c
··· 26 26 unsigned int key_code; 27 27 }; 28 28 29 - static void xiaomi_mutex_destroy(void *data) 30 - { 31 - struct mutex *lock = data; 32 - 33 - mutex_destroy(lock); 34 - } 35 - 36 29 static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context) 37 30 { 38 31 struct xiaomi_wmi *data; ··· 39 46 return -ENOMEM; 40 47 dev_set_drvdata(&wdev->dev, data); 41 48 42 - mutex_init(&data->key_lock); 43 - ret = devm_add_action_or_reset(&wdev->dev, xiaomi_mutex_destroy, &data->key_lock); 49 + ret = devm_mutex_init(&wdev->dev, &data->key_lock); 44 50 if (ret < 0) 45 51 return ret; 46 52
+1 -1
sound/soc/intel/boards/bytcr_wm5102.c
··· 552 552 acpi_dev_put(adev); 553 553 } else { 554 554 /* Special case for when the codec is missing from the DSTD */ 555 - strscpy(codec_name, "spi1.0", sizeof(codec_name)); 555 + strscpy(codec_name, "spi-wm5102", sizeof(codec_name)); 556 556 } 557 557 558 558 codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);