Skip to content

Commit 107ed86

Browse files
committed
power: supply: macsmc_power: Add CHWA charge thresholds
This is a hardcoded charge threshold feature present in firmware 13.0 or newer. Userspace settings are rounded to one of the two possible behaviors. Signed-off-by: Hector Martin <[email protected]>
1 parent bc095b4 commit 107ed86

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

drivers/power/supply/macsmc_power.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020
struct macsmc_power {
2121
struct device *dev;
2222
struct apple_smc *smc;
23+
struct power_supply_desc batt_desc;
2324

2425
struct power_supply *batt;
2526
char model_name[MAX_STRING_LENGTH];
2627
char serial_number[MAX_STRING_LENGTH];
2728
char mfg_date[MAX_STRING_LENGTH];
29+
bool has_chwa;
2830

2931
struct power_supply *ac;
3032

@@ -62,16 +64,22 @@ static struct macsmc_power *g_power;
6264

6365
#define CH0R_LOWER_FLAGS GENMASK(15, 0)
6466
#define CH0R_NOAC_CH0I BIT(0)
67+
#define CH0R_NOAC_DISCONNECTED BIT(4)
6568
#define CH0R_NOAC_CH0J BIT(5)
6669
#define CH0R_BMS_BUSY BIT(8)
6770
#define CH0R_NOAC_CH0K BIT(9)
71+
#define CH0R_NOAC_CHWA BIT(11)
6872

6973
#define CH0X_CH0C BIT(0)
7074
#define CH0X_CH0B BIT(1)
7175

7276
#define ACSt_CAN_BOOT_AP BIT(2)
7377
#define ACSt_CAN_BOOT_IBOOT BIT(1)
7478

79+
#define CHWA_FIXED_START_THRESHOLD 75
80+
#define CHWA_FIXED_END_THRESHOLD 80
81+
#define CHWA_PROP_WRITE_THRESHOLD 95
82+
7583
static void macsmc_do_dbg(struct macsmc_power *power)
7684
{
7785
int p_in = 0, p_sys = 0, p_3v8 = 0, p_mpmu = 0, p_spmu = 0, p_clvr = 0, p_cpu = 0;
@@ -107,6 +115,7 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
107115
u64 nocharge_flags;
108116
u32 nopower_flags;
109117
u16 ac_current;
118+
bool chwa_limit = false;
110119
int ret;
111120

112121
/*
@@ -153,14 +162,29 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
153162
else if (ret)
154163
return POWER_SUPPLY_STATUS_FULL;
155164

165+
/*
166+
* If we have charge limits supported and enabled and the SoC is > 75%,
167+
* that means we are not charging for that reason (if not charging).
168+
*/
169+
if (power->has_chwa && apple_smc_read_flag(power->smc, SMC_KEY(CHWA)) == 1) {
170+
u8 buic = 0;
171+
172+
if (apple_smc_read_u8(power->smc, SMC_KEY(BUIC), &buic) >= 0 &&
173+
buic >= CHWA_FIXED_START_THRESHOLD)
174+
chwa_limit = true;
175+
}
176+
156177
/* If there are reasons we aren't charging... */
157178
ret = apple_smc_read_u64(power->smc, SMC_KEY(CHNC), &nocharge_flags);
158179
if (!ret) {
159180
/* Perhaps the battery is full after all */
160181
if (nocharge_flags & CHNC_BATTERY_FULL)
161182
return POWER_SUPPLY_STATUS_FULL;
162-
/* Or maybe the BMS is just busy doing something, if so call it charging anyway */
163-
else if (nocharge_flags == CHNC_BMS_BUSY)
183+
/*
184+
* Or maybe the BMS is just busy doing something, if so call it charging anyway.
185+
* But CHWA limits show up as this, so exclude those.
186+
*/
187+
else if (nocharge_flags == CHNC_BMS_BUSY && !chwa_limit)
164188
return POWER_SUPPLY_STATUS_CHARGING;
165189
/* If we have other reasons we aren't charging, say we aren't */
166190
else if (nocharge_flags)
@@ -393,6 +417,16 @@ static int macsmc_battery_get_property(struct power_supply *psy,
393417
case POWER_SUPPLY_PROP_MANUFACTURE_DAY:
394418
ret = macsmc_battery_get_date(&power->mfg_date[4], &val->intval);
395419
break;
420+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
421+
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
422+
val->intval = ret == 1 ? CHWA_FIXED_START_THRESHOLD : 100;
423+
ret = ret < 0 ? ret : 0;
424+
break;
425+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
426+
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
427+
val->intval = ret == 1 ? CHWA_FIXED_END_THRESHOLD : 100;
428+
ret = ret < 0 ? ret : 0;
429+
break;
396430
default:
397431
return -EINVAL;
398432
}
@@ -409,6 +443,16 @@ static int macsmc_battery_set_property(struct power_supply *psy,
409443
switch (psp) {
410444
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
411445
return macsmc_battery_set_charge_behaviour(power, val->intval);
446+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
447+
/*
448+
* Ignore, we allow writes so userspace isn't confused but this is
449+
* not configurable independently, it always is 75 or 100 depending
450+
* on the end_threshold boolean setting.
451+
*/
452+
return 0;
453+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
454+
return apple_smc_write_flag(power->smc, SMC_KEY(CHWA),
455+
val->intval <= CHWA_PROP_WRITE_THRESHOLD);
412456
default:
413457
return -EINVAL;
414458
}
@@ -417,15 +461,20 @@ static int macsmc_battery_set_property(struct power_supply *psy,
417461
static int macsmc_battery_property_is_writeable(struct power_supply *psy,
418462
enum power_supply_property psp)
419463
{
464+
struct macsmc_power *power = power_supply_get_drvdata(psy);
465+
420466
switch (psp) {
421467
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
422468
return true;
469+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
470+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
471+
return power->has_chwa;
423472
default:
424473
return false;
425474
}
426475
}
427476

428-
static enum power_supply_property macsmc_battery_props[] = {
477+
static const enum power_supply_property macsmc_battery_props[] = {
429478
POWER_SUPPLY_PROP_STATUS,
430479
POWER_SUPPLY_PROP_PRESENT,
431480
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
@@ -454,6 +503,8 @@ static enum power_supply_property macsmc_battery_props[] = {
454503
POWER_SUPPLY_PROP_MANUFACTURE_YEAR,
455504
POWER_SUPPLY_PROP_MANUFACTURE_MONTH,
456505
POWER_SUPPLY_PROP_MANUFACTURE_DAY,
506+
POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD,
507+
POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD
457508
};
458509

459510
static const struct power_supply_desc macsmc_battery_desc = {
@@ -651,6 +702,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
651702

652703
power->dev = &pdev->dev;
653704
power->smc = smc;
705+
power->batt_desc = macsmc_battery_desc;
654706
dev_set_drvdata(&pdev->dev, power);
655707

656708
/* Ignore devices without a charger/battery */
@@ -666,11 +718,18 @@ static int macsmc_power_probe(struct platform_device *pdev)
666718
apple_smc_write_u8(power->smc, SMC_KEY(CH0K), 0);
667719
apple_smc_write_u8(power->smc, SMC_KEY(CH0B), 0);
668720

721+
if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA)) >= 0) {
722+
power->has_chwa = true;
723+
} else {
724+
/* Remove the last 2 properties that control the charge threshold */
725+
power->batt_desc.num_properties -= 2;
726+
}
727+
669728
/* Doing one read of this flag enables critical shutdown notifications */
670729
apple_smc_read_u32(power->smc, SMC_KEY(BCF0), &val);
671730

672731
psy_cfg.drv_data = power;
673-
power->batt = devm_power_supply_register(&pdev->dev, &macsmc_battery_desc, &psy_cfg);
732+
power->batt = devm_power_supply_register(&pdev->dev, &power->batt_desc, &psy_cfg);
674733
if (IS_ERR(power->batt)) {
675734
dev_err(&pdev->dev, "Failed to register battery\n");
676735
ret = PTR_ERR(power->batt);

0 commit comments

Comments
 (0)