Hi, On Fri, Jan 02, 2026 at 07:00:32PM +0100, Josua Mayer wrote: > Implement a simple battery driver for monitoring voltage with the > netronix embedded controller found in certain ebook readers. > > Signed-off-by: Josua Mayer > --- > drivers/power/supply/Kconfig | 9 ++++ > drivers/power/supply/Makefile | 1 + > drivers/power/supply/ntxec-battery.c | 101 +++++++++++++++++++++++++++++++++++ That's indeed simple :) > 3 files changed, 111 insertions(+) > > diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig > index 92f9f7aae92f..0f944c10e50b 100644 > --- a/drivers/power/supply/Kconfig > +++ b/drivers/power/supply/Kconfig > @@ -1132,4 +1132,13 @@ config FUEL_GAUGE_MM8013 > the state of charge, temperature, cycle count, actual and design > capacity, etc. > > +config BATTERY_NTXEC > + tristate "Battery driver for Netronix embedded controller" > + depends on MFD_NTXEC You can add "|| COMPILE_TEST" > + help > + Say yes here to enable netronix ec battery monitoring driver. > + It enables the monitoring battery voltage on certain e-book readers > + using an embedded controller by ODM Netronix. Battery design > + characteristics are read from device-tree if available. > + > endif # POWER_SUPPLY > diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile > index 4b79d5abc49a..db6fc815f9da 100644 > --- a/drivers/power/supply/Makefile > +++ b/drivers/power/supply/Makefile > @@ -128,3 +128,4 @@ obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o > obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o > obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_smbx.o > obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o > +obj-$(CONFIG_BATTERY_NTXEC) += ntxec-battery.o > diff --git a/drivers/power/supply/ntxec-battery.c b/drivers/power/supply/ntxec-battery.c > new file mode 100644 > index 000000000000..f49f0966d18d > --- /dev/null > +++ b/drivers/power/supply/ntxec-battery.c > @@ -0,0 +1,101 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * The Netronix embedded controller is a microcontroller found in some > + * e-book readers designed by the original design manufacturer Netronix, Inc. > + * It contains RTC, battery monitoring, system power management, and PWM > + * functionality. > + * > + * This driver implements battery monitoring. > + * > + * Copyright 2021 Josua Mayer > + */ > + > +#include ^ you probably don't need this with my comments down below :) > +#include > +#include > +#include > +#include > +#include > + > +static const enum power_supply_property ntxec_battery_properties[] = { > + POWER_SUPPLY_PROP_VOLTAGE_NOW, > +}; > + > +struct ntxec_battery { > + struct ntxec *ec; > +}; Store the regmap instead of the ec. You don't need anything else. > +#define NTXEC_REG_READ_BATTERY 0x41 > + > +static int ntxec_battery_get_property(struct power_supply *psy, > + enum power_supply_property psp, > + union power_supply_propval *val) > +{ > + struct ntxec_battery *priv = power_supply_get_drvdata(psy); > + int ret; > + unsigned int value; > + > + switch (psp) { > + case POWER_SUPPLY_PROP_VOLTAGE_NOW: > + ret = regmap_read(priv->ec->regmap, NTXEC_REG_READ_BATTERY, &value); > + if (ret < 0) > + return ret; > + > + /* ec value to microvolt conversion: > + * vendor kernel source suggests linear behaviour from 3V to 4.2V > + * with readings 767 to 1023; each increment represents 4687,5uV. 4687.5uV ? > + * adjust 3V boundary slightly to report exactly 4.2V when full. > + */ > + val->intval = 2999872 + (value - 767) * 4688; > + break; > + default: > + dev_err(&psy->dev, "%s: invalid property %u\n", __func__, psp); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static const struct power_supply_desc ntxec_battery_desc = { > + .name = "ec-battery", > + .type = POWER_SUPPLY_TYPE_BATTERY, > + .properties = ntxec_battery_properties, > + .get_property = ntxec_battery_get_property, > + .num_properties = ARRAY_SIZE(ntxec_battery_properties), > +}; > + > +static int ntxec_battery_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct ntxec *ec = dev_get_drvdata(dev->parent); Based on the regmap comment above, I think you can just do the following and completley avoid 'struct ntxec' (please test): struct regmap *regmap = dev_get_regmap(dev->parent, NULL); > + struct power_supply_config psy_cfg = {}; > + struct ntxec_battery *priv; > + struct power_supply *psy; > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + priv->ec = ec; > + psy_cfg.drv_data = priv; > + psy_cfg.fwnode = dev_fwnode(dev->parent); > + psy_cfg.no_wakeup_source = true; > + psy = devm_power_supply_register(dev, &ntxec_battery_desc, &psy_cfg); > + if (IS_ERR(psy)) > + return PTR_ERR(psy); > + > + return 0; > +} > + > +static struct platform_driver ntxec_battery_driver = { > + .driver = { > + .name = "ntxec-battery", > + }, > + .probe = ntxec_battery_probe, > +}; > +module_platform_driver(ntxec_battery_driver); > + > +MODULE_AUTHOR("Josua Mayer "); > +MODULE_DESCRIPTION("Battery driver for Netronix EC"); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("platform:ntxec-battery"); I know there are a bunch of wrong examples in my subsystem, but the proper way to do this is to drop this alias and instead add a platform_device_id table together with MODULE_DEVICE_TABLE(platform, ...). See for example cros_peripheral_charger.c Greetings, -- Sebastian