Lines Matching +full:li +full:- +full:ion

1 // SPDX-License-Identifier: GPL-2.0+
3 * Battery driver for 7th-generation Microsoft Surface devices via Surface
6 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
22 /* -- SAM interface. -------------------------------------------------------- */
112 /* -- Device structures. ---------------------------------------------------- */
140 /* -- Module parameters. ---------------------------------------------------- */
147 /* -- State management. ----------------------------------------------------- */
157 lockdep_assert_held(&bat->lock); in spwr_battery_present()
159 return le32_to_cpu(bat->sta) & SAM_BATTERY_STA_PRESENT; in spwr_battery_present()
164 lockdep_assert_held(&bat->lock); in spwr_battery_load_sta()
166 return ssam_retry(ssam_bat_get_sta, bat->sdev, &bat->sta); in spwr_battery_load_sta()
173 lockdep_assert_held(&bat->lock); in spwr_battery_load_bix()
178 status = ssam_retry(ssam_bat_get_bix, bat->sdev, &bat->bix); in spwr_battery_load_bix()
181 bat->bix.model[ARRAY_SIZE(bat->bix.model) - 1] = 0; in spwr_battery_load_bix()
182 bat->bix.serial[ARRAY_SIZE(bat->bix.serial) - 1] = 0; in spwr_battery_load_bix()
183 bat->bix.type[ARRAY_SIZE(bat->bix.type) - 1] = 0; in spwr_battery_load_bix()
184 bat->bix.oem_info[ARRAY_SIZE(bat->bix.oem_info) - 1] = 0; in spwr_battery_load_bix()
191 lockdep_assert_held(&bat->lock); in spwr_battery_load_bst()
196 return ssam_retry(ssam_bat_get_bst, bat->sdev, &bat->bst); in spwr_battery_load_bst()
203 lockdep_assert_held(&bat->lock); in spwr_battery_set_alarm_unlocked()
205 bat->alarm = value; in spwr_battery_set_alarm_unlocked()
206 return ssam_retry(ssam_bat_set_btp, bat->sdev, &value_le); in spwr_battery_set_alarm_unlocked()
211 unsigned long cache_deadline = bat->timestamp + msecs_to_jiffies(cache_time); in spwr_battery_update_bst_unlocked()
214 lockdep_assert_held(&bat->lock); in spwr_battery_update_bst_unlocked()
216 if (cached && bat->timestamp && time_is_after_jiffies(cache_deadline)) in spwr_battery_update_bst_unlocked()
227 bat->timestamp = jiffies; in spwr_battery_update_bst_unlocked()
235 mutex_lock(&bat->lock); in spwr_battery_update_bst()
237 mutex_unlock(&bat->lock); in spwr_battery_update_bst()
246 lockdep_assert_held(&bat->lock); in spwr_battery_update_bix_unlocked()
260 if (bat->bix.revision != SPWR_BIX_REVISION) in spwr_battery_update_bix_unlocked()
261 dev_warn(&bat->sdev->dev, "unsupported battery revision: %u\n", bat->bix.revision); in spwr_battery_update_bix_unlocked()
263 bat->timestamp = jiffies; in spwr_battery_update_bix_unlocked()
269 u32 full_cap = get_unaligned_le32(&bat->bix.last_full_charge_cap); in sprw_battery_get_full_cap_safe()
271 lockdep_assert_held(&bat->lock); in sprw_battery_get_full_cap_safe()
274 full_cap = get_unaligned_le32(&bat->bix.design_cap); in sprw_battery_get_full_cap_safe()
281 u32 state = get_unaligned_le32(&bat->bst.state); in spwr_battery_is_full()
283 u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap); in spwr_battery_is_full()
285 lockdep_assert_held(&bat->lock); in spwr_battery_is_full()
299 mutex_lock(&bat->lock); in spwr_battery_recheck_full()
300 unit = get_unaligned_le32(&bat->bix.power_unit); in spwr_battery_recheck_full()
307 /* If battery has been attached, (re-)initialize alarm. */ in spwr_battery_recheck_full()
309 u32 cap_warn = get_unaligned_le32(&bat->bix.design_cap_warn); in spwr_battery_recheck_full()
321 WARN_ON(unit != get_unaligned_le32(&bat->bix.power_unit)); in spwr_battery_recheck_full()
324 mutex_unlock(&bat->lock); in spwr_battery_recheck_full()
327 power_supply_changed(bat->psy); in spwr_battery_recheck_full()
338 power_supply_changed(bat->psy); in spwr_battery_recheck_status()
351 * would thus drop events, as those may have non-zero instance IDs in in spwr_notify_bat()
355 if (event->instance_id != bat->sdev->uid.instance) in spwr_notify_bat()
358 dev_dbg(&bat->sdev->dev, "power event (cid = %#04x, iid = %#04x, tid = %#04x)\n", in spwr_notify_bat()
359 event->command_id, event->instance_id, event->target_id); in spwr_notify_bat()
361 switch (event->command_id) { in spwr_notify_bat()
402 dev_err(&bat->sdev->dev, "failed to update battery state: %d\n", status); in spwr_battery_update_bst_workfn()
406 power_supply_changed(bat->psy); in spwr_battery_update_bst_workfn()
422 schedule_delayed_work(&bat->update_work, SPWR_AC_BAT_UPDATE_DELAY); in spwr_external_power_changed()
426 /* -- Properties. ----------------------------------------------------------- */
466 u32 state = get_unaligned_le32(&bat->bst.state); in spwr_battery_prop_status()
467 u32 present_rate = get_unaligned_le32(&bat->bst.present_rate); in spwr_battery_prop_status()
469 lockdep_assert_held(&bat->lock); in spwr_battery_prop_status()
488 lockdep_assert_held(&bat->lock); in spwr_battery_prop_technology()
490 if (!strcasecmp("NiCd", bat->bix.type)) in spwr_battery_prop_technology()
493 if (!strcasecmp("NiMH", bat->bix.type)) in spwr_battery_prop_technology()
496 if (!strcasecmp("LION", bat->bix.type)) in spwr_battery_prop_technology()
499 if (!strncasecmp("LI-ION", bat->bix.type, 6)) in spwr_battery_prop_technology()
502 if (!strcasecmp("LiP", bat->bix.type)) in spwr_battery_prop_technology()
511 u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap); in spwr_battery_prop_capacity()
513 lockdep_assert_held(&bat->lock); in spwr_battery_prop_capacity()
516 return -ENODATA; in spwr_battery_prop_capacity()
519 return -ENODATA; in spwr_battery_prop_capacity()
526 u32 state = get_unaligned_le32(&bat->bst.state); in spwr_battery_prop_capacity_level()
527 u32 remaining_cap = get_unaligned_le32(&bat->bst.remaining_cap); in spwr_battery_prop_capacity_level()
529 lockdep_assert_held(&bat->lock); in spwr_battery_prop_capacity_level()
537 if (remaining_cap <= bat->alarm) in spwr_battery_prop_capacity_level()
550 mutex_lock(&bat->lock); in spwr_battery_get_property()
558 status = -ENODEV; in spwr_battery_get_property()
564 val->intval = spwr_battery_prop_status(bat); in spwr_battery_get_property()
568 val->intval = spwr_battery_present(bat); in spwr_battery_get_property()
572 val->intval = spwr_battery_prop_technology(bat); in spwr_battery_get_property()
576 value = get_unaligned_le32(&bat->bix.cycle_count); in spwr_battery_get_property()
578 val->intval = value; in spwr_battery_get_property()
580 status = -ENODATA; in spwr_battery_get_property()
584 value = get_unaligned_le32(&bat->bix.design_voltage); in spwr_battery_get_property()
586 val->intval = value * 1000; in spwr_battery_get_property()
588 status = -ENODATA; in spwr_battery_get_property()
592 value = get_unaligned_le32(&bat->bst.present_voltage); in spwr_battery_get_property()
594 val->intval = value * 1000; in spwr_battery_get_property()
596 status = -ENODATA; in spwr_battery_get_property()
601 value = get_unaligned_le32(&bat->bst.present_rate); in spwr_battery_get_property()
603 val->intval = value * 1000; in spwr_battery_get_property()
605 status = -ENODATA; in spwr_battery_get_property()
610 value = get_unaligned_le32(&bat->bix.design_cap); in spwr_battery_get_property()
612 val->intval = value * 1000; in spwr_battery_get_property()
614 status = -ENODATA; in spwr_battery_get_property()
619 value = get_unaligned_le32(&bat->bix.last_full_charge_cap); in spwr_battery_get_property()
621 val->intval = value * 1000; in spwr_battery_get_property()
623 status = -ENODATA; in spwr_battery_get_property()
628 value = get_unaligned_le32(&bat->bst.remaining_cap); in spwr_battery_get_property()
630 val->intval = value * 1000; in spwr_battery_get_property()
632 status = -ENODATA; in spwr_battery_get_property()
636 val->intval = spwr_battery_prop_capacity(bat); in spwr_battery_get_property()
640 val->intval = spwr_battery_prop_capacity_level(bat); in spwr_battery_get_property()
644 val->strval = bat->bix.model; in spwr_battery_get_property()
648 val->strval = bat->bix.oem_info; in spwr_battery_get_property()
652 val->strval = bat->bix.serial; in spwr_battery_get_property()
656 status = -EINVAL; in spwr_battery_get_property()
661 mutex_unlock(&bat->lock); in spwr_battery_get_property()
666 /* -- Alarm attribute. ------------------------------------------------------ */
674 mutex_lock(&bat->lock); in alarm_show()
675 status = sysfs_emit(buf, "%d\n", bat->alarm * 1000); in alarm_show()
676 mutex_unlock(&bat->lock); in alarm_show()
693 mutex_lock(&bat->lock); in alarm_store()
696 mutex_unlock(&bat->lock); in alarm_store()
697 return -ENODEV; in alarm_store()
702 mutex_unlock(&bat->lock); in alarm_store()
706 mutex_unlock(&bat->lock); in alarm_store()
719 /* -- Device setup. --------------------------------------------------------- */
724 mutex_init(&bat->lock); in spwr_battery_init()
725 strscpy(bat->name, name, sizeof(bat->name)); in spwr_battery_init()
727 bat->sdev = sdev; in spwr_battery_init()
729 bat->notif.base.priority = 1; in spwr_battery_init()
730 bat->notif.base.fn = spwr_notify_bat; in spwr_battery_init()
731 bat->notif.event.reg = registry; in spwr_battery_init()
732 bat->notif.event.id.target_category = sdev->uid.category; in spwr_battery_init()
733 bat->notif.event.id.instance = 0; /* need to register with instance 0 */ in spwr_battery_init()
734 bat->notif.event.mask = SSAM_EVENT_MASK_TARGET; in spwr_battery_init()
735 bat->notif.event.flags = SSAM_EVENT_SEQUENCED; in spwr_battery_init()
737 bat->psy_desc.name = bat->name; in spwr_battery_init()
738 bat->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY; in spwr_battery_init()
739 bat->psy_desc.get_property = spwr_battery_get_property; in spwr_battery_init()
741 INIT_DELAYED_WORK(&bat->update_work, spwr_battery_update_bst_workfn); in spwr_battery_init()
751 status = ssam_retry(ssam_bat_get_sta, bat->sdev, &sta); in spwr_battery_register()
756 return -ENODEV; in spwr_battery_register()
759 mutex_lock(&bat->lock); in spwr_battery_register()
763 mutex_unlock(&bat->lock); in spwr_battery_register()
768 u32 cap_warn = get_unaligned_le32(&bat->bix.design_cap_warn); in spwr_battery_register()
772 mutex_unlock(&bat->lock); in spwr_battery_register()
777 mutex_unlock(&bat->lock); in spwr_battery_register()
779 bat->psy_desc.external_power_changed = spwr_external_power_changed; in spwr_battery_register()
781 switch (get_unaligned_le32(&bat->bix.power_unit)) { in spwr_battery_register()
783 bat->psy_desc.properties = spwr_battery_props_eng; in spwr_battery_register()
784 bat->psy_desc.num_properties = ARRAY_SIZE(spwr_battery_props_eng); in spwr_battery_register()
788 bat->psy_desc.properties = spwr_battery_props_chg; in spwr_battery_register()
789 bat->psy_desc.num_properties = ARRAY_SIZE(spwr_battery_props_chg); in spwr_battery_register()
793 dev_err(&bat->sdev->dev, "unsupported battery power unit: %u\n", in spwr_battery_register()
794 get_unaligned_le32(&bat->bix.power_unit)); in spwr_battery_register()
795 return -EINVAL; in spwr_battery_register()
801 bat->psy = devm_power_supply_register(&bat->sdev->dev, &bat->psy_desc, &psy_cfg); in spwr_battery_register()
802 if (IS_ERR(bat->psy)) in spwr_battery_register()
803 return PTR_ERR(bat->psy); in spwr_battery_register()
805 return ssam_device_notifier_register(bat->sdev, &bat->notif); in spwr_battery_register()
809 /* -- Driver setup. --------------------------------------------------------- */
824 return -ENODEV; in surface_battery_probe()
826 bat = devm_kzalloc(&sdev->dev, sizeof(*bat), GFP_KERNEL); in surface_battery_probe()
828 return -ENOMEM; in surface_battery_probe()
830 spwr_battery_init(bat, sdev, p->registry, p->name); in surface_battery_probe()
840 ssam_device_notifier_unregister(sdev, &bat->notif); in surface_battery_remove()
841 cancel_delayed_work_sync(&bat->update_work); in surface_battery_remove()