mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 04:11:49 +00:00
platform/x86: thinkpad_acpi: support inhibit-charge
This adds support for the inhibit-charge charge_behaviour through the embedded controller of ThinkPads. Co-developed-by: Thomas Koch <linrunner@gmx.net> Signed-off-by: Thomas Koch <linrunner@gmx.net> Co-developed-by: Nicolò Piazzalunga <nicolopiazzalunga@gmail.com> Signed-off-by: Nicolò Piazzalunga <nicolopiazzalunga@gmail.com> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> Link: https://lore.kernel.org/r/20211123232704.25394-5-linux@weissschuh.net Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
b55d416d48
commit
400cffd5f4
@ -9216,6 +9216,8 @@ static struct ibm_struct mute_led_driver_data = {
|
|||||||
#define SET_STOP "BCSS"
|
#define SET_STOP "BCSS"
|
||||||
#define GET_DISCHARGE "BDSG"
|
#define GET_DISCHARGE "BDSG"
|
||||||
#define SET_DISCHARGE "BDSS"
|
#define SET_DISCHARGE "BDSS"
|
||||||
|
#define GET_INHIBIT "BICG"
|
||||||
|
#define SET_INHIBIT "BICS"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BAT_ANY = 0,
|
BAT_ANY = 0,
|
||||||
@ -9233,6 +9235,7 @@ enum {
|
|||||||
THRESHOLD_START,
|
THRESHOLD_START,
|
||||||
THRESHOLD_STOP,
|
THRESHOLD_STOP,
|
||||||
FORCE_DISCHARGE,
|
FORCE_DISCHARGE,
|
||||||
|
INHIBIT_CHARGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tpacpi_battery_data {
|
struct tpacpi_battery_data {
|
||||||
@ -9304,6 +9307,12 @@ static int tpacpi_battery_get(int what, int battery, int *ret)
|
|||||||
/* The force discharge status is in bit 0 */
|
/* The force discharge status is in bit 0 */
|
||||||
*ret = *ret & 0x01;
|
*ret = *ret & 0x01;
|
||||||
return 0;
|
return 0;
|
||||||
|
case INHIBIT_CHARGE:
|
||||||
|
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:
|
default:
|
||||||
pr_crit("wrong parameter: %d", what);
|
pr_crit("wrong parameter: %d", what);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -9342,6 +9351,22 @@ static int tpacpi_battery_set(int what, int battery, int value)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
return 0;
|
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:
|
default:
|
||||||
pr_crit("wrong parameter: %d", what);
|
pr_crit("wrong parameter: %d", what);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -9389,6 +9414,8 @@ static int tpacpi_battery_probe(int battery)
|
|||||||
* 4) Check for support
|
* 4) Check for support
|
||||||
* 5) Get the current force discharge status
|
* 5) Get the current force discharge status
|
||||||
* 6) Check for support
|
* 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_has_method(hkey_handle, GET_START)) {
|
||||||
if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_START, &ret, battery)) {
|
if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_START, &ret, battery)) {
|
||||||
@ -9435,6 +9462,16 @@ static int tpacpi_battery_probe(int battery)
|
|||||||
battery_info.batteries[battery].charge_behaviours |=
|
battery_info.batteries[battery].charge_behaviours |=
|
||||||
BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE);
|
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 |=
|
battery_info.batteries[battery].charge_behaviours |=
|
||||||
BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO);
|
BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO);
|
||||||
@ -9593,10 +9630,22 @@ static ssize_t charge_behaviour_show(struct device *dev,
|
|||||||
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE)) {
|
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE)) {
|
||||||
if (tpacpi_battery_get(FORCE_DISCHARGE, battery, &ret))
|
if (tpacpi_battery_get(FORCE_DISCHARGE, battery, &ret))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if (ret)
|
if (ret) {
|
||||||
active = POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE;
|
active = POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
return power_supply_charge_behaviour_show(dev, available, active, buf);
|
return power_supply_charge_behaviour_show(dev, available, active, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9633,11 +9682,22 @@ static ssize_t charge_behaviour_store(struct device *dev,
|
|||||||
case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
|
case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
|
||||||
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE))
|
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE))
|
||||||
ret = tpacpi_battery_set_validate(FORCE_DISCHARGE, battery, 0);
|
ret = tpacpi_battery_set_validate(FORCE_DISCHARGE, battery, 0);
|
||||||
|
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE))
|
||||||
|
ret = min(ret, tpacpi_battery_set_validate(INHIBIT_CHARGE, battery, 0));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE:
|
case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE:
|
||||||
ret = tpacpi_battery_set_validate(FORCE_DISCHARGE, battery, 1);
|
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE))
|
||||||
|
ret = tpacpi_battery_set_validate(INHIBIT_CHARGE, battery, 0);
|
||||||
|
ret = min(ret, tpacpi_battery_set_validate(FORCE_DISCHARGE, battery, 1));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
|
||||||
|
if (available & BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE))
|
||||||
|
ret = tpacpi_battery_set_validate(FORCE_DISCHARGE, battery, 0);
|
||||||
|
ret = min(ret, tpacpi_battery_set_validate(INHIBIT_CHARGE, battery, 1));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user