Skip to content

Commit 6b930cb

Browse files
marcanjannau
authored andcommitted
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 7128e7f commit 6b930cb

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)
@@ -392,6 +416,16 @@ static int macsmc_battery_get_property(struct power_supply *psy,
392416
case POWER_SUPPLY_PROP_MANUFACTURE_DAY:
393417
ret = macsmc_battery_get_date(&power->mfg_date[4], &val->intval);
394418
break;
419+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
420+
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
421+
val->intval = ret == 1 ? CHWA_FIXED_START_THRESHOLD : 100;
422+
ret = ret < 0 ? ret : 0;
423+
break;
424+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
425+
ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA));
426+
val->intval = ret == 1 ? CHWA_FIXED_END_THRESHOLD : 100;
427+
ret = ret < 0 ? ret : 0;
428+
break;
395429
default:
396430
return -EINVAL;
397431
}
@@ -408,6 +442,16 @@ static int macsmc_battery_set_property(struct power_supply *psy,
408442
switch (psp) {
409443
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
410444
return macsmc_battery_set_charge_behaviour(power, val->intval);
445+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
446+
/*
447+
* Ignore, we allow writes so userspace isn't confused but this is
448+
* not configurable independently, it always is 75 or 100 depending
449+
* on the end_threshold boolean setting.
450+
*/
451+
return 0;
452+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
453+
return apple_smc_write_flag(power->smc, SMC_KEY(CHWA),
454+
val->intval <= CHWA_PROP_WRITE_THRESHOLD);
411455
default:
412456
return -EINVAL;
413457
}
@@ -416,15 +460,20 @@ static int macsmc_battery_set_property(struct power_supply *psy,
416460
static int macsmc_battery_property_is_writeable(struct power_supply *psy,
417461
enum power_supply_property psp)
418462
{
463+
struct macsmc_power *power = power_supply_get_drvdata(psy);
464+
419465
switch (psp) {
420466
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
421467
return true;
468+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
469+
case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
470+
return power->has_chwa;
422471
default:
423472
return false;
424473
}
425474
}
426475

427-
static enum power_supply_property macsmc_battery_props[] = {
476+
static const enum power_supply_property macsmc_battery_props[] = {
428477
POWER_SUPPLY_PROP_STATUS,
429478
POWER_SUPPLY_PROP_PRESENT,
430479
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
@@ -453,6 +502,8 @@ static enum power_supply_property macsmc_battery_props[] = {
453502
POWER_SUPPLY_PROP_MANUFACTURE_YEAR,
454503
POWER_SUPPLY_PROP_MANUFACTURE_MONTH,
455504
POWER_SUPPLY_PROP_MANUFACTURE_DAY,
505+
POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD,
506+
POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD
456507
};
457508

458509
static const struct power_supply_desc macsmc_battery_desc = {
@@ -650,6 +701,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
650701

651702
power->dev = &pdev->dev;
652703
power->smc = smc;
704+
power->batt_desc = macsmc_battery_desc;
653705
dev_set_drvdata(&pdev->dev, power);
654706

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

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

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

0 commit comments

Comments
 (0)