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: <9cc4868f-98c3-4f5a-a252-a9d00bdc8d87@gmx.de>
Date: Fri, 5 Sep 2025 20:54:16 +0200
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 v1 3/5] platform/x86: ayaneo-ec: Add charge control
 support

Am 22.08.25 um 23:04 schrieb Antheas Kapenekakis:

> On Fri, 22 Aug 2025 at 14:38, Armin Wolf <W_Armin@....de> wrote:
>> Am 20.08.25 um 18:06 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.
>> Does this include hibernation?
> No. S4/S5 reset the state. Can you give a reference for a regmap
> implementation? A hibernation hook would be a nice to have. Although I
> am not sure how I feel about restoring the fan speed after
> hibernation. It seems dangerous.

Take a look at this patch series: https://lore.kernel.org/platform-driver-x86/20250803210157.8185-1-W_Armin@gmx.de

Restoring the fan speed after hibernation should be OK as long as you also restore the other fan control settings.
This should be safe as long as you can test the driver on real hardware.

Thanks,
Armin Wolf

>> Thanks,
>> Armin Wolf
>>
>>> The EC does not support charge threshold control. Instead, userspace
>>> software on Windows manually toggles charge inhibition depending on
>>> battery level.
>>>
>>> Signed-off-by: Antheas Kapenekakis <lkml@...heas.dev>
>>> ---
>>>    drivers/platform/x86/Kconfig     |   1 +
>>>    drivers/platform/x86/ayaneo-ec.c | 111 +++++++++++++++++++++++++++++++
>>>    2 files changed, 112 insertions(+)
>>>
>>> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
>>> index 0a7ca2c78456..c871a722e5ef 100644
>>> --- a/drivers/platform/x86/Kconfig
>>> +++ b/drivers/platform/x86/Kconfig
>>> @@ -308,6 +308,7 @@ config AYANEO_EC
>>>        tristate "Ayaneo EC platform control"
>>>        depends on X86
>>>        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 8b1902706b81..a4bdc6ae7af7 100644
>>> --- a/drivers/platform/x86/ayaneo-ec.c
>>> +++ b/drivers/platform/x86/ayaneo-ec.c
>>> @@ -14,6 +14,7 @@
>>>    #include <linux/kernel.h>
>>>    #include <linux/module.h>
>>>    #include <linux/platform_device.h>
>>> +#include <acpi/battery.h>
>>>
>>>    #define AYANEO_PWM_ENABLE_REG        0x4A
>>>    #define AYANEO_PWM_REG               0x4B
>>> @@ -22,17 +23,27 @@
>>>
>>>    #define AYANEO_FAN_REG               0x76
>>>
>>> +#define EC_CHARGE_CONTROL_BEHAVIOURS                         \
>>> +     (BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) |           \
>>> +      BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE))
>>> +#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 ayaneo3 = {
>>>        .has_fan_control = true,
>>> +     .has_charge_control = true,
>>>    };
>>>
>>>    static const struct dmi_system_id dmi_table[] = {
>>> @@ -159,11 +170,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)
>>> @@ -184,6 +286,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