From patchwork Sat Nov 13 10:42:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 12617643 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A9B49C43219 for ; Sat, 13 Nov 2021 10:42:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 889A7610A1 for ; Sat, 13 Nov 2021 10:42:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235829AbhKMKpd (ORCPT ); Sat, 13 Nov 2021 05:45:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235821AbhKMKpa (ORCPT ); Sat, 13 Nov 2021 05:45:30 -0500 Received: from todd.t-8ch.de (todd.t-8ch.de [IPv6:2a01:4f8:c010:41de::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B7BC0C061767; Sat, 13 Nov 2021 02:42:38 -0800 (PST) From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=weissschuh.net; s=mail; t=1636800156; bh=QxJBOoxYey+j4x0YV6CgxD72MhZoalFtY91GcglpMkM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=senmAwS+5Prs+xkmfqgK4DzCHV/0/Wy1mE+ytdQMgJjrcqgDkWTPYeR0haIOTVXHC UruuOEfepHFSJ6Do9OeiMqjA06Bmu3M7KEFJuWfohZc4ehKJHm0mZNeXlTN7ZX5YkC rOO+bYVQKbUPwYN0DmRUr2HS3mmq6Ou5Dh75O7u4= To: linux-pm@vger.kernel.org, Sebastian Reichel , ibm-acpi-devel@lists.sourceforge.net, platform-driver-x86@vger.kernel.org, Mark Gross , Hans de Goede , Henrique de Moraes Holschuh Cc: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , linux-kernel@vger.kernel.org, linrunner@gmx.net, bberg@redhat.com, hadess@hadess.net, markpearson@lenovo.com, nicolopiazzalunga@gmail.com, njoshi1@lenovo.com, smclt30p@gmail.com Subject: [PATCH 1/4] power: supply: add charge_behaviour attributes Date: Sat, 13 Nov 2021 11:42:22 +0100 Message-Id: <20211113104225.141333-2-linux@weissschuh.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211113104225.141333-1-linux@weissschuh.net> References: <20211113104225.141333-1-linux@weissschuh.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org This a revised version of "[RFC] add standardized attributes for force_discharge and inhibit_charge" [0], incorporating discussion results. The biggest change is the switch from two boolean attributes to a single enum attribute. [0] https://lore.kernel.org/platform-driver-x86/21569a89-8303-8573-05fb-c2fec29983d1@gmail.com/ Signed-off-by: Thomas Weißschuh --- Documentation/ABI/testing/sysfs-class-power | 14 ++++++++++++++ include/linux/power_supply.h | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index f7904efc4cfa..cece094764f8 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -455,6 +455,20 @@ Description: "Unknown", "Charging", "Discharging", "Not charging", "Full" +What: /sys/class/power_supply//charge_behaviour +Date: November 2021 +Contact: linux-pm@vger.kernel.org +Description: + Represents the charging behaviour. + + Access: Read, Write + + Valid values: + ================ ==================================== + auto: Charge normally, respect thresholds + inhibit-charge: Do not charge while AC is attached + force-discharge: Force discharge while AC is attached + What: /sys/class/power_supply//technology Date: May 2007 Contact: linux-pm@vger.kernel.org diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 9ca1f120a211..70c333e86293 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -132,6 +132,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, /* in percents! */ POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, /* in percents! */ + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, POWER_SUPPLY_PROP_INPUT_POWER_LIMIT, @@ -202,6 +203,12 @@ enum power_supply_usb_type { POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ }; +enum power_supply_charge_behaviour { + POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO = 0, + POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE, + POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE, +}; + enum power_supply_notifier_events { PSY_EVENT_PROP_CHANGED, }; From patchwork Sat Nov 13 10:42:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 12617641 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE24CC433FE for ; Sat, 13 Nov 2021 10:42:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8660B610A1 for ; Sat, 13 Nov 2021 10:42:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235828AbhKMKpc (ORCPT ); Sat, 13 Nov 2021 05:45:32 -0500 Received: from todd.t-8ch.de ([159.69.126.157]:59913 "EHLO todd.t-8ch.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235804AbhKMKpa (ORCPT ); Sat, 13 Nov 2021 05:45:30 -0500 From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=weissschuh.net; s=mail; t=1636800156; bh=aTqKITwe2LA7y1VMDsmOTFPBsA/vzvyEueKa2dGlxMk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ln286Z6jptypnEoyobbtP9PxcPsWu8r/CKukBuUJkpJlubmpTSIXJf+RzbRNShdsu gJE8y00lA+rNzGD29LBgmuRg5TU7yewEpdrv1p5YRy8mkkzt82tZPsvqdIXwYYcPGi iwdb27ZTDLmhYeNN7WWcnbreYbdPkPG60lRd04TQ= To: linux-pm@vger.kernel.org, Sebastian Reichel , ibm-acpi-devel@lists.sourceforge.net, platform-driver-x86@vger.kernel.org, Mark Gross , Hans de Goede , Henrique de Moraes Holschuh Cc: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , linux-kernel@vger.kernel.org, linrunner@gmx.net, bberg@redhat.com, hadess@hadess.net, markpearson@lenovo.com, nicolopiazzalunga@gmail.com, njoshi1@lenovo.com, smclt30p@gmail.com Subject: [PATCH 2/4] power: supply: add helpers for charge_behaviour sysfs Date: Sat, 13 Nov 2021 11:42:23 +0100 Message-Id: <20211113104225.141333-3-linux@weissschuh.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211113104225.141333-1-linux@weissschuh.net> References: <20211113104225.141333-1-linux@weissschuh.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org These helper functions can be used by drivers to implement their own sysfs-attributes. This is useful for ACPI-drivers extending the default ACPI-battery with their own charge_behaviour attributes. Signed-off-by: Thomas Weißschuh --- drivers/power/supply/power_supply_sysfs.c | 51 +++++++++++++++++++++++ include/linux/power_supply.h | 9 ++++ 2 files changed, 60 insertions(+) diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index c3d7cbcd4fad..171341bcef1d 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -133,6 +133,12 @@ static const char * const POWER_SUPPLY_SCOPE_TEXT[] = { [POWER_SUPPLY_SCOPE_DEVICE] = "Device", }; +static const char * const POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[] = { + [POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO] = "auto", + [POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE] = "inhibit-charge", + [POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE] = "force-discharge", +}; + static struct power_supply_attr power_supply_attrs[] = { /* Properties of type `int' */ POWER_SUPPLY_ENUM_ATTR(STATUS), @@ -226,6 +232,51 @@ static enum power_supply_property dev_attr_psp(struct device_attribute *attr) return to_ps_attr(attr) - power_supply_attrs; } +ssize_t power_supply_charge_behaviour_show(struct device *dev, + unsigned int available_behaviours, + enum power_supply_charge_behaviour current_behaviour, + char *buf) +{ + bool match = false, available, active; + ssize_t count = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT); i++) { + available = available_behaviours & BIT(i); + active = i == current_behaviour; + + if (available && active) { + count += sprintf(buf + count, "[%s] ", + POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]); + match = true; + } else if (available) { + count += sprintf(buf + count, "%s ", + POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]); + } + } + + if (!match) { + dev_warn(dev, "driver reporting unsupported charge behaviour\n"); + return -EINVAL; + } + + if (count) + buf[count - 1] = '\n'; + + return count; +} +EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_show); + +int power_supply_charge_behaviour_parse(unsigned int available_behaviours, const char *buf) +{ + int i = sysfs_match_string(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT, buf); + + if (available_behaviours & BIT(i)) + return i; + return -EINVAL; +} +EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_parse); + static ssize_t power_supply_show_usb_type(struct device *dev, const struct power_supply_desc *desc, union power_supply_propval *value, diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 70c333e86293..71f0379c2af8 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -546,4 +546,13 @@ static inline void power_supply_remove_hwmon_sysfs(struct power_supply *psy) {} #endif +#ifdef CONFIG_SYSFS +ssize_t power_supply_charge_behaviour_show(struct device *dev, + unsigned int available_behaviours, + enum power_supply_charge_behaviour behaviour, + char *buf); + +int power_supply_charge_behaviour_parse(unsigned int available_behaviours, const char *buf); +#endif + #endif /* __LINUX_POWER_SUPPLY_H__ */ From patchwork Sat Nov 13 10:42:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 12617647 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C976C2BB1D for ; Sat, 13 Nov 2021 10:42:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0132E610A1 for ; Sat, 13 Nov 2021 10:42:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235846AbhKMKpe (ORCPT ); Sat, 13 Nov 2021 05:45:34 -0500 Received: from todd.t-8ch.de ([159.69.126.157]:59747 "EHLO todd.t-8ch.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231803AbhKMKpa (ORCPT ); Sat, 13 Nov 2021 05:45:30 -0500 From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=weissschuh.net; s=mail; t=1636800156; bh=88F+Nb2+6/LAaesDdFWd9B0WsQsw6AF3SgA9AxEuij8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LTGy5MteEq7t/nrju8mHqEYnFrSKi6x3CYJdZwZI2V5rraeiDk4L/YKOb2ndyFzpL 0AWY8wStDTPwntHQXyn9NihSD76SZVGYX8AgomUpuEuaaZNw5KmjaFaAPBJjJRoAjI wlOqYzctxkxZbT0YqXdHt9/OCVbOqFpuUpHEM4Qk= To: linux-pm@vger.kernel.org, Sebastian Reichel , ibm-acpi-devel@lists.sourceforge.net, platform-driver-x86@vger.kernel.org, Mark Gross , Hans de Goede , Henrique de Moraes Holschuh Cc: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , linux-kernel@vger.kernel.org, linrunner@gmx.net, bberg@redhat.com, hadess@hadess.net, markpearson@lenovo.com, nicolopiazzalunga@gmail.com, njoshi1@lenovo.com, smclt30p@gmail.com Subject: [PATCH 3/4] platform/x86: thinkpad_acpi: support force-discharge Date: Sat, 13 Nov 2021 11:42:24 +0100 Message-Id: <20211113104225.141333-4-linux@weissschuh.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211113104225.141333-1-linux@weissschuh.net> References: <20211113104225.141333-1-linux@weissschuh.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org This adds support for the force-discharge charge_behaviour through the embedded controller of ThinkPads. Signed-off-by: Thomas Weißschuh --- This patch is based on https://lore.kernel.org/platform-driver-x86/c2504700-06e9-e7d8-80f7-de90b0b6dfb5@gmail.com/ --- drivers/platform/x86/thinkpad_acpi.c | 103 +++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 9c632df734bb..e8c98e9aff71 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -9319,6 +9319,8 @@ static struct ibm_struct mute_led_driver_data = { #define SET_START "BCCS" #define GET_STOP "BCSG" #define SET_STOP "BCSS" +#define GET_DISCHARGE "BDSG" +#define SET_DISCHARGE "BDSS" enum { BAT_ANY = 0, @@ -9335,6 +9337,7 @@ enum { /* This is used in the get/set helpers */ THRESHOLD_START, THRESHOLD_STOP, + FORCE_DISCHARGE, }; struct tpacpi_battery_data { @@ -9342,6 +9345,7 @@ struct tpacpi_battery_data { int start_support; int charge_stop; int stop_support; + unsigned int charge_behaviours; }; struct tpacpi_battery_driver_data { @@ -9399,6 +9403,12 @@ static int tpacpi_battery_get(int what, int battery, int *ret) if (*ret == 0) *ret = 100; return 0; + case FORCE_DISCHARGE: + if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_DISCHARGE, ret, battery)) + return -ENODEV; + /* The force discharge status is in bit 0 */ + *ret = *ret & 0x01; + return 0; default: pr_crit("wrong parameter: %d", what); return -EINVAL; @@ -9427,6 +9437,16 @@ static int tpacpi_battery_set(int what, int battery, int value) return -ENODEV; } return 0; + case FORCE_DISCHARGE: + /* Force discharge is in bit 0, + * break on AC attach is in bit 1 (won't work on some ThinkPads), + * battery ID is in bits 8-9, 2 bits. + */ + if (ACPI_FAILURE(tpacpi_battery_acpi_eval(SET_DISCHARGE, &ret, param))) { + pr_err("failed to set force dischrage on %d", battery); + return -ENODEV; + } + return 0; default: pr_crit("wrong parameter: %d", what); return -EINVAL; @@ -9445,6 +9465,8 @@ static int tpacpi_battery_probe(int battery) * 2) Check for support * 3) Get the current stop threshold * 4) Check for support + * 5) Get the current force discharge status + * 6) Check for support */ if (acpi_has_method(hkey_handle, GET_START)) { if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_START, &ret, battery)) { @@ -9481,10 +9503,25 @@ static int tpacpi_battery_probe(int battery) return -ENODEV; } } - pr_info("battery %d registered (start %d, stop %d)", - battery, - battery_info.batteries[battery].charge_start, - battery_info.batteries[battery].charge_stop); + if (acpi_has_method(hkey_handle, GET_DISCHARGE)) { + if (ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_DISCHARGE, &ret, battery))) { + pr_err("Error probing battery discharge; %d\n", battery); + return -ENODEV; + } + /* Support is marked in bit 8 */ + if (ret & BIT(8)) + battery_info.batteries[battery].charge_behaviours |= + BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE); + } + + battery_info.batteries[battery].charge_behaviours |= + BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO); + + pr_info("battery %d registered (start %d, stop %d, behaviours: 0x%x)\n", + battery, + battery_info.batteries[battery].charge_start, + battery_info.batteries[battery].charge_stop, + battery_info.batteries[battery].charge_behaviours); return 0; } @@ -9619,6 +9656,28 @@ static ssize_t charge_control_end_threshold_show(struct device *device, return tpacpi_battery_show(THRESHOLD_STOP, device, buf); } +static ssize_t charge_behaviour_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + enum power_supply_charge_behaviour active = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO; + struct power_supply *supply = to_power_supply(dev); + unsigned int available; + int ret, battery; + + battery = tpacpi_battery_get_id(supply->desc->name); + available = battery_info.batteries[battery].charge_behaviours; + + if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE)) { + if (tpacpi_battery_get(FORCE_DISCHARGE, battery, &ret)) + return -ENODEV; + if (ret) + active = POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE; + } + + return power_supply_charge_behaviour_show(dev, available, active, buf); +} + static ssize_t charge_control_start_threshold_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -9633,8 +9692,43 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, return tpacpi_battery_store(THRESHOLD_STOP, dev, buf, count); } +static ssize_t charge_behaviour_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct power_supply *supply = to_power_supply(dev); + int selected, battery, ret; + unsigned int available; + + battery = tpacpi_battery_get_id(supply->desc->name); + available = battery_info.batteries[battery].charge_behaviours; + selected = power_supply_charge_behaviour_parse(available, buf); + + if (selected < 0) + return selected; + + switch (selected) { + case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO: + ret = tpacpi_battery_set(FORCE_DISCHARGE, battery, 0); + if (ret < 0) + return ret; + break; + case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE: + ret = tpacpi_battery_set(FORCE_DISCHARGE, battery, 1); + if (ret < 0) + return ret; + break; + default: + dev_err(dev, "Unexpected charge behaviour: %d\n", selected); + return -EINVAL; + } + + return count; +} + static DEVICE_ATTR_RW(charge_control_start_threshold); static DEVICE_ATTR_RW(charge_control_end_threshold); +static DEVICE_ATTR_RW(charge_behaviour); static struct device_attribute dev_attr_charge_start_threshold = __ATTR( charge_start_threshold, 0644, @@ -9653,6 +9747,7 @@ static struct attribute *tpacpi_battery_attrs[] = { &dev_attr_charge_control_end_threshold.attr, &dev_attr_charge_start_threshold.attr, &dev_attr_charge_stop_threshold.attr, + &dev_attr_charge_behaviour.attr, NULL, }; From patchwork Sat Nov 13 10:42:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 12617645 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9240C4167E for ; Sat, 13 Nov 2021 10:42:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BD74A61156 for ; Sat, 13 Nov 2021 10:42:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235836AbhKMKpd (ORCPT ); Sat, 13 Nov 2021 05:45:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55520 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235816AbhKMKpa (ORCPT ); Sat, 13 Nov 2021 05:45:30 -0500 Received: from todd.t-8ch.de (todd.t-8ch.de [IPv6:2a01:4f8:c010:41de::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7AEF7C061766; Sat, 13 Nov 2021 02:42:38 -0800 (PST) From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=weissschuh.net; s=mail; t=1636800156; bh=lvDFqz8JQafjLCe0upSmVTphFfWrJ150vakiSDVAzYk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bwPKh/IdeXu+QB2HHcfkpAfzWuPP+y1Ib58MrL8VbVeNvup4p64u26JA/B4JNs+Kf TXe4Y7Hy5hAFxRaBtX/JN4M9G5HOEmGc0LmdNMFDbwWy73sFfRPhoQfo0KGLmC3fIt PV10+saopaxxtLr8Ok356oXV/tVE+f2kvENgYi4E= To: linux-pm@vger.kernel.org, Sebastian Reichel , ibm-acpi-devel@lists.sourceforge.net, platform-driver-x86@vger.kernel.org, Mark Gross , Hans de Goede , Henrique de Moraes Holschuh Cc: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , linux-kernel@vger.kernel.org, linrunner@gmx.net, bberg@redhat.com, hadess@hadess.net, markpearson@lenovo.com, nicolopiazzalunga@gmail.com, njoshi1@lenovo.com, smclt30p@gmail.com Subject: [PATCH 4/4] platform/x86: thinkpad_acpi: support inhibit-charge Date: Sat, 13 Nov 2021 11:42:25 +0100 Message-Id: <20211113104225.141333-5-linux@weissschuh.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211113104225.141333-1-linux@weissschuh.net> References: <20211113104225.141333-1-linux@weissschuh.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org This adds support for the inhibit-charge charge_behaviour through the embedded controller of ThinkPads. Signed-off-by: Thomas Weißschuh --- This patch is based on https://lore.kernel.org/platform-driver-x86/d2808930-5840-6ffb-3a59-d235cdb1fe16@gmail.com/ --- drivers/platform/x86/thinkpad_acpi.c | 55 +++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e8c98e9aff71..7cd6475240b2 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -9321,6 +9321,8 @@ static struct ibm_struct mute_led_driver_data = { #define SET_STOP "BCSS" #define GET_DISCHARGE "BDSG" #define SET_DISCHARGE "BDSS" +#define GET_INHIBIT "PSSG" +#define SET_INHIBIT "BICS" enum { BAT_ANY = 0, @@ -9338,6 +9340,7 @@ enum { THRESHOLD_START, THRESHOLD_STOP, FORCE_DISCHARGE, + INHIBIT_CHARGE, }; struct tpacpi_battery_data { @@ -9409,6 +9412,13 @@ static int tpacpi_battery_get(int what, int battery, int *ret) /* The force discharge status is in bit 0 */ *ret = *ret & 0x01; return 0; + case INHIBIT_CHARGE: + /* This is actually reading peak shift state, like tpacpi-bat does */ + if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_INHIBIT, ret, battery)) + return -ENODEV; + /* The inhibit charge status is in bit 0 */ + *ret = *ret & 0x01; + return 0; default: pr_crit("wrong parameter: %d", what); return -EINVAL; @@ -9447,6 +9457,22 @@ static int tpacpi_battery_set(int what, int battery, int value) return -ENODEV; } return 0; + case INHIBIT_CHARGE: + /* When setting inhibit charge, we set a default value of + * always breaking on AC detach and the effective time is set to + * be permanent. + * The battery ID is in bits 4-5, 2 bits, + * the effective time is in bits 8-23, 2 bytes. + * A time of FFFF indicates forever. + */ + param = value; + param |= battery << 4; + param |= 0xFFFF << 8; + if (ACPI_FAILURE(tpacpi_battery_acpi_eval(SET_INHIBIT, &ret, param))) { + pr_err("failed to set inhibit charge on %d", battery); + return -ENODEV; + } + return 0; default: pr_crit("wrong parameter: %d", what); return -EINVAL; @@ -9467,6 +9493,8 @@ static int tpacpi_battery_probe(int battery) * 4) Check for support * 5) Get the current force discharge status * 6) Check for support + * 7) Get the current inhibit charge status + * 8) Check for support */ if (acpi_has_method(hkey_handle, GET_START)) { if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_START, &ret, battery)) { @@ -9513,6 +9541,16 @@ static int tpacpi_battery_probe(int battery) battery_info.batteries[battery].charge_behaviours |= BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE); } + if (acpi_has_method(hkey_handle, GET_INHIBIT)) { + if (ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_INHIBIT, &ret, battery))) { + pr_err("Error probing battery inhibit charge; %d\n", battery); + return -ENODEV; + } + /* Support is marked in bit 5 */ + if (ret & BIT(5)) + battery_info.batteries[battery].charge_behaviours |= + BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE); + } battery_info.batteries[battery].charge_behaviours |= BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO); @@ -9673,6 +9711,11 @@ static ssize_t charge_behaviour_show(struct device *dev, return -ENODEV; if (ret) active = POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE; + } else if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE)) { + if (tpacpi_battery_get(INHIBIT_CHARGE, battery, &ret)) + return -ENODEV; + if (ret) + active = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; } return power_supply_charge_behaviour_show(dev, available, active, buf); @@ -9710,12 +9753,20 @@ static ssize_t charge_behaviour_store(struct device *dev, switch (selected) { case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO: ret = tpacpi_battery_set(FORCE_DISCHARGE, battery, 0); - if (ret < 0) + ret = tpacpi_battery_set(INHIBIT_CHARGE, battery, 0) || ret; + if (ret) return ret; break; case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE: ret = tpacpi_battery_set(FORCE_DISCHARGE, battery, 1); - if (ret < 0) + ret = tpacpi_battery_set(INHIBIT_CHARGE, battery, 0) || ret; + if (ret) + return ret; + break; + case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE: + ret = tpacpi_battery_set(FORCE_DISCHARGE, battery, 0); + ret = tpacpi_battery_set(INHIBIT_CHARGE, battery, 1) || ret; + if (ret) return ret; break; default: