Skip to content

Commit bce8680

Browse files
Antheas KapenekakisKyleGospo
authored andcommitted
[FROM-ML] platform/x86: msi-wmi-platform: Add charge_threshold support
The battery of MSI laptops supports charge threshold. Add support for it. Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
1 parent a26edfc commit bce8680

2 files changed

Lines changed: 111 additions & 0 deletions

File tree

drivers/platform/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ config MSI_WMI
567567

568568
config MSI_WMI_PLATFORM
569569
tristate "MSI WMI Platform features"
570+
depends on ACPI_BATTERY
570571
depends on ACPI_WMI
571572
depends on DMI
572573
depends on HWMON

drivers/platform/x86/msi-wmi-platform.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/sysfs.h>
3232
#include <linux/types.h>
3333
#include <linux/wmi.h>
34+
#include <acpi/battery.h>
3435

3536
#include <linux/unaligned.h>
3637

@@ -79,6 +80,7 @@
7980
/* Get_Data() and Set_Data() Params */
8081
#define MSI_PLATFORM_PL1_ADDR 0x50
8182
#define MSI_PLATFORM_PL2_ADDR 0x51
83+
#define MSI_PLATFORM_BAT_ADDR 0xd7
8284

8385
static bool force;
8486
module_param_unsafe(force, bool, 0);
@@ -118,6 +120,7 @@ enum msi_wmi_platform_method {
118120

119121
struct msi_wmi_platform_quirk {
120122
bool shift_mode; /* Shift mode is supported */
123+
bool charge_threshold; /* Charge threshold is supported */
121124
int pl_min; /* Minimum PLx value */
122125
int pl1_max; /* Maximum PL1 value */
123126
int pl2_max; /* Maximum PL2 value */
@@ -128,6 +131,7 @@ struct msi_wmi_platform_data {
128131
struct msi_wmi_platform_quirk *quirks;
129132
struct mutex wmi_lock; /* Necessary when calling WMI methods */
130133
struct device *ppdev;
134+
struct acpi_battery_hook battery_hook;
131135
struct device *fw_attrs_dev;
132136
struct kset *fw_attrs_kset;
133137
};
@@ -211,12 +215,14 @@ static const char * const msi_wmi_platform_debugfs_names[] = {
211215
static struct msi_wmi_platform_quirk quirk_default = {};
212216
static struct msi_wmi_platform_quirk quirk_gen1 = {
213217
.shift_mode = true,
218+
.charge_threshold = true,
214219
.pl_min = 8,
215220
.pl1_max = 43,
216221
.pl2_max = 45
217222
};
218223
static struct msi_wmi_platform_quirk quirk_gen2 = {
219224
.shift_mode = true,
225+
.charge_threshold = true,
220226
.pl_min = 8,
221227
.pl1_max = 30,
222228
.pl2_max = 37
@@ -1013,6 +1019,94 @@ static int msi_wmi_fw_attrs_init(struct msi_wmi_platform_data *data)
10131019
return 0;
10141020
}
10151021

1022+
static int msi_platform_psy_ext_get_prop(struct power_supply *psy,
1023+
const struct power_supply_ext *ext,
1024+
void *data,
1025+
enum power_supply_property psp,
1026+
union power_supply_propval *val)
1027+
{
1028+
struct msi_wmi_platform_data *msi = data;
1029+
u8 buffer[32] = { 0 };
1030+
int ret;
1031+
1032+
switch (psp) {
1033+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
1034+
buffer[0] = MSI_PLATFORM_BAT_ADDR;
1035+
ret = msi_wmi_platform_query(msi, MSI_PLATFORM_GET_DATA,
1036+
buffer, sizeof(buffer));
1037+
if (ret)
1038+
return ret;
1039+
1040+
val->intval = buffer[1] & ~BIT(7);
1041+
if (val->intval > 100)
1042+
return -EINVAL;
1043+
1044+
return 0;
1045+
default:
1046+
return -EINVAL;
1047+
}
1048+
}
1049+
1050+
static int msi_platform_psy_ext_set_prop(struct power_supply *psy,
1051+
const struct power_supply_ext *ext,
1052+
void *data,
1053+
enum power_supply_property psp,
1054+
const union power_supply_propval *val)
1055+
{
1056+
struct msi_wmi_platform_data *msi = data;
1057+
u8 buffer[32] = { 0 };
1058+
1059+
switch (psp) {
1060+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
1061+
if (val->intval > 100)
1062+
return -EINVAL;
1063+
buffer[0] = MSI_PLATFORM_BAT_ADDR;
1064+
buffer[1] = val->intval | BIT(7);
1065+
return msi_wmi_platform_query(msi, MSI_PLATFORM_SET_DATA,
1066+
buffer, sizeof(buffer));
1067+
default:
1068+
return -EINVAL;
1069+
}
1070+
}
1071+
1072+
static int
1073+
msi_platform_psy_prop_is_writeable(struct power_supply *psy,
1074+
const struct power_supply_ext *ext,
1075+
void *data, enum power_supply_property psp)
1076+
{
1077+
return true;
1078+
}
1079+
1080+
static const enum power_supply_property oxp_psy_ext_props[] = {
1081+
POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
1082+
};
1083+
1084+
static const struct power_supply_ext msi_platform_psy_ext = {
1085+
.name = "msi-platform-charge-control",
1086+
.properties = oxp_psy_ext_props,
1087+
.num_properties = ARRAY_SIZE(oxp_psy_ext_props),
1088+
.get_property = msi_platform_psy_ext_get_prop,
1089+
.set_property = msi_platform_psy_ext_set_prop,
1090+
.property_is_writeable = msi_platform_psy_prop_is_writeable,
1091+
};
1092+
1093+
static int msi_wmi_platform_battery_add(struct power_supply *battery,
1094+
struct acpi_battery_hook *hook)
1095+
{
1096+
struct msi_wmi_platform_data *data =
1097+
container_of(hook, struct msi_wmi_platform_data, battery_hook);
1098+
1099+
return power_supply_register_extension(battery, &msi_platform_psy_ext,
1100+
&data->wdev->dev, data);
1101+
}
1102+
1103+
static int msi_wmi_platform_battery_remove(struct power_supply *battery,
1104+
struct acpi_battery_hook *hook)
1105+
{
1106+
power_supply_unregister_extension(battery, &msi_platform_psy_ext);
1107+
return 0;
1108+
}
1109+
10161110
static ssize_t msi_wmi_platform_debugfs_write(struct file *fp, const char __user *input,
10171111
size_t length, loff_t *offset)
10181112
{
@@ -1245,13 +1339,28 @@ static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
12451339
if (ret < 0)
12461340
return ret;
12471341

1342+
if (data->quirks->charge_threshold) {
1343+
data->battery_hook.name = "MSI Battery";
1344+
data->battery_hook.add_battery = msi_wmi_platform_battery_add;
1345+
data->battery_hook.remove_battery = msi_wmi_platform_battery_remove;
1346+
battery_hook_register(&data->battery_hook);
1347+
}
1348+
12481349
msi_wmi_platform_debugfs_init(data);
12491350

12501351
msi_wmi_platform_profile_setup(data);
12511352

12521353
return msi_wmi_platform_hwmon_init(data);
12531354
}
12541355

1356+
static void msi_wmi_platform_remove(struct wmi_device *wdev)
1357+
{
1358+
struct msi_wmi_platform_data *data = dev_get_drvdata(&wdev->dev);
1359+
1360+
if (data->quirks->charge_threshold)
1361+
battery_hook_unregister(&data->battery_hook);
1362+
}
1363+
12551364
static const struct wmi_device_id msi_wmi_platform_id_table[] = {
12561365
{ MSI_PLATFORM_GUID, NULL },
12571366
{ }
@@ -1265,6 +1374,7 @@ static struct wmi_driver msi_wmi_platform_driver = {
12651374
},
12661375
.id_table = msi_wmi_platform_id_table,
12671376
.probe = msi_wmi_platform_probe,
1377+
.remove = msi_wmi_platform_remove,
12681378
.no_singleton = true,
12691379
};
12701380

0 commit comments

Comments
 (0)