Skip to content

Commit c6ccbdd

Browse files
committed
power: supply: macsmc_power: Add CHLS charge thresholds
Since macOS Sequoia firmware, CHLS replaced CHWA and now allows an arbitrary end charge threshold to be configured. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent 8a4051e commit c6ccbdd

1 file changed

Lines changed: 43 additions & 15 deletions

File tree

drivers/power/supply/macsmc_power.c

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct macsmc_power {
3838
char serial_number[MAX_STRING_LENGTH];
3939
char mfg_date[MAX_STRING_LENGTH];
4040
bool has_chwa;
41+
bool has_chls;
4142
u8 num_cells;
4243
int nominal_voltage_mv;
4344

@@ -72,6 +73,7 @@ static struct macsmc_power *g_power;
7273
#define CHNC_NOCHG_CH0B_CH0K BIT(15)
7374
#define CHNC_BATTERY_FULL_2 BIT(18)
7475
#define CHNC_BMS_BUSY BIT(23)
76+
#define CHNC_CHLS_LIMIT BIT(24)
7577
#define CHNC_NOAC_CH0J BIT(53)
7678
#define CHNC_NOAC_CH0I BIT(54)
7779

@@ -89,7 +91,9 @@ static struct macsmc_power *g_power;
8991
#define ACSt_CAN_BOOT_AP BIT(2)
9092
#define ACSt_CAN_BOOT_IBOOT BIT(1)
9193

92-
#define CHWA_FIXED_START_THRESHOLD 75
94+
#define CHWA_CHLS_FIXED_START_OFFSET 5
95+
#define CHLS_MIN_END_THRESHOLD 10
96+
#define CHLS_FORCE_DISCHARGE 0x100
9397
#define CHWA_FIXED_END_THRESHOLD 80
9498
#define CHWA_PROP_WRITE_THRESHOLD 95
9599

@@ -183,7 +187,7 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
183187
u8 buic = 0;
184188

185189
if (apple_smc_read_u8(power->smc, SMC_KEY(BUIC), &buic) >= 0 &&
186-
buic >= CHWA_FIXED_START_THRESHOLD)
190+
buic >= (CHWA_FIXED_END_THRESHOLD - CHWA_CHLS_FIXED_START_OFFSET))
187191
chwa_limit = true;
188192
}
189193

@@ -465,14 +469,23 @@ static int macsmc_battery_get_property(struct power_supply *psy,
465469
ret = macsmc_battery_get_date(&power->mfg_date[4], &val->intval);
466470
break;
467471
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
468-
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
469-
val->intval = ret == 1 ? CHWA_FIXED_START_THRESHOLD : 100;
470-
ret = ret < 0 ? ret : 0;
471-
break;
472472
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
473-
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
474-
val->intval = ret == 1 ? CHWA_FIXED_END_THRESHOLD : 100;
475-
ret = ret < 0 ? ret : 0;
473+
if (power->has_chls) {
474+
ret = apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16);
475+
val->intval = vu16 & 0xff;
476+
if (val->intval < CHLS_MIN_END_THRESHOLD || val->intval >= 100)
477+
val->intval = 100;
478+
}
479+
else if (power->has_chwa) {
480+
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
481+
val->intval = ret == 1 ? CHWA_FIXED_END_THRESHOLD : 100;
482+
ret = ret < 0 ? ret : 0;
483+
} else {
484+
return -EINVAL;
485+
}
486+
if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD &&
487+
ret >= 0 && val->intval < 100 && val->intval >= CHLS_MIN_END_THRESHOLD)
488+
val->intval -= CHWA_CHLS_FIXED_START_OFFSET;
476489
break;
477490
default:
478491
return -EINVAL;
@@ -493,13 +506,25 @@ static int macsmc_battery_set_property(struct power_supply *psy,
493506
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
494507
/*
495508
* Ignore, we allow writes so userspace isn't confused but this is
496-
* not configurable independently, it always is 75 or 100 depending
497-
* on the end_threshold boolean setting.
509+
* not configurable independently, it always is end - 5 or 100 depending
510+
* on the end_threshold setting.
498511
*/
499512
return 0;
500513
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
501-
return apple_smc_write_flag(power->smc, SMC_KEY(CHWA),
502-
val->intval <= CHWA_PROP_WRITE_THRESHOLD);
514+
if (power->has_chls) {
515+
u16 kval = 0;
516+
/* TODO: Make CHLS_FORCE_DISCHARGE configurable */
517+
if (val->intval < CHLS_MIN_END_THRESHOLD)
518+
kval = CHLS_FORCE_DISCHARGE | CHLS_MIN_END_THRESHOLD;
519+
else if (val->intval < 100)
520+
kval = CHLS_FORCE_DISCHARGE | (val->intval & 0xff);
521+
return apple_smc_write_u16(power->smc, SMC_KEY(CHLS), kval);
522+
} else if (power->has_chwa) {
523+
return apple_smc_write_flag(power->smc, SMC_KEY(CHWA),
524+
val->intval <= CHWA_PROP_WRITE_THRESHOLD);
525+
} else {
526+
return -EINVAL;
527+
}
503528
default:
504529
return -EINVAL;
505530
}
@@ -515,7 +540,7 @@ static int macsmc_battery_property_is_writeable(struct power_supply *psy,
515540
return true;
516541
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
517542
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
518-
return power->has_chwa;
543+
return power->has_chwa || power->has_chls;
519544
default:
520545
return false;
521546
}
@@ -750,6 +775,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
750775
struct power_supply_config psy_cfg = {};
751776
struct macsmc_power *power;
752777
u32 val;
778+
u16 vu16;
753779
int ret;
754780

755781
power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);
@@ -774,7 +800,9 @@ static int macsmc_power_probe(struct platform_device *pdev)
774800
apple_smc_write_u8(power->smc, SMC_KEY(CH0K), 0);
775801
apple_smc_write_u8(power->smc, SMC_KEY(CH0B), 0);
776802

777-
if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA)) >= 0) {
803+
if (apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16) >= 0) {
804+
power->has_chls = true;
805+
} else if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA)) >= 0) {
778806
power->has_chwa = true;
779807
} else {
780808
/* Remove the last 2 properties that control the charge threshold */

0 commit comments

Comments
 (0)