NixDaemon

NixOS pentest workstation as one flake — IceBreaker's successor
git clone https://git.daemon-sec.xyz/NixDaemon.git
Log | Files | Refs | README

uniwill-acpi.c (48580B)


      1 // SPDX-License-Identifier: GPL-2.0-or-later
      2 /*
      3  * Linux driver for Uniwill notebooks.
      4  *
      5  * Special thanks go to Pőcze Barnabás, Christoffer Sandberg and Werner Sembach
      6  * for supporting the development of this driver either through prior work or
      7  * by answering questions regarding the underlying ACPI and WMI interfaces.
      8  *
      9  * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de>
     10  */
     11 
     12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     13 
     14 #include <linux/acpi.h>
     15 #include <linux/array_size.h>
     16 #include <linux/bits.h>
     17 #include <linux/bitfield.h>
     18 #include <linux/cleanup.h>
     19 #include <linux/debugfs.h>
     20 #include <linux/delay.h>
     21 #include <linux/device.h>
     22 #include <linux/device/driver.h>
     23 #include <linux/dmi.h>
     24 #include <linux/errno.h>
     25 #include <linux/fixp-arith.h>
     26 #include <linux/hwmon.h>
     27 #include <linux/hwmon-sysfs.h>
     28 #include <linux/init.h>
     29 #include <linux/input.h>
     30 #include <linux/input/sparse-keymap.h>
     31 #include <linux/kernel.h>
     32 #include <linux/kstrtox.h>
     33 #include <linux/leds.h>
     34 #include <linux/led-class-multicolor.h>
     35 #include <linux/limits.h>
     36 #include <linux/list.h>
     37 #include <linux/minmax.h>
     38 #include <linux/module.h>
     39 #include <linux/mutex.h>
     40 #include <linux/notifier.h>
     41 #include <linux/platform_device.h>
     42 #include <linux/pm.h>
     43 #include <linux/printk.h>
     44 #include <linux/regmap.h>
     45 #include <linux/string.h>
     46 #include <linux/sysfs.h>
     47 #include <linux/types.h>
     48 #include <linux/units.h>
     49 
     50 #include <acpi/battery.h>
     51 
     52 #include "uniwill-wmi.h"
     53 
     54 #define EC_ADDR_BAT_POWER_UNIT_1	0x0400
     55 
     56 #define EC_ADDR_BAT_POWER_UNIT_2	0x0401
     57 
     58 #define EC_ADDR_BAT_DESIGN_CAPACITY_1	0x0402
     59 
     60 #define EC_ADDR_BAT_DESIGN_CAPACITY_2	0x0403
     61 
     62 #define EC_ADDR_BAT_FULL_CAPACITY_1	0x0404
     63 
     64 #define EC_ADDR_BAT_FULL_CAPACITY_2	0x0405
     65 
     66 #define EC_ADDR_BAT_DESIGN_VOLTAGE_1	0x0408
     67 
     68 #define EC_ADDR_BAT_DESIGN_VOLTAGE_2	0x0409
     69 
     70 #define EC_ADDR_BAT_STATUS_1		0x0432
     71 #define BAT_DISCHARGING			BIT(0)
     72 
     73 #define EC_ADDR_BAT_STATUS_2		0x0433
     74 
     75 #define EC_ADDR_BAT_CURRENT_1		0x0434
     76 
     77 #define EC_ADDR_BAT_CURRENT_2		0x0435
     78 
     79 #define EC_ADDR_BAT_REMAIN_CAPACITY_1	0x0436
     80 
     81 #define EC_ADDR_BAT_REMAIN_CAPACITY_2	0x0437
     82 
     83 #define EC_ADDR_BAT_VOLTAGE_1		0x0438
     84 
     85 #define EC_ADDR_BAT_VOLTAGE_2		0x0439
     86 
     87 #define EC_ADDR_CPU_TEMP		0x043E
     88 
     89 #define EC_ADDR_GPU_TEMP		0x044F
     90 
     91 #define EC_ADDR_MAIN_FAN_RPM_1		0x0464
     92 
     93 #define EC_ADDR_MAIN_FAN_RPM_2		0x0465
     94 
     95 #define EC_ADDR_SECOND_FAN_RPM_1	0x046C
     96 
     97 #define EC_ADDR_SECOND_FAN_RPM_2	0x046D
     98 
     99 #define EC_ADDR_DEVICE_STATUS		0x047B
    100 #define WIFI_STATUS_ON			BIT(7)
    101 /* BIT(5) is also unset depending on the rfkill state (bluetooth?) */
    102 
    103 #define EC_ADDR_BAT_ALERT		0x0494
    104 
    105 #define EC_ADDR_BAT_CYCLE_COUNT_1	0x04A6
    106 
    107 #define EC_ADDR_BAT_CYCLE_COUNT_2	0x04A7
    108 
    109 #define EC_ADDR_PROJECT_ID		0x0740
    110 
    111 #define EC_ADDR_AP_OEM			0x0741
    112 #define	ENABLE_MANUAL_CTRL		BIT(0)
    113 #define ITE_KBD_EFFECT_REACTIVE		BIT(3)
    114 #define FAN_ABNORMAL			BIT(5)
    115 
    116 #define EC_ADDR_SUPPORT_5		0x0742
    117 #define FAN_TURBO_SUPPORTED		BIT(4)
    118 #define FAN_SUPPORT			BIT(5)
    119 
    120 #define EC_ADDR_CTGP_DB_CTRL		0x0743
    121 #define CTGP_DB_GENERAL_ENABLE		BIT(0)
    122 #define CTGP_DB_DB_ENABLE		BIT(1)
    123 #define CTGP_DB_CTGP_ENABLE		BIT(2)
    124 
    125 #define EC_ADDR_CTGP_OFFSET		0x0744
    126 
    127 #define EC_ADDR_TPP_OFFSET		0x0745
    128 
    129 #define EC_ADDR_MAX_TGP			0x0746
    130 
    131 #define EC_ADDR_LIGHTBAR_AC_CTRL	0x0748
    132 #define LIGHTBAR_APP_EXISTS		BIT(0)
    133 #define LIGHTBAR_POWER_SAVE		BIT(1)
    134 #define LIGHTBAR_S0_OFF			BIT(2)
    135 #define LIGHTBAR_S3_OFF			BIT(3)	// Breathing animation when suspended
    136 #define LIGHTBAR_WELCOME		BIT(7)	// Rainbow animation
    137 
    138 #define EC_ADDR_LIGHTBAR_AC_RED		0x0749
    139 
    140 #define EC_ADDR_LIGHTBAR_AC_GREEN	0x074A
    141 
    142 #define EC_ADDR_LIGHTBAR_AC_BLUE	0x074B
    143 
    144 #define EC_ADDR_BIOS_OEM		0x074E
    145 #define FN_LOCK_STATUS			BIT(4)
    146 
    147 #define EC_ADDR_MANUAL_FAN_CTRL		0x0751
    148 #define FAN_LEVEL_MASK			GENMASK(2, 0)
    149 #define FAN_MODE_TURBO			BIT(4)
    150 #define FAN_MODE_HIGH			BIT(5)
    151 #define FAN_MODE_BOOST			BIT(6)
    152 #define FAN_MODE_USER			BIT(7)
    153 
    154 #define EC_ADDR_PWM_1			0x075B
    155 
    156 #define EC_ADDR_PWM_2			0x075C
    157 
    158 /* Unreliable */
    159 #define EC_ADDR_SUPPORT_1		0x0765
    160 #define AIRPLANE_MODE			BIT(0)
    161 #define GPS_SWITCH			BIT(1)
    162 #define OVERCLOCK			BIT(2)
    163 #define MACRO_KEY			BIT(3)
    164 #define SHORTCUT_KEY			BIT(4)
    165 #define SUPER_KEY_LOCK			BIT(5)
    166 #define LIGHTBAR			BIT(6)
    167 #define FAN_BOOST			BIT(7)
    168 
    169 #define EC_ADDR_SUPPORT_2		0x0766
    170 #define SILENT_MODE			BIT(0)
    171 #define USB_CHARGING			BIT(1)
    172 #define RGB_KEYBOARD			BIT(2)
    173 #define CHINA_MODE			BIT(5)
    174 #define MY_BATTERY			BIT(6)
    175 
    176 #define EC_ADDR_TRIGGER			0x0767
    177 #define TRIGGER_SUPER_KEY_LOCK		BIT(0)
    178 #define TRIGGER_LIGHTBAR		BIT(1)
    179 #define TRIGGER_FAN_BOOST		BIT(2)
    180 #define TRIGGER_SILENT_MODE		BIT(3)
    181 #define TRIGGER_USB_CHARGING		BIT(4)
    182 #define RGB_APPLY_COLOR			BIT(5)
    183 #define RGB_LOGO_EFFECT			BIT(6)
    184 #define RGB_RAINBOW_EFFECT		BIT(7)
    185 
    186 #define EC_ADDR_SWITCH_STATUS		0x0768
    187 #define SUPER_KEY_LOCK_STATUS		BIT(0)
    188 #define LIGHTBAR_STATUS			BIT(1)
    189 #define FAN_BOOST_STATUS		BIT(2)
    190 #define MACRO_KEY_STATUS		BIT(3)
    191 #define MY_BAT_POWER_BAT_STATUS		BIT(4)
    192 
    193 #define EC_ADDR_RGB_RED			0x0769
    194 
    195 #define EC_ADDR_RGB_GREEN		0x076A
    196 
    197 #define EC_ADDR_RGB_BLUE		0x076B
    198 
    199 #define EC_ADDR_ROMID_START		0x0770
    200 #define ROMID_LENGTH			14
    201 
    202 #define EC_ADDR_ROMID_EXTRA_1		0x077E
    203 
    204 #define EC_ADDR_ROMID_EXTRA_2		0x077F
    205 
    206 #define EC_ADDR_BIOS_OEM_2		0x0782
    207 #define FAN_V2_NEW			BIT(0)
    208 #define FAN_QKEY			BIT(1)
    209 #define FAN_TABLE_OFFICE_MODE		BIT(2)
    210 #define FAN_V3				BIT(3)
    211 #define DEFAULT_MODE			BIT(4)
    212 
    213 #define EC_ADDR_PL1_SETTING		0x0783
    214 
    215 #define EC_ADDR_PL2_SETTING		0x0784
    216 
    217 #define EC_ADDR_PL4_SETTING		0x0785
    218 
    219 #define EC_ADDR_FAN_DEFAULT		0x0786
    220 #define FAN_CURVE_LENGTH		5
    221 
    222 #define EC_ADDR_KBD_STATUS		0x078C
    223 #define KBD_WHITE_ONLY			BIT(0)	// ~single color
    224 #define KBD_SINGLE_COLOR_OFF		BIT(1)
    225 #define KBD_TURBO_LEVEL_MASK		GENMASK(3, 2)
    226 #define KBD_APPLY			BIT(4)
    227 #define KBD_BRIGHTNESS			GENMASK(7, 5)
    228 
    229 #define EC_ADDR_FAN_CTRL		0x078E
    230 #define FAN3P5				BIT(1)
    231 #define CHARGING_PROFILE		BIT(3)
    232 #define UNIVERSAL_FAN_CTRL		BIT(6)
    233 
    234 #define EC_ADDR_BIOS_OEM_3		0x07A3
    235 #define FAN_REDUCED_DURY_CYCLE		BIT(5)
    236 #define FAN_ALWAYS_ON			BIT(6)
    237 
    238 #define EC_ADDR_BIOS_BYTE		0x07A4
    239 #define FN_LOCK_SWITCH			BIT(3)
    240 
    241 #define EC_ADDR_OEM_3			0x07A5
    242 #define POWER_LED_MASK			GENMASK(1, 0)
    243 #define POWER_LED_LEFT			0x00
    244 #define POWER_LED_BOTH			0x01
    245 #define POWER_LED_NONE			0x02
    246 #define FAN_QUIET			BIT(2)
    247 #define OVERBOOST			BIT(4)
    248 #define HIGH_POWER			BIT(7)
    249 
    250 #define EC_ADDR_OEM_4			0x07A6
    251 #define OVERBOOST_DYN_TEMP_OFF		BIT(1)
    252 #define TOUCHPAD_TOGGLE_OFF		BIT(6)
    253 
    254 #define EC_ADDR_CHARGE_CTRL		0x07B9
    255 #define CHARGE_CTRL_MASK		GENMASK(6, 0)
    256 #define CHARGE_CTRL_REACHED		BIT(7)
    257 
    258 #define EC_ADDR_UNIVERSAL_FAN_CTRL	0x07C5
    259 #define SPLIT_TABLES			BIT(7)
    260 
    261 #define EC_ADDR_AP_OEM_6		0x07C6
    262 #define ENABLE_UNIVERSAL_FAN_CTRL	BIT(2)
    263 #define BATTERY_CHARGE_FULL_OVER_24H	BIT(3)
    264 #define BATTERY_ERM_STATUS_REACHED	BIT(4)
    265 
    266 #define EC_ADDR_CHARGE_PRIO		0x07CC
    267 #define CHARGING_PERFORMANCE		BIT(7)
    268 
    269 /* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */
    270 #define EC_ADDR_LIGHTBAR_BAT_CTRL	0x07E2
    271 
    272 #define EC_ADDR_LIGHTBAR_BAT_RED	0x07E3
    273 
    274 #define EC_ADDR_LIGHTBAR_BAT_GREEN	0x07E4
    275 
    276 #define EC_ADDR_LIGHTBAR_BAT_BLUE	0x07E5
    277 
    278 #define EC_ADDR_CPU_TEMP_END_TABLE	0x0F00
    279 
    280 #define EC_ADDR_CPU_TEMP_START_TABLE	0x0F10
    281 
    282 #define EC_ADDR_CPU_FAN_SPEED_TABLE	0x0F20
    283 
    284 #define EC_ADDR_GPU_TEMP_END_TABLE	0x0F30
    285 
    286 #define EC_ADDR_GPU_TEMP_START_TABLE	0x0F40
    287 
    288 #define EC_ADDR_GPU_FAN_SPEED_TABLE	0x0F50
    289 
    290 /*
    291  * Those two registers technically allow for manual fan control,
    292  * but are unstable on some models and are likely not meant to
    293  * be used by applications as they are only accessible when using
    294  * the WMI interface.
    295  */
    296 #define EC_ADDR_PWM_1_WRITEABLE		0x1804
    297 
    298 #define EC_ADDR_PWM_2_WRITEABLE		0x1809
    299 
    300 #define DRIVER_NAME	"uniwill"
    301 
    302 /*
    303  * The OEM software always sleeps up to 6 ms after reading/writing EC
    304  * registers, so we emulate this behaviour for maximum compatibility.
    305  */
    306 #define UNIWILL_EC_DELAY_US	6000
    307 
    308 #define PWM_MAX			200
    309 #define FAN_TABLE_LENGTH	16
    310 
    311 #define LED_CHANNELS		3
    312 #define LED_MAX_BRIGHTNESS	200
    313 
    314 #define UNIWILL_FEATURE_FN_LOCK_TOGGLE		BIT(0)
    315 #define UNIWILL_FEATURE_SUPER_KEY_TOGGLE	BIT(1)
    316 #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE		BIT(2)
    317 #define UNIWILL_FEATURE_LIGHTBAR		BIT(3)
    318 #define UNIWILL_FEATURE_BATTERY			BIT(4)
    319 #define UNIWILL_FEATURE_HWMON			BIT(5)
    320 
    321 struct uniwill_data {
    322 	struct device *dev;
    323 	acpi_handle handle;
    324 	struct regmap *regmap;
    325 	struct acpi_battery_hook hook;
    326 	unsigned int last_charge_ctrl;
    327 	struct mutex battery_lock;	/* Protects the list of currently registered batteries */
    328 	unsigned int last_switch_status;
    329 	struct mutex super_key_lock;	/* Protects the toggling of the super key lock state */
    330 	struct list_head batteries;
    331 	struct mutex led_lock;		/* Protects writes to the lightbar registers */
    332 	struct led_classdev_mc led_mc_cdev;
    333 	struct mc_subled led_mc_subled_info[LED_CHANNELS];
    334 	struct mutex input_lock;	/* Protects input sequence during notify */
    335 	struct input_dev *input_device;
    336 	struct notifier_block nb;
    337 };
    338 
    339 struct uniwill_battery_entry {
    340 	struct list_head head;
    341 	struct power_supply *battery;
    342 };
    343 
    344 static bool force;
    345 module_param_unsafe(force, bool, 0);
    346 MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
    347 
    348 /* Feature bitmask since the associated registers are not reliable */
    349 static unsigned int supported_features;
    350 
    351 static const char * const uniwill_temp_labels[] = {
    352 	"CPU",
    353 	"GPU",
    354 };
    355 
    356 static const char * const uniwill_fan_labels[] = {
    357 	"Main",
    358 	"Secondary",
    359 };
    360 
    361 static const struct key_entry uniwill_keymap[] = {
    362 	/* Reported via keyboard controller */
    363 	{ KE_IGNORE,    UNIWILL_OSD_CAPSLOCK,                   { KEY_CAPSLOCK }},
    364 	{ KE_IGNORE,    UNIWILL_OSD_NUMLOCK,                    { KEY_NUMLOCK }},
    365 
    366 	/* Reported when the user locks/unlocks the super key */
    367 	{ KE_IGNORE,    UNIWILL_OSD_SUPER_KEY_LOCK_ENABLE,      { KEY_UNKNOWN }},
    368 	{ KE_IGNORE,    UNIWILL_OSD_SUPER_KEY_LOCK_DISABLE,     { KEY_UNKNOWN }},
    369 	/* Optional, might not be reported by all devices */
    370 	{ KE_IGNORE,	UNIWILL_OSD_SUPER_KEY_LOCK_CHANGED,	{ KEY_UNKNOWN }},
    371 
    372 	/* Reported in manual mode when toggling the airplane mode status */
    373 	{ KE_KEY,       UNIWILL_OSD_RFKILL,                     { KEY_RFKILL }},
    374 	{ KE_IGNORE,    UNIWILL_OSD_RADIOON,                    { KEY_UNKNOWN }},
    375 	{ KE_IGNORE,    UNIWILL_OSD_RADIOOFF,                   { KEY_UNKNOWN }},
    376 
    377 	/* Reported when user wants to cycle the platform profile */
    378 	{ KE_KEY,       UNIWILL_OSD_PERFORMANCE_MODE_TOGGLE,    { KEY_F14 }},
    379 
    380 	/* Reported when the user wants to adjust the brightness of the keyboard */
    381 	{ KE_KEY,       UNIWILL_OSD_KBDILLUMDOWN,               { KEY_KBDILLUMDOWN }},
    382 	{ KE_KEY,       UNIWILL_OSD_KBDILLUMUP,                 { KEY_KBDILLUMUP }},
    383 
    384 	/* Reported when the user wants to toggle the microphone mute status */
    385 	{ KE_KEY,       UNIWILL_OSD_MIC_MUTE,                   { KEY_MICMUTE }},
    386 
    387 	/* Reported when the user wants to toggle the mute status */
    388 	{ KE_IGNORE,    UNIWILL_OSD_MUTE,                       { KEY_MUTE }},
    389 
    390 	/* Reported when the user locks/unlocks the Fn key */
    391 	{ KE_IGNORE,    UNIWILL_OSD_FN_LOCK,                    { KEY_FN_ESC }},
    392 
    393 	/* Reported when the user wants to toggle the brightness of the keyboard */
    394 	{ KE_KEY,       UNIWILL_OSD_KBDILLUMTOGGLE,             { KEY_KBDILLUMTOGGLE }},
    395 	{ KE_KEY,       UNIWILL_OSD_KB_LED_LEVEL0,              { KEY_KBDILLUMTOGGLE }},
    396 	{ KE_KEY,       UNIWILL_OSD_KB_LED_LEVEL1,              { KEY_KBDILLUMTOGGLE }},
    397 	{ KE_KEY,       UNIWILL_OSD_KB_LED_LEVEL2,              { KEY_KBDILLUMTOGGLE }},
    398 	{ KE_KEY,       UNIWILL_OSD_KB_LED_LEVEL3,              { KEY_KBDILLUMTOGGLE }},
    399 	{ KE_KEY,       UNIWILL_OSD_KB_LED_LEVEL4,              { KEY_KBDILLUMTOGGLE }},
    400 
    401 	/* FIXME: find out the exact meaning of those events */
    402 	{ KE_IGNORE,    UNIWILL_OSD_BAT_CHARGE_FULL_24_H,       { KEY_UNKNOWN }},
    403 	{ KE_IGNORE,    UNIWILL_OSD_BAT_ERM_UPDATE,             { KEY_UNKNOWN }},
    404 
    405 	/* Reported when the user wants to toggle the benchmark mode status */
    406 	{ KE_IGNORE,    UNIWILL_OSD_BENCHMARK_MODE_TOGGLE,      { KEY_UNKNOWN }},
    407 
    408 	/* Reported when the user wants to toggle the webcam */
    409 	{ KE_IGNORE,    UNIWILL_OSD_WEBCAM_TOGGLE,              { KEY_UNKNOWN }},
    410 
    411 	{ KE_END }
    412 };
    413 
    414 static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
    415 {
    416 	union acpi_object params[2] = {
    417 		{
    418 			.integer = {
    419 				.type = ACPI_TYPE_INTEGER,
    420 				.value = reg,
    421 			},
    422 		},
    423 		{
    424 			.integer = {
    425 				.type = ACPI_TYPE_INTEGER,
    426 				.value = val,
    427 			},
    428 		},
    429 	};
    430 	struct uniwill_data *data = context;
    431 	struct acpi_object_list input = {
    432 		.count = ARRAY_SIZE(params),
    433 		.pointer = params,
    434 	};
    435 	acpi_status status;
    436 
    437 	status = acpi_evaluate_object(data->handle, "ECRW", &input, NULL);
    438 	if (ACPI_FAILURE(status))
    439 		return -EIO;
    440 
    441 	usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2);
    442 
    443 	return 0;
    444 }
    445 
    446 static int uniwill_ec_reg_read(void *context, unsigned int reg, unsigned int *val)
    447 {
    448 	union acpi_object params[1] = {
    449 		{
    450 			.integer = {
    451 				.type = ACPI_TYPE_INTEGER,
    452 				.value = reg,
    453 			},
    454 		},
    455 	};
    456 	struct uniwill_data *data = context;
    457 	struct acpi_object_list input = {
    458 		.count = ARRAY_SIZE(params),
    459 		.pointer = params,
    460 	};
    461 	unsigned long long output;
    462 	acpi_status status;
    463 
    464 	status = acpi_evaluate_integer(data->handle, "ECRR", &input, &output);
    465 	if (ACPI_FAILURE(status))
    466 		return -EIO;
    467 
    468 	if (output > U8_MAX)
    469 		return -ENXIO;
    470 
    471 	usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2);
    472 
    473 	*val = output;
    474 
    475 	return 0;
    476 }
    477 
    478 static const struct regmap_bus uniwill_ec_bus = {
    479 	.reg_write = uniwill_ec_reg_write,
    480 	.reg_read = uniwill_ec_reg_read,
    481 	.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
    482 	.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
    483 };
    484 
    485 static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
    486 {
    487 	switch (reg) {
    488 	case EC_ADDR_AP_OEM:
    489 	case EC_ADDR_LIGHTBAR_AC_CTRL:
    490 	case EC_ADDR_LIGHTBAR_AC_RED:
    491 	case EC_ADDR_LIGHTBAR_AC_GREEN:
    492 	case EC_ADDR_LIGHTBAR_AC_BLUE:
    493 	case EC_ADDR_BIOS_OEM:
    494 	case EC_ADDR_TRIGGER:
    495 	case EC_ADDR_OEM_4:
    496 	case EC_ADDR_CHARGE_CTRL:
    497 	case EC_ADDR_LIGHTBAR_BAT_CTRL:
    498 	case EC_ADDR_LIGHTBAR_BAT_RED:
    499 	case EC_ADDR_LIGHTBAR_BAT_GREEN:
    500 	case EC_ADDR_LIGHTBAR_BAT_BLUE:
    501 		return true;
    502 	default:
    503 		return false;
    504 	}
    505 }
    506 
    507 static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
    508 {
    509 	switch (reg) {
    510 	case EC_ADDR_CPU_TEMP:
    511 	case EC_ADDR_GPU_TEMP:
    512 	case EC_ADDR_MAIN_FAN_RPM_1:
    513 	case EC_ADDR_MAIN_FAN_RPM_2:
    514 	case EC_ADDR_SECOND_FAN_RPM_1:
    515 	case EC_ADDR_SECOND_FAN_RPM_2:
    516 	case EC_ADDR_BAT_ALERT:
    517 	case EC_ADDR_PROJECT_ID:
    518 	case EC_ADDR_AP_OEM:
    519 	case EC_ADDR_LIGHTBAR_AC_CTRL:
    520 	case EC_ADDR_LIGHTBAR_AC_RED:
    521 	case EC_ADDR_LIGHTBAR_AC_GREEN:
    522 	case EC_ADDR_LIGHTBAR_AC_BLUE:
    523 	case EC_ADDR_BIOS_OEM:
    524 	case EC_ADDR_PWM_1:
    525 	case EC_ADDR_PWM_2:
    526 	case EC_ADDR_TRIGGER:
    527 	case EC_ADDR_SWITCH_STATUS:
    528 	case EC_ADDR_OEM_4:
    529 	case EC_ADDR_CHARGE_CTRL:
    530 	case EC_ADDR_LIGHTBAR_BAT_CTRL:
    531 	case EC_ADDR_LIGHTBAR_BAT_RED:
    532 	case EC_ADDR_LIGHTBAR_BAT_GREEN:
    533 	case EC_ADDR_LIGHTBAR_BAT_BLUE:
    534 		return true;
    535 	default:
    536 		return false;
    537 	}
    538 }
    539 
    540 static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
    541 {
    542 	switch (reg) {
    543 	case EC_ADDR_CPU_TEMP:
    544 	case EC_ADDR_GPU_TEMP:
    545 	case EC_ADDR_MAIN_FAN_RPM_1:
    546 	case EC_ADDR_MAIN_FAN_RPM_2:
    547 	case EC_ADDR_SECOND_FAN_RPM_1:
    548 	case EC_ADDR_SECOND_FAN_RPM_2:
    549 	case EC_ADDR_BAT_ALERT:
    550 	case EC_ADDR_PWM_1:
    551 	case EC_ADDR_PWM_2:
    552 	case EC_ADDR_TRIGGER:
    553 	case EC_ADDR_SWITCH_STATUS:
    554 	case EC_ADDR_CHARGE_CTRL:
    555 		return true;
    556 	default:
    557 		return false;
    558 	}
    559 }
    560 
    561 static const struct regmap_config uniwill_ec_config = {
    562 	.reg_bits = 16,
    563 	.val_bits = 8,
    564 	.writeable_reg = uniwill_writeable_reg,
    565 	.readable_reg = uniwill_readable_reg,
    566 	.volatile_reg = uniwill_volatile_reg,
    567 	.can_sleep = true,
    568 	.max_register = 0xFFF,
    569 	.cache_type = REGCACHE_MAPLE,
    570 	.use_single_read = true,
    571 	.use_single_write = true,
    572 };
    573 
    574 static ssize_t fn_lock_toggle_enable_store(struct device *dev, struct device_attribute *attr,
    575 					   const char *buf, size_t count)
    576 {
    577 	struct uniwill_data *data = dev_get_drvdata(dev);
    578 	unsigned int value;
    579 	bool enable;
    580 	int ret;
    581 
    582 	ret = kstrtobool(buf, &enable);
    583 	if (ret < 0)
    584 		return ret;
    585 
    586 	if (enable)
    587 		value = FN_LOCK_STATUS;
    588 	else
    589 		value = 0;
    590 
    591 	ret = regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, value);
    592 	if (ret < 0)
    593 		return ret;
    594 
    595 	return count;
    596 }
    597 
    598 static ssize_t fn_lock_toggle_enable_show(struct device *dev, struct device_attribute *attr,
    599 					  char *buf)
    600 {
    601 	struct uniwill_data *data = dev_get_drvdata(dev);
    602 	unsigned int value;
    603 	int ret;
    604 
    605 	ret = regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &value);
    606 	if (ret < 0)
    607 		return ret;
    608 
    609 	return sysfs_emit(buf, "%d\n", !!(value & FN_LOCK_STATUS));
    610 }
    611 
    612 static DEVICE_ATTR_RW(fn_lock_toggle_enable);
    613 
    614 static ssize_t super_key_toggle_enable_store(struct device *dev, struct device_attribute *attr,
    615 					     const char *buf, size_t count)
    616 {
    617 	struct uniwill_data *data = dev_get_drvdata(dev);
    618 	unsigned int value;
    619 	bool enable;
    620 	int ret;
    621 
    622 	ret = kstrtobool(buf, &enable);
    623 	if (ret < 0)
    624 		return ret;
    625 
    626 	guard(mutex)(&data->super_key_lock);
    627 
    628 	ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
    629 	if (ret < 0)
    630 		return ret;
    631 
    632 	/*
    633 	 * We can only toggle the super key lock, so we return early if the setting
    634 	 * is already in the correct state.
    635 	 */
    636 	if (enable == !(value & SUPER_KEY_LOCK_STATUS))
    637 		return count;
    638 
    639 	ret = regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK,
    640 				TRIGGER_SUPER_KEY_LOCK);
    641 	if (ret < 0)
    642 		return ret;
    643 
    644 	return count;
    645 }
    646 
    647 static ssize_t super_key_toggle_enable_show(struct device *dev, struct device_attribute *attr,
    648 					    char *buf)
    649 {
    650 	struct uniwill_data *data = dev_get_drvdata(dev);
    651 	unsigned int value;
    652 	int ret;
    653 
    654 	ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
    655 	if (ret < 0)
    656 		return ret;
    657 
    658 	return sysfs_emit(buf, "%d\n", !(value & SUPER_KEY_LOCK_STATUS));
    659 }
    660 
    661 static DEVICE_ATTR_RW(super_key_toggle_enable);
    662 
    663 static ssize_t touchpad_toggle_enable_store(struct device *dev, struct device_attribute *attr,
    664 					    const char *buf, size_t count)
    665 {
    666 	struct uniwill_data *data = dev_get_drvdata(dev);
    667 	unsigned int value;
    668 	bool enable;
    669 	int ret;
    670 
    671 	ret = kstrtobool(buf, &enable);
    672 	if (ret < 0)
    673 		return ret;
    674 
    675 	if (enable)
    676 		value = 0;
    677 	else
    678 		value = TOUCHPAD_TOGGLE_OFF;
    679 
    680 	ret = regmap_update_bits(data->regmap, EC_ADDR_OEM_4, TOUCHPAD_TOGGLE_OFF, value);
    681 	if (ret < 0)
    682 		return ret;
    683 
    684 	return count;
    685 }
    686 
    687 static ssize_t touchpad_toggle_enable_show(struct device *dev, struct device_attribute *attr,
    688 					   char *buf)
    689 {
    690 	struct uniwill_data *data = dev_get_drvdata(dev);
    691 	unsigned int value;
    692 	int ret;
    693 
    694 	ret = regmap_read(data->regmap, EC_ADDR_OEM_4, &value);
    695 	if (ret < 0)
    696 		return ret;
    697 
    698 	return sysfs_emit(buf, "%d\n", !(value & TOUCHPAD_TOGGLE_OFF));
    699 }
    700 
    701 static DEVICE_ATTR_RW(touchpad_toggle_enable);
    702 
    703 static ssize_t rainbow_animation_store(struct device *dev, struct device_attribute *attr,
    704 				       const char *buf, size_t count)
    705 {
    706 	struct uniwill_data *data = dev_get_drvdata(dev);
    707 	unsigned int value;
    708 	bool enable;
    709 	int ret;
    710 
    711 	ret = kstrtobool(buf, &enable);
    712 	if (ret < 0)
    713 		return ret;
    714 
    715 	if (enable)
    716 		value = LIGHTBAR_WELCOME;
    717 	else
    718 		value = 0;
    719 
    720 	guard(mutex)(&data->led_lock);
    721 
    722 	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_WELCOME, value);
    723 	if (ret < 0)
    724 		return ret;
    725 
    726 	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_WELCOME, value);
    727 	if (ret < 0)
    728 		return ret;
    729 
    730 	return count;
    731 }
    732 
    733 static ssize_t rainbow_animation_show(struct device *dev, struct device_attribute *attr, char *buf)
    734 {
    735 	struct uniwill_data *data = dev_get_drvdata(dev);
    736 	unsigned int value;
    737 	int ret;
    738 
    739 	ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
    740 	if (ret < 0)
    741 		return ret;
    742 
    743 	return sysfs_emit(buf, "%d\n", !!(value & LIGHTBAR_WELCOME));
    744 }
    745 
    746 static DEVICE_ATTR_RW(rainbow_animation);
    747 
    748 static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attribute *attr,
    749 					  const char *buf, size_t count)
    750 {
    751 	struct uniwill_data *data = dev_get_drvdata(dev);
    752 	unsigned int value;
    753 	bool enable;
    754 	int ret;
    755 
    756 	ret = kstrtobool(buf, &enable);
    757 	if (ret < 0)
    758 		return ret;
    759 
    760 	if (enable)
    761 		value = 0;
    762 	else
    763 		value = LIGHTBAR_S3_OFF;
    764 
    765 	/* We only access a single register here, so we do not need to use data->led_lock */
    766 	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S3_OFF, value);
    767 	if (ret < 0)
    768 		return ret;
    769 
    770 	return count;
    771 }
    772 
    773 static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attribute *attr,
    774 					 char *buf)
    775 {
    776 	struct uniwill_data *data = dev_get_drvdata(dev);
    777 	unsigned int value;
    778 	int ret;
    779 
    780 	ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
    781 	if (ret < 0)
    782 		return ret;
    783 
    784 	return sysfs_emit(buf, "%d\n", !(value & LIGHTBAR_S3_OFF));
    785 }
    786 
    787 static DEVICE_ATTR_RW(breathing_in_suspend);
    788 
    789 static struct attribute *uniwill_attrs[] = {
    790 	/* Keyboard-related */
    791 	&dev_attr_fn_lock_toggle_enable.attr,
    792 	&dev_attr_super_key_toggle_enable.attr,
    793 	&dev_attr_touchpad_toggle_enable.attr,
    794 	/* Lightbar-related */
    795 	&dev_attr_rainbow_animation.attr,
    796 	&dev_attr_breathing_in_suspend.attr,
    797 	NULL
    798 };
    799 
    800 static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
    801 {
    802 	if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
    803 		if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
    804 			return attr->mode;
    805 	}
    806 
    807 	if (attr == &dev_attr_super_key_toggle_enable.attr) {
    808 		if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
    809 			return attr->mode;
    810 	}
    811 
    812 	if (attr == &dev_attr_touchpad_toggle_enable.attr) {
    813 		if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
    814 			return attr->mode;
    815 	}
    816 
    817 	if (attr == &dev_attr_rainbow_animation.attr ||
    818 	    attr == &dev_attr_breathing_in_suspend.attr) {
    819 		if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
    820 			return attr->mode;
    821 	}
    822 
    823 	return 0;
    824 }
    825 
    826 static const struct attribute_group uniwill_group = {
    827 	.is_visible = uniwill_attr_is_visible,
    828 	.attrs = uniwill_attrs,
    829 };
    830 
    831 static const struct attribute_group *uniwill_groups[] = {
    832 	&uniwill_group,
    833 	NULL
    834 };
    835 
    836 static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
    837 			long *val)
    838 {
    839 	struct uniwill_data *data = dev_get_drvdata(dev);
    840 	unsigned int value;
    841 	__be16 rpm;
    842 	int ret;
    843 
    844 	switch (type) {
    845 	case hwmon_temp:
    846 		switch (channel) {
    847 		case 0:
    848 			ret = regmap_read(data->regmap, EC_ADDR_CPU_TEMP, &value);
    849 			break;
    850 		case 1:
    851 			ret = regmap_read(data->regmap, EC_ADDR_GPU_TEMP, &value);
    852 			break;
    853 		default:
    854 			return -EOPNOTSUPP;
    855 		}
    856 
    857 		if (ret < 0)
    858 			return ret;
    859 
    860 		*val = value * MILLIDEGREE_PER_DEGREE;
    861 		return 0;
    862 	case hwmon_fan:
    863 		switch (channel) {
    864 		case 0:
    865 			ret = regmap_bulk_read(data->regmap, EC_ADDR_MAIN_FAN_RPM_1, &rpm,
    866 					       sizeof(rpm));
    867 			break;
    868 		case 1:
    869 			ret = regmap_bulk_read(data->regmap, EC_ADDR_SECOND_FAN_RPM_1, &rpm,
    870 					       sizeof(rpm));
    871 			break;
    872 		default:
    873 			return -EOPNOTSUPP;
    874 		}
    875 
    876 		if (ret < 0)
    877 			return ret;
    878 
    879 		*val = be16_to_cpu(rpm);
    880 		return 0;
    881 	case hwmon_pwm:
    882 		switch (channel) {
    883 		case 0:
    884 			ret = regmap_read(data->regmap, EC_ADDR_PWM_1, &value);
    885 			break;
    886 		case 1:
    887 			ret = regmap_read(data->regmap, EC_ADDR_PWM_2, &value);
    888 			break;
    889 		default:
    890 			return -EOPNOTSUPP;
    891 		}
    892 
    893 		if (ret < 0)
    894 			return ret;
    895 
    896 		*val = fixp_linear_interpolate(0, 0, PWM_MAX, U8_MAX, value);
    897 		return 0;
    898 	default:
    899 		return -EOPNOTSUPP;
    900 	}
    901 }
    902 
    903 static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
    904 			       int channel, const char **str)
    905 {
    906 	switch (type) {
    907 	case hwmon_temp:
    908 		*str = uniwill_temp_labels[channel];
    909 		return 0;
    910 	case hwmon_fan:
    911 		*str = uniwill_fan_labels[channel];
    912 		return 0;
    913 	default:
    914 		return -EOPNOTSUPP;
    915 	}
    916 }
    917 
    918 static const struct hwmon_ops uniwill_ops = {
    919 	.visible = 0444,
    920 	.read = uniwill_read,
    921 	.read_string = uniwill_read_string,
    922 };
    923 
    924 static const struct hwmon_channel_info * const uniwill_info[] = {
    925 	HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
    926 	HWMON_CHANNEL_INFO(temp,
    927 			   HWMON_T_INPUT | HWMON_T_LABEL,
    928 			   HWMON_T_INPUT | HWMON_T_LABEL),
    929 	HWMON_CHANNEL_INFO(fan,
    930 			   HWMON_F_INPUT | HWMON_F_LABEL,
    931 			   HWMON_F_INPUT | HWMON_F_LABEL),
    932 	HWMON_CHANNEL_INFO(pwm,
    933 			   HWMON_PWM_INPUT,
    934 			   HWMON_PWM_INPUT),
    935 	NULL
    936 };
    937 
    938 static const struct hwmon_chip_info uniwill_chip_info = {
    939 	.ops = &uniwill_ops,
    940 	.info = uniwill_info,
    941 };
    942 
    943 static int uniwill_hwmon_init(struct uniwill_data *data)
    944 {
    945 	struct device *hdev;
    946 
    947 	if (!(supported_features & UNIWILL_FEATURE_HWMON))
    948 		return 0;
    949 
    950 	hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
    951 						    &uniwill_chip_info, NULL);
    952 
    953 	return PTR_ERR_OR_ZERO(hdev);
    954 }
    955 
    956 static const unsigned int uniwill_led_channel_to_bat_reg[LED_CHANNELS] = {
    957 	EC_ADDR_LIGHTBAR_BAT_RED,
    958 	EC_ADDR_LIGHTBAR_BAT_GREEN,
    959 	EC_ADDR_LIGHTBAR_BAT_BLUE,
    960 };
    961 
    962 static const unsigned int uniwill_led_channel_to_ac_reg[LED_CHANNELS] = {
    963 	EC_ADDR_LIGHTBAR_AC_RED,
    964 	EC_ADDR_LIGHTBAR_AC_GREEN,
    965 	EC_ADDR_LIGHTBAR_AC_BLUE,
    966 };
    967 
    968 static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness)
    969 {
    970 	struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev);
    971 	struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, led_mc_cdev);
    972 	unsigned int value;
    973 	int ret;
    974 
    975 	ret = led_mc_calc_color_components(led_mc_cdev, brightness);
    976 	if (ret < 0)
    977 		return ret;
    978 
    979 	guard(mutex)(&data->led_lock);
    980 
    981 	for (int i = 0; i < LED_CHANNELS; i++) {
    982 		/* Prevent the brightness values from overflowing */
    983 		value = min(LED_MAX_BRIGHTNESS, data->led_mc_subled_info[i].brightness);
    984 		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
    985 		if (ret < 0)
    986 			return ret;
    987 
    988 		ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
    989 		if (ret < 0)
    990 			return ret;
    991 	}
    992 
    993 	if (brightness)
    994 		value = 0;
    995 	else
    996 		value = LIGHTBAR_S0_OFF;
    997 
    998 	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S0_OFF, value);
    999 	if (ret < 0)
   1000 		return ret;
   1001 
   1002 	return regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_S0_OFF, value);
   1003 }
   1004 
   1005 #define LIGHTBAR_MASK	(LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME)
   1006 
   1007 static int uniwill_led_init(struct uniwill_data *data)
   1008 {
   1009 	struct led_init_data init_data = {
   1010 		.devicename = DRIVER_NAME,
   1011 		.default_label = "multicolor:" LED_FUNCTION_STATUS,
   1012 		.devname_mandatory = true,
   1013 	};
   1014 	unsigned int color_indices[3] = {
   1015 		LED_COLOR_ID_RED,
   1016 		LED_COLOR_ID_GREEN,
   1017 		LED_COLOR_ID_BLUE,
   1018 	};
   1019 	unsigned int value;
   1020 	int ret;
   1021 
   1022 	if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
   1023 		return 0;
   1024 
   1025 	ret = devm_mutex_init(data->dev, &data->led_lock);
   1026 	if (ret < 0)
   1027 		return ret;
   1028 
   1029 	/*
   1030 	 * The EC has separate lightbar settings for AC and battery mode,
   1031 	 * so we have to ensure that both settings are the same.
   1032 	 */
   1033 	ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
   1034 	if (ret < 0)
   1035 		return ret;
   1036 
   1037 	value |= LIGHTBAR_APP_EXISTS;
   1038 	ret = regmap_write(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, value);
   1039 	if (ret < 0)
   1040 		return ret;
   1041 
   1042 	/*
   1043 	 * The breathing animation during suspend is not supported when
   1044 	 * running on battery power.
   1045 	 */
   1046 	value |= LIGHTBAR_S3_OFF;
   1047 	ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_MASK, value);
   1048 	if (ret < 0)
   1049 		return ret;
   1050 
   1051 	data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
   1052 	data->led_mc_cdev.led_cdev.max_brightness = LED_MAX_BRIGHTNESS;
   1053 	data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
   1054 	data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
   1055 
   1056 	if (value & LIGHTBAR_S0_OFF)
   1057 		data->led_mc_cdev.led_cdev.brightness = 0;
   1058 	else
   1059 		data->led_mc_cdev.led_cdev.brightness = LED_MAX_BRIGHTNESS;
   1060 
   1061 	for (int i = 0; i < LED_CHANNELS; i++) {
   1062 		data->led_mc_subled_info[i].color_index = color_indices[i];
   1063 
   1064 		ret = regmap_read(data->regmap, uniwill_led_channel_to_ac_reg[i], &value);
   1065 		if (ret < 0)
   1066 			return ret;
   1067 
   1068 		/*
   1069 		 * Make sure that the initial intensity value is not greater than
   1070 		 * the maximum brightness.
   1071 		 */
   1072 		value = min(LED_MAX_BRIGHTNESS, value);
   1073 		ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
   1074 		if (ret < 0)
   1075 			return ret;
   1076 
   1077 		ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
   1078 		if (ret < 0)
   1079 			return ret;
   1080 
   1081 		data->led_mc_subled_info[i].intensity = value;
   1082 		data->led_mc_subled_info[i].channel = i;
   1083 	}
   1084 
   1085 	data->led_mc_cdev.subled_info = data->led_mc_subled_info;
   1086 	data->led_mc_cdev.num_colors = LED_CHANNELS;
   1087 
   1088 	return devm_led_classdev_multicolor_register_ext(data->dev, &data->led_mc_cdev,
   1089 							 &init_data);
   1090 }
   1091 
   1092 static int uniwill_get_property(struct power_supply *psy, const struct power_supply_ext *ext,
   1093 				void *drvdata, enum power_supply_property psp,
   1094 				union power_supply_propval *val)
   1095 {
   1096 	struct uniwill_data *data = drvdata;
   1097 	union power_supply_propval prop;
   1098 	unsigned int regval;
   1099 	int ret;
   1100 
   1101 	switch (psp) {
   1102 	case POWER_SUPPLY_PROP_HEALTH:
   1103 		ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_PRESENT, &prop);
   1104 		if (ret < 0)
   1105 			return ret;
   1106 
   1107 		if (!prop.intval) {
   1108 			val->intval = POWER_SUPPLY_HEALTH_NO_BATTERY;
   1109 			return 0;
   1110 		}
   1111 
   1112 		ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_STATUS, &prop);
   1113 		if (ret < 0)
   1114 			return ret;
   1115 
   1116 		if (prop.intval == POWER_SUPPLY_STATUS_UNKNOWN) {
   1117 			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
   1118 			return 0;
   1119 		}
   1120 
   1121 		ret = regmap_read(data->regmap, EC_ADDR_BAT_ALERT, &regval);
   1122 		if (ret < 0)
   1123 			return ret;
   1124 
   1125 		if (regval) {
   1126 			/* Charging issue */
   1127 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
   1128 			return 0;
   1129 		}
   1130 
   1131 		val->intval = POWER_SUPPLY_HEALTH_GOOD;
   1132 		return 0;
   1133 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
   1134 		ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &regval);
   1135 		if (ret < 0)
   1136 			return ret;
   1137 
   1138 		val->intval = clamp_val(FIELD_GET(CHARGE_CTRL_MASK, regval), 0, 100);
   1139 		return 0;
   1140 	default:
   1141 		return -EINVAL;
   1142 	}
   1143 }
   1144 
   1145 static int uniwill_set_property(struct power_supply *psy, const struct power_supply_ext *ext,
   1146 				void *drvdata, enum power_supply_property psp,
   1147 				const union power_supply_propval *val)
   1148 {
   1149 	struct uniwill_data *data = drvdata;
   1150 
   1151 	switch (psp) {
   1152 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
   1153 		if (val->intval < 1 || val->intval > 100)
   1154 			return -EINVAL;
   1155 
   1156 		return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
   1157 					  val->intval);
   1158 	default:
   1159 		return -EINVAL;
   1160 	}
   1161 }
   1162 
   1163 static int uniwill_property_is_writeable(struct power_supply *psy,
   1164 					 const struct power_supply_ext *ext, void *drvdata,
   1165 					 enum power_supply_property psp)
   1166 {
   1167 	if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD)
   1168 		return true;
   1169 
   1170 	return false;
   1171 }
   1172 
   1173 static const enum power_supply_property uniwill_properties[] = {
   1174 	POWER_SUPPLY_PROP_HEALTH,
   1175 	POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
   1176 };
   1177 
   1178 static const struct power_supply_ext uniwill_extension = {
   1179 	.name = DRIVER_NAME,
   1180 	.properties = uniwill_properties,
   1181 	.num_properties = ARRAY_SIZE(uniwill_properties),
   1182 	.get_property = uniwill_get_property,
   1183 	.set_property = uniwill_set_property,
   1184 	.property_is_writeable = uniwill_property_is_writeable,
   1185 };
   1186 
   1187 static int uniwill_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
   1188 {
   1189 	struct uniwill_data *data = container_of(hook, struct uniwill_data, hook);
   1190 	struct uniwill_battery_entry *entry;
   1191 	int ret;
   1192 
   1193 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
   1194 	if (!entry)
   1195 		return -ENOMEM;
   1196 
   1197 	ret = power_supply_register_extension(battery, &uniwill_extension, data->dev, data);
   1198 	if (ret < 0) {
   1199 		kfree(entry);
   1200 		return ret;
   1201 	}
   1202 
   1203 	guard(mutex)(&data->battery_lock);
   1204 
   1205 	entry->battery = battery;
   1206 	list_add(&entry->head, &data->batteries);
   1207 
   1208 	return 0;
   1209 }
   1210 
   1211 static int uniwill_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
   1212 {
   1213 	struct uniwill_data *data = container_of(hook, struct uniwill_data, hook);
   1214 	struct uniwill_battery_entry *entry, *tmp;
   1215 
   1216 	scoped_guard(mutex, &data->battery_lock) {
   1217 		list_for_each_entry_safe(entry, tmp, &data->batteries, head) {
   1218 			if (entry->battery == battery) {
   1219 				list_del(&entry->head);
   1220 				kfree(entry);
   1221 				break;
   1222 			}
   1223 		}
   1224 	}
   1225 
   1226 	power_supply_unregister_extension(battery, &uniwill_extension);
   1227 
   1228 	return 0;
   1229 }
   1230 
   1231 static int uniwill_battery_init(struct uniwill_data *data)
   1232 {
   1233 	int ret;
   1234 
   1235 	if (!(supported_features & UNIWILL_FEATURE_BATTERY))
   1236 		return 0;
   1237 
   1238 	ret = devm_mutex_init(data->dev, &data->battery_lock);
   1239 	if (ret < 0)
   1240 		return ret;
   1241 
   1242 	INIT_LIST_HEAD(&data->batteries);
   1243 	data->hook.name = "Uniwill Battery Extension";
   1244 	data->hook.add_battery = uniwill_add_battery;
   1245 	data->hook.remove_battery = uniwill_remove_battery;
   1246 
   1247 	return devm_battery_hook_register(data->dev, &data->hook);
   1248 }
   1249 
   1250 static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action, void *dummy)
   1251 {
   1252 	struct uniwill_data *data = container_of(nb, struct uniwill_data, nb);
   1253 	struct uniwill_battery_entry *entry;
   1254 
   1255 	switch (action) {
   1256 	case UNIWILL_OSD_BATTERY_ALERT:
   1257 		mutex_lock(&data->battery_lock);
   1258 		list_for_each_entry(entry, &data->batteries, head) {
   1259 			power_supply_changed(entry->battery);
   1260 		}
   1261 		mutex_unlock(&data->battery_lock);
   1262 
   1263 		return NOTIFY_OK;
   1264 	case UNIWILL_OSD_DC_ADAPTER_CHANGED:
   1265 		/* noop for the time being, will change once charging priority
   1266 		 * gets implemented.
   1267 		 */
   1268 
   1269 		return NOTIFY_OK;
   1270 	default:
   1271 		mutex_lock(&data->input_lock);
   1272 		sparse_keymap_report_event(data->input_device, action, 1, true);
   1273 		mutex_unlock(&data->input_lock);
   1274 
   1275 		return NOTIFY_OK;
   1276 	}
   1277 }
   1278 
   1279 static int uniwill_input_init(struct uniwill_data *data)
   1280 {
   1281 	int ret;
   1282 
   1283 	ret = devm_mutex_init(data->dev, &data->input_lock);
   1284 	if (ret < 0)
   1285 		return ret;
   1286 
   1287 	data->input_device = devm_input_allocate_device(data->dev);
   1288 	if (!data->input_device)
   1289 		return -ENOMEM;
   1290 
   1291 	ret = sparse_keymap_setup(data->input_device, uniwill_keymap, NULL);
   1292 	if (ret < 0)
   1293 		return ret;
   1294 
   1295 	data->input_device->name = "Uniwill WMI hotkeys";
   1296 	data->input_device->phys = "wmi/input0";
   1297 	data->input_device->id.bustype = BUS_HOST;
   1298 	ret = input_register_device(data->input_device);
   1299 	if (ret < 0)
   1300 		return ret;
   1301 
   1302 	data->nb.notifier_call = uniwill_notifier_call;
   1303 
   1304 	return devm_uniwill_wmi_register_notifier(data->dev, &data->nb);
   1305 }
   1306 
   1307 static void uniwill_disable_manual_control(void *context)
   1308 {
   1309 	struct uniwill_data *data = context;
   1310 
   1311 	regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
   1312 }
   1313 
   1314 static int uniwill_ec_init(struct uniwill_data *data)
   1315 {
   1316 	unsigned int value;
   1317 	int ret;
   1318 
   1319 	ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
   1320 	if (ret < 0)
   1321 		return ret;
   1322 
   1323 	dev_dbg(data->dev, "Project ID: %u\n", value);
   1324 
   1325 	ret = regmap_set_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
   1326 	if (ret < 0)
   1327 		return ret;
   1328 
   1329 	return devm_add_action_or_reset(data->dev, uniwill_disable_manual_control, data);
   1330 }
   1331 
   1332 static int uniwill_probe(struct platform_device *pdev)
   1333 {
   1334 	struct uniwill_data *data;
   1335 	struct regmap *regmap;
   1336 	acpi_handle handle;
   1337 	int ret;
   1338 
   1339 	handle = ACPI_HANDLE(&pdev->dev);
   1340 	if (!handle)
   1341 		return -ENODEV;
   1342 
   1343 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
   1344 	if (!data)
   1345 		return -ENOMEM;
   1346 
   1347 	data->dev = &pdev->dev;
   1348 	data->handle = handle;
   1349 	platform_set_drvdata(pdev, data);
   1350 
   1351 	regmap = devm_regmap_init(&pdev->dev, &uniwill_ec_bus, data, &uniwill_ec_config);
   1352 	if (IS_ERR(regmap))
   1353 		return PTR_ERR(regmap);
   1354 
   1355 	data->regmap = regmap;
   1356 	ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
   1357 	if (ret < 0)
   1358 		return ret;
   1359 
   1360 	ret = uniwill_ec_init(data);
   1361 	if (ret < 0)
   1362 		return ret;
   1363 
   1364 	ret = uniwill_battery_init(data);
   1365 	if (ret < 0)
   1366 		return ret;
   1367 
   1368 	ret = uniwill_led_init(data);
   1369 	if (ret < 0)
   1370 		return ret;
   1371 
   1372 	ret = uniwill_hwmon_init(data);
   1373 	if (ret < 0)
   1374 		return ret;
   1375 
   1376 	return uniwill_input_init(data);
   1377 }
   1378 
   1379 static void uniwill_shutdown(struct platform_device *pdev)
   1380 {
   1381 	struct uniwill_data *data = platform_get_drvdata(pdev);
   1382 
   1383 	regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
   1384 }
   1385 
   1386 static int uniwill_suspend_keyboard(struct uniwill_data *data)
   1387 {
   1388 	if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
   1389 		return 0;
   1390 
   1391 	/*
   1392 	 * The EC_ADDR_SWITCH_STATUS is marked as volatile, so we have to restore it
   1393 	 * ourselves.
   1394 	 */
   1395 	return regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &data->last_switch_status);
   1396 }
   1397 
   1398 static int uniwill_suspend_battery(struct uniwill_data *data)
   1399 {
   1400 	if (!(supported_features & UNIWILL_FEATURE_BATTERY))
   1401 		return 0;
   1402 
   1403 	/*
   1404 	 * Save the current charge limit in order to restore it during resume.
   1405 	 * We cannot use the regmap code for that since this register needs to
   1406 	 * be declared as volatile due to CHARGE_CTRL_REACHED.
   1407 	 */
   1408 	return regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &data->last_charge_ctrl);
   1409 }
   1410 
   1411 static int uniwill_suspend(struct device *dev)
   1412 {
   1413 	struct uniwill_data *data = dev_get_drvdata(dev);
   1414 	int ret;
   1415 
   1416 	ret = uniwill_suspend_keyboard(data);
   1417 	if (ret < 0)
   1418 		return ret;
   1419 
   1420 	ret = uniwill_suspend_battery(data);
   1421 	if (ret < 0)
   1422 		return ret;
   1423 
   1424 	regcache_cache_only(data->regmap, true);
   1425 	regcache_mark_dirty(data->regmap);
   1426 
   1427 	return 0;
   1428 }
   1429 
   1430 static int uniwill_resume_keyboard(struct uniwill_data *data)
   1431 {
   1432 	unsigned int value;
   1433 	int ret;
   1434 
   1435 	if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
   1436 		return 0;
   1437 
   1438 	ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
   1439 	if (ret < 0)
   1440 		return ret;
   1441 
   1442 	if ((data->last_switch_status & SUPER_KEY_LOCK_STATUS) == (value & SUPER_KEY_LOCK_STATUS))
   1443 		return 0;
   1444 
   1445 	return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK,
   1446 				 TRIGGER_SUPER_KEY_LOCK);
   1447 }
   1448 
   1449 static int uniwill_resume_battery(struct uniwill_data *data)
   1450 {
   1451 	if (!(supported_features & UNIWILL_FEATURE_BATTERY))
   1452 		return 0;
   1453 
   1454 	return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
   1455 				  data->last_charge_ctrl);
   1456 }
   1457 
   1458 static int uniwill_resume(struct device *dev)
   1459 {
   1460 	struct uniwill_data *data = dev_get_drvdata(dev);
   1461 	int ret;
   1462 
   1463 	regcache_cache_only(data->regmap, false);
   1464 
   1465 	ret = regcache_sync(data->regmap);
   1466 	if (ret < 0)
   1467 		return ret;
   1468 
   1469 	ret = uniwill_resume_keyboard(data);
   1470 	if (ret < 0)
   1471 		return ret;
   1472 
   1473 	return uniwill_resume_battery(data);
   1474 }
   1475 
   1476 static DEFINE_SIMPLE_DEV_PM_OPS(uniwill_pm_ops, uniwill_suspend, uniwill_resume);
   1477 
   1478 /*
   1479  * We only use the DMI table for auoloading because the ACPI device itself
   1480  * does not guarantee that the underlying EC implementation is supported.
   1481  */
   1482 static const struct acpi_device_id uniwill_id_table[] = {
   1483 	{ "INOU0000" },
   1484 	{ },
   1485 };
   1486 
   1487 static struct platform_driver uniwill_driver = {
   1488 	.driver = {
   1489 		.name = DRIVER_NAME,
   1490 		.dev_groups = uniwill_groups,
   1491 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
   1492 		.acpi_match_table = uniwill_id_table,
   1493 		.pm = pm_sleep_ptr(&uniwill_pm_ops),
   1494 	},
   1495 	.probe = uniwill_probe,
   1496 	.shutdown = uniwill_shutdown,
   1497 };
   1498 
   1499 static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
   1500 	{
   1501 		.ident = "XMG FUSION 15",
   1502 		.matches = {
   1503 			DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
   1504 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
   1505 		},
   1506 	},
   1507 	{
   1508 		.ident = "XMG FUSION 15",
   1509 		.matches = {
   1510 			DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
   1511 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
   1512 		},
   1513 	},
   1514 	{
   1515 		.ident = "Intel NUC x15",
   1516 		.matches = {
   1517 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
   1518 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
   1519 		},
   1520 		.driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
   1521 					UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
   1522 					UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
   1523 					UNIWILL_FEATURE_BATTERY |
   1524 					UNIWILL_FEATURE_HWMON),
   1525 	},
   1526 	{
   1527 		.ident = "Intel NUC x15",
   1528 		.matches = {
   1529 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
   1530 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
   1531 		},
   1532 		.driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
   1533 					UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
   1534 					UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
   1535 					UNIWILL_FEATURE_LIGHTBAR |
   1536 					UNIWILL_FEATURE_BATTERY |
   1537 					UNIWILL_FEATURE_HWMON),
   1538 	},
   1539 	{
   1540 		.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
   1541 		.matches = {
   1542 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1543 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"),
   1544 		},
   1545 	},
   1546 	{
   1547 		.ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
   1548 		.matches = {
   1549 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1550 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"),
   1551 		},
   1552 	},
   1553 	{
   1554 		.ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
   1555 		.matches = {
   1556 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1557 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
   1558 		},
   1559 	},
   1560 	{
   1561 		.ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
   1562 		.matches = {
   1563 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1564 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"),
   1565 		},
   1566 	},
   1567 	{
   1568 		.ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
   1569 		.matches = {
   1570 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1571 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"),
   1572 		},
   1573 	},
   1574 	{
   1575 		.ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
   1576 		.matches = {
   1577 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1578 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"),
   1579 		},
   1580 	},
   1581 	{
   1582 		.ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
   1583 		.matches = {
   1584 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1585 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"),
   1586 		},
   1587 	},
   1588 	{
   1589 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
   1590 		.matches = {
   1591 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1592 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
   1593 		},
   1594 	},
   1595 	{
   1596 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
   1597 		.matches = {
   1598 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1599 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"),
   1600 		},
   1601 	},
   1602 	{
   1603 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
   1604 		.matches = {
   1605 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1606 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
   1607 		},
   1608 	},
   1609 	{
   1610 		.ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
   1611 		.matches = {
   1612 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1613 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
   1614 		},
   1615 	},
   1616 	{
   1617 		.ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
   1618 		.matches = {
   1619 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1620 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"),
   1621 		},
   1622 	},
   1623 	{
   1624 		.ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
   1625 		.matches = {
   1626 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1627 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
   1628 		},
   1629 	},
   1630 	{
   1631 		.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
   1632 		.matches = {
   1633 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1634 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"),
   1635 		},
   1636 	},
   1637 	{
   1638 		.ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
   1639 		.matches = {
   1640 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1641 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"),
   1642 		},
   1643 	},
   1644 	{
   1645 		.ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
   1646 		.matches = {
   1647 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1648 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"),
   1649 		},
   1650 	},
   1651 	{
   1652 		.ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
   1653 		.matches = {
   1654 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1655 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"),
   1656 		},
   1657 	},
   1658 	{
   1659 		.ident = "TUXEDO Polaris 15 Gen1 AMD",
   1660 		.matches = {
   1661 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1662 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
   1663 		},
   1664 	},
   1665 	{
   1666 		.ident = "TUXEDO Polaris 15 Gen1 AMD",
   1667 		.matches = {
   1668 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1669 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
   1670 		},
   1671 	},
   1672 	{
   1673 		.ident = "TUXEDO Polaris 17 Gen1 AMD",
   1674 		.matches = {
   1675 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1676 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
   1677 		},
   1678 	},
   1679 	{
   1680 		.ident = "TUXEDO Polaris 17 Gen1 AMD",
   1681 		.matches = {
   1682 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1683 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
   1684 		},
   1685 	},
   1686 	{
   1687 		.ident = "TUXEDO Polaris 15 Gen1 Intel",
   1688 		.matches = {
   1689 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1690 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"),
   1691 		},
   1692 	},
   1693 	{
   1694 		.ident = "TUXEDO Polaris 15 Gen1 Intel",
   1695 		.matches = {
   1696 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1697 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"),
   1698 		},
   1699 	},
   1700 	{
   1701 		.ident = "TUXEDO Polaris 17 Gen1 Intel",
   1702 		.matches = {
   1703 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1704 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"),
   1705 		},
   1706 	},
   1707 	{
   1708 		.ident = "TUXEDO Polaris 17 Gen1 Intel",
   1709 		.matches = {
   1710 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1711 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"),
   1712 		},
   1713 	},
   1714 	{
   1715 		.ident = "TUXEDO Trinity 15 Intel Gen1",
   1716 		.matches = {
   1717 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1718 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"),
   1719 		},
   1720 	},
   1721 	{
   1722 		.ident = "TUXEDO Trinity 17 Intel Gen1",
   1723 		.matches = {
   1724 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1725 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"),
   1726 		},
   1727 	},
   1728 	{
   1729 		.ident = "TUXEDO Polaris 15/17 Gen2 AMD",
   1730 		.matches = {
   1731 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1732 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"),
   1733 		},
   1734 	},
   1735 	{
   1736 		.ident = "TUXEDO Polaris 15/17 Gen2 Intel",
   1737 		.matches = {
   1738 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1739 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
   1740 		},
   1741 	},
   1742 	{
   1743 		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
   1744 		.matches = {
   1745 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1746 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
   1747 		},
   1748 	},
   1749 	{
   1750 		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
   1751 		.matches = {
   1752 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1753 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"),
   1754 		},
   1755 	},
   1756 	{
   1757 		.ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
   1758 		.matches = {
   1759 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1760 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
   1761 		},
   1762 	},
   1763 	{
   1764 		.ident = "TUXEDO Stellaris 15 Gen4 Intel",
   1765 		.matches = {
   1766 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1767 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"),
   1768 		},
   1769 	},
   1770 	{
   1771 		.ident = "TUXEDO Polaris 15/17 Gen5 AMD",
   1772 		.matches = {
   1773 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1774 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
   1775 		},
   1776 	},
   1777 	{
   1778 		.ident = "TUXEDO Stellaris 16 Gen5 AMD",
   1779 		.matches = {
   1780 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1781 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
   1782 		},
   1783 	},
   1784 	{
   1785 		.ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
   1786 		.matches = {
   1787 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1788 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"),
   1789 		},
   1790 	},
   1791 	{
   1792 		.ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
   1793 		.matches = {
   1794 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1795 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
   1796 		},
   1797 	},
   1798 	{
   1799 		.ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
   1800 		.matches = {
   1801 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1802 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"),
   1803 		},
   1804 	},
   1805 	{
   1806 		.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
   1807 		.matches = {
   1808 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1809 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"),
   1810 		},
   1811 	},
   1812 	{
   1813 		.ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
   1814 		.matches = {
   1815 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1816 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"),
   1817 		},
   1818 	},
   1819 	{
   1820 		.ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
   1821 		.matches = {
   1822 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1823 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"),
   1824 		},
   1825 	},
   1826 	{
   1827 		.ident = "TUXEDO Stellaris 16 Gen7 AMD",
   1828 		.matches = {
   1829 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1830 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"),
   1831 		},
   1832 	},
   1833 	{
   1834 		.ident = "TUXEDO Stellaris 16 Gen7 Intel",
   1835 		.matches = {
   1836 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1837 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"),
   1838 		},
   1839 	},
   1840 	{
   1841 		.ident = "TUXEDO Stellaris 16 Gen7 Intel",
   1842 		.matches = {
   1843 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1844 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"),
   1845 		},
   1846 	},
   1847 	{
   1848 		.ident = "TUXEDO Book BA15 Gen10 AMD",
   1849 		.matches = {
   1850 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1851 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
   1852 		},
   1853 	},
   1854 	{
   1855 		.ident = "TUXEDO Pulse 14 Gen1 AMD",
   1856 		.matches = {
   1857 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1858 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"),
   1859 		},
   1860 	},
   1861 	{
   1862 		.ident = "TUXEDO Pulse 15 Gen1 AMD",
   1863 		.matches = {
   1864 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1865 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"),
   1866 		},
   1867 	},
   1868 	{
   1869 		.ident = "TUXEDO Pulse 15 Gen2 AMD",
   1870 		.matches = {
   1871 			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
   1872 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
   1873 		},
   1874 	},
   1875 	{ }
   1876 };
   1877 MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
   1878 
   1879 static int __init uniwill_init(void)
   1880 {
   1881 	const struct dmi_system_id *id;
   1882 	int ret;
   1883 
   1884 	id = dmi_first_match(uniwill_dmi_table);
   1885 	if (!id) {
   1886 		if (!force)
   1887 			return -ENODEV;
   1888 
   1889 		/* Assume that the device supports all features */
   1890 		supported_features = UINT_MAX;
   1891 		pr_warn("Loading on a potentially unsupported device\n");
   1892 	} else {
   1893 		supported_features = (uintptr_t)id->driver_data;
   1894 	}
   1895 
   1896 	ret = platform_driver_register(&uniwill_driver);
   1897 	if (ret < 0)
   1898 		return ret;
   1899 
   1900 	ret = uniwill_wmi_register_driver();
   1901 	if (ret < 0) {
   1902 		platform_driver_unregister(&uniwill_driver);
   1903 		return ret;
   1904 	}
   1905 
   1906 	return 0;
   1907 }
   1908 module_init(uniwill_init);
   1909 
   1910 static void __exit uniwill_exit(void)
   1911 {
   1912 	uniwill_wmi_unregister_driver();
   1913 	platform_driver_unregister(&uniwill_driver);
   1914 }
   1915 module_exit(uniwill_exit);
   1916 
   1917 MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
   1918 MODULE_DESCRIPTION("Uniwill notebook driver");
   1919 MODULE_LICENSE("GPL");