The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Werner Sembach <wse@tuxedocomputers.com>
To: "Armin Wolf" <W_Armin@gmx.de>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Cc: Hans de Goede <hansg@kernel.org>,
	platform-driver-x86@vger.kernel.org,
	LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v2 7/7] platform/x86: uniwill-laptop: Add support for battery charge modes
Date: Mon, 11 May 2026 19:40:43 +0200	[thread overview]
Message-ID: <0526a23d-5922-4e4a-b8fe-faeb36bce653@tuxedocomputers.com> (raw)
In-Reply-To: <86500f41-d739-4a78-a4db-88063f5246a4@gmx.de>

Hi,

Am 06.05.26 um 09:47 schrieb Armin Wolf:
> Am 04.05.26 um 10:44 schrieb Werner Sembach:
>>
>> Am 30.04.26 um 15:41 schrieb Armin Wolf:
>>> Am 30.04.26 um 15:22 schrieb Ilpo Järvinen:
>>>> On Fri, 17 Apr 2026, Armin Wolf wrote:
>>>>
>>>>> Many Uniwill-based devices do not supports the already existing
>>>>> charge limit functionality, but instead support an alternative
>>>>> interface for controlling the battery charge algorithm.
>>>>>
>>>>> Add support for this interface and update the documentation.
>>>>>
>>>>> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
>>>>> ---
>>>>>   .../admin-guide/laptops/uniwill-laptop.rst    |  19 +-
>>>>>   drivers/platform/x86/uniwill/uniwill-acpi.c   | 243 +++++++++++++ +----
>>>>>   drivers/platform/x86/uniwill/uniwill-wmi.c    |   5 +-
>>>>>   3 files changed, 215 insertions(+), 52 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/admin-guide/laptops/uniwill-laptop.rst b/ 
>>>>> Documentation/admin-guide/laptops/uniwill-laptop.rst
>>>>> index 1f3ca84c7d88..24b41dbab886 100644
>>>>> --- a/Documentation/admin-guide/laptops/uniwill-laptop.rst
>>>>> +++ b/Documentation/admin-guide/laptops/uniwill-laptop.rst
>>>>> @@ -46,11 +46,20 @@ Battery Charging Control
>>>>>   .. warning:: Some devices do not properly implement the charging 
>>>>> threshold interface. Forcing
>>>>>                the driver to enable access to said interface on such 
>>>>> devices might damage the
>>>>>                battery [1]_. Because of this the driver will not enable 
>>>>> said feature even when
>>>>> -             using the ``force`` module parameter.
>>>>> -
>>>>> -The ``uniwill-laptop`` driver supports controlling the battery charge 
>>>>> limit. This happens over
>>>>> -the standard ``charge_control_end_threshold`` power supply sysfs 
>>>>> attribute. All values
>>>>> -between 1 and 100 percent are supported.
>>>>> +             using the ``force`` module parameter. The charging profile 
>>>>> interface will be
>>>>> +             available instead.
>>>>> +
>>>>> +The ``uniwill-laptop`` driver supports controlling the battery charge 
>>>>> limit. This either happens
>>>>> +over the standard ``charge_control_end_threshold`` or ``charge_types`` 
>>>>> power supply sysfs attribute,
>>>>> +depending on the device. When using the ``charge_control_end_threshold`` 
>>>>> sysfs attribute, all values
>>>>> +between 1 and 100 percent are supported. When using the ``charge_types`` 
>>>>> sysfs attribute, the driver
>>>>> +supports switching between the ``Standard``, ``Trickle`` and ``Long 
>>>>> Life`` profiles.
>>>>> +
>>>>> +Keep in mind that when using the ``charge_types`` sysfs attribute, the EC 
>>>>> firmware will hide the
>>>>> +true charging status of the battery from the operating system, 
>>>>> potentially misleading users into
>>>>> +thinking that the charging profile does not work. Checking the 
>>>>> ``current_now`` sysfs attribute
>>>>> +tells you the true charging status of the battery even when using the 
>>>>> ``charge_types`` sysfs
>>>>> +attribute (0 means that the battery is currently not charging).
>>>>>     Additionally the driver signals the presence of battery charging 
>>>>> issues through the standard
>>>>>   ``health`` power supply sysfs attribute.
>>>>> diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/ 
>>>>> platform/x86/uniwill/uniwill-acpi.c
>>>>> index d4abcaf87e39..e11b6c8aeb0d 100644
>>>>> --- a/drivers/platform/x86/uniwill/uniwill-acpi.c
>>>>> +++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
>>>>> @@ -254,6 +254,10 @@
>>>>>     #define EC_ADDR_OEM_4            0x07A6
>>>>>   #define OVERBOOST_DYN_TEMP_OFF        BIT(1)
>>>>> +#define CHARGING_PROFILE_MASK        GENMASK(5, 4)
>>>>> +#define CHARGING_PROFILE_HIGH_CAPACITY    0x00
>>>>> +#define CHARGING_PROFILE_BALANCED    0x01
>>>>> +#define CHARGING_PROFILE_STATIONARY    0x02
>>>>>   #define TOUCHPAD_TOGGLE_OFF        BIT(6)
>>>>>     #define EC_ADDR_CHARGE_CTRL        0x07B9
>>>>> @@ -320,13 +324,15 @@
>>>>>   #define UNIWILL_FEATURE_SUPER_KEY        BIT(1)
>>>>>   #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE        BIT(2)
>>>>>   #define UNIWILL_FEATURE_LIGHTBAR        BIT(3)
>>>>> -#define UNIWILL_FEATURE_BATTERY            BIT(4)
>>>>> -#define UNIWILL_FEATURE_CPU_TEMP        BIT(5)
>>>>> -#define UNIWILL_FEATURE_GPU_TEMP        BIT(6)
>>>>> -#define UNIWILL_FEATURE_PRIMARY_FAN        BIT(7)
>>>>> -#define UNIWILL_FEATURE_SECONDARY_FAN        BIT(8)
>>>>> -#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL    BIT(9)
>>>>> -#define UNIWILL_FEATURE_USB_C_POWER_PRIORITY    BIT(10)
>>>>> +#define UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT    BIT(4)
>>>>> +/* Mutually exclusive with the charge limit feature */
>>>>> +#define UNIWILL_FEATURE_BATTERY_CHARGE_MODES    BIT(5)
>>>>
>>>> This feature seems to be only available through force parameter?
>>>>
>>>
>>> Yes, this is expected to change as soon as Tuxedo can verify if their 
>>> devices support this feature. I tested it on my Tuxedo device, but i do
>>> not want to split the feature descriptors too much.
>> Shouldn't require too much testing, will spin up a patch for it.
>
> Thank you :)

Sorry for the delay, here is the patch ready to be included in v3: 
https://gitlab.com/tuxedocomputers/development/packages/linux/-/commit/b367ce0952a4d641ef1db9c98e9a03c00902b2ab

best regards

Werner

>
> Armin Wolf
>
>>>
>>> Thanks,
>>> Armin Wolf
>>>
>>>> -- 
>>>>   i.
>>>>
>>>>> +#define UNIWILL_FEATURE_CPU_TEMP BIT(6)
>>>>> +#define UNIWILL_FEATURE_GPU_TEMP        BIT(7)
>>>>> +#define UNIWILL_FEATURE_PRIMARY_FAN        BIT(8)
>>>>> +#define UNIWILL_FEATURE_SECONDARY_FAN        BIT(9)
>>>>> +#define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL    BIT(10)
>>>>> +#define UNIWILL_FEATURE_USB_C_POWER_PRIORITY    BIT(11)
>>>>>     enum usb_c_power_priority_options {
>>>>>       USB_C_POWER_PRIORITY_CHARGING = 0,
>>>>> @@ -339,8 +345,15 @@ struct uniwill_data {
>>>>>       struct regmap *regmap;
>>>>>       unsigned int features;
>>>>>       struct acpi_battery_hook hook;
>>>>> -    unsigned int last_charge_ctrl;
>>>>>       struct mutex battery_lock;    /* Protects the list of currently 
>>>>> registered batteries */
>>>>> +    union {
>>>>> +        struct {
>>>>> +            /* Protects writes to last_charge_type */
>>>>> +            struct mutex charge_type_lock;
>>>>> +            enum power_supply_charge_type last_charge_type;
>>>>> +        };
>>>>> +        unsigned int last_charge_ctrl;
>>>>> +    };
>>>>>       bool last_fn_lock_state;
>>>>>       bool last_super_key_enable_state;
>>>>>       bool last_touchpad_toggle_enable_state;
>>>>> @@ -447,6 +460,12 @@ static inline bool uniwill_device_supports(const 
>>>>> struct uniwill_data *data,
>>>>>       return (data->features & features) == features;
>>>>>   }
>>>>>   +static inline bool uniwill_device_supports_any(const struct 
>>>>> uniwill_data *data,
>>>>> +                           unsigned int features)
>>>>> +{
>>>>> +    return data->features & features;
>>>>> +}
>>>>> +
>>>>>   static int uniwill_ec_reg_write(void *context, unsigned int reg, 
>>>>> unsigned int val)
>>>>>   {
>>>>>       union acpi_object params[2] = {
>>>>> @@ -1421,6 +1440,30 @@ static int uniwill_led_init(struct uniwill_data *data)
>>>>>                                &init_data);
>>>>>   }
>>>>>   +static int uniwill_read_charge_type(struct uniwill_data *data, enum 
>>>>> power_supply_charge_type *type)
>>>>> +{
>>>>> +    unsigned int value;
>>>>> +    int ret;
>>>>> +
>>>>> +    ret = regmap_read(data->regmap, EC_ADDR_OEM_4, &value);
>>>>> +    if (ret < 0)
>>>>> +        return ret;
>>>>> +
>>>>> +    switch (FIELD_GET(CHARGING_PROFILE_MASK, value)) {
>>>>> +    case CHARGING_PROFILE_HIGH_CAPACITY:
>>>>> +        *type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
>>>>> +        return 0;
>>>>> +    case CHARGING_PROFILE_BALANCED:
>>>>> +        *type = POWER_SUPPLY_CHARGE_TYPE_LONGLIFE;
>>>>> +        return 0;
>>>>> +    case CHARGING_PROFILE_STATIONARY:
>>>>> +        *type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
>>>>> +        return 0;
>>>>> +    default:
>>>>> +        return -EPROTO;
>>>>> +    }
>>>>> +}
>>>>> +
>>>>>   static int uniwill_get_property(struct power_supply *psy, const struct 
>>>>> power_supply_ext *ext,
>>>>>                   void *drvdata, enum power_supply_property psp,
>>>>>                   union power_supply_propval *val)
>>>>> @@ -1431,6 +1474,16 @@ static int uniwill_get_property(struct power_supply 
>>>>> *psy, const struct power_sup
>>>>>       int ret;
>>>>>         switch (psp) {
>>>>> +    case POWER_SUPPLY_PROP_CHARGE_TYPES:
>>>>> +        /*
>>>>> +         * We need to use the cached value here because the charging mode
>>>>> +         * reported by the EC might temporarily change when a external power
>>>>> +         * source has been connected.
>>>>> +         */
>>>>> +        mutex_lock(&data->charge_type_lock);
>>>>> +        val->intval = data->last_charge_type;
>>>>> +        mutex_unlock(&data->charge_type_lock);
>>>>> +        return 0;
>>>>>       case POWER_SUPPLY_PROP_HEALTH:
>>>>>           ret = power_supply_get_property_direct(psy, 
>>>>> POWER_SUPPLY_PROP_PRESENT, &prop);
>>>>>           if (ret < 0)
>>>>> @@ -1479,13 +1532,52 @@ static int uniwill_get_property(struct 
>>>>> power_supply *psy, const struct power_sup
>>>>>       }
>>>>>   }
>>>>>   +static int uniwill_write_charge_type(struct uniwill_data *data, enum 
>>>>> power_supply_charge_type type)
>>>>> +{
>>>>> +    unsigned int value;
>>>>> +
>>>>> +    switch (type) {
>>>>> +    case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
>>>>> +        value = FIELD_PREP(CHARGING_PROFILE_MASK, 
>>>>> CHARGING_PROFILE_STATIONARY);
>>>>> +        break;
>>>>> +    case POWER_SUPPLY_CHARGE_TYPE_STANDARD:
>>>>> +        value = FIELD_PREP(CHARGING_PROFILE_MASK, 
>>>>> CHARGING_PROFILE_HIGH_CAPACITY);
>>>>> +        break;
>>>>> +    case POWER_SUPPLY_CHARGE_TYPE_LONGLIFE:
>>>>> +        value = FIELD_PREP(CHARGING_PROFILE_MASK, 
>>>>> CHARGING_PROFILE_BALANCED);
>>>>> +        break;
>>>>> +    default:
>>>>> +        return -EINVAL;
>>>>> +    }
>>>>> +
>>>>> +    return regmap_update_bits(data->regmap, EC_ADDR_OEM_4, 
>>>>> CHARGING_PROFILE_MASK, value);
>>>>> +}
>>>>> +
>>>>> +static int uniwill_restore_charge_type(struct uniwill_data *data)
>>>>> +{
>>>>> +    guard(mutex)(&data->charge_type_lock);
>>>>> +
>>>>> +    return uniwill_write_charge_type(data, data->last_charge_type);
>>>>> +}
>>>>> +
>>>>>   static int uniwill_set_property(struct power_supply *psy, const struct 
>>>>> power_supply_ext *ext,
>>>>>                   void *drvdata, enum power_supply_property psp,
>>>>>                   const union power_supply_propval *val)
>>>>>   {
>>>>>       struct uniwill_data *data = drvdata;
>>>>> +    int ret;
>>>>>         switch (psp) {
>>>>> +    case POWER_SUPPLY_PROP_CHARGE_TYPES:
>>>>> +        mutex_lock(&data->charge_type_lock);
>>>>> +
>>>>> +        ret = uniwill_write_charge_type(data, val->intval);
>>>>> +        if (ret >= 0)
>>>>> +            data->last_charge_type = val->intval;
>>>>> +
>>>>> +        mutex_unlock(&data->charge_type_lock);
>>>>> +
>>>>> +        return ret;
>>>>>       case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
>>>>>           if (val->intval < 0 || val->intval > 100)
>>>>>               return -EINVAL;
>>>>> @@ -1501,21 +1593,41 @@ static int uniwill_property_is_writeable(struct 
>>>>> power_supply *psy,
>>>>>                        const struct power_supply_ext *ext, void *drvdata,
>>>>>                        enum power_supply_property psp)
>>>>>   {
>>>>> -    if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD)
>>>>> +    switch (psp) {
>>>>> +    case POWER_SUPPLY_PROP_CHARGE_TYPES:
>>>>> +    case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
>>>>>           return true;
>>>>> -
>>>>> -    return false;
>>>>> +    default:
>>>>> +        return false;
>>>>> +    }
>>>>>   }
>>>>>   -static const enum power_supply_property uniwill_properties[] = {
>>>>> +static const enum power_supply_property uniwill_charge_limit_properties[] 
>>>>> = {
>>>>>       POWER_SUPPLY_PROP_HEALTH,
>>>>>       POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
>>>>>   };
>>>>>   -static const struct power_supply_ext uniwill_extension = {
>>>>> +static const struct power_supply_ext uniwill_charge_limit_extension = {
>>>>>       .name = DRIVER_NAME,
>>>>> -    .properties = uniwill_properties,
>>>>> -    .num_properties = ARRAY_SIZE(uniwill_properties),
>>>>> +    .properties = uniwill_charge_limit_properties,
>>>>> +    .num_properties = ARRAY_SIZE(uniwill_charge_limit_properties),
>>>>> +    .get_property = uniwill_get_property,
>>>>> +    .set_property = uniwill_set_property,
>>>>> +    .property_is_writeable = uniwill_property_is_writeable,
>>>>> +};
>>>>> +
>>>>> +static const enum power_supply_property uniwill_charge_modes_properties[] 
>>>>> = {
>>>>> +    POWER_SUPPLY_PROP_CHARGE_TYPES,
>>>>> +    POWER_SUPPLY_PROP_HEALTH,
>>>>> +};
>>>>> +
>>>>> +static const struct power_supply_ext uniwill_charge_modes_extension = {
>>>>> +    .name = DRIVER_NAME,
>>>>> +    .charge_types = BIT(POWER_SUPPLY_CHARGE_TYPE_TRICKLE) |
>>>>> +            BIT(POWER_SUPPLY_CHARGE_TYPE_STANDARD) |
>>>>> +            BIT(POWER_SUPPLY_CHARGE_TYPE_LONGLIFE),
>>>>> +    .properties = uniwill_charge_modes_properties,
>>>>> +    .num_properties = ARRAY_SIZE(uniwill_charge_modes_properties),
>>>>>       .get_property = uniwill_get_property,
>>>>>       .set_property = uniwill_set_property,
>>>>>       .property_is_writeable = uniwill_property_is_writeable,
>>>>> @@ -1531,7 +1643,13 @@ static int uniwill_add_battery(struct power_supply 
>>>>> *battery, struct acpi_battery
>>>>>       if (!entry)
>>>>>           return -ENOMEM;
>>>>>   -    ret = power_supply_register_extension(battery, &uniwill_extension, 
>>>>> data->dev, data);
>>>>> +    if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
>>>>> +        ret = power_supply_register_extension(battery, 
>>>>> &uniwill_charge_limit_extension,
>>>>> +                              data->dev, data);
>>>>> +    else
>>>>> +        ret = power_supply_register_extension(battery, 
>>>>> &uniwill_charge_modes_extension,
>>>>> +                              data->dev, data);
>>>>> +
>>>>>       if (ret < 0) {
>>>>>           kfree(entry);
>>>>>           return ret;
>>>>> @@ -1560,7 +1678,10 @@ static int uniwill_remove_battery(struct 
>>>>> power_supply *battery, struct acpi_batt
>>>>>           }
>>>>>       }
>>>>>   -    power_supply_unregister_extension(battery, &uniwill_extension);
>>>>> +    if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
>>>>> +        power_supply_unregister_extension(battery, 
>>>>> &uniwill_charge_limit_extension);
>>>>> +    else
>>>>> +        power_supply_unregister_extension(battery, 
>>>>> &uniwill_charge_modes_extension);
>>>>>         return 0;
>>>>>   }
>>>>> @@ -1570,27 +1691,36 @@ static int uniwill_battery_init(struct 
>>>>> uniwill_data *data)
>>>>>       unsigned int value, threshold;
>>>>>       int ret;
>>>>>   -    if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>>>>> -        return 0;
>>>>> +    if (uniwill_device_supports(data, 
>>>>> UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT)) {
>>>>> +        ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &value);
>>>>> +        if (ret < 0)
>>>>> +            return ret;
>>>>>   -    ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &value);
>>>>> -    if (ret < 0)
>>>>> -        return ret;
>>>>> +        /*
>>>>> +         * The charge control threshold might be initialized with 0 by
>>>>> +         * the EC to signal that said threshold is uninitialized. We thus
>>>>> +         * need to replace this value with 100 to signal that we want to
>>>>> +         * take control of battery charging. For the sake of completeness
>>>>> +         * we also set the charging threshold to 100 if the EC- provided
>>>>> +         * value is invalid.
>>>>> +         */
>>>>> +        threshold = FIELD_GET(CHARGE_CTRL_MASK, value);
>>>>> +        if (threshold == 0 || threshold > 100) {
>>>>> +            FIELD_MODIFY(CHARGE_CTRL_MASK, &value, 100);
>>>>> +            ret = regmap_write(data->regmap, EC_ADDR_CHARGE_CTRL, value);
>>>>> +            if (ret < 0)
>>>>> +                return ret;
>>>>> +        }
>>>>> +    } else if (uniwill_device_supports(data, 
>>>>> UNIWILL_FEATURE_BATTERY_CHARGE_MODES)) {
>>>>> +        ret = devm_mutex_init(data->dev, &data->charge_type_lock);
>>>>> +        if (ret < 0)
>>>>> +            return ret;
>>>>>   -    /*
>>>>> -     * The charge control threshold might be initialized with 0 by
>>>>> -     * the EC to signal that said threshold is uninitialized. We thus
>>>>> -     * need to replace this value with 100 to signal that we want to
>>>>> -     * take control of battery charging. For the sake of completeness
>>>>> -     * we also set the charging threshold to 100 if the EC-provided
>>>>> -     * value is invalid.
>>>>> -     */
>>>>> -    threshold = FIELD_GET(CHARGE_CTRL_MASK, value);
>>>>> -    if (threshold == 0 || threshold > 100) {
>>>>> -        FIELD_MODIFY(CHARGE_CTRL_MASK, &value, 100);
>>>>> -        ret = regmap_write(data->regmap, EC_ADDR_CHARGE_CTRL, value);
>>>>> +        ret = uniwill_read_charge_type(data, &data->last_charge_type);
>>>>>           if (ret < 0)
>>>>>               return ret;
>>>>> +    } else {
>>>>> +        return 0;
>>>>>       }
>>>>>         ret = devm_mutex_init(data->dev, &data->battery_lock);
>>>>> @@ -1609,10 +1739,13 @@ static int uniwill_notifier_call(struct 
>>>>> notifier_block *nb, unsigned long action
>>>>>   {
>>>>>       struct uniwill_data *data = container_of(nb, struct uniwill_data, nb);
>>>>>       struct uniwill_battery_entry *entry;
>>>>> +    int ret;
>>>>>         switch (action) {
>>>>>       case UNIWILL_OSD_BATTERY_ALERT:
>>>>> -        if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>>>>> +        if (!uniwill_device_supports_any(data,
>>>>> + UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
>>>>> + UNIWILL_FEATURE_BATTERY_CHARGE_MODES))
>>>>>               return NOTIFY_DONE;
>>>>>             mutex_lock(&data->battery_lock);
>>>>> @@ -1623,10 +1756,24 @@ static int uniwill_notifier_call(struct 
>>>>> notifier_block *nb, unsigned long action
>>>>>             return NOTIFY_OK;
>>>>>       case UNIWILL_OSD_DC_ADAPTER_CHANGED:
>>>>> -        if (!uniwill_device_supports(data, 
>>>>> UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
>>>>> +        if (!uniwill_device_supports_any(data,
>>>>> + UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
>>>>> + UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
>>>>>               return NOTIFY_DONE;
>>>>>   -        return notifier_from_errno(usb_c_power_priority_restore(data));
>>>>> +        if (uniwill_device_supports(data, 
>>>>> UNIWILL_FEATURE_BATTERY_CHARGE_MODES)) {
>>>>> +            ret = uniwill_restore_charge_type(data);
>>>>> +            if (ret < 0)
>>>>> +                return notifier_from_errno(ret);
>>>>> +        }
>>>>> +
>>>>> +        if (uniwill_device_supports(data, 
>>>>> UNIWILL_FEATURE_USB_C_POWER_PRIORITY)) {
>>>>> +            ret = usb_c_power_priority_restore(data);
>>>>> +            if (ret < 0)
>>>>> +                return notifier_from_errno(ret);
>>>>> +        }
>>>>> +
>>>>> +        return NOTIFY_OK;
>>>>>       case UNIWILL_OSD_FN_LOCK:
>>>>>           if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
>>>>>               return NOTIFY_DONE;
>>>>> @@ -1810,7 +1957,7 @@ static int uniwill_suspend_touchpad_toggle(struct 
>>>>> uniwill_data *data)
>>>>>     static int uniwill_suspend_battery(struct uniwill_data *data)
>>>>>   {
>>>>> -    if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>>>>> +    if (!uniwill_device_supports(data, 
>>>>> UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
>>>>>           return 0;
>>>>>         /*
>>>>> @@ -1887,11 +2034,15 @@ static int uniwill_resume_touchpad_toggle(struct 
>>>>> uniwill_data *data)
>>>>>     static int uniwill_resume_battery(struct uniwill_data *data)
>>>>>   {
>>>>> -    if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
>>>>> -        return 0;
>>>>>   -    return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, 
>>>>> CHARGE_CTRL_MASK,
>>>>> -                  data->last_charge_ctrl);
>>>>> +    if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_MODES))
>>>>> +        return uniwill_restore_charge_type(data);
>>>>> +
>>>>> +    if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
>>>>> +        return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, 
>>>>> CHARGE_CTRL_MASK,
>>>>> +                      data->last_charge_ctrl);
>>>>> +
>>>>> +    return 0;
>>>>>   }
>>>>>     static int uniwill_resume_nvidia_ctgp(struct uniwill_data *data)
>>>>> @@ -1970,7 +2121,7 @@ static struct platform_driver uniwill_driver = {
>>>>>     static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor 
>>>>> __initdata = {
>>>>>       .features = UNIWILL_FEATURE_SUPER_KEY |
>>>>> -            UNIWILL_FEATURE_BATTERY |
>>>>> +            UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
>>>>>               UNIWILL_FEATURE_CPU_TEMP |
>>>>>               UNIWILL_FEATURE_GPU_TEMP |
>>>>>               UNIWILL_FEATURE_PRIMARY_FAN |
>>>>> @@ -1981,7 +2132,7 @@ static struct uniwill_device_descriptor 
>>>>> lapac71h_descriptor __initdata = {
>>>>>       .features = UNIWILL_FEATURE_FN_LOCK |
>>>>>               UNIWILL_FEATURE_SUPER_KEY |
>>>>>               UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>>>> -            UNIWILL_FEATURE_BATTERY |
>>>>> +            UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
>>>>>               UNIWILL_FEATURE_CPU_TEMP |
>>>>>               UNIWILL_FEATURE_GPU_TEMP |
>>>>>               UNIWILL_FEATURE_PRIMARY_FAN |
>>>>> @@ -1993,7 +2144,7 @@ static struct uniwill_device_descriptor 
>>>>> lapkc71f_descriptor __initdata = {
>>>>>               UNIWILL_FEATURE_SUPER_KEY |
>>>>>               UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
>>>>>               UNIWILL_FEATURE_LIGHTBAR |
>>>>> -            UNIWILL_FEATURE_BATTERY |
>>>>> +            UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
>>>>>               UNIWILL_FEATURE_CPU_TEMP |
>>>>>               UNIWILL_FEATURE_GPU_TEMP |
>>>>>               UNIWILL_FEATURE_PRIMARY_FAN |
>>>>> @@ -2579,7 +2730,7 @@ static int __init uniwill_init(void)
>>>>>         if (force) {
>>>>>           /* Assume that the device supports all features except the 
>>>>> charge limit */
>>>>> -        device_descriptor.features = UINT_MAX & ~UNIWILL_FEATURE_BATTERY;
>>>>> +        device_descriptor.features = UINT_MAX & 
>>>>> ~UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT;
>>>>>           pr_warn("Enabling potentially unsupported features\n");
>>>>>       }
>>>>>   diff --git a/drivers/platform/x86/uniwill/uniwill-wmi.c b/drivers/ 
>>>>> platform/x86/uniwill/uniwill-wmi.c
>>>>> index 31d9c39f14ab..f1b89bc63df6 100644
>>>>> --- a/drivers/platform/x86/uniwill/uniwill-wmi.c
>>>>> +++ b/drivers/platform/x86/uniwill/uniwill-wmi.c
>>>>> @@ -48,6 +48,7 @@ int devm_uniwill_wmi_register_notifier(struct device 
>>>>> *dev, struct notifier_block
>>>>>   static void uniwill_wmi_notify(struct wmi_device *wdev, union 
>>>>> acpi_object *obj)
>>>>>   {
>>>>>       u32 value;
>>>>> +    int ret;
>>>>>         if (obj->type != ACPI_TYPE_INTEGER)
>>>>>           return;
>>>>> @@ -56,7 +57,9 @@ static void uniwill_wmi_notify(struct wmi_device *wdev, 
>>>>> union acpi_object *obj)
>>>>>         dev_dbg(&wdev->dev, "Received WMI event %u\n", value);
>>>>>   - blocking_notifier_call_chain(&uniwill_wmi_chain_head, value, NULL);
>>>>> +    ret = blocking_notifier_call_chain(&uniwill_wmi_chain_head, value, 
>>>>> NULL);
>>>>> +    if (notifier_to_errno(ret) < 0)
>>>>> +        dev_err(&wdev->dev, "Failed to handle event %u\n", value);
>>>>>   }
>>>>>     /*
>>>>>
>>>>
>>>
>>

  reply	other threads:[~2026-05-11 17:40 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260417050912.5582-1-W_Armin@gmx.de>
     [not found] ` <20260417050912.5582-8-W_Armin@gmx.de>
     [not found]   ` <e71bdb43-7fcf-519c-c25f-f59cf1489043@linux.intel.com>
     [not found]     ` <6570157d-d431-4275-9e73-d09bb1b344c8@gmx.de>
     [not found]       ` <c475d7de-48c8-4fe0-b414-2d32988f52dd@tuxedocomputers.com>
2026-05-06  7:47         ` [PATCH v2 7/7] platform/x86: uniwill-laptop: Add support for battery charge modes Armin Wolf
2026-05-11 17:40           ` Werner Sembach [this message]
     [not found] ` <20260417050912.5582-2-W_Armin@gmx.de>
     [not found]   ` <9cc1d286-f41a-c920-aaad-1c24c4e6f2f7@linux.intel.com>
     [not found]     ` <903a013e-a3fb-49ea-a6f9-ad6577d57a44@gmx.de>
2026-05-06 13:42       ` [PATCH v2 1/7] platform/x86: uniwill-laptop: Properly initialize charging threshold Ilpo Järvinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0526a23d-5922-4e4a-b8fe-faeb36bce653@tuxedocomputers.com \
    --to=wse@tuxedocomputers.com \
    --cc=W_Armin@gmx.de \
    --cc=hansg@kernel.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox