2020struct 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+
7583static 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,
416460static 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
458509static 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