Skip to content

Commit 9e19732

Browse files
marcanjannau
authored andcommitted
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. Prefer CHWA over CHLS since the SMC firmware from iBoot-10151.1.1 (macOS 14.0) is not compatible with our CHGLS usage. It was working with the SMC firmware from iBoot-10151.121.1 (macOS 14.5). Signed-off-by: Hector Martin <marcan@marcan.st> Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 7949af4 commit 9e19732

1 file changed

Lines changed: 46 additions & 14 deletions

File tree

drivers/power/supply/macsmc_power.c

Lines changed: 46 additions & 14 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,8 +800,14 @@ 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

803+
/*
804+
* Prefer CHWA as the SMC firmware from iBoot-10151.1.1 is not compatible with
805+
* this CHLS usage.
806+
*/
777807
if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA)) >= 0) {
778808
power->has_chwa = true;
809+
} else if (apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16) >= 0) {
810+
power->has_chls = true;
779811
} else {
780812
/* Remove the last 2 properties that control the charge threshold */
781813
power->batt_desc.num_properties -= 2;

0 commit comments

Comments
 (0)