lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d719d78f-5466-4d3f-a43c-dfd4c2c0190a@gmx.de>
Date: Tue, 4 Nov 2025 21:00:07 +0100
From: Armin Wolf <W_Armin@....de>
To: Antheas Kapenekakis <lkml@...heas.dev>
Cc: platform-driver-x86@...r.kernel.org, linux-kernel@...r.kernel.org,
 linux-hwmon@...r.kernel.org, Hans de Goede <hansg@...nel.org>,
 Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>,
 Derek John Clark <derekjohn.clark@...il.com>,
 Joaquín Ignacio Aramendía <samsagax@...il.com>,
 Jean Delvare <jdelvare@...e.com>, Guenter Roeck <linux@...ck-us.net>
Subject: Re: [PATCH v3 3/6] platform/x86: ayaneo-ec: Add charge control
 support

Am 02.11.25 um 19:37 schrieb Antheas Kapenekakis:

> On Sun, 2 Nov 2025 at 19:26, Armin Wolf <W_Armin@....de> wrote:
>> Am 31.10.25 um 17:36 schrieb Antheas Kapenekakis:
>>
>>> Ayaneo devices support charge inhibition via the EC. This inhibition
>>> only works while the device is powered on, and resets between restarts.
>>> However, it is maintained across suspend/resume cycles.
>>>
>>> The EC does not support charge threshold control. Instead, userspace
>>> software on Windows manually toggles charge inhibition depending on
>>> battery level.
>>>
>>> Reviewed-by: Armin Wolf <W_Armin@....de>
>>> Signed-off-by: Antheas Kapenekakis <lkml@...heas.dev>
>>> ---
>>>    drivers/platform/x86/Kconfig     |   1 +
>>>    drivers/platform/x86/ayaneo-ec.c | 112 +++++++++++++++++++++++++++++++
>>>    2 files changed, 113 insertions(+)
>>>
>>> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
>>> index b3beaff4b03a..a45449ae83f8 100644
>>> --- a/drivers/platform/x86/Kconfig
>>> +++ b/drivers/platform/x86/Kconfig
>>> @@ -319,6 +319,7 @@ config ASUS_TF103C_DOCK
>>>    config AYANEO_EC
>>>        tristate "Ayaneo EC platform control"
>>>        depends on ACPI_EC
>>> +     depends on ACPI_BATTERY
>>>        depends on HWMON
>>>        help
>>>          Enables support for the platform EC of Ayaneo devices. This
>>> diff --git a/drivers/platform/x86/ayaneo-ec.c b/drivers/platform/x86/ayaneo-ec.c
>>> index 108a23458a4f..697bb053a7d6 100644
>>> --- a/drivers/platform/x86/ayaneo-ec.c
>>> +++ b/drivers/platform/x86/ayaneo-ec.c
>>> @@ -15,6 +15,8 @@
>>>    #include <linux/kernel.h>
>>>    #include <linux/module.h>
>>>    #include <linux/platform_device.h>
>>> +#include <linux/power_supply.h>
>>> +#include <acpi/battery.h>
>>>
>>>    #define AYANEO_PWM_ENABLE_REG        0x4A
>>>    #define AYANEO_PWM_REG               0x4B
>>> @@ -23,17 +25,27 @@
>>>
>>>    #define AYANEO_FAN_REG               0x76
>>>
>>> +#define EC_CHARGE_CONTROL_BEHAVIOURS                         \
>>> +     (BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) |           \
>>> +      BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE))
>> I think POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE_AWAKE would be more suitable here.
> Charge inhibition works during sleep.

I must have suffered from a misunderstanding then. In this case:

Reviewed-by: Armin Wolf <W_Armin@....de>

>> Other than that:
>> Reviewed-by: Armin Wolf <W_Armin@....de>
>>
>>> +#define AYANEO_CHARGE_REG            0x1e
>>> +#define AYANEO_CHARGE_VAL_AUTO               0xaa
>>> +#define AYANEO_CHARGE_VAL_INHIBIT    0x55
>>> +
>>>    struct ayaneo_ec_quirk {
>>>        bool has_fan_control;
>>> +     bool has_charge_control;
>>>    };
>>>
>>>    struct ayaneo_ec_platform_data {
>>>        struct platform_device *pdev;
>>>        struct ayaneo_ec_quirk *quirks;
>>> +     struct acpi_battery_hook battery_hook;
>>>    };
>>>
>>>    static const struct ayaneo_ec_quirk quirk_ayaneo3 = {
>>>        .has_fan_control = true,
>>> +     .has_charge_control = true,
>>>    };
>>>
>>>    static const struct dmi_system_id dmi_table[] = {
>>> @@ -164,11 +176,102 @@ static const struct hwmon_chip_info ayaneo_ec_chip_info = {
>>>        .info = ayaneo_ec_sensors,
>>>    };
>>>
>>> +static int ayaneo_psy_ext_get_prop(struct power_supply *psy,
>>> +                                const struct power_supply_ext *ext,
>>> +                                void *data,
>>> +                                enum power_supply_property psp,
>>> +                                union power_supply_propval *val)
>>> +{
>>> +     int ret;
>>> +     u8 tmp;
>>> +
>>> +     switch (psp) {
>>> +     case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
>>> +             ret = ec_read(AYANEO_CHARGE_REG, &tmp);
>>> +             if (ret)
>>> +                     return ret;
>>> +
>>> +             if (tmp == AYANEO_CHARGE_VAL_INHIBIT)
>>> +                     val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
>>> +             else
>>> +                     val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
>>> +             return 0;
>>> +     default:
>>> +             return -EINVAL;
>>> +     }
>>> +}
>>> +
>>> +static int ayaneo_psy_ext_set_prop(struct power_supply *psy,
>>> +                                const struct power_supply_ext *ext,
>>> +                                void *data,
>>> +                                enum power_supply_property psp,
>>> +                                const union power_supply_propval *val)
>>> +{
>>> +     u8 raw_val;
>>> +
>>> +     switch (psp) {
>>> +     case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
>>> +             switch (val->intval) {
>>> +             case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
>>> +                     raw_val = AYANEO_CHARGE_VAL_AUTO;
>>> +                     break;
>>> +             case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
>>> +                     raw_val = AYANEO_CHARGE_VAL_INHIBIT;
>>> +                     break;
>>> +             default:
>>> +                     return -EINVAL;
>>> +             }
>>> +             return ec_write(AYANEO_CHARGE_REG, raw_val);
>>> +     default:
>>> +             return -EINVAL;
>>> +     }
>>> +}
>>> +
>>> +static int ayaneo_psy_prop_is_writeable(struct power_supply *psy,
>>> +                                     const struct power_supply_ext *ext,
>>> +                                     void *data,
>>> +                                     enum power_supply_property psp)
>>> +{
>>> +     return true;
>>> +}
>>> +
>>> +static const enum power_supply_property ayaneo_psy_ext_props[] = {
>>> +     POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
>>> +};
>>> +
>>> +static const struct power_supply_ext ayaneo_psy_ext = {
>>> +     .name                   = "ayaneo-charge-control",
>>> +     .properties             = ayaneo_psy_ext_props,
>>> +     .num_properties         = ARRAY_SIZE(ayaneo_psy_ext_props),
>>> +     .charge_behaviours      = EC_CHARGE_CONTROL_BEHAVIOURS,
>>> +     .get_property           = ayaneo_psy_ext_get_prop,
>>> +     .set_property           = ayaneo_psy_ext_set_prop,
>>> +     .property_is_writeable  = ayaneo_psy_prop_is_writeable,
>>> +};
>>> +
>>> +static int ayaneo_add_battery(struct power_supply *battery,
>>> +                           struct acpi_battery_hook *hook)
>>> +{
>>> +     struct ayaneo_ec_platform_data *data =
>>> +             container_of(hook, struct ayaneo_ec_platform_data, battery_hook);
>>> +
>>> +     return power_supply_register_extension(battery, &ayaneo_psy_ext,
>>> +                                            &data->pdev->dev, NULL);
>>> +}
>>> +
>>> +static int ayaneo_remove_battery(struct power_supply *battery,
>>> +                              struct acpi_battery_hook *hook)
>>> +{
>>> +     power_supply_unregister_extension(battery, &ayaneo_psy_ext);
>>> +     return 0;
>>> +}
>>> +
>>>    static int ayaneo_ec_probe(struct platform_device *pdev)
>>>    {
>>>        const struct dmi_system_id *dmi_entry;
>>>        struct ayaneo_ec_platform_data *data;
>>>        struct device *hwdev;
>>> +     int ret;
>>>
>>>        dmi_entry = dmi_first_match(dmi_table);
>>>        if (!dmi_entry)
>>> @@ -189,6 +292,15 @@ static int ayaneo_ec_probe(struct platform_device *pdev)
>>>                        return PTR_ERR(hwdev);
>>>        }
>>>
>>> +     if (data->quirks->has_charge_control) {
>>> +             data->battery_hook.add_battery = ayaneo_add_battery;
>>> +             data->battery_hook.remove_battery = ayaneo_remove_battery;
>>> +             data->battery_hook.name = "Ayaneo Battery";
>>> +             ret = devm_battery_hook_register(&pdev->dev, &data->battery_hook);
>>> +             if (ret)
>>> +                     return ret;
>>> +     }
>>> +
>>>        return 0;
>>>    }
>>>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ