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 	dev_dbg(&bat->sdev->dev, "power event (cid = %#04x, iid = %#04x, tid = %#04x)\n",
349 		event->command_id, event->instance_id, event->target_id);
350 
351 	switch (event->command_id) {
352 	case SAM_EVENT_CID_BAT_BIX:
353 		status = spwr_battery_recheck_full(bat);
354 		break;
355 
356 	case SAM_EVENT_CID_BAT_BST:
357 		status = spwr_battery_recheck_status(bat);
358 		break;
359 
360 	case SAM_EVENT_CID_BAT_PROT:
361 		/*
362 		 * TODO: Implement support for battery protection status change
363 		 *       event.
364 		 */
365 		status = 0;
366 		break;
367 
368 	case SAM_EVENT_CID_BAT_DPTF:
369 		/*
370 		 * TODO: Implement support for DPTF event.
371 		 */
372 		status = 0;
373 		break;
374 
375 	default:
376 		return 0;
377 	}
378 
379 	return ssam_notifier_from_errno(status) | SSAM_NOTIF_HANDLED;
380 }
381 
382 static void spwr_battery_update_bst_workfn(struct work_struct *work)
383 {
384 	struct delayed_work *dwork = to_delayed_work(work);
385 	struct spwr_battery_device *bat;
386 	int status;
387 
388 	bat = container_of(dwork, struct spwr_battery_device, update_work);
389 
390 	status = spwr_battery_update_bst(bat, false);
391 	if (status) {
392 		dev_err(&bat->sdev->dev, "failed to update battery state: %d\n", status);
393 		return;
394 	}
395 
396 	power_supply_changed(bat->psy);
397 }
398 
399 static void spwr_external_power_changed(struct power_supply *psy)
400 {
401 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
402 
403 	/*
404 	 * Handle battery update quirk: When the battery is fully charged (or
405 	 * charged up to the limit imposed by the UEFI battery limit) and the
406 	 * adapter is plugged in or removed, the EC does not send a separate
407 	 * event for the state (charging/discharging) change. Furthermore it
408 	 * may take some time until the state is updated on the battery.
409 	 * Schedule an update to solve this.
410 	 */
411 
412 	schedule_delayed_work(&bat->update_work, SPWR_AC_BAT_UPDATE_DELAY);
413 }
414 
415 
416 /* -- Properties. ----------------------------------------------------------- */
417 
418 static const enum power_supply_property spwr_battery_props_chg[] = {
419 	POWER_SUPPLY_PROP_STATUS,
420 	POWER_SUPPLY_PROP_PRESENT,
421 	POWER_SUPPLY_PROP_TECHNOLOGY,
422 	POWER_SUPPLY_PROP_CYCLE_COUNT,
423 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
424 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
425 	POWER_SUPPLY_PROP_CURRENT_NOW,
426 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
427 	POWER_SUPPLY_PROP_CHARGE_FULL,
428 	POWER_SUPPLY_PROP_CHARGE_NOW,
429 	POWER_SUPPLY_PROP_CAPACITY,
430 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
431 	POWER_SUPPLY_PROP_MODEL_NAME,
432 	POWER_SUPPLY_PROP_MANUFACTURER,
433 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
434 };
435 
436 static const enum power_supply_property spwr_battery_props_eng[] = {
437 	POWER_SUPPLY_PROP_STATUS,
438 	POWER_SUPPLY_PROP_PRESENT,
439 	POWER_SUPPLY_PROP_TECHNOLOGY,
440 	POWER_SUPPLY_PROP_CYCLE_COUNT,
441 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
442 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
443 	POWER_SUPPLY_PROP_POWER_NOW,
444 	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
445 	POWER_SUPPLY_PROP_ENERGY_FULL,
446 	POWER_SUPPLY_PROP_ENERGY_NOW,
447 	POWER_SUPPLY_PROP_CAPACITY,
448 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
449 	POWER_SUPPLY_PROP_MODEL_NAME,
450 	POWER_SUPPLY_PROP_MANUFACTURER,
451 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
452 };
453 
454 static int spwr_battery_prop_status(struct spwr_battery_device *bat)
455 {
456 	u32 state = get_unaligned_le32(&bat->bst.state);
457 	u32 present_rate = get_unaligned_le32(&bat->bst.present_rate);
458 
459 	lockdep_assert_held(&bat->lock);
460 
461 	if (state & SAM_BATTERY_STATE_DISCHARGING)
462 		return POWER_SUPPLY_STATUS_DISCHARGING;
463 
464 	if (state & SAM_BATTERY_STATE_CHARGING)
465 		return POWER_SUPPLY_STATUS_CHARGING;
466 
467 	if (spwr_battery_is_full(bat))
468 		return POWER_SUPPLY_STATUS_FULL;
469 
470 	if (present_rate == 0)
471 		return POWER_SUPPLY_STATUS_NOT_CHARGING;
472 
473 	return POWER_SUPPLY_STATUS_UNKNOWN;
474 }
475 
476 static int spwr_battery_prop_technology(struct spwr_battery_device *bat)
477 {
478 	lockdep_assert_held(&bat->lock);
479 
480 	if (!strcasecmp("NiCd", bat->bix.type))
481 		return POWER_SUPPLY_TECHNOLOGY_NiCd;
482 
483 	if (!strcasecmp("NiMH", bat->bix.type))
484 		return POWER_SUPPLY_TECHNOLOGY_NiMH;
485 
486 	if (!strcasecmp("LION", bat->bix.type))
487 		return POWER_SUPPLY_TECHNOLOGY_LION;
488 
489 	if (!strncasecmp("LI-ION", bat->bix.type, 6))
490 		return POWER_SUPPLY_TECHNOLOGY_LION;
491 
492 	if (!strcasecmp("LiP", bat->bix.type))
493 		return POWER_SUPPLY_TECHNOLOGY_LIPO;
494 
495 	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
496 }
497 
498 static int spwr_battery_prop_capacity(struct spwr_battery_device *bat)
499 {
500 	u32 full_cap = sprw_battery_get_full_cap_safe(bat);
501 	u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap);
502 
503 	lockdep_assert_held(&bat->lock);
504 
505 	if (full_cap == 0 || full_cap == SPWR_BATTERY_VALUE_UNKNOWN)
506 		return -ENODATA;
507 
508 	if (remaining_cap == SPWR_BATTERY_VALUE_UNKNOWN)
509 		return -ENODATA;
510 
511 	return remaining_cap * 100 / full_cap;
512 }
513 
514 static int spwr_battery_prop_capacity_level(struct spwr_battery_device *bat)
515 {
516 	u32 state = get_unaligned_le32(&bat->bst.state);
517 	u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap);
518 
519 	lockdep_assert_held(&bat->lock);
520 
521 	if (state & SAM_BATTERY_STATE_CRITICAL)
522 		return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
523 
524 	if (spwr_battery_is_full(bat))
525 		return POWER_SUPPLY_CAPACITY_LEVEL_FULL;
526 
527 	if (remaining_cap <= bat->alarm)
528 		return POWER_SUPPLY_CAPACITY_LEVEL_LOW;
529 
530 	return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
531 }
532 
533 static int spwr_battery_get_property(struct power_supply *psy, enum power_supply_property psp,
534 				     union power_supply_propval *val)
535 {
536 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
537 	u32 value;
538 	int status;
539 
540 	mutex_lock(&bat->lock);
541 
542 	status = spwr_battery_update_bst_unlocked(bat, true);
543 	if (status)
544 		goto out;
545 
546 	/* Abort if battery is not present. */
547 	if (!spwr_battery_present(bat) && psp != POWER_SUPPLY_PROP_PRESENT) {
548 		status = -ENODEV;
549 		goto out;
550 	}
551 
552 	switch (psp) {
553 	case POWER_SUPPLY_PROP_STATUS:
554 		val->intval = spwr_battery_prop_status(bat);
555 		break;
556 
557 	case POWER_SUPPLY_PROP_PRESENT:
558 		val->intval = spwr_battery_present(bat);
559 		break;
560 
561 	case POWER_SUPPLY_PROP_TECHNOLOGY:
562 		val->intval = spwr_battery_prop_technology(bat);
563 		break;
564 
565 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
566 		value = get_unaligned_le32(&bat->bix.cycle_count);
567 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
568 			val->intval = value;
569 		else
570 			status = -ENODATA;
571 		break;
572 
573 	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
574 		value = get_unaligned_le32(&bat->bix.design_voltage);
575 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
576 			val->intval = value * 1000;
577 		else
578 			status = -ENODATA;
579 		break;
580 
581 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
582 		value = get_unaligned_le32(&bat->bst.present_voltage);
583 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
584 			val->intval = value * 1000;
585 		else
586 			status = -ENODATA;
587 		break;
588 
589 	case POWER_SUPPLY_PROP_CURRENT_NOW:
590 	case POWER_SUPPLY_PROP_POWER_NOW:
591 		value = get_unaligned_le32(&bat->bst.present_rate);
592 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
593 			val->intval = value * 1000;
594 		else
595 			status = -ENODATA;
596 		break;
597 
598 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
599 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
600 		value = get_unaligned_le32(&bat->bix.design_cap);
601 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
602 			val->intval = value * 1000;
603 		else
604 			status = -ENODATA;
605 		break;
606 
607 	case POWER_SUPPLY_PROP_CHARGE_FULL:
608 	case POWER_SUPPLY_PROP_ENERGY_FULL:
609 		value = get_unaligned_le32(&bat->bix.last_full_charge_cap);
610 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
611 			val->intval = value * 1000;
612 		else
613 			status = -ENODATA;
614 		break;
615 
616 	case POWER_SUPPLY_PROP_CHARGE_NOW:
617 	case POWER_SUPPLY_PROP_ENERGY_NOW:
618 		value = get_unaligned_le32(&bat->bst.remaining_cap);
619 		if (value != SPWR_BATTERY_VALUE_UNKNOWN)
620 			val->intval = value * 1000;
621 		else
622 			status = -ENODATA;
623 		break;
624 
625 	case POWER_SUPPLY_PROP_CAPACITY:
626 		val->intval = spwr_battery_prop_capacity(bat);
627 		break;
628 
629 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
630 		val->intval = spwr_battery_prop_capacity_level(bat);
631 		break;
632 
633 	case POWER_SUPPLY_PROP_MODEL_NAME:
634 		val->strval = bat->bix.model;
635 		break;
636 
637 	case POWER_SUPPLY_PROP_MANUFACTURER:
638 		val->strval = bat->bix.oem_info;
639 		break;
640 
641 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
642 		val->strval = bat->bix.serial;
643 		break;
644 
645 	default:
646 		status = -EINVAL;
647 		break;
648 	}
649 
650 out:
651 	mutex_unlock(&bat->lock);
652 	return status;
653 }
654 
655 
656 /* -- Alarm attribute. ------------------------------------------------------ */
657 
658 static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, char *buf)
659 {
660 	struct power_supply *psy = dev_get_drvdata(dev);
661 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
662 	int status;
663 
664 	mutex_lock(&bat->lock);
665 	status = sysfs_emit(buf, "%d\n", bat->alarm * 1000);
666 	mutex_unlock(&bat->lock);
667 
668 	return status;
669 }
670 
671 static ssize_t alarm_store(struct device *dev, struct device_attribute *attr, const char *buf,
672 			   size_t count)
673 {
674 	struct power_supply *psy = dev_get_drvdata(dev);
675 	struct spwr_battery_device *bat = power_supply_get_drvdata(psy);
676 	unsigned long value;
677 	int status;
678 
679 	status = kstrtoul(buf, 0, &value);
680 	if (status)
681 		return status;
682 
683 	mutex_lock(&bat->lock);
684 
685 	if (!spwr_battery_present(bat)) {
686 		mutex_unlock(&bat->lock);
687 		return -ENODEV;
688 	}
689 
690 	status = spwr_battery_set_alarm_unlocked(bat, value / 1000);
691 	if (status) {
692 		mutex_unlock(&bat->lock);
693 		return status;
694 	}
695 
696 	mutex_unlock(&bat->lock);
697 	return count;
698 }
699 
700 static DEVICE_ATTR_RW(alarm);
701 
702 static struct attribute *spwr_battery_attrs[] = {
703 	&dev_attr_alarm.attr,
704 	NULL,
705 };
706 ATTRIBUTE_GROUPS(spwr_battery);
707 
708 
709 /* -- Device setup. --------------------------------------------------------- */
710 
711 static void spwr_battery_init(struct spwr_battery_device *bat, struct ssam_device *sdev,
712 			      struct ssam_event_registry registry, const char *name)
713 {
714 	mutex_init(&bat->lock);
715 	strncpy(bat->name, name, ARRAY_SIZE(bat->name) - 1);
716 
717 	bat->sdev = sdev;
718 
719 	bat->notif.base.priority = 1;
720 	bat->notif.base.fn = spwr_notify_bat;
721 	bat->notif.event.reg = registry;
722 	bat->notif.event.id.target_category = sdev->uid.category;
723 	bat->notif.event.id.instance = 0;
724 	bat->notif.event.mask = SSAM_EVENT_MASK_STRICT;
725 	bat->notif.event.flags = SSAM_EVENT_SEQUENCED;
726 
727 	bat->psy_desc.name = bat->name;
728 	bat->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
729 	bat->psy_desc.get_property = spwr_battery_get_property;
730 
731 	INIT_DELAYED_WORK(&bat->update_work, spwr_battery_update_bst_workfn);
732 }
733 
734 static int spwr_battery_register(struct spwr_battery_device *bat)
735 {
736 	struct power_supply_config psy_cfg = {};
737 	__le32 sta;
738 	int status;
739 
740 	/* Make sure the device is there and functioning properly. */
741 	status = ssam_retry(ssam_bat_get_sta, bat->sdev, &sta);
742 	if (status)
743 		return status;
744 
745 	if ((le32_to_cpu(sta) & SAM_BATTERY_STA_OK) != SAM_BATTERY_STA_OK)
746 		return -ENODEV;
747 
748 	/* Satisfy lockdep although we are in an exclusive context here. */
749 	mutex_lock(&bat->lock);
750 
751 	status = spwr_battery_update_bix_unlocked(bat);
752 	if (status) {
753 		mutex_unlock(&bat->lock);
754 		return status;
755 	}
756 
757 	if (spwr_battery_present(bat)) {
758 		u32 cap_warn = get_unaligned_le32(&bat->bix.design_cap_warn);
759 
760 		status = spwr_battery_set_alarm_unlocked(bat, cap_warn);
761 		if (status) {
762 			mutex_unlock(&bat->lock);
763 			return status;
764 		}
765 	}
766 
767 	mutex_unlock(&bat->lock);
768 
769 	bat->psy_desc.external_power_changed = spwr_external_power_changed;
770 
771 	switch (get_unaligned_le32(&bat->bix.power_unit)) {
772 	case SAM_BATTERY_POWER_UNIT_mW:
773 		bat->psy_desc.properties = spwr_battery_props_eng;
774 		bat->psy_desc.num_properties = ARRAY_SIZE(spwr_battery_props_eng);
775 		break;
776 
777 	case SAM_BATTERY_POWER_UNIT_mA:
778 		bat->psy_desc.properties = spwr_battery_props_chg;
779 		bat->psy_desc.num_properties = ARRAY_SIZE(spwr_battery_props_chg);
780 		break;
781 
782 	default:
783 		dev_err(&bat->sdev->dev, "unsupported battery power unit: %u\n",
784 			get_unaligned_le32(&bat->bix.power_unit));
785 		return -EINVAL;
786 	}
787 
788 	psy_cfg.drv_data = bat;
789 	psy_cfg.attr_grp = spwr_battery_groups;
790 
791 	bat->psy = devm_power_supply_register(&bat->sdev->dev, &bat->psy_desc, &psy_cfg);
792 	if (IS_ERR(bat->psy))
793 		return PTR_ERR(bat->psy);
794 
795 	return ssam_notifier_register(bat->sdev->ctrl, &bat->notif);
796 }
797 
798 
799 /* -- Driver setup. --------------------------------------------------------- */
800 
801 static int __maybe_unused surface_battery_resume(struct device *dev)
802 {
803 	return spwr_battery_recheck_full(dev_get_drvdata(dev));
804 }
805 static SIMPLE_DEV_PM_OPS(surface_battery_pm_ops, NULL, surface_battery_resume);
806 
807 static int surface_battery_probe(struct ssam_device *sdev)
808 {
809 	const struct spwr_psy_properties *p;
810 	struct spwr_battery_device *bat;
811 
812 	p = ssam_device_get_match_data(sdev);
813 	if (!p)
814 		return -ENODEV;
815 
816 	bat = devm_kzalloc(&sdev->dev, sizeof(*bat), GFP_KERNEL);
817 	if (!bat)
818 		return -ENOMEM;
819 
820 	spwr_battery_init(bat, sdev, p->registry, p->name);
821 	ssam_device_set_drvdata(sdev, bat);
822 
823 	return spwr_battery_register(bat);
824 }
825 
826 static void surface_battery_remove(struct ssam_device *sdev)
827 {
828 	struct spwr_battery_device *bat = ssam_device_get_drvdata(sdev);
829 
830 	ssam_notifier_unregister(sdev->ctrl, &bat->notif);
831 	cancel_delayed_work_sync(&bat->update_work);
832 }
833 
834 static const struct spwr_psy_properties spwr_psy_props_bat1 = {
835 	.name = "BAT1",
836 	.registry = SSAM_EVENT_REGISTRY_SAM,
837 };
838 
839 static const struct spwr_psy_properties spwr_psy_props_bat2_sb3 = {
840 	.name = "BAT2",
841 	.registry = SSAM_EVENT_REGISTRY_KIP,
842 };
843 
844 static const struct ssam_device_id surface_battery_match[] = {
845 	{ SSAM_SDEV(BAT, 0x01, 0x01, 0x00), (unsigned long)&spwr_psy_props_bat1     },
846 	{ SSAM_SDEV(BAT, 0x02, 0x01, 0x00), (unsigned long)&spwr_psy_props_bat2_sb3 },
847 	{ },
848 };
849 MODULE_DEVICE_TABLE(ssam, surface_battery_match);
850 
851 static struct ssam_device_driver surface_battery_driver = {
852 	.probe = surface_battery_probe,
853 	.remove = surface_battery_remove,
854 	.match_table = surface_battery_match,
855 	.driver = {
856 		.name = "surface_battery",
857 		.pm = &surface_battery_pm_ops,
858 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
859 	},
860 };
861 module_ssam_device_driver(surface_battery_driver);
862 
863 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
864 MODULE_DESCRIPTION("Battery driver for Surface System Aggregator Module");
865 MODULE_LICENSE("GPL");
866