1717
1818#define MAX_STRING_LENGTH 256
1919
20+ /*
21+ * This number is not reported anywhere by SMC, but seems to be a good
22+ * conversion factor for charge to energy across machines. We need this
23+ * to convert in the driver, since if we don't userspace will try to do
24+ * the conversion with a randomly guessed voltage and get it wrong.
25+ *
26+ * Ideally there would be a power supply prop to inform userspace of this
27+ * number, but there isn't, only min/max.
28+ */
29+ #define MACSMC_NOMINAL_CELL_VOLTAGE_MV 3800
30+
2031struct macsmc_power {
2132 struct device * dev ;
2233 struct apple_smc * smc ;
@@ -27,6 +38,8 @@ struct macsmc_power {
2738 char serial_number [MAX_STRING_LENGTH ];
2839 char mfg_date [MAX_STRING_LENGTH ];
2940 bool has_chwa ;
41+ u8 num_cells ;
42+ int nominal_voltage_mv ;
3043
3144 struct power_supply * ac ;
3245
@@ -352,6 +365,29 @@ static int macsmc_battery_get_property(struct power_supply *psy,
352365 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (BITV ), & vu16 );
353366 val -> intval = vu16 * 1000 ;
354367 break ;
368+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN :
369+ /*
370+ * Battery cell max voltage? BVV* seem to return per-cell voltages,
371+ * BVV[NOP] are probably the max voltages for the 3 cells but we don't
372+ * know what will happen if they ever change the number of cells.
373+ * So go with BVVN and multiply by the cell count (BNCB).
374+ * BVVL seems to be the per-cell limit adjusted dynamically.
375+ * Guess: BVVL = Limit, BVVN = Nominal, and the other cells got filled
376+ * in around nearby letters?
377+ */
378+ ret = apple_smc_read_u16 (power -> smc , SMC_KEY (BVVN ), & vu16 );
379+ val -> intval = vu16 * 1000 * power -> num_cells ;
380+ break ;
381+ case POWER_SUPPLY_PROP_VOLTAGE_MIN :
382+ /* Lifetime min */
383+ ret = apple_smc_read_s16 (power -> smc , SMC_KEY (BLPM ), & vs16 );
384+ val -> intval = vs16 * 1000 ;
385+ break ;
386+ case POWER_SUPPLY_PROP_VOLTAGE_MAX :
387+ /* Lifetime max */
388+ ret = apple_smc_read_s16 (power -> smc , SMC_KEY (BLPX ), & vs16 );
389+ val -> intval = vs16 * 1000 ;
390+ break ;
355391 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT :
356392 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0RC ), & vu16 );
357393 val -> intval = vu16 * 1000 ;
@@ -380,6 +416,18 @@ static int macsmc_battery_get_property(struct power_supply *psy,
380416 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0RM ), & vu16 );
381417 val -> intval = swab16 (vu16 ) * 1000 ;
382418 break ;
419+ case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN :
420+ ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0DC ), & vu16 );
421+ val -> intval = vu16 * power -> nominal_voltage_mv ;
422+ break ;
423+ case POWER_SUPPLY_PROP_ENERGY_FULL :
424+ ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0FC ), & vu16 );
425+ val -> intval = vu16 * power -> nominal_voltage_mv ;
426+ break ;
427+ case POWER_SUPPLY_PROP_ENERGY_NOW :
428+ ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0RM ), & vu16 );
429+ val -> intval = swab16 (vu16 ) * power -> nominal_voltage_mv ;
430+ break ;
383431 case POWER_SUPPLY_PROP_TEMP :
384432 ret = apple_smc_read_u16 (power -> smc , SMC_KEY (B0AT ), & vu16 );
385433 val -> intval = vu16 - 2732 ;
@@ -485,13 +533,19 @@ static const enum power_supply_property macsmc_battery_props[] = {
485533 POWER_SUPPLY_PROP_CURRENT_NOW ,
486534 POWER_SUPPLY_PROP_POWER_NOW ,
487535 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ,
536+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ,
537+ POWER_SUPPLY_PROP_VOLTAGE_MIN ,
538+ POWER_SUPPLY_PROP_VOLTAGE_MAX ,
488539 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT ,
489540 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ,
490541 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX ,
491542 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE ,
492543 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN ,
493544 POWER_SUPPLY_PROP_CHARGE_FULL ,
494545 POWER_SUPPLY_PROP_CHARGE_NOW ,
546+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN ,
547+ POWER_SUPPLY_PROP_ENERGY_FULL ,
548+ POWER_SUPPLY_PROP_ENERGY_NOW ,
495549 POWER_SUPPLY_PROP_TEMP ,
496550 POWER_SUPPLY_PROP_CHARGE_COUNTER ,
497551 POWER_SUPPLY_PROP_CYCLE_COUNT ,
@@ -727,6 +781,9 @@ static int macsmc_power_probe(struct platform_device *pdev)
727781 power -> batt_desc .num_properties -= 2 ;
728782 }
729783
784+ apple_smc_read_u8 (power -> smc , SMC_KEY (BNCB ), & power -> num_cells );
785+ power -> nominal_voltage_mv = MACSMC_NOMINAL_CELL_VOLTAGE_MV * power -> num_cells ;
786+
730787 /* Doing one read of this flag enables critical shutdown notifications */
731788 apple_smc_read_u32 (power -> smc , SMC_KEY (BCF0 ), & val );
732789
0 commit comments