cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sbs.c (19490B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
      4 *
      5 *  Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
      6 *  Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
      7 *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
      8 */
      9
     10#define pr_fmt(fmt) "ACPI: " fmt
     11
     12#include <linux/init.h>
     13#include <linux/slab.h>
     14#include <linux/module.h>
     15#include <linux/moduleparam.h>
     16#include <linux/kernel.h>
     17
     18#include <linux/acpi.h>
     19#include <linux/timer.h>
     20#include <linux/jiffies.h>
     21#include <linux/delay.h>
     22#include <linux/power_supply.h>
     23#include <linux/platform_data/x86/apple.h>
     24#include <acpi/battery.h>
     25
     26#include "sbshc.h"
     27
     28#define ACPI_SBS_CLASS			"sbs"
     29#define ACPI_AC_CLASS			"ac_adapter"
     30#define ACPI_SBS_DEVICE_NAME		"Smart Battery System"
     31#define ACPI_BATTERY_DIR_NAME		"BAT%i"
     32#define ACPI_AC_DIR_NAME		"AC0"
     33
     34#define ACPI_SBS_NOTIFY_STATUS		0x80
     35#define ACPI_SBS_NOTIFY_INFO		0x81
     36
     37MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
     38MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
     39MODULE_LICENSE("GPL");
     40
     41static unsigned int cache_time = 1000;
     42module_param(cache_time, uint, 0644);
     43MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
     44
     45#define MAX_SBS_BAT			4
     46#define ACPI_SBS_BLOCK_MAX		32
     47
     48static const struct acpi_device_id sbs_device_ids[] = {
     49	{"ACPI0002", 0},
     50	{"", 0},
     51};
     52MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
     53
     54struct acpi_battery {
     55	struct power_supply *bat;
     56	struct power_supply_desc bat_desc;
     57	struct acpi_sbs *sbs;
     58	unsigned long update_time;
     59	char name[8];
     60	char manufacturer_name[ACPI_SBS_BLOCK_MAX];
     61	char device_name[ACPI_SBS_BLOCK_MAX];
     62	char device_chemistry[ACPI_SBS_BLOCK_MAX];
     63	u16 alarm_capacity;
     64	u16 full_charge_capacity;
     65	u16 design_capacity;
     66	u16 design_voltage;
     67	u16 serial_number;
     68	u16 cycle_count;
     69	u16 temp_now;
     70	u16 voltage_now;
     71	s16 rate_now;
     72	s16 rate_avg;
     73	u16 capacity_now;
     74	u16 state_of_charge;
     75	u16 state;
     76	u16 mode;
     77	u16 spec;
     78	u8 id;
     79	u8 present:1;
     80	u8 have_sysfs_alarm:1;
     81};
     82
     83#define to_acpi_battery(x) power_supply_get_drvdata(x)
     84
     85struct acpi_sbs {
     86	struct power_supply *charger;
     87	struct acpi_device *device;
     88	struct acpi_smb_hc *hc;
     89	struct mutex lock;
     90	struct acpi_battery battery[MAX_SBS_BAT];
     91	u8 batteries_supported:4;
     92	u8 manager_present:1;
     93	u8 charger_present:1;
     94	u8 charger_exists:1;
     95};
     96
     97#define to_acpi_sbs(x) power_supply_get_drvdata(x)
     98
     99static int acpi_sbs_remove(struct acpi_device *device);
    100static int acpi_battery_get_state(struct acpi_battery *battery);
    101
    102static inline int battery_scale(int log)
    103{
    104	int scale = 1;
    105	while (log--)
    106		scale *= 10;
    107	return scale;
    108}
    109
    110static inline int acpi_battery_vscale(struct acpi_battery *battery)
    111{
    112	return battery_scale((battery->spec & 0x0f00) >> 8);
    113}
    114
    115static inline int acpi_battery_ipscale(struct acpi_battery *battery)
    116{
    117	return battery_scale((battery->spec & 0xf000) >> 12);
    118}
    119
    120static inline int acpi_battery_mode(struct acpi_battery *battery)
    121{
    122	return (battery->mode & 0x8000);
    123}
    124
    125static inline int acpi_battery_scale(struct acpi_battery *battery)
    126{
    127	return (acpi_battery_mode(battery) ? 10 : 1) *
    128	    acpi_battery_ipscale(battery);
    129}
    130
    131static int sbs_get_ac_property(struct power_supply *psy,
    132			       enum power_supply_property psp,
    133			       union power_supply_propval *val)
    134{
    135	struct acpi_sbs *sbs = to_acpi_sbs(psy);
    136	switch (psp) {
    137	case POWER_SUPPLY_PROP_ONLINE:
    138		val->intval = sbs->charger_present;
    139		break;
    140	default:
    141		return -EINVAL;
    142	}
    143	return 0;
    144}
    145
    146static int acpi_battery_technology(struct acpi_battery *battery)
    147{
    148	if (!strcasecmp("NiCd", battery->device_chemistry))
    149		return POWER_SUPPLY_TECHNOLOGY_NiCd;
    150	if (!strcasecmp("NiMH", battery->device_chemistry))
    151		return POWER_SUPPLY_TECHNOLOGY_NiMH;
    152	if (!strcasecmp("LION", battery->device_chemistry))
    153		return POWER_SUPPLY_TECHNOLOGY_LION;
    154	if (!strcasecmp("LiP", battery->device_chemistry))
    155		return POWER_SUPPLY_TECHNOLOGY_LIPO;
    156	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
    157}
    158
    159static int acpi_sbs_battery_get_property(struct power_supply *psy,
    160					 enum power_supply_property psp,
    161					 union power_supply_propval *val)
    162{
    163	struct acpi_battery *battery = to_acpi_battery(psy);
    164
    165	if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
    166		return -ENODEV;
    167
    168	acpi_battery_get_state(battery);
    169	switch (psp) {
    170	case POWER_SUPPLY_PROP_STATUS:
    171		if (battery->rate_now < 0)
    172			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
    173		else if (battery->rate_now > 0)
    174			val->intval = POWER_SUPPLY_STATUS_CHARGING;
    175		else
    176			val->intval = POWER_SUPPLY_STATUS_FULL;
    177		break;
    178	case POWER_SUPPLY_PROP_PRESENT:
    179		val->intval = battery->present;
    180		break;
    181	case POWER_SUPPLY_PROP_TECHNOLOGY:
    182		val->intval = acpi_battery_technology(battery);
    183		break;
    184	case POWER_SUPPLY_PROP_CYCLE_COUNT:
    185		val->intval = battery->cycle_count;
    186		break;
    187	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
    188		val->intval = battery->design_voltage *
    189			acpi_battery_vscale(battery) * 1000;
    190		break;
    191	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
    192		val->intval = battery->voltage_now *
    193				acpi_battery_vscale(battery) * 1000;
    194		break;
    195	case POWER_SUPPLY_PROP_CURRENT_NOW:
    196	case POWER_SUPPLY_PROP_POWER_NOW:
    197		val->intval = abs(battery->rate_now) *
    198				acpi_battery_ipscale(battery) * 1000;
    199		val->intval *= (acpi_battery_mode(battery)) ?
    200				(battery->voltage_now *
    201				acpi_battery_vscale(battery) / 1000) : 1;
    202		break;
    203	case POWER_SUPPLY_PROP_CURRENT_AVG:
    204	case POWER_SUPPLY_PROP_POWER_AVG:
    205		val->intval = abs(battery->rate_avg) *
    206				acpi_battery_ipscale(battery) * 1000;
    207		val->intval *= (acpi_battery_mode(battery)) ?
    208				(battery->voltage_now *
    209				acpi_battery_vscale(battery) / 1000) : 1;
    210		break;
    211	case POWER_SUPPLY_PROP_CAPACITY:
    212		val->intval = battery->state_of_charge;
    213		break;
    214	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
    215	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
    216		val->intval = battery->design_capacity *
    217			acpi_battery_scale(battery) * 1000;
    218		break;
    219	case POWER_SUPPLY_PROP_CHARGE_FULL:
    220	case POWER_SUPPLY_PROP_ENERGY_FULL:
    221		val->intval = battery->full_charge_capacity *
    222			acpi_battery_scale(battery) * 1000;
    223		break;
    224	case POWER_SUPPLY_PROP_CHARGE_NOW:
    225	case POWER_SUPPLY_PROP_ENERGY_NOW:
    226		val->intval = battery->capacity_now *
    227				acpi_battery_scale(battery) * 1000;
    228		break;
    229	case POWER_SUPPLY_PROP_TEMP:
    230		val->intval = battery->temp_now - 2730;	// dK -> dC
    231		break;
    232	case POWER_SUPPLY_PROP_MODEL_NAME:
    233		val->strval = battery->device_name;
    234		break;
    235	case POWER_SUPPLY_PROP_MANUFACTURER:
    236		val->strval = battery->manufacturer_name;
    237		break;
    238	default:
    239		return -EINVAL;
    240	}
    241	return 0;
    242}
    243
    244static enum power_supply_property sbs_ac_props[] = {
    245	POWER_SUPPLY_PROP_ONLINE,
    246};
    247
    248static enum power_supply_property sbs_charge_battery_props[] = {
    249	POWER_SUPPLY_PROP_STATUS,
    250	POWER_SUPPLY_PROP_PRESENT,
    251	POWER_SUPPLY_PROP_TECHNOLOGY,
    252	POWER_SUPPLY_PROP_CYCLE_COUNT,
    253	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
    254	POWER_SUPPLY_PROP_VOLTAGE_NOW,
    255	POWER_SUPPLY_PROP_CURRENT_NOW,
    256	POWER_SUPPLY_PROP_CURRENT_AVG,
    257	POWER_SUPPLY_PROP_CAPACITY,
    258	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
    259	POWER_SUPPLY_PROP_CHARGE_FULL,
    260	POWER_SUPPLY_PROP_CHARGE_NOW,
    261	POWER_SUPPLY_PROP_TEMP,
    262	POWER_SUPPLY_PROP_MODEL_NAME,
    263	POWER_SUPPLY_PROP_MANUFACTURER,
    264};
    265
    266static enum power_supply_property sbs_energy_battery_props[] = {
    267	POWER_SUPPLY_PROP_STATUS,
    268	POWER_SUPPLY_PROP_PRESENT,
    269	POWER_SUPPLY_PROP_TECHNOLOGY,
    270	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
    271	POWER_SUPPLY_PROP_VOLTAGE_NOW,
    272	POWER_SUPPLY_PROP_CURRENT_NOW,
    273	POWER_SUPPLY_PROP_CURRENT_AVG,
    274	POWER_SUPPLY_PROP_POWER_NOW,
    275	POWER_SUPPLY_PROP_POWER_AVG,
    276	POWER_SUPPLY_PROP_CAPACITY,
    277	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
    278	POWER_SUPPLY_PROP_ENERGY_FULL,
    279	POWER_SUPPLY_PROP_ENERGY_NOW,
    280	POWER_SUPPLY_PROP_TEMP,
    281	POWER_SUPPLY_PROP_MODEL_NAME,
    282	POWER_SUPPLY_PROP_MANUFACTURER,
    283};
    284
    285static const struct power_supply_desc acpi_sbs_charger_desc = {
    286	.name		= "sbs-charger",
    287	.type		= POWER_SUPPLY_TYPE_MAINS,
    288	.properties	= sbs_ac_props,
    289	.num_properties	= ARRAY_SIZE(sbs_ac_props),
    290	.get_property	= sbs_get_ac_property,
    291};
    292
    293/* --------------------------------------------------------------------------
    294                            Smart Battery System Management
    295   -------------------------------------------------------------------------- */
    296
    297struct acpi_battery_reader {
    298	u8 command;		/* command for battery */
    299	u8 mode;		/* word or block? */
    300	size_t offset;		/* offset inside struct acpi_sbs_battery */
    301};
    302
    303static struct acpi_battery_reader info_readers[] = {
    304	{0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
    305	{0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
    306	{0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
    307	{0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
    308	{0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
    309	{0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
    310	{0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
    311	{0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
    312	{0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
    313	{0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
    314	{0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
    315};
    316
    317static struct acpi_battery_reader state_readers[] = {
    318	{0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
    319	{0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
    320	{0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)},
    321	{0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)},
    322	{0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
    323	{0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
    324	{0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
    325};
    326
    327static int acpi_manager_get_info(struct acpi_sbs *sbs)
    328{
    329	int result = 0;
    330	u16 battery_system_info;
    331
    332	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
    333				 0x04, (u8 *)&battery_system_info);
    334	if (!result)
    335		sbs->batteries_supported = battery_system_info & 0x000f;
    336	return result;
    337}
    338
    339static int acpi_battery_get_info(struct acpi_battery *battery)
    340{
    341	int i, result = 0;
    342
    343	for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
    344		result = acpi_smbus_read(battery->sbs->hc,
    345					 info_readers[i].mode,
    346					 ACPI_SBS_BATTERY,
    347					 info_readers[i].command,
    348					 (u8 *) battery +
    349						info_readers[i].offset);
    350		if (result)
    351			break;
    352	}
    353	return result;
    354}
    355
    356static int acpi_battery_get_state(struct acpi_battery *battery)
    357{
    358	int i, result = 0;
    359
    360	if (battery->update_time &&
    361	    time_before(jiffies, battery->update_time +
    362				msecs_to_jiffies(cache_time)))
    363		return 0;
    364	for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
    365		result = acpi_smbus_read(battery->sbs->hc,
    366					 state_readers[i].mode,
    367					 ACPI_SBS_BATTERY,
    368					 state_readers[i].command,
    369					 (u8 *)battery +
    370						state_readers[i].offset);
    371		if (result)
    372			goto end;
    373	}
    374      end:
    375	battery->update_time = jiffies;
    376	return result;
    377}
    378
    379static int acpi_battery_get_alarm(struct acpi_battery *battery)
    380{
    381	return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
    382				 ACPI_SBS_BATTERY, 0x01,
    383				 (u8 *)&battery->alarm_capacity);
    384}
    385
    386static int acpi_battery_set_alarm(struct acpi_battery *battery)
    387{
    388	struct acpi_sbs *sbs = battery->sbs;
    389	u16 value, sel = 1 << (battery->id + 12);
    390
    391	int ret;
    392
    393
    394	if (sbs->manager_present) {
    395		ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
    396				0x01, (u8 *)&value);
    397		if (ret)
    398			goto end;
    399		if ((value & 0xf000) != sel) {
    400			value &= 0x0fff;
    401			value |= sel;
    402			ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
    403					 ACPI_SBS_MANAGER,
    404					 0x01, (u8 *)&value, 2);
    405			if (ret)
    406				goto end;
    407		}
    408	}
    409	ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
    410				0x01, (u8 *)&battery->alarm_capacity, 2);
    411      end:
    412	return ret;
    413}
    414
    415static int acpi_ac_get_present(struct acpi_sbs *sbs)
    416{
    417	int result;
    418	u16 status;
    419
    420	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
    421				 0x13, (u8 *) & status);
    422
    423	if (result)
    424		return result;
    425
    426	/*
    427	 * The spec requires that bit 4 always be 1. If it's not set, assume
    428	 * that the implementation doesn't support an SBS charger.
    429	 *
    430	 * And on some MacBooks a status of 0xffff is always returned, no
    431	 * matter whether the charger is plugged in or not, which is also
    432	 * wrong, so ignore the SBS charger for those too.
    433	 */
    434	if (!((status >> 4) & 0x1) || status == 0xffff)
    435		return -ENODEV;
    436
    437	sbs->charger_present = (status >> 15) & 0x1;
    438	return 0;
    439}
    440
    441static ssize_t acpi_battery_alarm_show(struct device *dev,
    442					struct device_attribute *attr,
    443					char *buf)
    444{
    445	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
    446	acpi_battery_get_alarm(battery);
    447	return sprintf(buf, "%d\n", battery->alarm_capacity *
    448				acpi_battery_scale(battery) * 1000);
    449}
    450
    451static ssize_t acpi_battery_alarm_store(struct device *dev,
    452					struct device_attribute *attr,
    453					const char *buf, size_t count)
    454{
    455	unsigned long x;
    456	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
    457	if (sscanf(buf, "%lu\n", &x) == 1)
    458		battery->alarm_capacity = x /
    459			(1000 * acpi_battery_scale(battery));
    460	if (battery->present)
    461		acpi_battery_set_alarm(battery);
    462	return count;
    463}
    464
    465static const struct device_attribute alarm_attr = {
    466	.attr = {.name = "alarm", .mode = 0644},
    467	.show = acpi_battery_alarm_show,
    468	.store = acpi_battery_alarm_store,
    469};
    470
    471/* --------------------------------------------------------------------------
    472                                 Driver Interface
    473   -------------------------------------------------------------------------- */
    474static int acpi_battery_read(struct acpi_battery *battery)
    475{
    476	int result = 0, saved_present = battery->present;
    477	u16 state;
    478
    479	if (battery->sbs->manager_present) {
    480		result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
    481				ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
    482		if (!result)
    483			battery->present = state & (1 << battery->id);
    484		state &= 0x0fff;
    485		state |= 1 << (battery->id + 12);
    486		acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
    487				  ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
    488	} else if (battery->id == 0)
    489		battery->present = 1;
    490
    491	if (result || !battery->present)
    492		return result;
    493
    494	if (saved_present != battery->present) {
    495		battery->update_time = 0;
    496		result = acpi_battery_get_info(battery);
    497		if (result) {
    498			battery->present = 0;
    499			return result;
    500		}
    501	}
    502	result = acpi_battery_get_state(battery);
    503	if (result)
    504		battery->present = 0;
    505	return result;
    506}
    507
    508/* Smart Battery */
    509static int acpi_battery_add(struct acpi_sbs *sbs, int id)
    510{
    511	struct acpi_battery *battery = &sbs->battery[id];
    512	struct power_supply_config psy_cfg = { .drv_data = battery, };
    513	int result;
    514
    515	battery->id = id;
    516	battery->sbs = sbs;
    517	result = acpi_battery_read(battery);
    518	if (result)
    519		return result;
    520
    521	sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
    522	battery->bat_desc.name = battery->name;
    523	battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
    524	if (!acpi_battery_mode(battery)) {
    525		battery->bat_desc.properties = sbs_charge_battery_props;
    526		battery->bat_desc.num_properties =
    527		    ARRAY_SIZE(sbs_charge_battery_props);
    528	} else {
    529		battery->bat_desc.properties = sbs_energy_battery_props;
    530		battery->bat_desc.num_properties =
    531		    ARRAY_SIZE(sbs_energy_battery_props);
    532	}
    533	battery->bat_desc.get_property = acpi_sbs_battery_get_property;
    534	battery->bat = power_supply_register(&sbs->device->dev,
    535					&battery->bat_desc, &psy_cfg);
    536	if (IS_ERR(battery->bat)) {
    537		result = PTR_ERR(battery->bat);
    538		battery->bat = NULL;
    539		goto end;
    540	}
    541
    542	result = device_create_file(&battery->bat->dev, &alarm_attr);
    543	if (result)
    544		goto end;
    545	battery->have_sysfs_alarm = 1;
    546      end:
    547	pr_info("%s [%s]: Battery Slot [%s] (battery %s)\n",
    548	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
    549	       battery->name, battery->present ? "present" : "absent");
    550	return result;
    551}
    552
    553static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
    554{
    555	struct acpi_battery *battery = &sbs->battery[id];
    556
    557	if (battery->bat) {
    558		if (battery->have_sysfs_alarm)
    559			device_remove_file(&battery->bat->dev, &alarm_attr);
    560		power_supply_unregister(battery->bat);
    561	}
    562}
    563
    564static int acpi_charger_add(struct acpi_sbs *sbs)
    565{
    566	int result;
    567	struct power_supply_config psy_cfg = { .drv_data = sbs, };
    568
    569	result = acpi_ac_get_present(sbs);
    570	if (result)
    571		goto end;
    572
    573	sbs->charger_exists = 1;
    574	sbs->charger = power_supply_register(&sbs->device->dev,
    575					&acpi_sbs_charger_desc, &psy_cfg);
    576	if (IS_ERR(sbs->charger)) {
    577		result = PTR_ERR(sbs->charger);
    578		sbs->charger = NULL;
    579	}
    580	pr_info("%s [%s]: AC Adapter [%s] (%s)\n",
    581	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
    582	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
    583end:
    584	return result;
    585}
    586
    587static void acpi_charger_remove(struct acpi_sbs *sbs)
    588{
    589	if (sbs->charger)
    590		power_supply_unregister(sbs->charger);
    591}
    592
    593static void acpi_sbs_callback(void *context)
    594{
    595	int id;
    596	struct acpi_sbs *sbs = context;
    597	struct acpi_battery *bat;
    598	u8 saved_charger_state = sbs->charger_present;
    599	u8 saved_battery_state;
    600
    601	if (sbs->charger_exists) {
    602		acpi_ac_get_present(sbs);
    603		if (sbs->charger_present != saved_charger_state)
    604			kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE);
    605	}
    606
    607	if (sbs->manager_present) {
    608		for (id = 0; id < MAX_SBS_BAT; ++id) {
    609			if (!(sbs->batteries_supported & (1 << id)))
    610				continue;
    611			bat = &sbs->battery[id];
    612			saved_battery_state = bat->present;
    613			acpi_battery_read(bat);
    614			if (saved_battery_state == bat->present)
    615				continue;
    616			kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE);
    617		}
    618	}
    619}
    620
    621static int acpi_sbs_add(struct acpi_device *device)
    622{
    623	struct acpi_sbs *sbs;
    624	int result = 0;
    625	int id;
    626
    627	sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
    628	if (!sbs) {
    629		result = -ENOMEM;
    630		goto end;
    631	}
    632
    633	mutex_init(&sbs->lock);
    634
    635	sbs->hc = acpi_driver_data(device->parent);
    636	sbs->device = device;
    637	strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
    638	strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
    639	device->driver_data = sbs;
    640
    641	result = acpi_charger_add(sbs);
    642	if (result && result != -ENODEV)
    643		goto end;
    644
    645	result = 0;
    646
    647	if (!x86_apple_machine) {
    648		result = acpi_manager_get_info(sbs);
    649		if (!result) {
    650			sbs->manager_present = 1;
    651			for (id = 0; id < MAX_SBS_BAT; ++id)
    652				if ((sbs->batteries_supported & (1 << id)))
    653					acpi_battery_add(sbs, id);
    654		}
    655	}
    656
    657	if (!sbs->manager_present)
    658		acpi_battery_add(sbs, 0);
    659
    660	acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
    661end:
    662	if (result)
    663		acpi_sbs_remove(device);
    664	return result;
    665}
    666
    667static int acpi_sbs_remove(struct acpi_device *device)
    668{
    669	struct acpi_sbs *sbs;
    670	int id;
    671
    672	if (!device)
    673		return -EINVAL;
    674	sbs = acpi_driver_data(device);
    675	if (!sbs)
    676		return -EINVAL;
    677	mutex_lock(&sbs->lock);
    678	acpi_smbus_unregister_callback(sbs->hc);
    679	for (id = 0; id < MAX_SBS_BAT; ++id)
    680		acpi_battery_remove(sbs, id);
    681	acpi_charger_remove(sbs);
    682	mutex_unlock(&sbs->lock);
    683	mutex_destroy(&sbs->lock);
    684	kfree(sbs);
    685	return 0;
    686}
    687
    688#ifdef CONFIG_PM_SLEEP
    689static int acpi_sbs_resume(struct device *dev)
    690{
    691	struct acpi_sbs *sbs;
    692	if (!dev)
    693		return -EINVAL;
    694	sbs = to_acpi_device(dev)->driver_data;
    695	acpi_sbs_callback(sbs);
    696	return 0;
    697}
    698#else
    699#define acpi_sbs_resume NULL
    700#endif
    701
    702static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
    703
    704static struct acpi_driver acpi_sbs_driver = {
    705	.name = "sbs",
    706	.class = ACPI_SBS_CLASS,
    707	.ids = sbs_device_ids,
    708	.ops = {
    709		.add = acpi_sbs_add,
    710		.remove = acpi_sbs_remove,
    711		},
    712	.drv.pm = &acpi_sbs_pm,
    713};
    714module_acpi_driver(acpi_sbs_driver);