@@ -86,6 +86,11 @@ struct macsmc_power {
8686 bool has_ch0i ; /* Force discharge (Older firmware) */
8787 bool has_ch0c ; /* Inhibit charge (Older firmware) */
8888 bool has_chte ; /* Inhibit charge (Modern firmware) */
89+ /*
90+ * Battery critical key is 1 byte and charge key is little endian
91+ * (Modern firmware)
92+ */
93+ bool fw_ge_27 ;
8994
9095 u8 num_cells ;
9196 int nominal_voltage_mv ;
@@ -273,14 +278,28 @@ static int macsmc_battery_get_date(const char *s, int *out)
273278 return 0 ;
274279}
275280
281+ static int macsmc_battery_read_bcf0 (struct macsmc_power * power , u32 * val )
282+ {
283+ u8 tval = 0 ;
284+ int ret ;
285+
286+ if (power -> fw_ge_27 ) {
287+ ret = apple_smc_read_u8 (power -> smc , SMC_KEY (BCF0 ), & tval );
288+ * val = tval ;
289+ return ret ;
290+ }
291+
292+ return apple_smc_read_u32 (power -> smc , SMC_KEY (BCF0 ), val );
293+ }
294+
276295static int macsmc_battery_get_capacity_level (struct macsmc_power * power )
277296{
278297 bool flag ;
279298 u32 val ;
280299 int ret ;
281300
282301 /* Check for emergency shutdown condition */
283- if (apple_smc_read_u32 (power -> smc , SMC_KEY ( BCF0 ) , & val ) >= 0 && val )
302+ if (macsmc_battery_read_bcf0 (power , & val ) >= 0 && val )
284303 return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL ;
285304
286305 /* Check AC status for whether we could boot in this state */
@@ -303,6 +322,12 @@ static int macsmc_battery_get_capacity_level(struct macsmc_power *power)
303322 return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL ;
304323}
305324
325+ static s16 macsmc_swap_b0rm (struct macsmc_power * power , s16 b0rm )
326+ {
327+ /* B0RM was Big Endian, likely pass through from TI gas gauge */
328+ return power -> fw_ge_27 ? b0rm : (s16 )swab16 (b0rm );
329+ }
330+
306331static int macsmc_battery_get_property (struct power_supply * psy ,
307332 enum power_supply_property psp ,
308333 union power_supply_propval * val )
@@ -397,8 +422,7 @@ static int macsmc_battery_get_property(struct power_supply *psy,
397422 break ;
398423 case POWER_SUPPLY_PROP_CHARGE_NOW :
399424 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0RM ), & vu16 );
400- /* B0RM is Big Endian, likely pass through from TI gas gauge */
401- val -> intval = (s16 )swab16 (vu16 ) * 1000 ;
425+ val -> intval = macsmc_swap_b0rm (power , vu16 ) * 1000 ;
402426 break ;
403427 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN :
404428 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0DC ), & vu16 );
@@ -410,8 +434,7 @@ static int macsmc_battery_get_property(struct power_supply *psy,
410434 break ;
411435 case POWER_SUPPLY_PROP_ENERGY_NOW :
412436 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0RM ), & vu16 );
413- /* B0RM is Big Endian, likely pass through from TI gas gauge */
414- val -> intval = (s16 )swab16 (vu16 ) * power -> nominal_voltage_mv ;
437+ val -> intval = macsmc_swap_b0rm (power , vu16 ) * power -> nominal_voltage_mv ;
415438 break ;
416439 case POWER_SUPPLY_PROP_TEMP :
417440 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0AT ), & vu16 );
@@ -577,7 +600,7 @@ static void macsmc_power_critical_work(struct work_struct *wrk)
577600 * Check if SMC flagged the battery as empty.
578601 * We trigger a graceful shutdown to let the OS save data.
579602 */
580- if (apple_smc_read_u32 (power -> smc , SMC_KEY ( BCF0 ) , & bcf0 ) == 0 && bcf0 != 0 ) {
603+ if (macsmc_battery_read_bcf0 (power , & bcf0 ) == 0 && bcf0 != 0 ) {
581604 power -> orderly_shutdown_triggered = true;
582605 dev_crit (power -> dev , "Battery critical (empty flag set). Triggering orderly shutdown.\n" );
583606 orderly_poweroff (true);
@@ -616,6 +639,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
616639 struct device * dev = & pdev -> dev ;
617640 struct apple_smc * smc = dev_get_drvdata (pdev -> dev .parent );
618641 struct power_supply_config psy_cfg = {};
642+ struct apple_smc_key_info info ;
619643 struct macsmc_power * power ;
620644 bool has_battery = false;
621645 bool has_ac_adapter = false;
@@ -714,6 +738,20 @@ static int macsmc_power_probe(struct platform_device *pdev)
714738 if (apple_smc_key_exists (smc , SMC_KEY (CH0I )))
715739 power -> has_ch0i = true;
716740
741+ ret = apple_smc_get_key_info (power -> smc , SMC_KEY (BCF0 ), & info );
742+ if (ret ) {
743+ dev_err (& pdev -> dev , "Failed to determine BCF0 key size\n" );
744+ return ret ;
745+ }
746+ if (info .size == 1 )
747+ power -> fw_ge_27 = true;
748+ else if (info .size == 4 )
749+ power -> fw_ge_27 = false;
750+ else {
751+ dev_err (& pdev -> dev , "Unexpected BCF0 key size %d\n" , info .size );
752+ return - EIO ;
753+ }
754+
717755 /* Reset "Optimised Battery Charging" flags to default state */
718756 if (power -> has_chte )
719757 apple_smc_write_u32 (smc , SMC_KEY (CHTE ), 0 );
@@ -766,7 +804,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
766804 power -> nominal_voltage_mv = MACSMC_NOMINAL_CELL_VOLTAGE_MV * power -> num_cells ;
767805
768806 /* Enable critical shutdown notifications by reading status once */
769- apple_smc_read_u32 (power -> smc , SMC_KEY ( BCF0 ) , & val32 );
807+ macsmc_battery_read_bcf0 (power , & val32 );
770808
771809 psy_cfg .drv_data = power ;
772810 power -> batt = devm_power_supply_register (dev , & power -> batt_desc , & psy_cfg );
0 commit comments