The Ayaneo 3 features hot-swappable controller modules. The ejection
and management is done through HID. However, after ejecting the modules,
the controller needs to be power cycled via the EC to re-initialize.
For this, the EC provides a variable that holds whether the left or
right modules are connected, and a power control register to turn
the controller on or off. After ejecting the modules, the controller
should be turned off. Then, after both modules are reinserted,
the controller may be powered on again to re-initialize.
This patch introduces two new firmware attributes:
- `controller_modules`: a read-only attribute that indicates whether
the left and right modules are connected (none, left, right, both).
- `controller_power`: a read-write attribute that allows the user
to turn the controller on or off (with 'on'/'off').
Therefore, after ejection is complete, userspace can power off the
controller, then wait until both modules have been reinserted
(`controller_modules` will return 'both') to turn on the controller.
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/platform/x86/ayaneo-ec.c | 235 ++++++++++++++++++++++++++++++-
1 file changed, 234 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/ayaneo-ec.c b/drivers/platform/x86/ayaneo-ec.c
index a4bdc6ae7af7..eb7f9ae03b4f 100644
--- a/drivers/platform/x86/ayaneo-ec.c
+++ b/drivers/platform/x86/ayaneo-ec.c
@@ -16,6 +16,10 @@
#include <linux/platform_device.h>
#include <acpi/battery.h>
+#include "firmware_attributes_class.h"
+
+#define DRIVER_NAME "ayaneo-ec"
+
#define AYANEO_PWM_ENABLE_REG 0x4A
#define AYANEO_PWM_REG 0x4B
#define AYANEO_PWM_MODE_AUTO 0x00
@@ -30,20 +34,60 @@
#define AYANEO_CHARGE_VAL_AUTO 0xaa
#define AYANEO_CHARGE_VAL_INHIBIT 0x55
+#define AYANEO_POWER_REG 0x2d
+#define AYANEO_POWER_OFF 0xfe
+#define AYANEO_POWER_ON 0xff
+#define AYANEO_MODULE_REG 0x2f
+#define AYANEO_MODULE_LEFT BIT(0)
+#define AYANEO_MODULE_RIGHT BIT(1)
+
+enum ayaneo_fw_attr_id {
+ AYANEO_ATTR_CONTROLLER_MODULES,
+ AYANEO_ATTR_CONTROLLER_POWER,
+};
+
+static const char *const ayaneo_fw_attr_name[] = {
+ [AYANEO_ATTR_CONTROLLER_MODULES] = "controller_modules",
+ [AYANEO_ATTR_CONTROLLER_POWER] = "controller_power",
+};
+
+static const char *const ayaneo_fw_attr_desc[] = {
+ [AYANEO_ATTR_CONTROLLER_MODULES] =
+ "Which controller Magic Modules are connected (none, left, right, both)",
+ [AYANEO_ATTR_CONTROLLER_POWER] = "Controller power state (on, off)",
+};
+
+#define AYANEO_ATTR_ENUM_MAX_ATTRS 7
+#define AYANEO_ATTR_LANGUAGE_CODE "en_US.UTF-8"
+
struct ayaneo_ec_quirk {
bool has_fan_control;
bool has_charge_control;
+ bool has_magic_modules;
+ bool has_controller_power;
};
struct ayaneo_ec_platform_data {
struct platform_device *pdev;
struct ayaneo_ec_quirk *quirks;
struct acpi_battery_hook battery_hook;
+ struct device *fw_attrs_dev;
+ struct kset *fw_attrs_kset;
+};
+
+struct ayaneo_fw_attr {
+ struct ayaneo_ec_platform_data *data;
+ enum ayaneo_fw_attr_id fw_attr_id;
+ struct attribute_group attr_group;
+ struct kobj_attribute display_name;
+ struct kobj_attribute current_value;
};
static const struct ayaneo_ec_quirk ayaneo3 = {
.has_fan_control = true,
.has_charge_control = true,
+ .has_magic_modules = true,
+ .has_controller_power = true,
};
static const struct dmi_system_id dmi_table[] = {
@@ -260,6 +304,159 @@ static int ayaneo_remove_battery(struct power_supply *battery,
return 0;
}
+static void ayaneo_kset_unregister(void *data)
+{
+ struct kset *kset = data;
+
+ kset_unregister(kset);
+}
+
+static void ayaneo_fw_attrs_dev_unregister(void *data)
+{
+ struct device *fw_attrs_dev = data;
+
+ device_unregister(fw_attrs_dev);
+}
+
+static ssize_t display_name_language_code_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%s\n", AYANEO_ATTR_LANGUAGE_CODE);
+}
+
+static struct kobj_attribute fw_attr_display_name_language_code =
+ __ATTR_RO(display_name_language_code);
+
+static ssize_t display_name_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ayaneo_fw_attr *fw_attr =
+ container_of(attr, struct ayaneo_fw_attr, display_name);
+
+ return sysfs_emit(buf, "%s\n", ayaneo_fw_attr_desc[fw_attr->fw_attr_id]);
+}
+
+static ssize_t current_value_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ayaneo_fw_attr *fw_attr =
+ container_of(attr, struct ayaneo_fw_attr, current_value);
+ bool left, right;
+ char *out;
+ int ret;
+ u8 tmp;
+
+ switch (fw_attr->fw_attr_id) {
+ case AYANEO_ATTR_CONTROLLER_MODULES:
+ ret = ec_read(AYANEO_MODULE_REG, &tmp);
+ if (ret)
+ return ret;
+ left = !(tmp & AYANEO_MODULE_LEFT);
+ right = !(tmp & AYANEO_MODULE_RIGHT);
+
+ if (left && right)
+ out = "both";
+ else if (left)
+ out = "left";
+ else if (right)
+ out = "right";
+ else
+ out = "none";
+
+ return sysfs_emit(buf, "%s\n", out);
+ case AYANEO_ATTR_CONTROLLER_POWER:
+ ret = ec_read(AYANEO_POWER_REG, &tmp);
+ if (ret)
+ return ret;
+
+ if (tmp == AYANEO_POWER_OFF)
+ out = "off";
+ else
+ out = "on";
+
+ return sysfs_emit(buf, "%s\n", out);
+ }
+ return -EINVAL;
+}
+
+static ssize_t current_value_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct ayaneo_fw_attr *fw_attr =
+ container_of(attr, struct ayaneo_fw_attr, current_value);
+ int ret;
+
+ switch (fw_attr->fw_attr_id) {
+ case AYANEO_ATTR_CONTROLLER_POWER:
+ if (sysfs_streq(buf, "on"))
+ ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_ON);
+ else if (sysfs_streq(buf, "off"))
+ ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF);
+ if (ret)
+ return ret;
+ return count;
+ case AYANEO_ATTR_CONTROLLER_MODULES:
+ return -EINVAL;
+ }
+ return -EINVAL;
+}
+
+static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "string\n");
+}
+
+static struct kobj_attribute fw_attr_type_string = {
+ .attr = { .name = "type", .mode = 0444 },
+ .show = type_show,
+};
+
+static int ayaneo_fw_attr_init(struct ayaneo_ec_platform_data *data,
+ const enum ayaneo_fw_attr_id fw_attr_id,
+ bool read_only)
+{
+ struct ayaneo_fw_attr *fw_attr;
+ struct attribute **attrs;
+ int idx = 0;
+
+ fw_attr = devm_kzalloc(&data->pdev->dev, sizeof(*fw_attr), GFP_KERNEL);
+ if (!fw_attr)
+ return -ENOMEM;
+
+ attrs = devm_kcalloc(&data->pdev->dev, AYANEO_ATTR_ENUM_MAX_ATTRS + 1,
+ sizeof(*attrs), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ fw_attr->data = data;
+ fw_attr->fw_attr_id = fw_attr_id;
+ fw_attr->attr_group.name = ayaneo_fw_attr_name[fw_attr_id];
+ fw_attr->attr_group.attrs = attrs;
+
+ attrs[idx++] = &fw_attr_type_string.attr;
+ attrs[idx++] = &fw_attr_display_name_language_code.attr;
+
+ sysfs_attr_init(&fw_attr->display_name.attr);
+ fw_attr->display_name.attr.name = "display_name";
+ fw_attr->display_name.attr.mode = 0444;
+ fw_attr->display_name.show = display_name_show;
+ attrs[idx++] = &fw_attr->display_name.attr;
+
+ sysfs_attr_init(&fw_attr->current_value.attr);
+ fw_attr->current_value.attr.name = "current_value";
+ fw_attr->current_value.attr.mode = read_only ? 0444 : 0644;
+ fw_attr->current_value.show = current_value_show;
+ fw_attr->current_value.store = current_value_store;
+ attrs[idx++] = &fw_attr->current_value.attr;
+
+ attrs[idx] = NULL;
+ return sysfs_create_group(&data->fw_attrs_kset->kobj,
+ &fw_attr->attr_group);
+}
+
static int ayaneo_ec_probe(struct platform_device *pdev)
{
const struct dmi_system_id *dmi_entry;
@@ -295,12 +492,48 @@ static int ayaneo_ec_probe(struct platform_device *pdev)
return ret;
}
+ if (data->quirks->has_magic_modules || data->quirks->has_controller_power) {
+ data->fw_attrs_dev = device_create(&firmware_attributes_class, NULL,
+ MKDEV(0, 0), NULL, "%s",
+ DRIVER_NAME);
+ if (IS_ERR(data->fw_attrs_dev))
+ return PTR_ERR(data->fw_attrs_dev);
+
+ ret = devm_add_action_or_reset(&data->pdev->dev,
+ ayaneo_fw_attrs_dev_unregister,
+ data->fw_attrs_dev);
+ if (ret)
+ return ret;
+
+ data->fw_attrs_kset = kset_create_and_add("attributes", NULL,
+ &data->fw_attrs_dev->kobj);
+ if (!data->fw_attrs_kset)
+ return -ENOMEM;
+
+ ret = devm_add_action_or_reset(&data->pdev->dev, ayaneo_kset_unregister,
+ data->fw_attrs_kset);
+
+ if (data->quirks->has_magic_modules) {
+ ret = ayaneo_fw_attr_init(
+ data, AYANEO_ATTR_CONTROLLER_MODULES, true);
+ if (ret)
+ return ret;
+ }
+
+ if (data->quirks->has_controller_power) {
+ ret = ayaneo_fw_attr_init(
+ data, AYANEO_ATTR_CONTROLLER_POWER, false);
+ if (ret)
+ return ret;
+ }
+ }
+
return 0;
}
static struct platform_driver ayaneo_platform_driver = {
.driver = {
- .name = "ayaneo-ec",
+ .name = DRIVER_NAME,
},
.probe = ayaneo_ec_probe,
};
--
2.50.1
Am 20.08.25 um 18:06 schrieb Antheas Kapenekakis: > The Ayaneo 3 features hot-swappable controller modules. The ejection > and management is done through HID. However, after ejecting the modules, > the controller needs to be power cycled via the EC to re-initialize. > > For this, the EC provides a variable that holds whether the left or > right modules are connected, and a power control register to turn > the controller on or off. After ejecting the modules, the controller > should be turned off. Then, after both modules are reinserted, > the controller may be powered on again to re-initialize. > > This patch introduces two new firmware attributes: > - `controller_modules`: a read-only attribute that indicates whether > the left and right modules are connected (none, left, right, both). > - `controller_power`: a read-write attribute that allows the user > to turn the controller on or off (with 'on'/'off'). > > Therefore, after ejection is complete, userspace can power off the > controller, then wait until both modules have been reinserted > (`controller_modules` will return 'both') to turn on the controller. I do not think that those controls should be exposed as firmware attributes, as they are live values not persistent across power cycles. Better use sysfs attributes instead. Thanks, Armin Wolf > > Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev> > --- > drivers/platform/x86/ayaneo-ec.c | 235 ++++++++++++++++++++++++++++++- > 1 file changed, 234 insertions(+), 1 deletion(-) > > diff --git a/drivers/platform/x86/ayaneo-ec.c b/drivers/platform/x86/ayaneo-ec.c > index a4bdc6ae7af7..eb7f9ae03b4f 100644 > --- a/drivers/platform/x86/ayaneo-ec.c > +++ b/drivers/platform/x86/ayaneo-ec.c > @@ -16,6 +16,10 @@ > #include <linux/platform_device.h> > #include <acpi/battery.h> > > +#include "firmware_attributes_class.h" > + > +#define DRIVER_NAME "ayaneo-ec" > + > #define AYANEO_PWM_ENABLE_REG 0x4A > #define AYANEO_PWM_REG 0x4B > #define AYANEO_PWM_MODE_AUTO 0x00 > @@ -30,20 +34,60 @@ > #define AYANEO_CHARGE_VAL_AUTO 0xaa > #define AYANEO_CHARGE_VAL_INHIBIT 0x55 > > +#define AYANEO_POWER_REG 0x2d > +#define AYANEO_POWER_OFF 0xfe > +#define AYANEO_POWER_ON 0xff > +#define AYANEO_MODULE_REG 0x2f > +#define AYANEO_MODULE_LEFT BIT(0) > +#define AYANEO_MODULE_RIGHT BIT(1) > + > +enum ayaneo_fw_attr_id { > + AYANEO_ATTR_CONTROLLER_MODULES, > + AYANEO_ATTR_CONTROLLER_POWER, > +}; > + > +static const char *const ayaneo_fw_attr_name[] = { > + [AYANEO_ATTR_CONTROLLER_MODULES] = "controller_modules", > + [AYANEO_ATTR_CONTROLLER_POWER] = "controller_power", > +}; > + > +static const char *const ayaneo_fw_attr_desc[] = { > + [AYANEO_ATTR_CONTROLLER_MODULES] = > + "Which controller Magic Modules are connected (none, left, right, both)", > + [AYANEO_ATTR_CONTROLLER_POWER] = "Controller power state (on, off)", > +}; > + > +#define AYANEO_ATTR_ENUM_MAX_ATTRS 7 > +#define AYANEO_ATTR_LANGUAGE_CODE "en_US.UTF-8" > + > struct ayaneo_ec_quirk { > bool has_fan_control; > bool has_charge_control; > + bool has_magic_modules; > + bool has_controller_power; > }; > > struct ayaneo_ec_platform_data { > struct platform_device *pdev; > struct ayaneo_ec_quirk *quirks; > struct acpi_battery_hook battery_hook; > + struct device *fw_attrs_dev; > + struct kset *fw_attrs_kset; > +}; > + > +struct ayaneo_fw_attr { > + struct ayaneo_ec_platform_data *data; > + enum ayaneo_fw_attr_id fw_attr_id; > + struct attribute_group attr_group; > + struct kobj_attribute display_name; > + struct kobj_attribute current_value; > }; > > static const struct ayaneo_ec_quirk ayaneo3 = { > .has_fan_control = true, > .has_charge_control = true, > + .has_magic_modules = true, > + .has_controller_power = true, > }; > > static const struct dmi_system_id dmi_table[] = { > @@ -260,6 +304,159 @@ static int ayaneo_remove_battery(struct power_supply *battery, > return 0; > } > > +static void ayaneo_kset_unregister(void *data) > +{ > + struct kset *kset = data; > + > + kset_unregister(kset); > +} > + > +static void ayaneo_fw_attrs_dev_unregister(void *data) > +{ > + struct device *fw_attrs_dev = data; > + > + device_unregister(fw_attrs_dev); > +} > + > +static ssize_t display_name_language_code_show(struct kobject *kobj, > + struct kobj_attribute *attr, > + char *buf) > +{ > + return sysfs_emit(buf, "%s\n", AYANEO_ATTR_LANGUAGE_CODE); > +} > + > +static struct kobj_attribute fw_attr_display_name_language_code = > + __ATTR_RO(display_name_language_code); > + > +static ssize_t display_name_show(struct kobject *kobj, > + struct kobj_attribute *attr, char *buf) > +{ > + struct ayaneo_fw_attr *fw_attr = > + container_of(attr, struct ayaneo_fw_attr, display_name); > + > + return sysfs_emit(buf, "%s\n", ayaneo_fw_attr_desc[fw_attr->fw_attr_id]); > +} > + > +static ssize_t current_value_show(struct kobject *kobj, > + struct kobj_attribute *attr, char *buf) > +{ > + struct ayaneo_fw_attr *fw_attr = > + container_of(attr, struct ayaneo_fw_attr, current_value); > + bool left, right; > + char *out; > + int ret; > + u8 tmp; > + > + switch (fw_attr->fw_attr_id) { > + case AYANEO_ATTR_CONTROLLER_MODULES: > + ret = ec_read(AYANEO_MODULE_REG, &tmp); > + if (ret) > + return ret; > + left = !(tmp & AYANEO_MODULE_LEFT); > + right = !(tmp & AYANEO_MODULE_RIGHT); > + > + if (left && right) > + out = "both"; > + else if (left) > + out = "left"; > + else if (right) > + out = "right"; > + else > + out = "none"; > + > + return sysfs_emit(buf, "%s\n", out); > + case AYANEO_ATTR_CONTROLLER_POWER: > + ret = ec_read(AYANEO_POWER_REG, &tmp); > + if (ret) > + return ret; > + > + if (tmp == AYANEO_POWER_OFF) > + out = "off"; > + else > + out = "on"; > + > + return sysfs_emit(buf, "%s\n", out); > + } > + return -EINVAL; > +} > + > +static ssize_t current_value_store(struct kobject *kobj, > + struct kobj_attribute *attr, const char *buf, > + size_t count) > +{ > + struct ayaneo_fw_attr *fw_attr = > + container_of(attr, struct ayaneo_fw_attr, current_value); > + int ret; > + > + switch (fw_attr->fw_attr_id) { > + case AYANEO_ATTR_CONTROLLER_POWER: > + if (sysfs_streq(buf, "on")) > + ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_ON); > + else if (sysfs_streq(buf, "off")) > + ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF); > + if (ret) > + return ret; > + return count; > + case AYANEO_ATTR_CONTROLLER_MODULES: > + return -EINVAL; > + } > + return -EINVAL; > +} > + > +static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, > + char *buf) > +{ > + return sysfs_emit(buf, "string\n"); > +} > + > +static struct kobj_attribute fw_attr_type_string = { > + .attr = { .name = "type", .mode = 0444 }, > + .show = type_show, > +}; > + > +static int ayaneo_fw_attr_init(struct ayaneo_ec_platform_data *data, > + const enum ayaneo_fw_attr_id fw_attr_id, > + bool read_only) > +{ > + struct ayaneo_fw_attr *fw_attr; > + struct attribute **attrs; > + int idx = 0; > + > + fw_attr = devm_kzalloc(&data->pdev->dev, sizeof(*fw_attr), GFP_KERNEL); > + if (!fw_attr) > + return -ENOMEM; > + > + attrs = devm_kcalloc(&data->pdev->dev, AYANEO_ATTR_ENUM_MAX_ATTRS + 1, > + sizeof(*attrs), GFP_KERNEL); > + if (!attrs) > + return -ENOMEM; > + > + fw_attr->data = data; > + fw_attr->fw_attr_id = fw_attr_id; > + fw_attr->attr_group.name = ayaneo_fw_attr_name[fw_attr_id]; > + fw_attr->attr_group.attrs = attrs; > + > + attrs[idx++] = &fw_attr_type_string.attr; > + attrs[idx++] = &fw_attr_display_name_language_code.attr; > + > + sysfs_attr_init(&fw_attr->display_name.attr); > + fw_attr->display_name.attr.name = "display_name"; > + fw_attr->display_name.attr.mode = 0444; > + fw_attr->display_name.show = display_name_show; > + attrs[idx++] = &fw_attr->display_name.attr; > + > + sysfs_attr_init(&fw_attr->current_value.attr); > + fw_attr->current_value.attr.name = "current_value"; > + fw_attr->current_value.attr.mode = read_only ? 0444 : 0644; > + fw_attr->current_value.show = current_value_show; > + fw_attr->current_value.store = current_value_store; > + attrs[idx++] = &fw_attr->current_value.attr; > + > + attrs[idx] = NULL; > + return sysfs_create_group(&data->fw_attrs_kset->kobj, > + &fw_attr->attr_group); > +} > + > static int ayaneo_ec_probe(struct platform_device *pdev) > { > const struct dmi_system_id *dmi_entry; > @@ -295,12 +492,48 @@ static int ayaneo_ec_probe(struct platform_device *pdev) > return ret; > } > > + if (data->quirks->has_magic_modules || data->quirks->has_controller_power) { > + data->fw_attrs_dev = device_create(&firmware_attributes_class, NULL, > + MKDEV(0, 0), NULL, "%s", > + DRIVER_NAME); > + if (IS_ERR(data->fw_attrs_dev)) > + return PTR_ERR(data->fw_attrs_dev); > + > + ret = devm_add_action_or_reset(&data->pdev->dev, > + ayaneo_fw_attrs_dev_unregister, > + data->fw_attrs_dev); > + if (ret) > + return ret; > + > + data->fw_attrs_kset = kset_create_and_add("attributes", NULL, > + &data->fw_attrs_dev->kobj); > + if (!data->fw_attrs_kset) > + return -ENOMEM; > + > + ret = devm_add_action_or_reset(&data->pdev->dev, ayaneo_kset_unregister, > + data->fw_attrs_kset); > + > + if (data->quirks->has_magic_modules) { > + ret = ayaneo_fw_attr_init( > + data, AYANEO_ATTR_CONTROLLER_MODULES, true); > + if (ret) > + return ret; > + } > + > + if (data->quirks->has_controller_power) { > + ret = ayaneo_fw_attr_init( > + data, AYANEO_ATTR_CONTROLLER_POWER, false); > + if (ret) > + return ret; > + } > + } > + > return 0; > } > > static struct platform_driver ayaneo_platform_driver = { > .driver = { > - .name = "ayaneo-ec", > + .name = DRIVER_NAME, > }, > .probe = ayaneo_ec_probe, > };
Hi Antheas, kernel test robot noticed the following build errors: [auto build test ERROR on c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9] url: https://github.com/intel-lab-lkp/linux/commits/Antheas-Kapenekakis/platform-x86-ayaneo-ec-Add-Ayaneo-Embedded-Controller-platform-driver/20250821-002525 base: c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9 patch link: https://lore.kernel.org/r/20250820160628.99678-5-lkml%40antheas.dev patch subject: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20250821/202508211626.9Cxkta6K-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250821/202508211626.9Cxkta6K-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202508211626.9Cxkta6K-lkp@intel.com/ All errors (new ones prefixed by >>): drivers/platform/x86/ayaneo-ec.c: In function 'ayaneo_ec_probe': >> drivers/platform/x86/ayaneo-ec.c:497:49: error: implicit declaration of function 'MKDEV' [-Werror=implicit-function-declaration] 497 | MKDEV(0, 0), NULL, "%s", | ^~~~~ cc1: some warnings being treated as errors vim +/MKDEV +497 drivers/platform/x86/ayaneo-ec.c 459 460 static int ayaneo_ec_probe(struct platform_device *pdev) 461 { 462 const struct dmi_system_id *dmi_entry; 463 struct ayaneo_ec_platform_data *data; 464 struct device *hwdev; 465 int ret; 466 467 dmi_entry = dmi_first_match(dmi_table); 468 if (!dmi_entry) 469 return -ENODEV; 470 471 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 472 if (!data) 473 return -ENOMEM; 474 475 data->pdev = pdev; 476 data->quirks = dmi_entry->driver_data; 477 platform_set_drvdata(pdev, data); 478 479 if (data->quirks->has_fan_control) { 480 hwdev = devm_hwmon_device_register_with_info( 481 &pdev->dev, "ayaneo_ec", NULL, &ayaneo_ec_chip_info, NULL); 482 if (IS_ERR(hwdev)) 483 return PTR_ERR(hwdev); 484 } 485 486 if (data->quirks->has_charge_control) { 487 data->battery_hook.add_battery = ayaneo_add_battery; 488 data->battery_hook.remove_battery = ayaneo_remove_battery; 489 data->battery_hook.name = "Ayaneo Battery"; 490 ret = devm_battery_hook_register(&pdev->dev, &data->battery_hook); 491 if (ret) 492 return ret; 493 } 494 495 if (data->quirks->has_magic_modules || data->quirks->has_controller_power) { 496 data->fw_attrs_dev = device_create(&firmware_attributes_class, NULL, > 497 MKDEV(0, 0), NULL, "%s", 498 DRIVER_NAME); 499 if (IS_ERR(data->fw_attrs_dev)) 500 return PTR_ERR(data->fw_attrs_dev); 501 502 ret = devm_add_action_or_reset(&data->pdev->dev, 503 ayaneo_fw_attrs_dev_unregister, 504 data->fw_attrs_dev); 505 if (ret) 506 return ret; 507 508 data->fw_attrs_kset = kset_create_and_add("attributes", NULL, 509 &data->fw_attrs_dev->kobj); 510 if (!data->fw_attrs_kset) 511 return -ENOMEM; 512 513 ret = devm_add_action_or_reset(&data->pdev->dev, ayaneo_kset_unregister, 514 data->fw_attrs_kset); 515 516 if (data->quirks->has_magic_modules) { 517 ret = ayaneo_fw_attr_init( 518 data, AYANEO_ATTR_CONTROLLER_MODULES, true); 519 if (ret) 520 return ret; 521 } 522 523 if (data->quirks->has_controller_power) { 524 ret = ayaneo_fw_attr_init( 525 data, AYANEO_ATTR_CONTROLLER_POWER, false); 526 if (ret) 527 return ret; 528 } 529 } 530 531 return 0; 532 } 533 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Hi Antheas, kernel test robot noticed the following build warnings: [auto build test WARNING on c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9] url: https://github.com/intel-lab-lkp/linux/commits/Antheas-Kapenekakis/platform-x86-ayaneo-ec-Add-Ayaneo-Embedded-Controller-platform-driver/20250821-002525 base: c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9 patch link: https://lore.kernel.org/r/20250820160628.99678-5-lkml%40antheas.dev patch subject: [PATCH v1 4/5] platform/x86: ayaneo-ec: Add controller power and modules attributes config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20250821/202508211640.8MtPueLL-lkp@intel.com/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250821/202508211640.8MtPueLL-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202508211640.8MtPueLL-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/platform/x86/ayaneo-ec.c:395:12: warning: variable 'ret' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized] 395 | else if (sysfs_streq(buf, "off")) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/platform/x86/ayaneo-ec.c:397:7: note: uninitialized use occurs here 397 | if (ret) | ^~~ drivers/platform/x86/ayaneo-ec.c:395:8: note: remove the 'if' if its condition is always true 395 | else if (sysfs_streq(buf, "off")) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ 396 | ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF); drivers/platform/x86/ayaneo-ec.c:389:9: note: initialize the variable 'ret' to silence this warning 389 | int ret; | ^ | = 0 1 warning generated. vim +395 drivers/platform/x86/ayaneo-ec.c 382 383 static ssize_t current_value_store(struct kobject *kobj, 384 struct kobj_attribute *attr, const char *buf, 385 size_t count) 386 { 387 struct ayaneo_fw_attr *fw_attr = 388 container_of(attr, struct ayaneo_fw_attr, current_value); 389 int ret; 390 391 switch (fw_attr->fw_attr_id) { 392 case AYANEO_ATTR_CONTROLLER_POWER: 393 if (sysfs_streq(buf, "on")) 394 ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_ON); > 395 else if (sysfs_streq(buf, "off")) 396 ret = ec_write(AYANEO_POWER_REG, AYANEO_POWER_OFF); 397 if (ret) 398 return ret; 399 return count; 400 case AYANEO_ATTR_CONTROLLER_MODULES: 401 return -EINVAL; 402 } 403 return -EINVAL; 404 } 405 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
© 2016 - 2025 Red Hat, Inc.