On Fri, 17 Apr 2026, Armin Wolf wrote: > Currently the suspend handling for the FN lock and super key enable > features saves the whole values of the affected registers instead of > the individual feature state. This duplicates the register access > logic from the associated sysfs attributes. > > Rework the suspend handling to reuse said register access logic and > only store the individual feature state as a boolean value. > > Reviewed-by: Werner Sembach > Signed-off-by: Armin Wolf > --- > drivers/platform/x86/uniwill/uniwill-acpi.c | 117 ++++++++++++-------- > 1 file changed, 73 insertions(+), 44 deletions(-) > > diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c > index dac80c78ca0b..8c00d762ab08 100644 > --- a/drivers/platform/x86/uniwill/uniwill-acpi.c > +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c > @@ -341,8 +341,8 @@ struct uniwill_data { > struct acpi_battery_hook hook; > unsigned int last_charge_ctrl; > struct mutex battery_lock; /* Protects the list of currently registered batteries */ > - unsigned int last_status; > - unsigned int last_switch_status; > + bool last_fn_lock_state; > + bool last_super_key_enable_state; > struct mutex super_key_lock; /* Protects the toggling of the super key lock state */ > struct list_head batteries; > struct mutex led_lock; /* Protects writes to the lightbar registers */ > @@ -619,11 +619,22 @@ static const struct regmap_config uniwill_ec_config = { > .use_single_write = true, > }; > > +static int uniwill_write_fn_lock(struct uniwill_data *data, bool status) > +{ > + unsigned int value; > + > + if (status) > + value = FN_LOCK_STATUS; > + else > + value = 0; > + > + return regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, value); > +} > + > static ssize_t fn_lock_store(struct device *dev, struct device_attribute *attr, const char *buf, > size_t count) > { > struct uniwill_data *data = dev_get_drvdata(dev); > - unsigned int value; > bool enable; > int ret; > > @@ -631,21 +642,15 @@ static ssize_t fn_lock_store(struct device *dev, struct device_attribute *attr, > if (ret < 0) > return ret; > > - if (enable) > - value = FN_LOCK_STATUS; > - else > - value = 0; > - > - ret = regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, value); > + ret = uniwill_write_fn_lock(data, enable); > if (ret < 0) > return ret; > > return count; > } > > -static ssize_t fn_lock_show(struct device *dev, struct device_attribute *attr, char *buf) > +static int uniwill_read_fn_lock(struct uniwill_data *data, bool *status) > { > - struct uniwill_data *data = dev_get_drvdata(dev); > unsigned int value; > int ret; > > @@ -653,23 +658,31 @@ static ssize_t fn_lock_show(struct device *dev, struct device_attribute *attr, c > if (ret < 0) > return ret; > > - return sysfs_emit(buf, "%d\n", !!(value & FN_LOCK_STATUS)); > -} > + *status = !!(value & FN_LOCK_STATUS); > > -static DEVICE_ATTR_RW(fn_lock); > + return 0; > +} > > -static ssize_t super_key_enable_store(struct device *dev, struct device_attribute *attr, > - const char *buf, size_t count) > +static ssize_t fn_lock_show(struct device *dev, struct device_attribute *attr, char *buf) > { > struct uniwill_data *data = dev_get_drvdata(dev); > - unsigned int value; > - bool enable; > + bool status; > int ret; > > - ret = kstrtobool(buf, &enable); > + ret = uniwill_read_fn_lock(data, &status); > if (ret < 0) > return ret; > > + return sysfs_emit(buf, "%d\n", status); > +} > + > +static DEVICE_ATTR_RW(fn_lock); > + > +static int uniwill_write_super_key_enable(struct uniwill_data *data, bool status) > +{ > + unsigned int value; > + int ret; > + > guard(mutex)(&data->super_key_lock); > > ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value); > @@ -680,20 +693,33 @@ static ssize_t super_key_enable_store(struct device *dev, struct device_attribut > * We can only toggle the super key lock, so we return early if the setting > * is already in the correct state. > */ > - if (enable == !(value & SUPER_KEY_LOCK_STATUS)) > - return count; > + if (status == !(value & SUPER_KEY_LOCK_STATUS)) > + return 0; > + > + return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK, > + TRIGGER_SUPER_KEY_LOCK); > +} > + > +static ssize_t super_key_enable_store(struct device *dev, struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct uniwill_data *data = dev_get_drvdata(dev); > + bool enable; > + int ret; > > - ret = regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK, > - TRIGGER_SUPER_KEY_LOCK); > + ret = kstrtobool(buf, &enable); > + if (ret < 0) > + return ret; > + > + ret = uniwill_write_super_key_enable(data, enable); > if (ret < 0) > return ret; > > return count; > } > > -static ssize_t super_key_enable_show(struct device *dev, struct device_attribute *attr, char *buf) > +static int uniwill_read_super_key_enable(struct uniwill_data *data, bool *status) > { > - struct uniwill_data *data = dev_get_drvdata(dev); > unsigned int value; > int ret; > > @@ -701,7 +727,22 @@ static ssize_t super_key_enable_show(struct device *dev, struct device_attribute > if (ret < 0) > return ret; > > - return sysfs_emit(buf, "%d\n", !(value & SUPER_KEY_LOCK_STATUS)); > + *status = !(value & SUPER_KEY_LOCK_STATUS); > + > + return 0; > +} > + > +static ssize_t super_key_enable_show(struct device *dev, struct device_attribute *attr, char *buf) > +{ > + struct uniwill_data *data = dev_get_drvdata(dev); > + bool status; > + int ret; > + > + ret = uniwill_read_super_key_enable(data, &status); > + if (ret < 0) > + return ret; > + > + return sysfs_emit(buf, "%d\n", status); > } > > static DEVICE_ATTR_RW(super_key_enable); > @@ -1715,10 +1756,10 @@ static int uniwill_suspend_fn_lock(struct uniwill_data *data) > return 0; > > /* > - * The EC_ADDR_BIOS_OEM is marked as volatile, so we have to restore it > + * EC_ADDR_BIOS_OEM is marked as volatile, so we have to restore it > * ourselves. > */ > - return regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &data->last_status); > + return uniwill_read_fn_lock(data, &data->last_fn_lock_state); > } > > static int uniwill_suspend_super_key(struct uniwill_data *data) > @@ -1727,10 +1768,10 @@ static int uniwill_suspend_super_key(struct uniwill_data *data) > return 0; > > /* > - * The EC_ADDR_SWITCH_STATUS is marked as volatile, so we have to restore it > + * EC_ADDR_SWITCH_STATUS is marked as volatile, so we have to restore it > * ourselves. > */ > - return regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &data->last_switch_status); > + return uniwill_read_super_key_enable(data, &data->last_super_key_enable_state); > } > > static int uniwill_suspend_battery(struct uniwill_data *data) > @@ -1787,27 +1828,15 @@ static int uniwill_resume_fn_lock(struct uniwill_data *data) > if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK)) > return 0; > > - return regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, > - data->last_status); > + return uniwill_write_fn_lock(data, data->last_fn_lock_state); > } > > static int uniwill_resume_super_key(struct uniwill_data *data) > { > - unsigned int value; > - int ret; > - > if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY)) > return 0; > > - ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value); > - if (ret < 0) > - return ret; > - > - if ((data->last_switch_status & SUPER_KEY_LOCK_STATUS) == (value & SUPER_KEY_LOCK_STATUS)) > - return 0; > - > - return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK, > - TRIGGER_SUPER_KEY_LOCK); > + return uniwill_write_super_key_enable(data, data->last_super_key_enable_state); > } > > static int uniwill_resume_battery(struct uniwill_data *data) > Reviewed-by: Ilpo Järvinen -- i.