Lines Matching +full:sbs +full:- +full:battery

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
6 * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
24 #include <acpi/battery.h>
28 #define ACPI_SBS_CLASS "sbs"
30 #define ACPI_SBS_DEVICE_NAME "Smart Battery System"
38 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
57 struct acpi_sbs *sbs; member
89 struct acpi_battery battery[MAX_SBS_BAT]; member
99 static int acpi_battery_get_state(struct acpi_battery *battery);
104 while (log--) in battery_scale()
109 static inline int acpi_battery_vscale(struct acpi_battery *battery) in acpi_battery_vscale() argument
111 return battery_scale((battery->spec & 0x0f00) >> 8); in acpi_battery_vscale()
114 static inline int acpi_battery_ipscale(struct acpi_battery *battery) in acpi_battery_ipscale() argument
116 return battery_scale((battery->spec & 0xf000) >> 12); in acpi_battery_ipscale()
119 static inline int acpi_battery_mode(struct acpi_battery *battery) in acpi_battery_mode() argument
121 return (battery->mode & 0x8000); in acpi_battery_mode()
124 static inline int acpi_battery_scale(struct acpi_battery *battery) in acpi_battery_scale() argument
126 return (acpi_battery_mode(battery) ? 10 : 1) * in acpi_battery_scale()
127 acpi_battery_ipscale(battery); in acpi_battery_scale()
134 struct acpi_sbs *sbs = to_acpi_sbs(psy); in sbs_get_ac_property() local
137 val->intval = sbs->charger_present; in sbs_get_ac_property()
140 return -EINVAL; in sbs_get_ac_property()
145 static int acpi_battery_technology(struct acpi_battery *battery) in acpi_battery_technology() argument
147 if (!strcasecmp("NiCd", battery->device_chemistry)) in acpi_battery_technology()
149 if (!strcasecmp("NiMH", battery->device_chemistry)) in acpi_battery_technology()
151 if (!strcasecmp("LION", battery->device_chemistry)) in acpi_battery_technology()
153 if (!strcasecmp("LiP", battery->device_chemistry)) in acpi_battery_technology()
162 struct acpi_battery *battery = to_acpi_battery(psy); in acpi_sbs_battery_get_property() local
164 if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT) in acpi_sbs_battery_get_property()
165 return -ENODEV; in acpi_sbs_battery_get_property()
167 acpi_battery_get_state(battery); in acpi_sbs_battery_get_property()
170 if (battery->rate_now < 0) in acpi_sbs_battery_get_property()
171 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; in acpi_sbs_battery_get_property()
172 else if (battery->rate_now > 0) in acpi_sbs_battery_get_property()
173 val->intval = POWER_SUPPLY_STATUS_CHARGING; in acpi_sbs_battery_get_property()
175 val->intval = POWER_SUPPLY_STATUS_FULL; in acpi_sbs_battery_get_property()
178 val->intval = battery->present; in acpi_sbs_battery_get_property()
181 val->intval = acpi_battery_technology(battery); in acpi_sbs_battery_get_property()
184 val->intval = battery->cycle_count; in acpi_sbs_battery_get_property()
187 val->intval = battery->design_voltage * in acpi_sbs_battery_get_property()
188 acpi_battery_vscale(battery) * 1000; in acpi_sbs_battery_get_property()
191 val->intval = battery->voltage_now * in acpi_sbs_battery_get_property()
192 acpi_battery_vscale(battery) * 1000; in acpi_sbs_battery_get_property()
196 val->intval = abs(battery->rate_now) * in acpi_sbs_battery_get_property()
197 acpi_battery_ipscale(battery) * 1000; in acpi_sbs_battery_get_property()
198 val->intval *= (acpi_battery_mode(battery)) ? in acpi_sbs_battery_get_property()
199 (battery->voltage_now * in acpi_sbs_battery_get_property()
200 acpi_battery_vscale(battery) / 1000) : 1; in acpi_sbs_battery_get_property()
204 val->intval = abs(battery->rate_avg) * in acpi_sbs_battery_get_property()
205 acpi_battery_ipscale(battery) * 1000; in acpi_sbs_battery_get_property()
206 val->intval *= (acpi_battery_mode(battery)) ? in acpi_sbs_battery_get_property()
207 (battery->voltage_now * in acpi_sbs_battery_get_property()
208 acpi_battery_vscale(battery) / 1000) : 1; in acpi_sbs_battery_get_property()
211 val->intval = battery->state_of_charge; in acpi_sbs_battery_get_property()
215 val->intval = battery->design_capacity * in acpi_sbs_battery_get_property()
216 acpi_battery_scale(battery) * 1000; in acpi_sbs_battery_get_property()
220 val->intval = battery->full_charge_capacity * in acpi_sbs_battery_get_property()
221 acpi_battery_scale(battery) * 1000; in acpi_sbs_battery_get_property()
225 val->intval = battery->capacity_now * in acpi_sbs_battery_get_property()
226 acpi_battery_scale(battery) * 1000; in acpi_sbs_battery_get_property()
229 val->intval = battery->temp_now - 2730; // dK -> dC in acpi_sbs_battery_get_property()
232 val->strval = battery->device_name; in acpi_sbs_battery_get_property()
235 val->strval = battery->manufacturer_name; in acpi_sbs_battery_get_property()
238 return -EINVAL; in acpi_sbs_battery_get_property()
285 .name = "sbs-charger",
292 /* --------------------------------------------------------------------------
293 Smart Battery System Management
294 -------------------------------------------------------------------------- */
297 u8 command; /* command for battery */
326 static int acpi_manager_get_info(struct acpi_sbs *sbs) in acpi_manager_get_info() argument
331 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, in acpi_manager_get_info()
334 sbs->batteries_supported = battery_system_info & 0x000f; in acpi_manager_get_info()
338 static int acpi_battery_get_info(struct acpi_battery *battery) in acpi_battery_get_info() argument
343 result = acpi_smbus_read(battery->sbs->hc, in acpi_battery_get_info()
347 (u8 *) battery + in acpi_battery_get_info()
355 static int acpi_battery_get_state(struct acpi_battery *battery) in acpi_battery_get_state() argument
359 if (battery->update_time && in acpi_battery_get_state()
360 time_before(jiffies, battery->update_time + in acpi_battery_get_state()
364 result = acpi_smbus_read(battery->sbs->hc, in acpi_battery_get_state()
368 (u8 *)battery + in acpi_battery_get_state()
374 battery->update_time = jiffies; in acpi_battery_get_state()
378 static int acpi_battery_get_alarm(struct acpi_battery *battery) in acpi_battery_get_alarm() argument
380 return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, in acpi_battery_get_alarm()
382 (u8 *)&battery->alarm_capacity); in acpi_battery_get_alarm()
385 static int acpi_battery_set_alarm(struct acpi_battery *battery) in acpi_battery_set_alarm() argument
387 struct acpi_sbs *sbs = battery->sbs; in acpi_battery_set_alarm() local
388 u16 value, sel = 1 << (battery->id + 12); in acpi_battery_set_alarm()
393 if (sbs->manager_present) { in acpi_battery_set_alarm()
394 ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, in acpi_battery_set_alarm()
401 ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, in acpi_battery_set_alarm()
408 ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, in acpi_battery_set_alarm()
409 0x01, (u8 *)&battery->alarm_capacity, 2); in acpi_battery_set_alarm()
414 static int acpi_ac_get_present(struct acpi_sbs *sbs) in acpi_ac_get_present() argument
419 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, in acpi_ac_get_present()
427 * that the implementation doesn't support an SBS charger. in acpi_ac_get_present()
431 * wrong, so ignore the SBS charger for those too. in acpi_ac_get_present()
434 return -ENODEV; in acpi_ac_get_present()
436 sbs->charger_present = (status >> 15) & 0x1; in acpi_ac_get_present()
444 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); in acpi_battery_alarm_show() local
445 acpi_battery_get_alarm(battery); in acpi_battery_alarm_show()
446 return sprintf(buf, "%d\n", battery->alarm_capacity * in acpi_battery_alarm_show()
447 acpi_battery_scale(battery) * 1000); in acpi_battery_alarm_show()
455 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); in acpi_battery_alarm_store() local
457 battery->alarm_capacity = x / in acpi_battery_alarm_store()
458 (1000 * acpi_battery_scale(battery)); in acpi_battery_alarm_store()
459 if (battery->present) in acpi_battery_alarm_store()
460 acpi_battery_set_alarm(battery); in acpi_battery_alarm_store()
476 /* --------------------------------------------------------------------------
478 -------------------------------------------------------------------------- */
479 static int acpi_battery_read(struct acpi_battery *battery) in acpi_battery_read() argument
481 int result, saved_present = battery->present; in acpi_battery_read()
484 if (battery->sbs->manager_present) { in acpi_battery_read()
485 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, in acpi_battery_read()
490 battery->present = state & (1 << battery->id); in acpi_battery_read()
491 if (!battery->present) in acpi_battery_read()
494 /* Masking necessary for Smart Battery Selectors */ in acpi_battery_read()
496 state |= 1 << (battery->id + 12); in acpi_battery_read()
497 acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, in acpi_battery_read()
500 if (battery->id == 0) { in acpi_battery_read()
501 battery->present = 1; in acpi_battery_read()
503 if (!battery->present) in acpi_battery_read()
508 if (saved_present != battery->present) { in acpi_battery_read()
509 battery->update_time = 0; in acpi_battery_read()
510 result = acpi_battery_get_info(battery); in acpi_battery_read()
512 battery->present = 0; in acpi_battery_read()
516 result = acpi_battery_get_state(battery); in acpi_battery_read()
518 battery->present = 0; in acpi_battery_read()
522 /* Smart Battery */
523 static int acpi_battery_add(struct acpi_sbs *sbs, int id) in acpi_battery_add() argument
525 struct acpi_battery *battery = &sbs->battery[id]; in acpi_battery_add() local
527 .drv_data = battery, in acpi_battery_add()
532 battery->id = id; in acpi_battery_add()
533 battery->sbs = sbs; in acpi_battery_add()
534 result = acpi_battery_read(battery); in acpi_battery_add()
538 sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); in acpi_battery_add()
539 battery->bat_desc.name = battery->name; in acpi_battery_add()
540 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; in acpi_battery_add()
541 if (!acpi_battery_mode(battery)) { in acpi_battery_add()
542 battery->bat_desc.properties = sbs_charge_battery_props; in acpi_battery_add()
543 battery->bat_desc.num_properties = in acpi_battery_add()
546 battery->bat_desc.properties = sbs_energy_battery_props; in acpi_battery_add()
547 battery->bat_desc.num_properties = in acpi_battery_add()
550 battery->bat_desc.get_property = acpi_sbs_battery_get_property; in acpi_battery_add()
551 battery->bat = power_supply_register(&sbs->device->dev, in acpi_battery_add()
552 &battery->bat_desc, &psy_cfg); in acpi_battery_add()
553 if (IS_ERR(battery->bat)) { in acpi_battery_add()
554 result = PTR_ERR(battery->bat); in acpi_battery_add()
555 battery->bat = NULL; in acpi_battery_add()
560 pr_info("%s [%s]: Battery Slot [%s] (battery %s)\n", in acpi_battery_add()
561 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), in acpi_battery_add()
562 battery->name, battery->present ? "present" : "absent"); in acpi_battery_add()
566 static void acpi_battery_remove(struct acpi_sbs *sbs, int id) in acpi_battery_remove() argument
568 struct acpi_battery *battery = &sbs->battery[id]; in acpi_battery_remove() local
570 if (battery->bat) in acpi_battery_remove()
571 power_supply_unregister(battery->bat); in acpi_battery_remove()
574 static int acpi_charger_add(struct acpi_sbs *sbs) in acpi_charger_add() argument
577 struct power_supply_config psy_cfg = { .drv_data = sbs, }; in acpi_charger_add()
579 result = acpi_ac_get_present(sbs); in acpi_charger_add()
583 sbs->charger_exists = 1; in acpi_charger_add()
584 sbs->charger = power_supply_register(&sbs->device->dev, in acpi_charger_add()
586 if (IS_ERR(sbs->charger)) { in acpi_charger_add()
587 result = PTR_ERR(sbs->charger); in acpi_charger_add()
588 sbs->charger = NULL; in acpi_charger_add()
591 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), in acpi_charger_add()
592 ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); in acpi_charger_add()
597 static void acpi_charger_remove(struct acpi_sbs *sbs) in acpi_charger_remove() argument
599 if (sbs->charger) in acpi_charger_remove()
600 power_supply_unregister(sbs->charger); in acpi_charger_remove()
606 struct acpi_sbs *sbs = context; in acpi_sbs_callback() local
608 u8 saved_charger_state = sbs->charger_present; in acpi_sbs_callback()
611 if (sbs->charger_exists) { in acpi_sbs_callback()
612 acpi_ac_get_present(sbs); in acpi_sbs_callback()
613 if (sbs->charger_present != saved_charger_state) in acpi_sbs_callback()
614 power_supply_changed(sbs->charger); in acpi_sbs_callback()
617 if (sbs->manager_present) { in acpi_sbs_callback()
619 if (!(sbs->batteries_supported & (1 << id))) in acpi_sbs_callback()
621 bat = &sbs->battery[id]; in acpi_sbs_callback()
622 saved_battery_state = bat->present; in acpi_sbs_callback()
624 if (saved_battery_state == bat->present) in acpi_sbs_callback()
626 power_supply_changed(bat->bat); in acpi_sbs_callback()
633 struct acpi_sbs *sbs; in acpi_sbs_add() local
637 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); in acpi_sbs_add()
638 if (!sbs) { in acpi_sbs_add()
639 result = -ENOMEM; in acpi_sbs_add()
643 mutex_init(&sbs->lock); in acpi_sbs_add()
645 sbs->hc = acpi_driver_data(acpi_dev_parent(device)); in acpi_sbs_add()
646 sbs->device = device; in acpi_sbs_add()
649 device->driver_data = sbs; in acpi_sbs_add()
651 result = acpi_charger_add(sbs); in acpi_sbs_add()
652 if (result && result != -ENODEV) in acpi_sbs_add()
658 result = acpi_manager_get_info(sbs); in acpi_sbs_add()
660 sbs->manager_present = 1; in acpi_sbs_add()
662 if ((sbs->batteries_supported & (1 << id))) in acpi_sbs_add()
663 acpi_battery_add(sbs, id); in acpi_sbs_add()
667 if (!sbs->manager_present) in acpi_sbs_add()
668 acpi_battery_add(sbs, 0); in acpi_sbs_add()
670 acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); in acpi_sbs_add()
679 struct acpi_sbs *sbs; in acpi_sbs_remove() local
684 sbs = acpi_driver_data(device); in acpi_sbs_remove()
685 if (!sbs) in acpi_sbs_remove()
687 mutex_lock(&sbs->lock); in acpi_sbs_remove()
688 acpi_smbus_unregister_callback(sbs->hc); in acpi_sbs_remove()
690 acpi_battery_remove(sbs, id); in acpi_sbs_remove()
691 acpi_charger_remove(sbs); in acpi_sbs_remove()
692 mutex_unlock(&sbs->lock); in acpi_sbs_remove()
693 mutex_destroy(&sbs->lock); in acpi_sbs_remove()
694 kfree(sbs); in acpi_sbs_remove()
700 struct acpi_sbs *sbs; in acpi_sbs_resume() local
702 return -EINVAL; in acpi_sbs_resume()
703 sbs = to_acpi_device(dev)->driver_data; in acpi_sbs_resume()
704 acpi_sbs_callback(sbs); in acpi_sbs_resume()
714 .name = "sbs",