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