Skip to content

Commit 1ff187a

Browse files
marcanjannau
authored andcommitted
power: supply: macsmc_power: Add more properties
Report more voltages from the battery, and also fudge energy numbers from charge numbers. This way userspace doesn't try to convert on its own (and gets it very wrong). Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent 2ace298 commit 1ff187a

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

drivers/power/supply/macsmc_power.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
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+
2031
struct 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

Comments
 (0)