From: Antheas Kapenekakis <lkml@antheas.dev>
To: platform-driver-x86@vger.kernel.org
Cc: "Armin Wolf" <W_Armin@gmx.de>, "Jonathan Corbet" <corbet@lwn.net>,
"Hans de Goede" <hdegoede@redhat.com>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Jean Delvare" <jdelvare@suse.com>,
"Guenter Roeck" <linux@roeck-us.net>,
"Kurt Borja" <kuurtb@gmail.com>,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-hwmon@vger.kernel.org,
"Antheas Kapenekakis" <lkml@antheas.dev>
Subject: [PATCH v1 07/10] platform/x86: msi-wmi-platform: Add charge_threshold support
Date: Sun, 11 May 2025 22:44:24 +0200 [thread overview]
Message-ID: <20250511204427.327558-8-lkml@antheas.dev> (raw)
In-Reply-To: <20250511204427.327558-1-lkml@antheas.dev>
The battery of MSI laptops supports charge threshold. Add support for it.
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/platform/x86/Kconfig | 1 +
drivers/platform/x86/msi-wmi-platform.c | 110 ++++++++++++++++++++++++
2 files changed, 111 insertions(+)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index fd3da718731e7..51a34ab476ffc 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -744,6 +744,7 @@ config MSI_WMI
config MSI_WMI_PLATFORM
tristate "MSI WMI Platform features"
+ depends on ACPI_BATTERY
depends on ACPI_WMI
depends on HWMON
select ACPI_PLATFORM_PROFILE
diff --git a/drivers/platform/x86/msi-wmi-platform.c b/drivers/platform/x86/msi-wmi-platform.c
index 6498f4b44fe53..46928fb4da8a6 100644
--- a/drivers/platform/x86/msi-wmi-platform.c
+++ b/drivers/platform/x86/msi-wmi-platform.c
@@ -31,6 +31,7 @@
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/wmi.h>
+#include <acpi/battery.h>
#include <linux/unaligned.h>
@@ -79,6 +80,7 @@
/* Get_Data() and Set_Data() Params */
#define MSI_PLATFORM_PL1_ADDR 0x50
#define MSI_PLATFORM_PL2_ADDR 0x51
+#define MSI_PLATFORM_BAT_ADDR 0xd7
static bool force;
module_param_unsafe(force, bool, 0);
@@ -118,6 +120,7 @@ enum msi_wmi_platform_method {
struct msi_wmi_platform_quirk {
bool shift_mode; /* Shift mode is supported */
+ bool charge_threshold; /* Charge threshold is supported */
int pl_min; /* Minimum PLx value */
int pl1_max; /* Maximum PL1 value */
int pl2_max; /* Maximum PL2 value */
@@ -128,6 +131,7 @@ struct msi_wmi_platform_data {
struct msi_wmi_platform_quirk *quirks;
struct mutex wmi_lock; /* Necessary when calling WMI methods */
struct device *ppdev;
+ struct acpi_battery_hook battery_hook;
struct device *fw_attrs_dev;
struct kset *fw_attrs_kset;
};
@@ -211,12 +215,14 @@ static const char * const msi_wmi_platform_debugfs_names[] = {
static struct msi_wmi_platform_quirk quirk_default = {};
static struct msi_wmi_platform_quirk quirk_gen1 = {
.shift_mode = true,
+ .charge_threshold = true,
.pl_min = 8,
.pl1_max = 43,
.pl2_max = 45
};
static struct msi_wmi_platform_quirk quirk_gen2 = {
.shift_mode = true,
+ .charge_threshold = true,
.pl_min = 8,
.pl1_max = 30,
.pl2_max = 37
@@ -1013,6 +1019,94 @@ static int msi_wmi_fw_attrs_init(struct msi_wmi_platform_data *data)
return 0;
}
+static int msi_platform_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)
+{
+ struct msi_wmi_platform_data *msi = data;
+ u8 buffer[32] = { 0 };
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
+ buffer[0] = MSI_PLATFORM_BAT_ADDR;
+ ret = msi_wmi_platform_query(msi, MSI_PLATFORM_GET_DATA,
+ buffer, sizeof(buffer));
+ if (ret)
+ return ret;
+
+ val->intval = buffer[1] & ~BIT(7);
+ if (val->intval > 100)
+ return -EINVAL;
+
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int msi_platform_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)
+{
+ struct msi_wmi_platform_data *msi = data;
+ u8 buffer[32] = { 0 };
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
+ if (val->intval > 100)
+ return -EINVAL;
+ buffer[0] = MSI_PLATFORM_BAT_ADDR;
+ buffer[1] = val->intval | BIT(7);
+ return msi_wmi_platform_query(msi, MSI_PLATFORM_SET_DATA,
+ buffer, sizeof(buffer));
+ default:
+ return -EINVAL;
+ }
+}
+
+static int
+msi_platform_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 oxp_psy_ext_props[] = {
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
+};
+
+static const struct power_supply_ext msi_platform_psy_ext = {
+ .name = "msi-platform-charge-control",
+ .properties = oxp_psy_ext_props,
+ .num_properties = ARRAY_SIZE(oxp_psy_ext_props),
+ .get_property = msi_platform_psy_ext_get_prop,
+ .set_property = msi_platform_psy_ext_set_prop,
+ .property_is_writeable = msi_platform_psy_prop_is_writeable,
+};
+
+static int msi_wmi_platform_battery_add(struct power_supply *battery,
+ struct acpi_battery_hook *hook)
+{
+ struct msi_wmi_platform_data *data =
+ container_of(hook, struct msi_wmi_platform_data, battery_hook);
+
+ return power_supply_register_extension(battery, &msi_platform_psy_ext,
+ &data->wdev->dev, data);
+}
+
+static int msi_wmi_platform_battery_remove(struct power_supply *battery,
+ struct acpi_battery_hook *hook)
+{
+ power_supply_unregister_extension(battery, &msi_platform_psy_ext);
+ return 0;
+}
+
static ssize_t msi_wmi_platform_debugfs_write(struct file *fp, const char __user *input,
size_t length, loff_t *offset)
{
@@ -1245,6 +1339,13 @@ static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
if (ret < 0)
return ret;
+ if (data->quirks->charge_threshold) {
+ data->battery_hook.name = "MSI Battery";
+ data->battery_hook.add_battery = msi_wmi_platform_battery_add;
+ data->battery_hook.remove_battery = msi_wmi_platform_battery_remove;
+ battery_hook_register(&data->battery_hook);
+ }
+
msi_wmi_platform_debugfs_init(data);
msi_wmi_platform_profile_setup(data);
@@ -1252,6 +1353,14 @@ static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
return msi_wmi_platform_hwmon_init(data);
}
+static void msi_wmi_platform_remove(struct wmi_device *wdev)
+{
+ struct msi_wmi_platform_data *data = dev_get_drvdata(&wdev->dev);
+
+ if (data->quirks->charge_threshold)
+ battery_hook_unregister(&data->battery_hook);
+}
+
static const struct wmi_device_id msi_wmi_platform_id_table[] = {
{ MSI_PLATFORM_GUID, NULL },
{ }
@@ -1265,6 +1374,7 @@ static struct wmi_driver msi_wmi_platform_driver = {
},
.id_table = msi_wmi_platform_id_table,
.probe = msi_wmi_platform_probe,
+ .remove = msi_wmi_platform_remove,
.no_singleton = true,
};
module_wmi_driver(msi_wmi_platform_driver);
--
2.49.0
next prev parent reply other threads:[~2025-05-11 20:44 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-11 20:44 [PATCH v1 00/10] platform/x86: msi-wmi-platform: Add fan curves/platform profile/tdp/battery limiting Antheas Kapenekakis
2025-05-11 20:44 ` [PATCH v1 01/10] platform/x86: msi-wmi-platform: Use input buffer for returning result Antheas Kapenekakis
2025-05-11 23:31 ` Kurt Borja
2025-05-13 19:42 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 02/10] platform/x86: msi-wmi-platform: Add unlocked msi_wmi_platform_query Antheas Kapenekakis
2025-05-12 19:21 ` Kurt Borja
2025-05-12 20:51 ` Antheas Kapenekakis
2025-05-12 21:23 ` Kurt Borja
2025-05-12 21:51 ` Antheas Kapenekakis
2025-05-13 19:45 ` Armin Wolf
2025-05-13 19:47 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 03/10] platform/x86: msi-wmi-platform: Add quirk system Antheas Kapenekakis
2025-05-11 23:32 ` Kurt Borja
2025-05-13 20:43 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 04/10] platform/x86: msi-wmi-platform: Add support for fan control Antheas Kapenekakis
2025-05-11 23:32 ` Kurt Borja
2025-05-13 20:58 ` Armin Wolf
2025-05-19 1:35 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 05/10] platform/x86: msi-wmi-platform: Add platform profile through shift mode Antheas Kapenekakis
2025-05-11 23:33 ` Kurt Borja
2025-05-12 21:59 ` Antheas Kapenekakis
2025-05-19 1:51 ` Armin Wolf
2025-05-19 1:58 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 06/10] platform/x86: msi-wmi-platform: Add PL1/PL2 support via firmware attributes Antheas Kapenekakis
2025-05-11 23:34 ` Kurt Borja
2025-05-12 10:22 ` Antheas Kapenekakis
2025-05-19 2:08 ` Armin Wolf
2025-05-11 20:44 ` Antheas Kapenekakis [this message]
2025-05-11 23:34 ` [PATCH v1 07/10] platform/x86: msi-wmi-platform: Add charge_threshold support Kurt Borja
2025-05-19 2:32 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 08/10] platform/x86: msi-wmi-platform: Drop excess fans in dual fan devices Antheas Kapenekakis
2025-05-11 23:35 ` Kurt Borja
2025-05-11 20:44 ` [PATCH v1 09/10] platform/x86: msi-wmi-platform: Update header text Antheas Kapenekakis
2025-05-19 2:33 ` Armin Wolf
2025-05-11 20:44 ` [PATCH v1 10/10] platform/x86: msi-wmi-platform: Restore fan curves on PWM disable and unload Antheas Kapenekakis
2025-05-12 19:16 ` Kurt Borja
2025-05-12 20:50 ` Antheas Kapenekakis
2025-05-11 23:30 ` [PATCH v1 00/10] platform/x86: msi-wmi-platform: Add fan curves/platform profile/tdp/battery limiting Kurt Borja
2025-05-12 10:16 ` Antheas Kapenekakis
2025-05-12 19:05 ` Kurt Borja
2025-05-19 2:37 ` Armin Wolf
2025-05-30 20:50 ` Antheas Kapenekakis
2025-05-30 21:15 ` Armin Wolf
2025-05-30 21:28 ` Antheas Kapenekakis
2025-05-30 22:00 ` Armin Wolf
2026-05-08 18:41 ` Derek J. Clark
2026-05-09 17:25 ` Antheas Kapenekakis
2026-08-03 22:16 ` [PATCH 0/6] " Derek J. Clark
2026-08-03 22:16 ` [PATCH 1/6] platform/x86: msi-wmi-platform: Move guard out of switch in platform_write() Derek J. Clark
2026-08-18 14:12 ` Ilpo Järvinen
2026-08-18 14:42 ` Guenter Roeck
2026-08-18 15:20 ` Derek John Clark
2026-08-18 15:26 ` Antheas Kapenekakis
2026-08-03 22:16 ` [PATCH 2/6] platform/x86: msi-wmi-platform: fix: Remove unused err Derek J. Clark
2026-08-03 22:16 ` [PATCH 3/6] platform/x86: msi-wmi-platform: terminate msi_quirks DMI table Derek J. Clark
2026-08-03 22:16 ` [PATCH 4/6] platform/x86: msi-wmi-platform: Clean up devices Derek J. Clark
2026-08-03 22:16 ` [PATCH 5/6] platform/x86: wmi-msi-platform: Add MSI Claw A8 support Derek J. Clark
2026-08-03 22:16 ` [PATCH 6/6] platform-x86: msi-wmi-platform: Add Gen 4 device Derek J. Clark
2026-08-05 17:41 ` [PATCH 0/6] Re: [PATCH v1 00/10] platform/x86: msi-wmi-platform: Add fan curves/platform profile/tdp/battery limiting Antheas Kapenekakis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250511204427.327558-8-lkml@antheas.dev \
--to=lkml@antheas.dev \
--cc=W_Armin@gmx.de \
--cc=corbet@lwn.net \
--cc=hdegoede@redhat.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=jdelvare@suse.com \
--cc=kuurtb@gmail.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®