summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArvid Norlander <lkml@vorpal.se>2022-09-02 20:00:36 +0200
committerHans de Goede <hdegoede@redhat.com>2022-09-09 21:58:16 +0200
commit8ef5db9eb084f6212345a7b09355c78ce05f71e2 (patch)
treefb304614e59cb1f3f223cd30748bc967b4a2c8ec
parentplatform/x86: Battery charge mode in toshiba_acpi (internals) (diff)
downloadlinux-8ef5db9eb084f6212345a7b09355c78ce05f71e2.tar.xz
linux-8ef5db9eb084f6212345a7b09355c78ce05f71e2.zip
platform/x86: Battery charge mode in toshiba_acpi (sysfs)
This commit adds the ACPI battery hook which in turns adds the sysfs entries. Because the Toshiba laptops only support two modes (eco or normal), which in testing correspond to 80% and 100% we simply round to the nearest possible level when set. It is possible that Toshiba laptops other than the Z830 has different set points for the charging. If so, a quirk table could be introduced in the future for this. For now, assume that all laptops that support this feature work the same way. Tested on a Toshiba Satellite Z830. Signed-off-by: Arvid Norlander <lkml@vorpal.se> Link: https://lore.kernel.org/r/20220902180037.1728546-3-lkml@vorpal.se Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/toshiba_acpi.c96
2 files changed, 97 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index daefe57c7b86..f5312f51de19 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -791,6 +791,7 @@ config SAMSUNG_Q10
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on ACPI
+ depends on ACPI_BATTERY
depends on ACPI_WMI
select LEDS_CLASS
select NEW_LEDS
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index b55e6e17f723..1b3357a4207a 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -45,6 +45,7 @@
#include <linux/hwmon.h>
#include <linux/iio/iio.h>
#include <linux/toshiba.h>
+#include <acpi/battery.h>
#include <acpi/video.h>
MODULE_AUTHOR("John Belmonte");
@@ -3045,6 +3046,91 @@ static const struct hwmon_chip_info toshiba_acpi_hwmon_chip_info = {
};
#endif
+/* ACPI battery hooking */
+static ssize_t charge_control_end_threshold_show(struct device *device,
+ struct device_attribute *attr,
+ char *buf)
+{
+ u32 state;
+ int status;
+
+ if (toshiba_acpi == NULL) {
+ pr_err("Toshiba ACPI object invalid\n");
+ return -ENODEV;
+ }
+
+ status = toshiba_battery_charge_mode_get(toshiba_acpi, &state);
+
+ if (status != 0)
+ return status;
+
+ if (state == 1)
+ return sprintf(buf, "80\n");
+ else
+ return sprintf(buf, "100\n");
+}
+
+static ssize_t charge_control_end_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ u32 value;
+ int rval;
+
+ if (toshiba_acpi == NULL) {
+ pr_err("Toshiba ACPI object invalid\n");
+ return -ENODEV;
+ }
+
+ rval = kstrtou32(buf, 10, &value);
+ if (rval)
+ return rval;
+
+ if (value < 1 || value > 100)
+ return -EINVAL;
+ rval = toshiba_battery_charge_mode_set(toshiba_acpi,
+ (value < 90) ? 1 : 0);
+ if (rval < 0)
+ return rval;
+ else
+ return count;
+}
+
+static DEVICE_ATTR_RW(charge_control_end_threshold);
+
+static struct attribute *toshiba_acpi_battery_attrs[] = {
+ &dev_attr_charge_control_end_threshold.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(toshiba_acpi_battery);
+
+static int toshiba_acpi_battery_add(struct power_supply *battery)
+{
+ if (toshiba_acpi == NULL) {
+ pr_err("Init order issue\n");
+ return -ENODEV;
+ }
+ if (!toshiba_acpi->battery_charge_mode_supported)
+ return -ENODEV;
+ if (device_add_groups(&battery->dev, toshiba_acpi_battery_groups))
+ return -ENODEV;
+ return 0;
+}
+
+static int toshiba_acpi_battery_remove(struct power_supply *battery)
+{
+ device_remove_groups(&battery->dev, toshiba_acpi_battery_groups);
+ return 0;
+}
+
+static struct acpi_battery_hook battery_hook = {
+ .add_battery = toshiba_acpi_battery_add,
+ .remove_battery = toshiba_acpi_battery_remove,
+ .name = "Toshiba Battery Extension",
+};
+
static void print_supported_features(struct toshiba_acpi_dev *dev)
{
pr_info("Supported laptop features:");
@@ -3134,6 +3220,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
rfkill_destroy(dev->wwan_rfk);
}
+ if (dev->battery_charge_mode_supported)
+ battery_hook_unregister(&battery_hook);
+
if (toshiba_acpi)
toshiba_acpi = NULL;
@@ -3332,6 +3421,13 @@ iio_error:
toshiba_acpi = dev;
+ /*
+ * As the battery hook relies on the static variable toshiba_acpi being
+ * set, this must be done after toshiba_acpi is assigned.
+ */
+ if (dev->battery_charge_mode_supported)
+ battery_hook_register(&battery_hook);
+
return 0;
error: