Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Documentation/ABI/testing/sysfs-class-power
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ Description:
inhibit-charge: Do not charge while AC is attached
inhibit-charge-awake: inhibit-charge only when device is awake
force-discharge: Force discharge while AC is attached
auto-discharge: auto, but actively discharge down to
the charge control end threshold
===================== ========================================

What: /sys/class/power_supply/<supply_name>/technology
Expand Down
48 changes: 42 additions & 6 deletions drivers/power/supply/macsmc-power.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ static int macsmc_battery_get_charge_behaviour(struct macsmc_power *power)
int ret;
u8 val8;
u8 chte_buf[4];
u16 vu16;

if (power->has_ch0i) {
ret = apple_smc_read_u8(power->smc, SMC_KEY(CH0I), &val8);
Expand All @@ -319,6 +320,14 @@ static int macsmc_battery_get_charge_behaviour(struct macsmc_power *power)
return POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
}

if (power->has_chls) {
ret = apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16);
if (ret)
return ret;
if (vu16 & CHLS_FORCE_DISCHARGE)
return POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO_DISCHARGE;
}

return POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
}

Expand All @@ -327,6 +336,10 @@ static int macsmc_battery_set_charge_behaviour(struct macsmc_power *power, int v
int ret;

switch (val) {
case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO_DISCHARGE:
if (!power->has_chls)
return -EOPNOTSUPP;
fallthrough;
case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
/* Reset all inhibitors to a known-good 'auto' state */
if (power->has_ch0i) {
Expand All @@ -344,6 +357,20 @@ static int macsmc_battery_set_charge_behaviour(struct macsmc_power *power, int v
if (ret)
return ret;
}

/* Set or clear force-discharge to the CHLS charge limit */
if (power->has_chls) {
u16 vu16;

ret = apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16);
if (ret)
return ret;
if (val == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO_DISCHARGE)
vu16 |= CHLS_FORCE_DISCHARGE;
else
vu16 &= ~CHLS_FORCE_DISCHARGE;
return apple_smc_write_u16(power->smc, SMC_KEY(CHLS), vu16);
}
return 0;

case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
Expand Down Expand Up @@ -606,12 +633,18 @@ static int macsmc_battery_set_property(struct power_supply *psy,
return 0;
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
if (power->has_chls) {
u16 kval = 0;
/* TODO: Make CHLS_FORCE_DISCHARGE configurable */
u16 kval;
int ret;

/* Preserve the force-discharge (auto-discharge) charge_behaviour */
ret = apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &kval);
if (ret)
return ret;
kval &= CHLS_FORCE_DISCHARGE;
if (val->intval < CHLS_MIN_END_THRESHOLD)
kval = CHLS_FORCE_DISCHARGE | CHLS_MIN_END_THRESHOLD;
kval |= CHLS_MIN_END_THRESHOLD;
else if (val->intval < 100)
kval = CHLS_FORCE_DISCHARGE | (val->intval & 0xff);
kval |= val->intval & 0xff;
return apple_smc_write_u16(power->smc, SMC_KEY(CHLS), kval);
} else if (power->has_chwa) {
return apple_smc_write_flag(power->smc, SMC_KEY(CHWA),
Expand Down Expand Up @@ -945,10 +978,13 @@ static int macsmc_power_probe(struct platform_device *pdev)
}

/* Detect charge limit method (CHWA vs CHLS) */
if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA), &flag) == 0)
if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA), &flag) == 0) {
power->has_chwa = true;
else if (apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16) >= 0)
} else if (apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16) >= 0) {
power->has_chls = true;
power->batt_desc.charge_behaviours |=
BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO_DISCHARGE);
}

if (power->has_chwa || power->has_chls) {
props[nprops++] = POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD;
Expand Down
1 change: 1 addition & 0 deletions drivers/power/supply/power_supply_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ static const char * const POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[] = {
[POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE] = "inhibit-charge",
[POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE_AWAKE] = "inhibit-charge-awake",
[POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE] = "force-discharge",
[POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO_DISCHARGE] = "auto-discharge",
};

static struct power_supply_attr power_supply_attrs[] __ro_after_init = {
Expand Down
1 change: 1 addition & 0 deletions include/linux/power_supply.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ enum power_supply_charge_behaviour {
POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE,
POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE_AWAKE,
POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE,
POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO_DISCHARGE,
};

enum power_supply_notifier_events {
Expand Down