xref: /linux/drivers/power/supply/macsmc-power.c (revision fab183d632628381b466a41479489541ac0e29a0)
1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
2 /*
3  * Apple SMC Power/Battery Management Driver
4  *
5  * This driver exposes battery telemetry (voltage, current, temperature, health)
6  * and AC adapter status provided by the Apple SMC (System Management Controller)
7  * on Apple Silicon systems.
8  *
9  * Copyright The Asahi Linux Contributors
10  */
11 
12 #include <linux/ctype.h>
13 #include <linux/delay.h>
14 #include <linux/devm-helpers.h>
15 #include <linux/limits.h>
16 #include <linux/module.h>
17 #include <linux/mfd/macsmc.h>
18 #include <linux/notifier.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <linux/power_supply.h>
22 #include <linux/reboot.h>
23 #include <linux/workqueue.h>
24 
25 #define MAX_STRING_LENGTH 256
26 
27 /*
28  * The SMC reports charge in mAh (Coulombs) but energy in mWh (Joules).
29  * We lack a register for "Nominal Voltage" or "Energy Accumulator".
30  * We use a fixed 3.8V/cell constant to approximate energy stats for userspace,
31  * derived from empirical data across supported MacBook models.
32  */
33 #define MACSMC_NOMINAL_CELL_VOLTAGE_MV 3800
34 
35 /* SMC Key Flags */
36 #define CHNC_BATTERY_FULL	BIT(0)
37 #define CHNC_NO_CHARGER		BIT(7)
38 #define CHNC_NOCHG_CH0C		BIT(14)
39 #define CHNC_NOCHG_CH0B_CH0K	BIT(15)
40 #define CHNC_BATTERY_FULL_2	BIT(18)
41 #define CHNC_BMS_BUSY		BIT(23)
42 #define CHNC_CHLS_LIMIT		BIT(24)
43 #define CHNC_NOAC_CH0J		BIT(53)
44 #define CHNC_NOAC_CH0I		BIT(54)
45 
46 #define CH0R_LOWER_FLAGS	GENMASK(15, 0)
47 #define CH0R_NOAC_CH0I		BIT(0)
48 #define CH0R_NOAC_DISCONNECTED	BIT(4)
49 #define CH0R_NOAC_CH0J		BIT(5)
50 #define CH0R_BMS_BUSY		BIT(8)
51 #define CH0R_NOAC_CH0K		BIT(9)
52 #define CH0R_NOAC_CHWA		BIT(11)
53 
54 #define CH0X_CH0C		BIT(0)
55 #define CH0X_CH0B		BIT(1)
56 
57 #define ACSt_CAN_BOOT_AP	BIT(2)
58 #define ACSt_CAN_BOOT_IBOOT	BIT(1)
59 
60 #define CHWA_CHLS_FIXED_START_OFFSET	5
61 #define CHLS_MIN_END_THRESHOLD		10
62 #define CHLS_FORCE_DISCHARGE		0x100
63 #define CHWA_FIXED_END_THRESHOLD	80
64 #define CHWA_PROP_WRITE_THRESHOLD	95
65 
66 #define MACSMC_MAX_BATT_PROPS		50
67 #define MACSMC_MAX_AC_PROPS		10
68 
69 struct macsmc_power {
70 	struct device *dev;
71 	struct apple_smc *smc;
72 
73 	struct power_supply_desc ac_desc;
74 	struct power_supply_desc batt_desc;
75 
76 	struct power_supply *batt;
77 	struct power_supply *ac;
78 
79 	char model_name[MAX_STRING_LENGTH];
80 	char serial_number[MAX_STRING_LENGTH];
81 	char mfg_date[MAX_STRING_LENGTH];
82 
83 	/* Supported feature flags based on SMC key presence */
84 	bool has_chwa; /* Charge limit (Modern firmware) */
85 	bool has_chls; /* Charge limit (Older firmware) */
86 	bool has_ch0i; /* Force discharge (Older firmware) */
87 	bool has_ch0c; /* Inhibit charge (Older firmware) */
88 	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;
94 
95 	u8 num_cells;
96 	int nominal_voltage_mv;
97 
98 	struct notifier_block nb;
99 	struct work_struct critical_work;
100 	bool emergency_shutdown_triggered;
101 	bool orderly_shutdown_triggered;
102 };
103 
macsmc_battery_get_status(struct macsmc_power * power)104 static int macsmc_battery_get_status(struct macsmc_power *power)
105 {
106 	u64 nocharge_flags;
107 	u32 nopower_flags;
108 	u16 ac_current;
109 	int charge_limit = 0;
110 	bool limited = false;
111 	bool flag;
112 	int ret;
113 
114 	/*
115 	 * B0AV (Voltage) is fundamental. If we can't read it, we assume the
116 	 * battery is gone. CHCE (Hardware charger present) / CHCC (Hardware
117 	 * charger capable) are fundamental status flags.
118 	 * BSFC (System full charge) / CHSC (System charging) are fundamental
119 	 * status flags.
120 	 */
121 
122 	/* Check if power input is inhibited (e.g. BMS balancing cycle) */
123 	ret = apple_smc_read_u32(power->smc, SMC_KEY(CH0R), &nopower_flags);
124 	if (!ret && (nopower_flags & CH0R_LOWER_FLAGS & ~CH0R_BMS_BUSY))
125 		return POWER_SUPPLY_STATUS_DISCHARGING;
126 
127 	/* Check if charger is present */
128 	ret = apple_smc_read_flag(power->smc, SMC_KEY(CHCE), &flag);
129 	if (ret < 0)
130 		return ret;
131 	if (!flag)
132 		return POWER_SUPPLY_STATUS_DISCHARGING;
133 
134 	/* Check if AC is charge capable */
135 	ret = apple_smc_read_flag(power->smc, SMC_KEY(CHCC), &flag);
136 	if (ret < 0)
137 		return ret;
138 	if (!flag)
139 		return POWER_SUPPLY_STATUS_DISCHARGING;
140 
141 	/* Check if AC input limit is too low */
142 	ret = apple_smc_read_u16(power->smc, SMC_KEY(AC-i), &ac_current);
143 	if (!ret && ac_current < 100)
144 		return POWER_SUPPLY_STATUS_DISCHARGING;
145 
146 	/* Check if battery is full */
147 	ret = apple_smc_read_flag(power->smc, SMC_KEY(BSFC), &flag);
148 	if (ret < 0)
149 		return ret;
150 	if (flag)
151 		return POWER_SUPPLY_STATUS_FULL;
152 
153 	/* Check for user-defined charge limits */
154 	if (power->has_chls) {
155 		u16 vu16;
156 
157 		ret = apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16);
158 		if (ret == 0 && (vu16 & 0xff) >= CHLS_MIN_END_THRESHOLD)
159 			charge_limit = (vu16 & 0xff) - CHWA_CHLS_FIXED_START_OFFSET;
160 	} else if (power->has_chwa) {
161 		ret = apple_smc_read_flag(power->smc, SMC_KEY(CHWA), &flag);
162 		if (ret == 0 && flag)
163 			charge_limit = CHWA_FIXED_END_THRESHOLD - CHWA_CHLS_FIXED_START_OFFSET;
164 	}
165 
166 	if (charge_limit > 0) {
167 		u8 buic = 0;
168 
169 		if (apple_smc_read_u8(power->smc, SMC_KEY(BUIC), &buic) >= 0 &&
170 		    buic >= charge_limit)
171 			limited = true;
172 	}
173 
174 	/* Check charging inhibitors */
175 	ret = apple_smc_read_u64(power->smc, SMC_KEY(CHNC), &nocharge_flags);
176 	if (!ret) {
177 		if (nocharge_flags & CHNC_BATTERY_FULL)
178 			return POWER_SUPPLY_STATUS_FULL;
179 		/* BMS busy shows up as inhibit, but we treat it as charging */
180 		else if (nocharge_flags == CHNC_BMS_BUSY && !limited)
181 			return POWER_SUPPLY_STATUS_CHARGING;
182 		else if (nocharge_flags)
183 			return POWER_SUPPLY_STATUS_NOT_CHARGING;
184 		else
185 			return POWER_SUPPLY_STATUS_CHARGING;
186 	}
187 
188 	/* Fallback: System charging flag */
189 	ret = apple_smc_read_flag(power->smc, SMC_KEY(CHSC), &flag);
190 	if (ret < 0)
191 		return ret;
192 	if (!flag)
193 		return POWER_SUPPLY_STATUS_NOT_CHARGING;
194 
195 	return POWER_SUPPLY_STATUS_CHARGING;
196 }
197 
macsmc_battery_get_charge_behaviour(struct macsmc_power * power)198 static int macsmc_battery_get_charge_behaviour(struct macsmc_power *power)
199 {
200 	int ret;
201 	u8 val8;
202 	u8 chte_buf[4];
203 
204 	if (power->has_ch0i) {
205 		ret = apple_smc_read_u8(power->smc, SMC_KEY(CH0I), &val8);
206 		if (ret)
207 			return ret;
208 		if (val8 & CH0R_NOAC_CH0I)
209 			return POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE;
210 	}
211 
212 	if (power->has_chte) {
213 		ret = apple_smc_read(power->smc, SMC_KEY(CHTE), chte_buf, 4);
214 		if (ret < 0)
215 			return ret;
216 
217 		if (chte_buf[0] == 0x01)
218 			return POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
219 	} else if (power->has_ch0c) {
220 		ret = apple_smc_read_u8(power->smc, SMC_KEY(CH0C), &val8);
221 		if (ret)
222 			return ret;
223 		if (val8 & CH0X_CH0C)
224 			return POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
225 	}
226 
227 	return POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
228 }
229 
macsmc_battery_set_charge_behaviour(struct macsmc_power * power,int val)230 static int macsmc_battery_set_charge_behaviour(struct macsmc_power *power, int val)
231 {
232 	int ret;
233 
234 	switch (val) {
235 	case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
236 		/* Reset all inhibitors to a known-good 'auto' state */
237 		if (power->has_ch0i) {
238 			ret = apple_smc_write_u8(power->smc, SMC_KEY(CH0I), 0);
239 			if (ret)
240 				return ret;
241 		}
242 
243 		if (power->has_chte) {
244 			ret = apple_smc_write_u32(power->smc, SMC_KEY(CHTE), 0);
245 			if (ret)
246 				return ret;
247 		} else if (power->has_ch0c) {
248 			ret = apple_smc_write_u8(power->smc, SMC_KEY(CH0C), 0);
249 			if (ret)
250 				return ret;
251 		}
252 		return 0;
253 
254 	case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
255 		if (power->has_chte)
256 			return apple_smc_write_u32(power->smc, SMC_KEY(CHTE), 1);
257 		else if (power->has_ch0c)
258 			return apple_smc_write_u8(power->smc, SMC_KEY(CH0C), 1);
259 		else
260 			return -EOPNOTSUPP;
261 
262 	case POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE:
263 		if (!power->has_ch0i)
264 			return -EOPNOTSUPP;
265 		return apple_smc_write_u8(power->smc, SMC_KEY(CH0I), 1);
266 
267 	default:
268 		return -EINVAL;
269 	}
270 }
271 
macsmc_battery_get_date(const char * s,int * out)272 static int macsmc_battery_get_date(const char *s, int *out)
273 {
274 	if (!isdigit(s[0]) || !isdigit(s[1]))
275 		return -EOPNOTSUPP;
276 
277 	*out = (s[0] - '0') * 10 + s[1] - '0';
278 	return 0;
279 }
280 
macsmc_battery_read_bcf0(struct macsmc_power * power,u32 * val)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 
macsmc_battery_get_capacity_level(struct macsmc_power * power)295 static int macsmc_battery_get_capacity_level(struct macsmc_power *power)
296 {
297 	bool flag;
298 	u32 val;
299 	int ret;
300 
301 	/* Check for emergency shutdown condition */
302 	if (macsmc_battery_read_bcf0(power, &val) >= 0 && val)
303 		return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
304 
305 	/* Check AC status for whether we could boot in this state */
306 	if (apple_smc_read_u32(power->smc, SMC_KEY(ACSt), &val) >= 0) {
307 		if (!(val & ACSt_CAN_BOOT_IBOOT))
308 			return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
309 
310 		if (!(val & ACSt_CAN_BOOT_AP))
311 			return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
312 	}
313 
314 	/* BSFC = Battery System Full Charge */
315 	ret = apple_smc_read_flag(power->smc, SMC_KEY(BSFC), &flag);
316 	if (ret < 0)
317 		return POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
318 
319 	if (flag)
320 		return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
321 	else
322 		return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
323 }
324 
macsmc_swap_b0rm(struct macsmc_power * power,s16 b0rm)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 
macsmc_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)331 static int macsmc_battery_get_property(struct power_supply *psy,
332 				       enum power_supply_property psp,
333 				       union power_supply_propval *val)
334 {
335 	struct macsmc_power *power = power_supply_get_drvdata(psy);
336 	int ret = 0;
337 	u8 vu8;
338 	u16 vu16;
339 	s16 vs16;
340 	s32 vs32;
341 	s64 vs64;
342 	bool flag;
343 
344 	switch (psp) {
345 	case POWER_SUPPLY_PROP_STATUS:
346 		val->intval = macsmc_battery_get_status(power);
347 		ret = val->intval < 0 ? val->intval : 0;
348 		break;
349 	case POWER_SUPPLY_PROP_PRESENT:
350 		val->intval = 1;
351 		break;
352 	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
353 		val->intval = macsmc_battery_get_charge_behaviour(power);
354 		ret = val->intval < 0 ? val->intval : 0;
355 		break;
356 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
357 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0TE), &vu16);
358 		val->intval = vu16 == 0xffff ? 0 : vu16 * 60;
359 		break;
360 	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
361 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0TF), &vu16);
362 		val->intval = vu16 == 0xffff ? 0 : vu16 * 60;
363 		break;
364 	case POWER_SUPPLY_PROP_CAPACITY:
365 		ret = apple_smc_read_u8(power->smc, SMC_KEY(BUIC), &vu8);
366 		val->intval = vu8;
367 		break;
368 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
369 		val->intval = macsmc_battery_get_capacity_level(power);
370 		ret = val->intval < 0 ? val->intval : 0;
371 		break;
372 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
373 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0AV), &vu16);
374 		val->intval = vu16 * 1000;
375 		break;
376 	case POWER_SUPPLY_PROP_CURRENT_NOW:
377 		ret = apple_smc_read_s16(power->smc, SMC_KEY(B0AC), &vs16);
378 		val->intval = vs16 * 1000;
379 		break;
380 	case POWER_SUPPLY_PROP_POWER_NOW:
381 		ret = apple_smc_read_s32(power->smc, SMC_KEY(B0AP), &vs32);
382 		val->intval = vs32 * 1000;
383 		break;
384 	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
385 		ret = apple_smc_read_u16(power->smc, SMC_KEY(BITV), &vu16);
386 		val->intval = vu16 * 1000;
387 		break;
388 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
389 		/* Calculate total max design voltage from per-cell maximum voltage */
390 		ret = apple_smc_read_u16(power->smc, SMC_KEY(BVVN), &vu16);
391 		val->intval = vu16 * 1000 * power->num_cells;
392 		break;
393 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
394 		/* Lifetime min */
395 		ret = apple_smc_read_s16(power->smc, SMC_KEY(BLPM), &vs16);
396 		val->intval = vs16 * 1000;
397 		break;
398 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
399 		/* Lifetime max */
400 		ret = apple_smc_read_s16(power->smc, SMC_KEY(BLPX), &vs16);
401 		val->intval = vs16 * 1000;
402 		break;
403 	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
404 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0RC), &vu16);
405 		val->intval = vu16 * 1000;
406 		break;
407 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
408 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0RI), &vu16);
409 		val->intval = vu16 * 1000;
410 		break;
411 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
412 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0RV), &vu16);
413 		val->intval = vu16 * 1000;
414 		break;
415 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
416 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0DC), &vu16);
417 		val->intval = vu16 * 1000;
418 		break;
419 	case POWER_SUPPLY_PROP_CHARGE_FULL:
420 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0FC), &vu16);
421 		val->intval = vu16 * 1000;
422 		break;
423 	case POWER_SUPPLY_PROP_CHARGE_NOW:
424 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0RM), &vu16);
425 		val->intval = macsmc_swap_b0rm(power, vu16) * 1000;
426 		break;
427 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
428 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0DC), &vu16);
429 		val->intval = vu16 * power->nominal_voltage_mv;
430 		break;
431 	case POWER_SUPPLY_PROP_ENERGY_FULL:
432 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0FC), &vu16);
433 		val->intval = vu16 * power->nominal_voltage_mv;
434 		break;
435 	case POWER_SUPPLY_PROP_ENERGY_NOW:
436 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0RM), &vu16);
437 		val->intval = macsmc_swap_b0rm(power, vu16) * power->nominal_voltage_mv;
438 		break;
439 	case POWER_SUPPLY_PROP_TEMP:
440 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0AT), &vu16);
441 		val->intval = vu16 - 2732; /* Kelvin x10 to Celsius x10 */
442 		break;
443 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
444 		ret = apple_smc_read_s64(power->smc, SMC_KEY(BAAC), &vs64);
445 		val->intval = vs64;
446 		break;
447 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
448 		ret = apple_smc_read_u16(power->smc, SMC_KEY(B0CT), &vu16);
449 		val->intval = vu16;
450 		break;
451 	case POWER_SUPPLY_PROP_SCOPE:
452 		val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
453 		break;
454 	case POWER_SUPPLY_PROP_HEALTH:
455 		flag = false;
456 		ret = apple_smc_read_flag(power->smc, SMC_KEY(BBAD), &flag);
457 		val->intval = flag ? POWER_SUPPLY_HEALTH_DEAD : POWER_SUPPLY_HEALTH_GOOD;
458 		break;
459 	case POWER_SUPPLY_PROP_MODEL_NAME:
460 		val->strval = power->model_name;
461 		break;
462 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
463 		val->strval = power->serial_number;
464 		break;
465 	case POWER_SUPPLY_PROP_MANUFACTURE_YEAR:
466 		ret = macsmc_battery_get_date(&power->mfg_date[0], &val->intval);
467 		/* The SMC reports the manufacture year as an offset from 1992. */
468 		val->intval += 1992;
469 		break;
470 	case POWER_SUPPLY_PROP_MANUFACTURE_MONTH:
471 		ret = macsmc_battery_get_date(&power->mfg_date[2], &val->intval);
472 		break;
473 	case POWER_SUPPLY_PROP_MANUFACTURE_DAY:
474 		ret = macsmc_battery_get_date(&power->mfg_date[4], &val->intval);
475 		break;
476 	default:
477 		return -EINVAL;
478 	}
479 
480 	return ret;
481 }
482 
macsmc_battery_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)483 static int macsmc_battery_set_property(struct power_supply *psy,
484 				       enum power_supply_property psp,
485 				       const union power_supply_propval *val)
486 {
487 	struct macsmc_power *power = power_supply_get_drvdata(psy);
488 
489 	switch (psp) {
490 	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
491 		return macsmc_battery_set_charge_behaviour(power, val->intval);
492 	default:
493 		return -EINVAL;
494 	}
495 }
496 
macsmc_battery_property_is_writeable(struct power_supply * psy,enum power_supply_property psp)497 static int macsmc_battery_property_is_writeable(struct power_supply *psy,
498 						enum power_supply_property psp)
499 {
500 	switch (psp) {
501 	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
502 		return true;
503 	default:
504 		return false;
505 	}
506 }
507 
508 static const struct power_supply_desc macsmc_battery_desc_template = {
509 	.name			= "macsmc-battery",
510 	.type			= POWER_SUPPLY_TYPE_BATTERY,
511 	.get_property		= macsmc_battery_get_property,
512 	.set_property		= macsmc_battery_set_property,
513 	.property_is_writeable	= macsmc_battery_property_is_writeable,
514 };
515 
macsmc_ac_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)516 static int macsmc_ac_get_property(struct power_supply *psy,
517 				  enum power_supply_property psp,
518 				  union power_supply_propval *val)
519 {
520 	struct macsmc_power *power = power_supply_get_drvdata(psy);
521 	int ret = 0;
522 	u16 vu16;
523 	u32 vu32;
524 
525 	switch (psp) {
526 	case POWER_SUPPLY_PROP_ONLINE:
527 		ret = apple_smc_read_u32(power->smc, SMC_KEY(CHIS), &vu32);
528 		val->intval = !!vu32;
529 		break;
530 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
531 		ret = apple_smc_read_u16(power->smc, SMC_KEY(AC-n), &vu16);
532 		val->intval = vu16 * 1000;
533 		break;
534 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
535 		ret = apple_smc_read_u16(power->smc, SMC_KEY(AC-i), &vu16);
536 		val->intval = vu16 * 1000;
537 		break;
538 	case POWER_SUPPLY_PROP_INPUT_POWER_LIMIT:
539 		ret = apple_smc_read_u32(power->smc, SMC_KEY(ACPW), &vu32);
540 		val->intval = vu32 * 1000;
541 		break;
542 	default:
543 		return -EINVAL;
544 	}
545 
546 	return ret;
547 }
548 
549 static const struct power_supply_desc macsmc_ac_desc_template = {
550 	.name			= "macsmc-ac",
551 	.type			= POWER_SUPPLY_TYPE_MAINS,
552 	.get_property		= macsmc_ac_get_property,
553 };
554 
macsmc_power_critical_work(struct work_struct * wrk)555 static void macsmc_power_critical_work(struct work_struct *wrk)
556 {
557 	struct macsmc_power *power = container_of(wrk, struct macsmc_power, critical_work);
558 	u16 bitv, b0av;
559 	u32 bcf0;
560 
561 	if (!power->batt)
562 		return;
563 
564 	/*
565 	 * Avoid duplicate atempts at emergency shutdown
566 	 */
567 	if (power->emergency_shutdown_triggered || system_state > SYSTEM_RUNNING)
568 		return;
569 
570 	/*
571 	 * EMERGENCY: Check voltage vs design minimum.
572 	 * If we are below BITV, the battery is physically exhausted.
573 	 * We must shut down NOW to protect the filesystem.
574 	 */
575 	if (apple_smc_read_u16(power->smc, SMC_KEY(BITV), &bitv) >= 0 &&
576 	    apple_smc_read_u16(power->smc, SMC_KEY(B0AV), &b0av) >= 0 &&
577 	    b0av < bitv) {
578 		power->emergency_shutdown_triggered = true;
579 		dev_emerg(power->dev,
580 			  "Battery voltage (%d mV) below design minimum (%d mV)! Emergency shutdown.\n",
581 			  b0av, bitv);
582 
583 		/*
584 		 * Shutdown is now imminent. Kick userspace again and give it some
585 		 * brief time to (hopefully) flush what's needed, before forcing.
586 		 */
587 		hw_protection_trigger("Battery voltage below design minimum", 1500);
588 	}
589 
590 	/*
591 	 * Avoid duplicate attempts at orderly shutdown.
592 	 * Voltage check is above this as we may want to
593 	 * "upgrade" an orderly shutdown to a critical power
594 	 * off if voltage drops.
595 	 */
596 	if (power->orderly_shutdown_triggered || system_state > SYSTEM_RUNNING)
597 		return;
598 
599 	/*
600 	 * Check if SMC flagged the battery as empty.
601 	 * We trigger a graceful shutdown to let the OS save data.
602 	 */
603 	if (macsmc_battery_read_bcf0(power, &bcf0) == 0 && bcf0 != 0) {
604 		power->orderly_shutdown_triggered = true;
605 		dev_crit(power->dev, "Battery critical (empty flag set). Triggering orderly shutdown.\n");
606 		orderly_poweroff(true);
607 	}
608 }
609 
macsmc_power_event(struct notifier_block * nb,unsigned long event,void * data)610 static int macsmc_power_event(struct notifier_block *nb, unsigned long event, void *data)
611 {
612 	struct macsmc_power *power = container_of(nb, struct macsmc_power, nb);
613 
614 	/*
615 	 * SMC Event IDs are correlated to physical events (e.g. charger
616 	 * connect/disconnect) but the exact meaning of each ID is predicted.
617 	 * 0x71... indicates power/battery events.
618 	 */
619 	if ((event & 0xffffff00) == 0x71010100 || /* Charger status change */
620 	    (event & 0xffff0000) == 0x71060000 || /* Port charge state change */
621 	    (event & 0xffff0000) == 0x71130000) { /* Connector insert/remove event */
622 		if (power->batt)
623 			power_supply_changed(power->batt);
624 		if (power->ac)
625 			power_supply_changed(power->ac);
626 		return NOTIFY_OK;
627 	} else if (event == 0x71020000) {
628 		/* Critical battery warning */
629 		if (power->batt)
630 			schedule_work(&power->critical_work);
631 		return NOTIFY_OK;
632 	}
633 
634 	return NOTIFY_DONE;
635 }
636 
macsmc_power_probe(struct platform_device * pdev)637 static int macsmc_power_probe(struct platform_device *pdev)
638 {
639 	struct device *dev = &pdev->dev;
640 	struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
641 	struct power_supply_config psy_cfg = {};
642 	struct apple_smc_key_info info;
643 	struct macsmc_power *power;
644 	bool has_battery = false;
645 	bool has_ac_adapter = false;
646 	int ret = -ENODEV;
647 	bool flag;
648 	u16 vu16;
649 	u32 val32;
650 	enum power_supply_property *props;
651 	size_t nprops;
652 
653 	if (!smc)
654 		return -ENODEV;
655 
656 	power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
657 	if (!power)
658 		return -ENOMEM;
659 
660 	power->dev = dev;
661 	power->smc = smc;
662 	dev_set_drvdata(dev, power);
663 
664 	INIT_WORK(&power->critical_work, macsmc_power_critical_work);
665 	ret = devm_work_autocancel(dev, &power->critical_work, macsmc_power_critical_work);
666 	if (ret)
667 		return ret;
668 
669 	/*
670 	 * Check for battery presence.
671 	 * B0AV is a fundamental key.
672 	 */
673 	if (apple_smc_read_u16(power->smc, SMC_KEY(B0AV), &vu16) == 0 &&
674 	    macsmc_battery_get_status(power) > POWER_SUPPLY_STATUS_UNKNOWN)
675 		has_battery = true;
676 
677 	/*
678 	 * Check for AC adapter presence.
679 	 * CHIS is a fundamental key.
680 	 */
681 	if (apple_smc_key_exists(smc, SMC_KEY(CHIS)))
682 		has_ac_adapter = true;
683 
684 	if (!has_battery && !has_ac_adapter)
685 		return -ENODEV;
686 
687 	if (has_battery) {
688 		power->batt_desc = macsmc_battery_desc_template;
689 		props = devm_kcalloc(dev, MACSMC_MAX_BATT_PROPS,
690 				     sizeof(enum power_supply_property),
691 				     GFP_KERNEL);
692 		if (!props)
693 			return -ENOMEM;
694 
695 		nprops = 0;
696 
697 		/* Fundamental properties */
698 		props[nprops++] = POWER_SUPPLY_PROP_STATUS;
699 		props[nprops++] = POWER_SUPPLY_PROP_PRESENT;
700 		props[nprops++] = POWER_SUPPLY_PROP_VOLTAGE_NOW;
701 		props[nprops++] = POWER_SUPPLY_PROP_CURRENT_NOW;
702 		props[nprops++] = POWER_SUPPLY_PROP_POWER_NOW;
703 		props[nprops++] = POWER_SUPPLY_PROP_CAPACITY;
704 		props[nprops++] = POWER_SUPPLY_PROP_CAPACITY_LEVEL;
705 		props[nprops++] = POWER_SUPPLY_PROP_TEMP;
706 		props[nprops++] = POWER_SUPPLY_PROP_CYCLE_COUNT;
707 		props[nprops++] = POWER_SUPPLY_PROP_HEALTH;
708 		props[nprops++] = POWER_SUPPLY_PROP_SCOPE;
709 		props[nprops++] = POWER_SUPPLY_PROP_MODEL_NAME;
710 		props[nprops++] = POWER_SUPPLY_PROP_SERIAL_NUMBER;
711 		props[nprops++] = POWER_SUPPLY_PROP_MANUFACTURE_YEAR;
712 		props[nprops++] = POWER_SUPPLY_PROP_MANUFACTURE_MONTH;
713 		props[nprops++] = POWER_SUPPLY_PROP_MANUFACTURE_DAY;
714 
715 		/* Extended properties usually present */
716 		props[nprops++] = POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW;
717 		props[nprops++] = POWER_SUPPLY_PROP_TIME_TO_FULL_NOW;
718 		props[nprops++] = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
719 		props[nprops++] = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
720 		props[nprops++] = POWER_SUPPLY_PROP_VOLTAGE_MIN;
721 		props[nprops++] = POWER_SUPPLY_PROP_VOLTAGE_MAX;
722 		props[nprops++] = POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT;
723 		props[nprops++] = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
724 		props[nprops++] = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
725 		props[nprops++] = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
726 		props[nprops++] = POWER_SUPPLY_PROP_CHARGE_FULL;
727 		props[nprops++] = POWER_SUPPLY_PROP_CHARGE_NOW;
728 		props[nprops++] = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
729 		props[nprops++] = POWER_SUPPLY_PROP_ENERGY_FULL;
730 		props[nprops++] = POWER_SUPPLY_PROP_ENERGY_NOW;
731 		props[nprops++] = POWER_SUPPLY_PROP_CHARGE_COUNTER;
732 
733 		/* Detect features based on key availability */
734 		if (apple_smc_key_exists(smc, SMC_KEY(CHTE)))
735 			power->has_chte = true;
736 		if (apple_smc_key_exists(smc, SMC_KEY(CH0C)))
737 			power->has_ch0c = true;
738 		if (apple_smc_key_exists(smc, SMC_KEY(CH0I)))
739 			power->has_ch0i = true;
740 
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 
755 		/* Reset "Optimised Battery Charging" flags to default state */
756 		if (power->has_chte)
757 			apple_smc_write_u32(smc, SMC_KEY(CHTE), 0);
758 		else if (power->has_ch0c)
759 			apple_smc_write_u8(smc, SMC_KEY(CH0C), 0);
760 
761 		if (power->has_ch0i)
762 			apple_smc_write_u8(smc, SMC_KEY(CH0I), 0);
763 
764 		apple_smc_write_u8(smc, SMC_KEY(CH0K), 0);
765 		apple_smc_write_u8(smc, SMC_KEY(CH0B), 0);
766 
767 		/* Configure charge behaviour if supported */
768 		if (power->has_ch0i || power->has_ch0c || power->has_chte) {
769 			props[nprops++] = POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR;
770 
771 			power->batt_desc.charge_behaviours =
772 				BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO);
773 
774 			if (power->has_ch0i)
775 				power->batt_desc.charge_behaviours |=
776 					BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE);
777 
778 			if (power->has_chte || power->has_ch0c)
779 				power->batt_desc.charge_behaviours |=
780 					BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE);
781 		}
782 
783 		/* Detect charge limit method (CHWA vs CHLS) */
784 		if (apple_smc_read_flag(power->smc, SMC_KEY(CHWA), &flag) == 0)
785 			power->has_chwa = true;
786 		else if (apple_smc_read_u16(power->smc, SMC_KEY(CHLS), &vu16) >= 0)
787 			power->has_chls = true;
788 
789 		if (nprops > MACSMC_MAX_BATT_PROPS)
790 			return -ENOMEM;
791 
792 		power->batt_desc.properties = props;
793 		power->batt_desc.num_properties = nprops;
794 
795 		/* Fetch identity strings */
796 		apple_smc_read(smc, SMC_KEY(BMDN), power->model_name,
797 			       sizeof(power->model_name) - 1);
798 		apple_smc_read(smc, SMC_KEY(BMSN), power->serial_number,
799 			       sizeof(power->serial_number) - 1);
800 		apple_smc_read(smc, SMC_KEY(BMDT), power->mfg_date,
801 			       sizeof(power->mfg_date) - 1);
802 
803 		apple_smc_read_u8(power->smc, SMC_KEY(BNCB), &power->num_cells);
804 		power->nominal_voltage_mv = MACSMC_NOMINAL_CELL_VOLTAGE_MV * power->num_cells;
805 
806 		/* Enable critical shutdown notifications by reading status once */
807 		macsmc_battery_read_bcf0(power, &val32);
808 
809 		psy_cfg.drv_data = power;
810 		power->batt = devm_power_supply_register(dev, &power->batt_desc, &psy_cfg);
811 		if (IS_ERR(power->batt)) {
812 			dev_err_probe(dev, PTR_ERR(power->batt),
813 				      "Failed to register battery\n");
814 			/* Don't return failure yet; try AC registration first */
815 			power->batt = NULL;
816 		}
817 	}
818 
819 	if (has_ac_adapter) {
820 		power->ac_desc = macsmc_ac_desc_template;
821 		props = devm_kcalloc(dev, MACSMC_MAX_AC_PROPS,
822 				     sizeof(enum power_supply_property),
823 				     GFP_KERNEL);
824 		if (!props)
825 			return -ENOMEM;
826 
827 		nprops = 0;
828 
829 		/* Online status is fundamental */
830 		props[nprops++] = POWER_SUPPLY_PROP_ONLINE;
831 
832 		/* Input power limits are usually available */
833 		if (apple_smc_key_exists(power->smc, SMC_KEY(ACPW)))
834 			props[nprops++] = POWER_SUPPLY_PROP_INPUT_POWER_LIMIT;
835 
836 		/* macOS 15.4+ firmware dropped legacy AC keys (AC-n, AC-i) */
837 		if (apple_smc_read_u16(power->smc, SMC_KEY(AC-n), &vu16) >= 0) {
838 			props[nprops++] = POWER_SUPPLY_PROP_VOLTAGE_NOW;
839 			props[nprops++] = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
840 		}
841 
842 		if (nprops > MACSMC_MAX_AC_PROPS)
843 			return -ENOMEM;
844 
845 		power->ac_desc.properties = props;
846 		power->ac_desc.num_properties = nprops;
847 
848 		psy_cfg.drv_data = power;
849 		power->ac = devm_power_supply_register(dev, &power->ac_desc, &psy_cfg);
850 		if (IS_ERR(power->ac)) {
851 			dev_err_probe(dev, PTR_ERR(power->ac),
852 				      "Failed to register AC adapter\n");
853 			power->ac = NULL;
854 		}
855 	}
856 
857 	/* Final check: did we register anything? */
858 	if (!power->batt && !power->ac)
859 		return -ENODEV;
860 
861 	power->nb.notifier_call = macsmc_power_event;
862 	blocking_notifier_chain_register(&smc->event_handlers, &power->nb);
863 
864 	return 0;
865 }
866 
macsmc_power_remove(struct platform_device * pdev)867 static void macsmc_power_remove(struct platform_device *pdev)
868 {
869 	struct macsmc_power *power = dev_get_drvdata(&pdev->dev);
870 
871 	blocking_notifier_chain_unregister(&power->smc->event_handlers, &power->nb);
872 }
873 
874 static const struct platform_device_id macsmc_power_id[] = {
875 	{ .name = "macsmc-power" },
876 	{ /* sentinel */ }
877 };
878 MODULE_DEVICE_TABLE(platform, macsmc_power_id);
879 
880 static struct platform_driver macsmc_power_driver = {
881 	.driver = {
882 		.name = "macsmc-power",
883 	},
884 	.id_table = macsmc_power_id,
885 	.probe = macsmc_power_probe,
886 	.remove = macsmc_power_remove,
887 };
888 module_platform_driver(macsmc_power_driver);
889 
890 MODULE_LICENSE("Dual MIT/GPL");
891 MODULE_DESCRIPTION("Apple SMC battery and power management driver");
892 MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
893 MODULE_AUTHOR("Michael Reeves <michael.reeves077@gmail.com>");
894