Most newer ASUS laptops supports limiting the battery charge level, which help prolonging the battery life. Tested on a Zenbook UX430UNR.
Unified · Split
| @@ -195,6 +195,8 @@ struct asus_wmi { · 194 unmodified lines | ||
| 195 | 195 | u8 fan_boost_mode_mask; |
| 196 | 196 | u8 fan_boost_mode; |
| 197 | 197 | |
| 198 | + int charge_threshold; | |
| 199 | + | |
| 198 | 200 | struct hotplug_slot hotplug_slot; |
| 199 | 201 | struct mutex hotplug_lock; |
| 200 | 202 | struct mutex wmi_lock; |
| @@ -2075,6 +2077,43 @@ static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr, · 1874 unmodified lines | ||
| 2075 | 2077 | |
| 2076 | 2078 | static DEVICE_ATTR_WO(cpufv); |
| 2077 | 2079 | |
| 2080 | + | |
| 2081 | +static ssize_t charge_threshold_store(struct device *dev, | |
| 2082 | + struct device_attribute *attr, | |
| 2083 | + const char *buf, size_t count) | |
| 2084 | +{ | |
| 2085 | + struct asus_wmi *asus = dev_get_drvdata(dev); | |
| 2086 | + int value, ret, rv; | |
| 2087 | + | |
| 2088 | + ret = kstrtouint(buf, 10, &value); | |
| 2089 | + | |
| 2090 | + if (!count || ret != 0) | |
| 2091 | + return -EINVAL; | |
| 2092 | + if (value < 0 || value > 100) | |
| 2093 | + return -EINVAL; | |
| 2094 | + | |
| 2095 | + asus_wmi_set_devstate(ASUS_WMI_CHARGE_THRESHOLD, value, &rv); | |
| 2096 | + | |
| 2097 | + if (rv != 1) | |
| 2098 | + return -EIO; | |
| 2099 | + | |
| 2100 | + /* There isn't any method in the DSDT to read the threshold, so we | |
| 2101 | + * save the threshold. | |
| 2102 | + */ | |
| 2103 | + asus->charge_threshold = value; | |
| 2104 | + return count; | |
| 2105 | +} | |
| 2106 | + | |
| 2107 | +static ssize_t charge_threshold_show(struct device *dev, | |
| 2108 | + struct device_attribute *attr, char *buf) | |
| 2109 | +{ | |
| 2110 | + struct asus_wmi *asus = dev_get_drvdata(dev); | |
| 2111 | + | |
| 2112 | + return sprintf(buf, "%d\n", asus->charge_threshold); | |
| 2113 | +} | |
| 2114 | + | |
| 2115 | +static DEVICE_ATTR_RW(charge_threshold); | |
| 2116 | + | |
| 2078 | 2117 | static struct attribute *platform_attributes[] = { |
| 2079 | 2118 | &dev_attr_cpufv.attr, |
| 2080 | 2119 | &dev_attr_camera.attr, |
| @@ -2083,6 +2122,7 @@ static struct attribute *platform_attributes[] = { · 2 unmodified lines | ||
| 2083 | 2122 | &dev_attr_lid_resume.attr, |
| 2084 | 2123 | &dev_attr_als_enable.attr, |
| 2085 | 2124 | &dev_attr_fan_boost_mode.attr, |
| 2125 | + &dev_attr_charge_threshold.attr, | |
| 2086 | 2126 | NULL |
| 2087 | 2127 | }; |
| 2088 | 2128 | |
| @@ -2106,6 +2146,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, · 17 unmodified lines | ||
| 2106 | 2146 | devid = ASUS_WMI_DEVID_ALS_ENABLE; |
| 2107 | 2147 | else if (attr == &dev_attr_fan_boost_mode.attr) |
| 2108 | 2148 | ok = asus->fan_boost_mode_available; |
| 2149 | + else if (attr == &dev_attr_charge_threshold.attr) | |
| 2150 | + devid = ASUS_WMI_CHARGE_THRESHOLD; | |
| 2109 | 2151 | |
| 2110 | 2152 | if (devid != -1) |
| 2111 | 2153 | ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); |
| @@ -2434,6 +2476,12 @@ static int asus_wmi_add(struct platform_device *pdev) · 322 unmodified lines | ||
| 2434 | 2476 | } |
| 2435 | 2477 | |
| 2436 | 2478 | asus_wmi_debugfs_init(asus); |
| 2479 | + /* The charge threshold is only reset when the system is power cycled, | |
| 2480 | + * and we can't get the current threshold so let set it to 100% on | |
| 2481 | + * module load. | |
| 2482 | + */ | |
| 2483 | + asus_wmi_set_devstate(ASUS_WMI_CHARGE_THRESHOLD, 100, NULL); | |
| 2484 | + asus->charge_threshold = 100; | |
| 2437 | 2485 | |
| 2438 | 2486 | return 0; |
| 2439 | 2487 | |
| @@ -61,6 +61,7 @@ · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | /* Misc */ |
| 63 | 63 | #define ASUS_WMI_DEVID_CAMERA 0x00060013 |
| 64 | +#define ASUS_WMI_CHARGE_THRESHOLD 0x00120057 | |
| 64 | 65 | |
| 65 | 66 | /* Storage */ |
| 66 | 67 | #define ASUS_WMI_DEVID_CARDREADER 0x00080013 |