xref: /linux/drivers/power/supply/surface_battery.c (revision bfb921b2a9d5d1123d1d10b196a39db629ddef87)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Battery driver for 7th-generation Microsoft Surface devices via Surface
4  * System Aggregator Module (SSAM).
5  *
6  * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
7  */
8 
9 #include <asm/unaligned.h>
10 #include <linux/jiffies.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/power_supply.h>
15 #include <linux/sysfs.h>
16 #include <linux/types.h>
17 #include <linux/workqueue.h>
18 
19 #include <linux/surface_aggregator/device.h>
20 
21 
22 /* -- SAM interface. -------------------------------------------------------- */
23 
24 enum sam_event_cid_bat {
25 	SAM_EVENT_CID_BAT_BIX         = 0x15,
26 	SAM_EVENT_CID_BAT_BST         = 0x16,
27 	SAM_EVENT_CID_BAT_ADP         = 0x17,
28 	SAM_EVENT_CID_BAT_PROT        = 0x18,
29 	SAM_EVENT_CID_BAT_DPTF        = 0x53,
30 };
31 
32 enum sam_battery_sta {
33 	SAM_BATTERY_STA_OK            = 0x0f,
34 	SAM_BATTERY_STA_PRESENT	      = 0x10,
35 };
36 
37 enum sam_battery_state {
38 	SAM_BATTERY_STATE_DISCHARGING = BIT(0),
39 	SAM_BATTERY_STATE_CHARGING    = BIT(1),
40 	SAM_BATTERY_STATE_CRITICAL    = BIT(2),
41 };
42 
43 enum sam_battery_power_unit {
44 	SAM_BATTERY_POWER_UNIT_mW     = 0,
45 	SAM_BATTERY_POWER_UNIT_mA     = 1,
46 };
47 
48 /* Equivalent to data returned in ACPI _BIX method, revision 0. */
49 struct spwr_bix {
50 	u8  revision;
51 	__le32 power_unit;
52 	__le32 design_cap;
53 	__le32 last_full_charge_cap;
54 	__le32 technology;
55 	__le32 design_voltage;
56 	__le32 design_cap_warn;
57 	__le32 design_cap_low;
58 	__le32 cycle_count;
59 	__le32 measurement_accuracy;
60 	__le32 max_sampling_time;
61 	__le32 min_sampling_time;
62 	__le32 max_avg_interval;
63 	__le32 min_avg_interval;
64 	__le32 bat_cap_granularity_1;
65 	__le32 bat_cap_granularity_2;
66 	__u8 model[21];
67 	__u8 serial[11];
68 	__u8 type[5];
69 	__u8 oem_info[21];
70 } __packed;
71 
72 static_assert(sizeof(struct spwr_bix) == 119);
73 
74 /* Equivalent to data returned in ACPI _BST method. */
75 struct spwr_bst {
76 	__le32 state;
77 	__le32 present_rate;
78 	__le32 remaining_cap;
79 	__le32 present_voltage;
80 } __packed;
81 
82 static_assert(sizeof(struct spwr_bst) == 16);
83 
84 #define SPWR_BIX_REVISION		0
85 #define SPWR_BATTERY_VALUE_UNKNOWN	0xffffffff
86 
87 /* Get battery status (_STA) */
88 SSAM_DEFINE_SYNC_REQUEST_CL_R(ssam_bat_get_sta, __le32, {
89 	.target_category = SSAM_SSH_TC_BAT,
90 	.command_id      = 0x01,
91 });
92 
93 /* Get battery static information (_BIX). */
94 SSAM_DEFINE_SYNC_REQUEST_CL_R(ssam_bat_get_bix, struct spwr_bix, {
95 	.target_category = SSAM_SSH_TC_BAT,
96 	.command_id      = 0x02,
97 });
98 
99 /* Get battery dynamic information (_BST). */
100 SSAM_DEFINE_SYNC_REQUEST_CL_R(ssam_bat_get_bst, struct spwr_bst, {
101 	.target_category = SSAM_SSH_TC_BAT,
102 	.command_id      = 0x03,
103 });
104 
105 /* Set battery trip point (_BTP). */
106 SSAM_DEFINE_SYNC_REQUEST_CL_W(ssam_bat_set_btp, __le32, {
107 	.target_category = SSAM_SSH_TC_BAT,
108 	.command_id      = 0x04,
109 });
110 
111 
112 /* -- Device structures. ---------------------------------------------------- */
113 
114 struct spwr_psy_properties {
115 	const char *name;
116 	struct ssam_event_registry registry;
117 };
118 
119 struct spwr_battery_device {
120 	struct ssam_device *sdev;
121 
122 	char name[32];
123 	struct power_supply *psy;
124 	struct power_supply_desc psy_desc;
125 
126 	struct delayed_work update_work;
127 
128 	struct ssam_event_notifier notif;
129 
130 	struct mutex lock;  /* Guards access to state data below. */
131 	unsigned long timestamp;
132 
133 	__le32 sta;
134 	struct spwr_bix bix;
135 	struct spwr_bst bst;
136 	u32 alarm;
137 };
138 
139 
140 /* -- Module parameters. ---------------------------------------------------- */
141 
142 static unsigned int cache_time = 1000;
143 module_param(cache_time, uint, 0644);
144 MODULE_PARM_DESC(cache_time, "battery state caching time in milliseconds [default: 1000]");
145 
146 
147 /* -- State management. ----------------------------------------------------- */
148 
149 /*
150  * Delay for battery update quirk. See spwr_external_power_changed() below
151  * for more details.
152  */
153 #define SPWR_AC_BAT_UPDATE_DELAY	msecs_to_jiffies(5000)
154 
155 static bool spwr_battery_present(struct spwr_battery_device *bat)
156 {
157 	lockdep_assert_held(&bat->lock);
158 
159 	return le32_to_cpu(bat->sta) & SAM_BATTERY_STA_PRESENT;
160 }
161 
162 static int spwr_battery_load_sta(struct spwr_battery_device *bat)
163 {
164 	lockdep_assert_held(&bat->lock);
165 
166 	return ssam_retry(ssam_bat_get_sta, bat->sdev, &bat->sta);
167 }
168 
169 static int spwr_battery_load_bix(struct spwr_battery_device *bat)
170 {
171 	int status;
172 
173 	lockdep_assert_held(&bat->lock);
174 
175 	if (!spwr_battery_present(bat))
176 		return 0;
177 
178 	status = ssam_retry(ssam_bat_get_bix, bat->sdev, &bat->bix);
179 
180 	/* Enforce NULL terminated strings in case anything goes wrong... */
181 	bat->bix.model[ARRAY_SIZE(bat->bix.model) - 1] = 0;
182 	bat->bix.serial[ARRAY_SIZE(bat->bix.serial) - 1] = 0;
183 	bat->bix.type[ARRAY_SIZE(bat->bix.type) - 1] = 0;
184 	bat->bix.oem_info[ARRAY_SIZE(bat->bix.oem_info) - 1] = 0;
185 
186 	return status;
187 }
188 
189 static int spwr_battery_load_bst(struct spwr_battery_device *bat)
190 {
191 	lockdep_assert_held(&bat->lock);
192 
193 	if (!spwr_battery_present(bat))
194 		return 0;
195 
196 	return ssam_retry(ssam_bat_get_bst, bat->sdev, &bat->bst);
197 }
198 
199 static int spwr_battery_set_alarm_unlocked(struct spwr_battery_device *bat, u32 value)
200 {
201 	__le32 value_le = cpu_to_le32(value);
202 
203 	lockdep_assert_held(&bat->lock);
204 
205 	bat->alarm = value;
206 	return ssam_retry(ssam_bat_set_btp, bat->sdev, &value_le);
207 }
208 
209 static int spwr_battery_update_bst_unlocked(struct spwr_battery_device *bat, bool cached)
210 {
211 	unsigned long cache_deadline = bat->timestamp + msecs_to_jiffies(cache_time);
212 	int status;
213 
214 	lockdep_assert_held(&bat->lock);
215 
216 	if (cached && bat->timestamp && time_is_after_jiffies(cache_deadline))
217 		return 0;
218 
219 	status = spwr_battery_load_sta(bat);
220 	if (status)
221 		return status;
222 
223 	status = spwr_battery_load_bst(bat);
224 	if (status)
225 		return status;
226 
227 	bat->timestamp = jiffies;
228 	return 0;
229 }
230 
231 static int spwr_battery_update_bst(struct spwr_battery_device *bat, bool cached)
232 {
233 	int status;
234 
235 	mutex_lock(&bat->lock);
236 	status = spwr_battery_update_bst_unlocked(bat, cached);
237 	mutex_unlock(&bat->lock);
238 
239 	return status;
240 }
241 
242 static int spwr_battery_update_bix_unlocked(struct spwr_battery_device *bat)
243 {
244 	int status;
245 
246 	lockdep_assert_held(&bat->lock);
247 
248 	status = spwr_battery_load_sta(bat);
249 	if (status)
250 		return status;
251 
252 	status = spwr_battery_load_bix(bat);
253 	if (status)
254 		return status;
255 
256 	status = spwr_battery_load_bst(bat);
257 	if (status)
258 		return status;
259 
260 	if (bat->bix.revision != SPWR_BIX_REVISION)
261 		dev_warn(&bat->sdev->dev, "unsupported battery revision: %u\n", bat->bix.revision);
262 
263 	bat->timestamp = jiffies;
264 	return 0;
265 }
266 
267 static u32 sprw_battery_get_full_cap_safe(struct spwr_battery_device *bat)
268 {
269 	u32 full_cap = get_unaligned_le32(&bat->bix.last_full_charge_cap);
270 
271 	lockdep_assert_held(&bat->lock);
272 
273 	if (full_cap == 0 || full_cap == SPWR_BATTERY_VALUE_UNKNOWN)
274 		full_cap = get_unaligned_le32(&bat->bix.design_cap);
275 
276 	return full_cap;
277 }
278 
279 static bool spwr_battery_is_full(struct spwr_battery_device *bat)
280 {
281 	u32 state = get_unaligned_le32(&bat->bst.state);
282 	u32 full_cap = sprw_battery_get_full_cap_safe(bat);
283 	u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap);
284 
285 	lockdep_assert_held(&bat->lock);
286 
287 	return full_cap != SPWR_BATTERY_VALUE_UNKNOWN && full_cap != 0 &&
288 		remaining_cap != SPWR_BATTERY_VALUE_UNKNOWN &&
289 		remaining_cap >= full_cap &&
290 		state == 0;
291 }
292 
293 static int spwr_battery_recheck_full(struct spwr_battery_device *bat)
294 {
295 	bool present;
296 	u32 unit;
297 	int status;
298 
299 	mutex_lock(&bat->lock);
300 	unit = get_unaligned_le32(&bat->bix.power_unit);
301 	present = spwr_battery_present(bat);
302 
303 	status = spwr_battery_update_bix_unlocked(bat);
304 	if (status)
305 		goto out;
306 
307 	/* If battery has been attached, (re-)initialize alarm. */
308 	if (!present && spwr_battery_present(bat)) {
309 		u32 cap_warn = get_unaligned_le32(&bat->bix.design_cap_warn);
310 
311 		status = spwr_battery_set_alarm_unlocked(bat, cap_warn);
312 		if (status)
313 			goto out;
314 	}
315 
316 	/*
317 	 * Warn if the unit has changed. This is something we genuinely don't
318 	 * expect to happen, so make this a big warning. If it does, we'll
319 	 * need to add support for it.
320 	 */
321 	WARN_ON(unit != get_unaligned_le32(&bat->bix.power_unit));
322 
323 out:
324 	mutex_unlock(&bat->lock);
325 
326 	if (!status)
327 		power_supply_changed(bat->psy);
328 
329 	return status;
330 }
331 
332 static int spwr_battery_recheck_status(struct spwr_battery_device *bat)
333 {
334 	int status;
335 
336 	status = spwr_battery_update_bst(bat, false);
337 	if (!status)
338 		power_supply_changed(bat->psy);
339 
340 	return status;
341 }
342 
343 static u32 spwr_notify_bat(struct ssam_event_notifier *nf, const struct ssam_event *event)
344 {
345 	struct spwr_battery_device *bat = container_of(nf, struct spwr_battery_device, notif);
346 	int status;
347 
348 	/*
349 	 * We cannot use strict matching when registering the notifier as the
350 	 * EC expects us to register it against instance ID 0. Strict matching
351 	 * would thus drop events, as those may have non-zero instance IDs in
352 	 * this subsystem. So we need to check the instance ID of the event
353 	 * here manually.
354 	 */
355 	if (event->instance_id != bat->sdev->uid.instance)
356 		return 0;
357 
358 	dev_dbg(&bat->sdev->dev, "power event (cid = %#04x, iid = %#04x, tid = %#04x)\n",
359 		event->command_id, event->instance_id, event->target_id);
360 
361 	switch (event->command_id) {
362 	case SAM_EVENT_CID_BAT_BIX:
363 		status = spwr_battery_recheck_full(bat);
364 		break;
365 
366 	case SAM_EVENT_CID_BAT_BST:
367 		status = spwr_battery_recheck_status(bat);
368 		break;
369 
370 	case SAM_EVENT_CID_BAT_PROT:
371 		/*
372 		 * TODO: Implement support for battery protection status change
373 		 *       event.
374 		 */
375 		status = 0;
376 		break;
377 
378 	case SAM_EVENT_CID_BAT_DPTF:
379 		/*
380 		 * TODO: Implement support for DPTF event.
381 		 */
382 		status = 0;
383 		break;
384 
385 	default:
386 		return 0;
387 	}
388 
389 	return ssam_notifier_from_errno(status) | SSAM_NOTIF_HANDLED;
390 }
391 
392 static void spwr_battery_update_bst_workfn(struct work_struct *work)
393 {
394 	struct delayed_work *dwork = to_delayed_work(work);
395 	struct spwr_battery_device *bat;
396 	int status;
397 
398 	bat = container_of(dwork, struct spwr_battery_device, update_work);
399 
400 	status = spwr_battery_update_bst(bat, false);
401 	if (status) {
402 		dev_err(&bat->sdev->dev, "failed to update battery state: %d\n", status);
403 		return;
404 	}
405 
406 	power_supply_changed(bat->psy);
407 }
408 
409 static void spwr_external_power_changed(struct power_supply *psy)
410 {
411 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
412 
413 	/*
414 	 * Handle battery update quirk: When the battery is fully charged (or
415 	 * charged up to the limit imposed by the UEFI battery limit) and the
416 	 * adapter is plugged in or removed, the EC does not send a separate
417 	 * event for the state (charging/discharging) change. Furthermore it
418 	 * may take some time until the state is updated on the battery.
419 	 * Schedule an update to solve this.
420 	 */
421 
422 	schedule_delayed_work(&bat->update_work, SPWR_AC_BAT_UPDATE_DELAY);
423 }
424 
425 
426 /* -- Properties. ----------------------------------------------------------- */
427 
428 static const enum power_supply_property spwr_battery_props_chg[] = {
429 	POWER_SUPPLY_PROP_STATUS,
430 	POWER_SUPPLY_PROP_PRESENT,
431 	POWER_SUPPLY_PROP_TECHNOLOGY,
432 	POWER_SUPPLY_PROP_CYCLE_COUNT,
433 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
434 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
435 	POWER_SUPPLY_PROP_CURRENT_NOW,
436 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
437 	POWER_SUPPLY_PROP_CHARGE_FULL,
438 	POWER_SUPPLY_PROP_CHARGE_NOW,
439 	POWER_SUPPLY_PROP_CAPACITY,
440 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
441 	POWER_SUPPLY_PROP_MODEL_NAME,
442 	POWER_SUPPLY_PROP_MANUFACTURER,
443 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
444 };
445 
446 static const enum power_supply_property spwr_battery_props_eng[] = {
447 	POWER_SUPPLY_PROP_STATUS,
448 	POWER_SUPPLY_PROP_PRESENT,
449 	POWER_SUPPLY_PROP_TECHNOLOGY,
450 	POWER_SUPPLY_PROP_CYCLE_COUNT,
451 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
452 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
453 	POWER_SUPPLY_PROP_POWER_NOW,
454 	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
455 	POWER_SUPPLY_PROP_ENERGY_FULL,
456 	POWER_SUPPLY_PROP_ENERGY_NOW,
457 	POWER_SUPPLY_PROP_CAPACITY,
458 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
459 	POWER_SUPPLY_PROP_MODEL_NAME,
460 	POWER_SUPPLY_PROP_MANUFACTURER,
461 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
462 };
463 
464 static int spwr_battery_prop_status(struct spwr_battery_device *bat)
465 {
466 	u32 state = get_unaligned_le32(&bat->bst.state);
467 	u32 present_rate = get_unaligned_le32(&bat->bst.present_rate);
468 
469 	lockdep_assert_held(&bat->lock);
470 
471 	if (state & SAM_BATTERY_STATE_DISCHARGING)
472 		return POWER_SUPPLY_STATUS_DISCHARGING;
473 
474 	if (state & SAM_BATTERY_STATE_CHARGING)
475 		return POWER_SUPPLY_STATUS_CHARGING;
476 
477 	if (spwr_battery_is_full(bat))
478 		return POWER_SUPPLY_STATUS_FULL;
479 
480 	if (present_rate == 0)
481 		return POWER_SUPPLY_STATUS_NOT_CHARGING;
482 
483 	return POWER_SUPPLY_STATUS_UNKNOWN;
484 }
485 
486 static int spwr_battery_prop_technology(struct spwr_battery_device *bat)
487 {
488 	lockdep_assert_held(&bat->lock);
489 
490 	if (!strcasecmp("NiCd", bat->bix.type))
491 		return POWER_SUPPLY_TECHNOLOGY_NiCd;
492 
493 	if (!strcasecmp("NiMH", bat->bix.type))
494 		return POWER_SUPPLY_TECHNOLOGY_NiMH;
495 
496 	if (!strcasecmp("LION", bat->bix.type))
497 		return POWER_SUPPLY_TECHNOLOGY_LION;
498 
499 	if (!strncasecmp("LI-ION", bat->bix.type, 6))
500 		return POWER_SUPPLY_TECHNOLOGY_LION;
501 
502 	if (!strcasecmp("LiP", bat->bix.type))
503 		return POWER_SUPPLY_TECHNOLOGY_LIPO;
504 
505 	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
506 }
507 
508 static int spwr_battery_prop_capacity(struct spwr_battery_device *bat)
509 {
510 	u32 full_cap = sprw_battery_get_full_cap_safe(bat);
511 	u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap);
512 
513 	lockdep_assert_held(&bat->lock);
514 
515 	if (full_cap == 0 || full_cap == SPWR_BATTERY_VALUE_UNKNOWN)
516 		return -ENODATA;
517 
518 	if (remaining_cap == SPWR_BATTERY_VALUE_UNKNOWN)
519 		return -ENODATA;
520 
521 	return remaining_cap * 100 / full_cap;
522 }
523 
524 static int spwr_battery_prop_capacity_level(struct spwr_battery_device *bat)
525 {
526 	u32 state = get_unaligned_le32(&bat->bst.state);
527 	u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap);
528 
529 	lockdep_assert_held(&bat->lock);
530 
531 	if (state & SAM_BATTERY_STATE_CRITICAL)
532 		return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
533 
534 	if (spwr_battery_is_full(bat))
535 		return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
536 
537 	if (remaining_cap <= bat->alarm)
538 		return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
539 
540 	return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
541 }
542 
543 static int spwr_battery_get_property(struct power_supply *psy, enum power_supply_property psp,
544 				     union power_supply_propval *val)
545 {
546 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
547 	u32 value;
548 	int status;
549 
550 	mutex_lock(&bat->lock);
551 
552 	status = spwr_battery_update_bst_unlocked(bat, true);
553 	if (status)
554 		goto out;
555 
556 	/* Abort if battery is not present. */
557 	if (!spwr_battery_present(bat) && psp != POWER_SUPPLY_PROP_PRESENT) {
558 		status = -ENODEV;
559 		goto out;
560 	}
561 
562 	switch (psp) {
563 	case POWER_SUPPLY_PROP_STATUS:
564 		val->intval = spwr_battery_prop_status(bat);
565 		break;
566 
567 	case POWER_SUPPLY_PROP_PRESENT:
568 		val->intval = spwr_battery_present(bat);
569 		break;
570 
571 	case POWER_SUPPLY_PROP_TECHNOLOGY:
572 		val->intval = spwr_battery_prop_technology(bat);
573 		break;
574 
575 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
576 		value = get_unaligned_le32(&bat->bix.cycle_count);
577 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
578 			val->intval = value;
579 		else
580 			status = -ENODATA;
581 		break;
582 
583 	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
584 		value = get_unaligned_le32(&bat->bix.design_voltage);
585 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
586 			val->intval = value * 1000;
587 		else
588 			status = -ENODATA;
589 		break;
590 
591 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
592 		value = get_unaligned_le32(&bat->bst.present_voltage);
593 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
594 			val->intval = value * 1000;
595 		else
596 			status = -ENODATA;
597 		break;
598 
599 	case POWER_SUPPLY_PROP_CURRENT_NOW:
600 	case POWER_SUPPLY_PROP_POWER_NOW:
601 		value = get_unaligned_le32(&bat->bst.present_rate);
602 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
603 			val->intval = value * 1000;
604 		else
605 			status = -ENODATA;
606 		break;
607 
608 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
609 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
610 		value = get_unaligned_le32(&bat->bix.design_cap);
611 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
612 			val->intval = value * 1000;
613 		else
614 			status = -ENODATA;
615 		break;
616 
617 	case POWER_SUPPLY_PROP_CHARGE_FULL:
618 	case POWER_SUPPLY_PROP_ENERGY_FULL:
619 		value = get_unaligned_le32(&bat->bix.last_full_charge_cap);
620 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
621 			val->intval = value * 1000;
622 		else
623 			status = -ENODATA;
624 		break;
625 
626 	case POWER_SUPPLY_PROP_CHARGE_NOW:
627 	case POWER_SUPPLY_PROP_ENERGY_NOW:
628 		value = get_unaligned_le32(&bat->bst.remaining_cap);
629 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
630 			val->intval = value * 1000;
631 		else
632 			status = -ENODATA;
633 		break;
634 
635 	case POWER_SUPPLY_PROP_CAPACITY:
636 		val->intval = spwr_battery_prop_capacity(bat);
637 		break;
638 
639 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
640 		val->intval = spwr_battery_prop_capacity_level(bat);
641 		break;
642 
643 	case POWER_SUPPLY_PROP_MODEL_NAME:
644 		val->strval = bat->bix.model;
645 		break;
646 
647 	case POWER_SUPPLY_PROP_MANUFACTURER:
648 		val->strval = bat->bix.oem_info;
649 		break;
650 
651 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
652 		val->strval = bat->bix.serial;
653 		break;
654 
655 	default:
656 		status = -EINVAL;
657 		break;
658 	}
659 
660 out:
661 	mutex_unlock(&bat->lock);
662 	return status;
663 }
664 
665 
666 /* -- Alarm attribute. ------------------------------------------------------ */
667 
668 static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf)
669 {
670 	struct power_supply *psy = dev_get_drvdata(dev);
671 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
672 	int status;
673 
674 	mutex_lock(&bat->lock);
675 	status = sysfs_emit(buf, "%d\n", bat->alarm * 1000);
676 	mutex_unlock(&bat->lock);
677 
678 	return status;
679 }
680 
681 static ssize_t alarm_store(struct device *dev, struct device_attribute *attr, const char *buf,
682 			   size_t count)
683 {
684 	struct power_supply *psy = dev_get_drvdata(dev);
685 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
686 	unsigned long value;
687 	int status;
688 
689 	status = kstrtoul(buf, 0, &value);
690 	if (status)
691 		return status;
692 
693 	mutex_lock(&bat->lock);
694 
695 	if (!spwr_battery_present(bat)) {
696 		mutex_unlock(&bat->lock);
697 		return -ENODEV;
698 	}
699 
700 	status = spwr_battery_set_alarm_unlocked(bat, value / 1000);
701 	if (status) {
702 		mutex_unlock(&bat->lock);
703 		return status;
704 	}
705 
706 	mutex_unlock(&bat->lock);
707 	return count;
708 }
709 
710 static DEVICE_ATTR_RW(alarm);
711 
712 static struct attribute *spwr_battery_attrs[] = {
713 	&dev_attr_alarm.attr,
714 	NULL,
715 };
716 ATTRIBUTE_GROUPS(spwr_battery);
717 
718 
719 /* -- Device setup. --------------------------------------------------------- */
720 
721 static void spwr_battery_init(struct spwr_battery_device *bat, struct ssam_device *sdev,
722 			      struct ssam_event_registry registry, const char *name)
723 {
724 	mutex_init(&bat->lock);
725 	strscpy(bat->name, name, sizeof(bat->name));
726 
727 	bat->sdev = sdev;
728 
729 	bat->notif.base.priority = 1;
730 	bat->notif.base.fn = spwr_notify_bat;
731 	bat->notif.event.reg = registry;
732 	bat->notif.event.id.target_category = sdev->uid.category;
733 	bat->notif.event.id.instance = 0;	/* need to register with instance 0 */
734 	bat->notif.event.mask = SSAM_EVENT_MASK_TARGET;
735 	bat->notif.event.flags = SSAM_EVENT_SEQUENCED;
736 
737 	bat->psy_desc.name = bat->name;
738 	bat->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
739 	bat->psy_desc.get_property = spwr_battery_get_property;
740 
741 	INIT_DELAYED_WORK(&bat->update_work, spwr_battery_update_bst_workfn);
742 }
743 
744 static int spwr_battery_register(struct spwr_battery_device *bat)
745 {
746 	struct power_supply_config psy_cfg = {};
747 	__le32 sta;
748 	int status;
749 
750 	/* Make sure the device is there and functioning properly. */
751 	status = ssam_retry(ssam_bat_get_sta, bat->sdev, &sta);
752 	if (status)
753 		return status;
754 
755 	if ((le32_to_cpu(sta) & SAM_BATTERY_STA_OK) != SAM_BATTERY_STA_OK)
756 		return -ENODEV;
757 
758 	/* Satisfy lockdep although we are in an exclusive context here. */
759 	mutex_lock(&bat->lock);
760 
761 	status = spwr_battery_update_bix_unlocked(bat);
762 	if (status) {
763 		mutex_unlock(&bat->lock);
764 		return status;
765 	}
766 
767 	if (spwr_battery_present(bat)) {
768 		u32 cap_warn = get_unaligned_le32(&bat->bix.design_cap_warn);
769 
770 		status = spwr_battery_set_alarm_unlocked(bat, cap_warn);
771 		if (status) {
772 			mutex_unlock(&bat->lock);
773 			return status;
774 		}
775 	}
776 
777 	mutex_unlock(&bat->lock);
778 
779 	bat->psy_desc.external_power_changed = spwr_external_power_changed;
780 
781 	switch (get_unaligned_le32(&bat->bix.power_unit)) {
782 	case SAM_BATTERY_POWER_UNIT_mW:
783 		bat->psy_desc.properties = spwr_battery_props_eng;
784 		bat->psy_desc.num_properties = ARRAY_SIZE(spwr_battery_props_eng);
785 		break;
786 
787 	case SAM_BATTERY_POWER_UNIT_mA:
788 		bat->psy_desc.properties = spwr_battery_props_chg;
789 		bat->psy_desc.num_properties = ARRAY_SIZE(spwr_battery_props_chg);
790 		break;
791 
792 	default:
793 		dev_err(&bat->sdev->dev, "unsupported battery power unit: %u\n",
794 			get_unaligned_le32(&bat->bix.power_unit));
795 		return -EINVAL;
796 	}
797 
798 	psy_cfg.drv_data = bat;
799 	psy_cfg.attr_grp = spwr_battery_groups;
800 
801 	bat->psy = devm_power_supply_register(&bat->sdev->dev, &bat->psy_desc, &psy_cfg);
802 	if (IS_ERR(bat->psy))
803 		return PTR_ERR(bat->psy);
804 
805 	return ssam_device_notifier_register(bat->sdev, &bat->notif);
806 }
807 
808 
809 /* -- Driver setup. --------------------------------------------------------- */
810 
811 static int __maybe_unused surface_battery_resume(struct device *dev)
812 {
813 	return spwr_battery_recheck_full(dev_get_drvdata(dev));
814 }
815 static SIMPLE_DEV_PM_OPS(surface_battery_pm_ops, NULL, surface_battery_resume);
816 
817 static int surface_battery_probe(struct ssam_device *sdev)
818 {
819 	const struct spwr_psy_properties *p;
820 	struct spwr_battery_device *bat;
821 
822 	p = ssam_device_get_match_data(sdev);
823 	if (!p)
824 		return -ENODEV;
825 
826 	bat = devm_kzalloc(&sdev->dev, sizeof(*bat), GFP_KERNEL);
827 	if (!bat)
828 		return -ENOMEM;
829 
830 	spwr_battery_init(bat, sdev, p->registry, p->name);
831 	ssam_device_set_drvdata(sdev, bat);
832 
833 	return spwr_battery_register(bat);
834 }
835 
836 static void surface_battery_remove(struct ssam_device *sdev)
837 {
838 	struct spwr_battery_device *bat = ssam_device_get_drvdata(sdev);
839 
840 	ssam_device_notifier_unregister(sdev, &bat->notif);
841 	cancel_delayed_work_sync(&bat->update_work);
842 }
843 
844 static const struct spwr_psy_properties spwr_psy_props_bat1 = {
845 	.name = "BAT1",
846 	.registry = SSAM_EVENT_REGISTRY_SAM,
847 };
848 
849 static const struct spwr_psy_properties spwr_psy_props_bat2_sb3 = {
850 	.name = "BAT2",
851 	.registry = SSAM_EVENT_REGISTRY_KIP,
852 };
853 
854 static const struct ssam_device_id surface_battery_match[] = {
855 	{ SSAM_SDEV(BAT, SAM, 0x01, 0x00), (unsigned long)&spwr_psy_props_bat1     },
856 	{ SSAM_SDEV(BAT, KIP, 0x01, 0x00), (unsigned long)&spwr_psy_props_bat2_sb3 },
857 	{ },
858 };
859 MODULE_DEVICE_TABLE(ssam, surface_battery_match);
860 
861 static struct ssam_device_driver surface_battery_driver = {
862 	.probe = surface_battery_probe,
863 	.remove = surface_battery_remove,
864 	.match_table = surface_battery_match,
865 	.driver = {
866 		.name = "surface_battery",
867 		.pm = &surface_battery_pm_ops,
868 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
869 	},
870 };
871 module_ssam_device_driver(surface_battery_driver);
872 
873 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
874 MODULE_DESCRIPTION("Battery driver for Surface System Aggregator Module");
875 MODULE_LICENSE("GPL");
876