20
20
struct macsmc_power {
21
21
struct device * dev ;
22
22
struct apple_smc * smc ;
23
+ struct power_supply_desc batt_desc ;
23
24
24
25
struct power_supply * batt ;
25
26
char model_name [MAX_STRING_LENGTH ];
26
27
char serial_number [MAX_STRING_LENGTH ];
27
28
char mfg_date [MAX_STRING_LENGTH ];
29
+ bool has_chwa ;
28
30
29
31
struct power_supply * ac ;
30
32
@@ -62,16 +64,22 @@ static struct macsmc_power *g_power;
62
64
63
65
#define CH0R_LOWER_FLAGS GENMASK(15, 0)
64
66
#define CH0R_NOAC_CH0I BIT(0)
67
+ #define CH0R_NOAC_DISCONNECTED BIT(4)
65
68
#define CH0R_NOAC_CH0J BIT(5)
66
69
#define CH0R_BMS_BUSY BIT(8)
67
70
#define CH0R_NOAC_CH0K BIT(9)
71
+ #define CH0R_NOAC_CHWA BIT(11)
68
72
69
73
#define CH0X_CH0C BIT(0)
70
74
#define CH0X_CH0B BIT(1)
71
75
72
76
#define ACSt_CAN_BOOT_AP BIT(2)
73
77
#define ACSt_CAN_BOOT_IBOOT BIT(1)
74
78
79
+ #define CHWA_FIXED_START_THRESHOLD 75
80
+ #define CHWA_FIXED_END_THRESHOLD 80
81
+ #define CHWA_PROP_WRITE_THRESHOLD 95
82
+
75
83
static void macsmc_do_dbg (struct macsmc_power * power )
76
84
{
77
85
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)
107
115
u64 nocharge_flags ;
108
116
u32 nopower_flags ;
109
117
u16 ac_current ;
118
+ bool chwa_limit = false;
110
119
int ret ;
111
120
112
121
/*
@@ -153,14 +162,29 @@ static int macsmc_battery_get_status(struct macsmc_power *power)
153
162
else if (ret )
154
163
return POWER_SUPPLY_STATUS_FULL ;
155
164
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
+
156
177
/* If there are reasons we aren't charging... */
157
178
ret = apple_smc_read_u64 (power -> smc , SMC_KEY (CHNC ), & nocharge_flags );
158
179
if (!ret ) {
159
180
/* Perhaps the battery is full after all */
160
181
if (nocharge_flags & CHNC_BATTERY_FULL )
161
182
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 )
164
188
return POWER_SUPPLY_STATUS_CHARGING ;
165
189
/* If we have other reasons we aren't charging, say we aren't */
166
190
else if (nocharge_flags )
@@ -392,6 +416,16 @@ static int macsmc_battery_get_property(struct power_supply *psy,
392
416
case POWER_SUPPLY_PROP_MANUFACTURE_DAY :
393
417
ret = macsmc_battery_get_date (& power -> mfg_date [4 ], & val -> intval );
394
418
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 ;
395
429
default :
396
430
return - EINVAL ;
397
431
}
@@ -408,6 +442,16 @@ static int macsmc_battery_set_property(struct power_supply *psy,
408
442
switch (psp ) {
409
443
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR :
410
444
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 );
411
455
default :
412
456
return - EINVAL ;
413
457
}
@@ -416,15 +460,20 @@ static int macsmc_battery_set_property(struct power_supply *psy,
416
460
static int macsmc_battery_property_is_writeable (struct power_supply * psy ,
417
461
enum power_supply_property psp )
418
462
{
463
+ struct macsmc_power * power = power_supply_get_drvdata (psy );
464
+
419
465
switch (psp ) {
420
466
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR :
421
467
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 ;
422
471
default :
423
472
return false;
424
473
}
425
474
}
426
475
427
- static enum power_supply_property macsmc_battery_props [] = {
476
+ static const enum power_supply_property macsmc_battery_props [] = {
428
477
POWER_SUPPLY_PROP_STATUS ,
429
478
POWER_SUPPLY_PROP_PRESENT ,
430
479
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR ,
@@ -453,6 +502,8 @@ static enum power_supply_property macsmc_battery_props[] = {
453
502
POWER_SUPPLY_PROP_MANUFACTURE_YEAR ,
454
503
POWER_SUPPLY_PROP_MANUFACTURE_MONTH ,
455
504
POWER_SUPPLY_PROP_MANUFACTURE_DAY ,
505
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD ,
506
+ POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD
456
507
};
457
508
458
509
static const struct power_supply_desc macsmc_battery_desc = {
@@ -650,6 +701,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
650
701
651
702
power -> dev = & pdev -> dev ;
652
703
power -> smc = smc ;
704
+ power -> batt_desc = macsmc_battery_desc ;
653
705
dev_set_drvdata (& pdev -> dev , power );
654
706
655
707
/* Ignore devices without a charger/battery */
@@ -665,11 +717,18 @@ static int macsmc_power_probe(struct platform_device *pdev)
665
717
apple_smc_write_u8 (power -> smc , SMC_KEY (CH0K ), 0 );
666
718
apple_smc_write_u8 (power -> smc , SMC_KEY (CH0B ), 0 );
667
719
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
+
668
727
/* Doing one read of this flag enables critical shutdown notifications */
669
728
apple_smc_read_u32 (power -> smc , SMC_KEY (BCF0 ), & val );
670
729
671
730
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 );
673
732
if (IS_ERR (power -> batt )) {
674
733
dev_err (& pdev -> dev , "Failed to register battery\n" );
675
734
ret = PTR_ERR (power -> batt );
0 commit comments