Blame view

drivers/acpi/sbs.c 19.4 KB
c942fddf8   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
3f86b8324   Rich Townsend   ACPI: add support...
2
  /*
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
3
   *  sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
3f86b8324   Rich Townsend   ACPI: add support...
4
   *
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
5
6
   *  Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
   *  Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
3f86b8324   Rich Townsend   ACPI: add support...
7
   *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
3f86b8324   Rich Townsend   ACPI: add support...
8
9
10
   */
  
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/slab.h>
3f86b8324   Rich Townsend   ACPI: add support...
12
13
14
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/kernel.h>
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
15

3f86b8324   Rich Townsend   ACPI: add support...
16
  #include <linux/acpi.h>
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
17
  #include <linux/timer.h>
722062334   Vladimir Lebedev   ACPI: sbs: Common...
18
  #include <linux/jiffies.h>
3f86b8324   Rich Townsend   ACPI: add support...
19
  #include <linux/delay.h>
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
20
  #include <linux/power_supply.h>
630b3aff8   Lukas Wunner   treewide: Consoli...
21
  #include <linux/platform_data/x86/apple.h>
fa93854f7   Ognjen Galic   battery: Add the ...
22
  #include <acpi/battery.h>
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
23

91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
24
  #include "sbshc.h"
a192a9580   Len Brown   ACPI: Move defini...
25
  #define PREFIX "ACPI: "
3f86b8324   Rich Townsend   ACPI: add support...
26
27
  #define ACPI_SBS_CLASS			"sbs"
  #define ACPI_AC_CLASS			"ac_adapter"
3f86b8324   Rich Townsend   ACPI: add support...
28
  #define ACPI_SBS_DEVICE_NAME		"Smart Battery System"
3f86b8324   Rich Townsend   ACPI: add support...
29
30
  #define ACPI_BATTERY_DIR_NAME		"BAT%i"
  #define ACPI_AC_DIR_NAME		"AC0"
3f86b8324   Rich Townsend   ACPI: add support...
31

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
32
33
  #define ACPI_SBS_NOTIFY_STATUS		0x80
  #define ACPI_SBS_NOTIFY_INFO		0x81
3f86b8324   Rich Townsend   ACPI: add support...
34

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
35
  MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
3f86b8324   Rich Townsend   ACPI: add support...
36
37
  MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
  MODULE_LICENSE("GPL");
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
38
39
40
  static unsigned int cache_time = 1000;
  module_param(cache_time, uint, 0644);
  MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
41

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
42
  #define MAX_SBS_BAT			4
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
43
  #define ACPI_SBS_BLOCK_MAX		32
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
44
  static const struct acpi_device_id sbs_device_ids[] = {
91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
45
  	{"ACPI0002", 0},
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
46
47
48
  	{"", 0},
  };
  MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
3f86b8324   Rich Townsend   ACPI: add support...
49
  struct acpi_battery {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
50
51
  	struct power_supply *bat;
  	struct power_supply_desc bat_desc;
3f86b8324   Rich Townsend   ACPI: add support...
52
  	struct acpi_sbs *sbs;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
53
54
  	unsigned long update_time;
  	char name[8];
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
55
56
57
  	char manufacturer_name[ACPI_SBS_BLOCK_MAX];
  	char device_name[ACPI_SBS_BLOCK_MAX];
  	char device_chemistry[ACPI_SBS_BLOCK_MAX];
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
58
  	u16 alarm_capacity;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
59
60
61
62
  	u16 full_charge_capacity;
  	u16 design_capacity;
  	u16 design_voltage;
  	u16 serial_number;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
63
64
  	u16 cycle_count;
  	u16 temp_now;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
65
  	u16 voltage_now;
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
66
67
  	s16 rate_now;
  	s16 rate_avg;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
68
  	u16 capacity_now;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
69
  	u16 state_of_charge;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
70
  	u16 state;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
71
  	u16 mode;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
72
  	u16 spec;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
73
  	u8 id;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
74
  	u8 present:1;
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
75
  	u8 have_sysfs_alarm:1;
3f86b8324   Rich Townsend   ACPI: add support...
76
  };
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
77
  #define to_acpi_battery(x) power_supply_get_drvdata(x)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
78

3f86b8324   Rich Townsend   ACPI: add support...
79
  struct acpi_sbs {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
80
  	struct power_supply *charger;
3f86b8324   Rich Townsend   ACPI: add support...
81
  	struct acpi_device *device;
91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
82
  	struct acpi_smb_hc *hc;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
83
  	struct mutex lock;
3f86b8324   Rich Townsend   ACPI: add support...
84
  	struct acpi_battery battery[MAX_SBS_BAT];
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
85
  	u8 batteries_supported:4;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
86
87
  	u8 manager_present:1;
  	u8 charger_present:1;
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
88
  	u8 charger_exists:1;
3f86b8324   Rich Townsend   ACPI: add support...
89
  };
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
90
  #define to_acpi_sbs(x) power_supply_get_drvdata(x)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
91

51fac8388   Rafael J. Wysocki   ACPI: Remove usel...
92
  static int acpi_sbs_remove(struct acpi_device *device);
1dd5c715e   Lan Tianyu   ACPI / SBS: Add g...
93
  static int acpi_battery_get_state(struct acpi_battery *battery);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
94
  static inline int battery_scale(int log)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
95
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
96
97
98
99
  	int scale = 1;
  	while (log--)
  		scale *= 10;
  	return scale;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
100
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
101
  static inline int acpi_battery_vscale(struct acpi_battery *battery)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
102
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
103
  	return battery_scale((battery->spec & 0x0f00) >> 8);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
104
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
105
  static inline int acpi_battery_ipscale(struct acpi_battery *battery)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
106
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
107
  	return battery_scale((battery->spec & 0xf000) >> 12);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
108
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
109
  static inline int acpi_battery_mode(struct acpi_battery *battery)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
110
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
111
  	return (battery->mode & 0x8000);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
112
  }
3f86b8324   Rich Townsend   ACPI: add support...
113

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
114
  static inline int acpi_battery_scale(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
115
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
116
117
  	return (acpi_battery_mode(battery) ? 10 : 1) *
  	    acpi_battery_ipscale(battery);
3f86b8324   Rich Townsend   ACPI: add support...
118
  }
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  static int sbs_get_ac_property(struct power_supply *psy,
  			       enum power_supply_property psp,
  			       union power_supply_propval *val)
  {
  	struct acpi_sbs *sbs = to_acpi_sbs(psy);
  	switch (psp) {
  	case POWER_SUPPLY_PROP_ONLINE:
  		val->intval = sbs->charger_present;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static int acpi_battery_technology(struct acpi_battery *battery)
  {
  	if (!strcasecmp("NiCd", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_NiCd;
  	if (!strcasecmp("NiMH", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_NiMH;
  	if (!strcasecmp("LION", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_LION;
  	if (!strcasecmp("LiP", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_LIPO;
  	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
  }
  
  static int acpi_sbs_battery_get_property(struct power_supply *psy,
  					 enum power_supply_property psp,
  					 union power_supply_propval *val)
  {
  	struct acpi_battery *battery = to_acpi_battery(psy);
  
  	if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
  		return -ENODEV;
1dd5c715e   Lan Tianyu   ACPI / SBS: Add g...
155
156
  
  	acpi_battery_get_state(battery);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
157
158
  	switch (psp) {
  	case POWER_SUPPLY_PROP_STATUS:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
159
  		if (battery->rate_now < 0)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
160
  			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
161
  		else if (battery->rate_now > 0)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
162
163
164
165
166
167
168
169
170
171
  			val->intval = POWER_SUPPLY_STATUS_CHARGING;
  		else
  			val->intval = POWER_SUPPLY_STATUS_FULL;
  		break;
  	case POWER_SUPPLY_PROP_PRESENT:
  		val->intval = battery->present;
  		break;
  	case POWER_SUPPLY_PROP_TECHNOLOGY:
  		val->intval = acpi_battery_technology(battery);
  		break;
16698857f   Alexey Starikovskiy   ACPI: SBS: Export...
172
173
174
  	case POWER_SUPPLY_PROP_CYCLE_COUNT:
  		val->intval = battery->cycle_count;
  		break;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
175
176
177
178
179
180
181
182
183
  	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
  		val->intval = battery->design_voltage *
  			acpi_battery_vscale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
  		val->intval = battery->voltage_now *
  				acpi_battery_vscale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_NOW:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
184
185
  	case POWER_SUPPLY_PROP_POWER_NOW:
  		val->intval = abs(battery->rate_now) *
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
186
  				acpi_battery_ipscale(battery) * 1000;
e4108292c   Lan Tianyu   ACPI / SBS: Corre...
187
188
189
  		val->intval *= (acpi_battery_mode(battery)) ?
  				(battery->voltage_now *
  				acpi_battery_vscale(battery) / 1000) : 1;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
190
191
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_AVG:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
192
193
  	case POWER_SUPPLY_PROP_POWER_AVG:
  		val->intval = abs(battery->rate_avg) *
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
194
  				acpi_battery_ipscale(battery) * 1000;
e4108292c   Lan Tianyu   ACPI / SBS: Corre...
195
196
197
  		val->intval *= (acpi_battery_mode(battery)) ?
  				(battery->voltage_now *
  				acpi_battery_vscale(battery) / 1000) : 1;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  		break;
  	case POWER_SUPPLY_PROP_CAPACITY:
  		val->intval = battery->state_of_charge;
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
  		val->intval = battery->design_capacity *
  			acpi_battery_scale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL:
  	case POWER_SUPPLY_PROP_ENERGY_FULL:
  		val->intval = battery->full_charge_capacity *
  			acpi_battery_scale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_NOW:
  	case POWER_SUPPLY_PROP_ENERGY_NOW:
  		val->intval = battery->capacity_now *
  				acpi_battery_scale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_TEMP:
  		val->intval = battery->temp_now - 2730;	// dK -> dC
  		break;
  	case POWER_SUPPLY_PROP_MODEL_NAME:
  		val->strval = battery->device_name;
  		break;
  	case POWER_SUPPLY_PROP_MANUFACTURER:
  		val->strval = battery->manufacturer_name;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static enum power_supply_property sbs_ac_props[] = {
  	POWER_SUPPLY_PROP_ONLINE,
  };
  
  static enum power_supply_property sbs_charge_battery_props[] = {
  	POWER_SUPPLY_PROP_STATUS,
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_TECHNOLOGY,
16698857f   Alexey Starikovskiy   ACPI: SBS: Export...
240
  	POWER_SUPPLY_PROP_CYCLE_COUNT,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CURRENT_AVG,
  	POWER_SUPPLY_PROP_CAPACITY,
  	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  	POWER_SUPPLY_PROP_CHARGE_FULL,
  	POWER_SUPPLY_PROP_CHARGE_NOW,
  	POWER_SUPPLY_PROP_TEMP,
  	POWER_SUPPLY_PROP_MODEL_NAME,
  	POWER_SUPPLY_PROP_MANUFACTURER,
  };
  
  static enum power_supply_property sbs_energy_battery_props[] = {
  	POWER_SUPPLY_PROP_STATUS,
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_TECHNOLOGY,
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CURRENT_AVG,
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
262
263
  	POWER_SUPPLY_PROP_POWER_NOW,
  	POWER_SUPPLY_PROP_POWER_AVG,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
264
265
266
267
268
269
270
271
  	POWER_SUPPLY_PROP_CAPACITY,
  	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
  	POWER_SUPPLY_PROP_ENERGY_FULL,
  	POWER_SUPPLY_PROP_ENERGY_NOW,
  	POWER_SUPPLY_PROP_TEMP,
  	POWER_SUPPLY_PROP_MODEL_NAME,
  	POWER_SUPPLY_PROP_MANUFACTURER,
  };
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
272

297d716f6   Krzysztof Kozlowski   power_supply: Cha...
273
274
275
276
277
278
279
  static const struct power_supply_desc acpi_sbs_charger_desc = {
  	.name		= "sbs-charger",
  	.type		= POWER_SUPPLY_TYPE_MAINS,
  	.properties	= sbs_ac_props,
  	.num_properties	= ARRAY_SIZE(sbs_ac_props),
  	.get_property	= sbs_get_ac_property,
  };
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
280

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
281
282
283
  /* --------------------------------------------------------------------------
                              Smart Battery System Management
     -------------------------------------------------------------------------- */
3f86b8324   Rich Townsend   ACPI: add support...
284

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
285
286
287
288
289
  struct acpi_battery_reader {
  	u8 command;		/* command for battery */
  	u8 mode;		/* word or block? */
  	size_t offset;		/* offset inside struct acpi_sbs_battery */
  };
3f86b8324   Rich Townsend   ACPI: add support...
290

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
291
292
293
294
295
296
297
298
299
300
301
302
303
  static struct acpi_battery_reader info_readers[] = {
  	{0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
  	{0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
  	{0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
  	{0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
  	{0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
  	{0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
  	{0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
  	{0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
  	{0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
  	{0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
  	{0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
  };
3f86b8324   Rich Townsend   ACPI: add support...
304

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
305
306
307
  static struct acpi_battery_reader state_readers[] = {
  	{0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
  	{0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
308
309
  	{0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)},
  	{0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)},
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
310
311
312
313
  	{0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
  	{0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
  	{0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
  };
3f86b8324   Rich Townsend   ACPI: add support...
314

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
315
  static int acpi_manager_get_info(struct acpi_sbs *sbs)
3f86b8324   Rich Townsend   ACPI: add support...
316
  {
3f86b8324   Rich Townsend   ACPI: add support...
317
  	int result = 0;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
318
  	u16 battery_system_info;
3f86b8324   Rich Townsend   ACPI: add support...
319

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
320
  	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
321
  				 0x04, (u8 *)&battery_system_info);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
322
323
  	if (!result)
  		sbs->batteries_supported = battery_system_info & 0x000f;
635227ee8   Len Brown   ACPI: remove func...
324
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
325
326
327
328
  }
  
  static int acpi_battery_get_info(struct acpi_battery *battery)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
329
  	int i, result = 0;
3f86b8324   Rich Townsend   ACPI: add support...
330

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
331
  	for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
332
333
334
335
336
337
  		result = acpi_smbus_read(battery->sbs->hc,
  					 info_readers[i].mode,
  					 ACPI_SBS_BATTERY,
  					 info_readers[i].command,
  					 (u8 *) battery +
  						info_readers[i].offset);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
338
339
  		if (result)
  			break;
3f86b8324   Rich Townsend   ACPI: add support...
340
  	}
635227ee8   Len Brown   ACPI: remove func...
341
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
342
  }
3f86b8324   Rich Townsend   ACPI: add support...
343
344
  static int acpi_battery_get_state(struct acpi_battery *battery)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
345
  	int i, result = 0;
3f86b8324   Rich Townsend   ACPI: add support...
346

94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
347
348
  	if (battery->update_time &&
  	    time_before(jiffies, battery->update_time +
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
349
350
351
352
353
354
355
  				msecs_to_jiffies(cache_time)))
  		return 0;
  	for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
  		result = acpi_smbus_read(battery->sbs->hc,
  					 state_readers[i].mode,
  					 ACPI_SBS_BATTERY,
  					 state_readers[i].command,
c6237b210   Maximilian Luz   ACPI: Fix whitesp...
356
  					 (u8 *)battery +
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
357
358
  						state_readers[i].offset);
  		if (result)
3f86b8324   Rich Townsend   ACPI: add support...
359
  			goto end;
3f86b8324   Rich Townsend   ACPI: add support...
360
  	}
3f86b8324   Rich Townsend   ACPI: add support...
361
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
362
  	battery->update_time = jiffies;
635227ee8   Len Brown   ACPI: remove func...
363
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
364
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
365
  static int acpi_battery_get_alarm(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
366
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
367
368
  	return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
  				 ACPI_SBS_BATTERY, 0x01,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
369
  				 (u8 *)&battery->alarm_capacity);
3f86b8324   Rich Townsend   ACPI: add support...
370
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
371
  static int acpi_battery_set_alarm(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
372
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
373
  	struct acpi_sbs *sbs = battery->sbs;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
374
375
376
  	u16 value, sel = 1 << (battery->id + 12);
  
  	int ret;
3f86b8324   Rich Townsend   ACPI: add support...
377

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
378
  	if (sbs->manager_present) {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
379
  		ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
380
  				0x01, (u8 *)&value);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
381
382
383
384
385
  		if (ret)
  			goto end;
  		if ((value & 0xf000) != sel) {
  			value &= 0x0fff;
  			value |= sel;
a84bc8cfb   Colin Ian King   ACPI / SBS: fix i...
386
  			ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
387
388
  					 ACPI_SBS_MANAGER,
  					 0x01, (u8 *)&value, 2);
a84bc8cfb   Colin Ian King   ACPI / SBS: fix i...
389
390
  			if (ret)
  				goto end;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
391
  		}
3f86b8324   Rich Townsend   ACPI: add support...
392
  	}
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
393
394
395
396
  	ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
  				0x01, (u8 *)&battery->alarm_capacity, 2);
        end:
  	return ret;
3f86b8324   Rich Townsend   ACPI: add support...
397
398
399
400
  }
  
  static int acpi_ac_get_present(struct acpi_sbs *sbs)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
401
402
  	int result;
  	u16 status;
3f86b8324   Rich Townsend   ACPI: add support...
403

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
404
405
  	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
  				 0x13, (u8 *) & status);
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
406
407
408
409
410
411
  
  	if (result)
  		return result;
  
  	/*
  	 * The spec requires that bit 4 always be 1. If it's not set, assume
ca1721c5b   Ronald Tschalär   ACPI / SBS: Fix G...
412
413
414
415
416
  	 * that the implementation doesn't support an SBS charger.
  	 *
  	 * And on some MacBooks a status of 0xffff is always returned, no
  	 * matter whether the charger is plugged in or not, which is also
  	 * wrong, so ignore the SBS charger for those too.
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
417
  	 */
ca1721c5b   Ronald Tschalär   ACPI / SBS: Fix G...
418
  	if (!((status >> 4) & 0x1) || status == 0xffff)
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
419
420
421
422
  		return -ENODEV;
  
  	sbs->charger_present = (status >> 15) & 0x1;
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
423
  }
8bd955320   Alexey Starikovskiy   ACPI: SBS: Add sy...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  static ssize_t acpi_battery_alarm_show(struct device *dev,
  					struct device_attribute *attr,
  					char *buf)
  {
  	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
  	acpi_battery_get_alarm(battery);
  	return sprintf(buf, "%d
  ", battery->alarm_capacity *
  				acpi_battery_scale(battery) * 1000);
  }
  
  static ssize_t acpi_battery_alarm_store(struct device *dev,
  					struct device_attribute *attr,
  					const char *buf, size_t count)
  {
  	unsigned long x;
  	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
32a905120   Luis G.F   ACPI / SBS: Fix i...
441
442
  	if (sscanf(buf, "%lu
  ", &x) == 1)
8bd955320   Alexey Starikovskiy   ACPI: SBS: Add sy...
443
444
445
446
447
448
  		battery->alarm_capacity = x /
  			(1000 * acpi_battery_scale(battery));
  	if (battery->present)
  		acpi_battery_set_alarm(battery);
  	return count;
  }
82d2b6105   Bhumika Goyal   ACPI: make device...
449
  static const struct device_attribute alarm_attr = {
01e8ef11b   Parag Warudkar   x86: sysfs: kill ...
450
  	.attr = {.name = "alarm", .mode = 0644},
8bd955320   Alexey Starikovskiy   ACPI: SBS: Add sy...
451
452
453
  	.show = acpi_battery_alarm_show,
  	.store = acpi_battery_alarm_store,
  };
3f86b8324   Rich Townsend   ACPI: add support...
454
  /* --------------------------------------------------------------------------
3f86b8324   Rich Townsend   ACPI: add support...
455
456
                                   Driver Interface
     -------------------------------------------------------------------------- */
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
457
  static int acpi_battery_read(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
458
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
459
460
  	int result = 0, saved_present = battery->present;
  	u16 state;
3f86b8324   Rich Townsend   ACPI: add support...
461

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
462
463
464
465
466
467
468
469
470
471
472
  	if (battery->sbs->manager_present) {
  		result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
  				ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
  		if (!result)
  			battery->present = state & (1 << battery->id);
  		state &= 0x0fff;
  		state |= 1 << (battery->id + 12);
  		acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
  				  ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
  	} else if (battery->id == 0)
  		battery->present = 1;
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
473

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
474
475
  	if (result || !battery->present)
  		return result;
3f86b8324   Rich Townsend   ACPI: add support...
476

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
477
478
479
  	if (saved_present != battery->present) {
  		battery->update_time = 0;
  		result = acpi_battery_get_info(battery);
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
480
481
  		if (result) {
  			battery->present = 0;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
482
  			return result;
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
483
  		}
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
484
485
  	}
  	result = acpi_battery_get_state(battery);
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
486
487
  	if (result)
  		battery->present = 0;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
488
489
  	return result;
  }
3f86b8324   Rich Townsend   ACPI: add support...
490

94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
491
  /* Smart Battery */
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
492
493
  static int acpi_battery_add(struct acpi_sbs *sbs, int id)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
494
  	struct acpi_battery *battery = &sbs->battery[id];
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
495
  	struct power_supply_config psy_cfg = { .drv_data = battery, };
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
496
  	int result;
3f86b8324   Rich Townsend   ACPI: add support...
497
498
  	battery->id = id;
  	battery->sbs = sbs;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
499
500
501
  	result = acpi_battery_read(battery);
  	if (result)
  		return result;
3f86b8324   Rich Townsend   ACPI: add support...
502

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
503
  	sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
504
505
  	battery->bat_desc.name = battery->name;
  	battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
506
  	if (!acpi_battery_mode(battery)) {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
507
508
  		battery->bat_desc.properties = sbs_charge_battery_props;
  		battery->bat_desc.num_properties =
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
509
510
  		    ARRAY_SIZE(sbs_charge_battery_props);
  	} else {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
511
512
  		battery->bat_desc.properties = sbs_energy_battery_props;
  		battery->bat_desc.num_properties =
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
513
514
  		    ARRAY_SIZE(sbs_energy_battery_props);
  	}
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
515
516
517
518
519
520
  	battery->bat_desc.get_property = acpi_sbs_battery_get_property;
  	battery->bat = power_supply_register(&sbs->device->dev,
  					&battery->bat_desc, &psy_cfg);
  	if (IS_ERR(battery->bat)) {
  		result = PTR_ERR(battery->bat);
  		battery->bat = NULL;
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
521
  		goto end;
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
522
  	}
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
523

297d716f6   Krzysztof Kozlowski   power_supply: Cha...
524
  	result = device_create_file(&battery->bat->dev, &alarm_attr);
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
525
526
527
528
  	if (result)
  		goto end;
  	battery->have_sysfs_alarm = 1;
        end:
722062334   Vladimir Lebedev   ACPI: sbs: Common...
529
530
  	printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
531
  	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
bbafbecb2   Alexey Starikovskiy   ACPI: SBS: Host c...
532
  	       battery->name, battery->present ? "present" : "absent");
635227ee8   Len Brown   ACPI: remove func...
533
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
534
535
536
537
  }
  
  static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
  {
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
538
  	struct acpi_battery *battery = &sbs->battery[id];
c19bdb612   Rakib Mullick   ACPI: Fix unused ...
539

297d716f6   Krzysztof Kozlowski   power_supply: Cha...
540
  	if (battery->bat) {
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
541
  		if (battery->have_sysfs_alarm)
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
542
543
  			device_remove_file(&battery->bat->dev, &alarm_attr);
  		power_supply_unregister(battery->bat);
3f86b8324   Rich Townsend   ACPI: add support...
544
545
  	}
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
546
  static int acpi_charger_add(struct acpi_sbs *sbs)
3f86b8324   Rich Townsend   ACPI: add support...
547
548
  {
  	int result;
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
549
  	struct power_supply_config psy_cfg = { .drv_data = sbs, };
3f86b8324   Rich Townsend   ACPI: add support...
550

3f86b8324   Rich Townsend   ACPI: add support...
551
  	result = acpi_ac_get_present(sbs);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
552
  	if (result)
3f86b8324   Rich Townsend   ACPI: add support...
553
  		goto end;
2a68b995c   Lan Tianyu   ACPI / SBS: Remov...
554

3031cddea   Matthew Garrett   ACPI / SBS: Don't...
555
  	sbs->charger_exists = 1;
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
556
557
558
559
560
561
  	sbs->charger = power_supply_register(&sbs->device->dev,
  					&acpi_sbs_charger_desc, &psy_cfg);
  	if (IS_ERR(sbs->charger)) {
  		result = PTR_ERR(sbs->charger);
  		sbs->charger = NULL;
  	}
722062334   Vladimir Lebedev   ACPI: sbs: Common...
562
563
564
  	printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)
  ",
  	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
565
  	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
3f86b8324   Rich Townsend   ACPI: add support...
566
        end:
635227ee8   Len Brown   ACPI: remove func...
567
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
568
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
569
  static void acpi_charger_remove(struct acpi_sbs *sbs)
3f86b8324   Rich Townsend   ACPI: add support...
570
  {
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
571
572
  	if (sbs->charger)
  		power_supply_unregister(sbs->charger);
3f86b8324   Rich Townsend   ACPI: add support...
573
  }
e5685b9d3   Adrian Bunk   ACPI: misc cleanups
574
  static void acpi_sbs_callback(void *context)
3f86b8324   Rich Townsend   ACPI: add support...
575
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
576
577
578
579
580
  	int id;
  	struct acpi_sbs *sbs = context;
  	struct acpi_battery *bat;
  	u8 saved_charger_state = sbs->charger_present;
  	u8 saved_battery_state;
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
581
582
583
584
  
  	if (sbs->charger_exists) {
  		acpi_ac_get_present(sbs);
  		if (sbs->charger_present != saved_charger_state)
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
585
  			kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE);
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
586
  	}
1696d9dc5   Thomas Renninger   ACPI: Remove the ...
587

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
588
589
590
591
592
593
594
595
596
  	if (sbs->manager_present) {
  		for (id = 0; id < MAX_SBS_BAT; ++id) {
  			if (!(sbs->batteries_supported & (1 << id)))
  				continue;
  			bat = &sbs->battery[id];
  			saved_battery_state = bat->present;
  			acpi_battery_read(bat);
  			if (saved_battery_state == bat->present)
  				continue;
297d716f6   Krzysztof Kozlowski   power_supply: Cha...
597
  			kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE);
3f86b8324   Rich Townsend   ACPI: add support...
598
  		}
3f86b8324   Rich Townsend   ACPI: add support...
599
  	}
3f86b8324   Rich Townsend   ACPI: add support...
600
  }
3f86b8324   Rich Townsend   ACPI: add support...
601
602
  static int acpi_sbs_add(struct acpi_device *device)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
603
604
  	struct acpi_sbs *sbs;
  	int result = 0;
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
605
  	int id;
3f86b8324   Rich Townsend   ACPI: add support...
606

36bcbec7c   Burman Yan   ACPI: replace kma...
607
  	sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
3f86b8324   Rich Townsend   ACPI: add support...
608
  	if (!sbs) {
722062334   Vladimir Lebedev   ACPI: sbs: Common...
609
610
  		result = -ENOMEM;
  		goto end;
3f86b8324   Rich Townsend   ACPI: add support...
611
  	}
3f86b8324   Rich Townsend   ACPI: add support...
612

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
613
  	mutex_init(&sbs->lock);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
614

91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
615
  	sbs->hc = acpi_driver_data(device->parent);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
616
  	sbs->device = device;
3f86b8324   Rich Townsend   ACPI: add support...
617
618
  	strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
db89b4f0d   Pavel Machek   ACPI: catch calls...
619
  	device->driver_data = sbs;
3f86b8324   Rich Townsend   ACPI: add support...
620

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
621
  	result = acpi_charger_add(sbs);
3031cddea   Matthew Garrett   ACPI / SBS: Don't...
622
  	if (result && result != -ENODEV)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
623
  		goto end;
3f86b8324   Rich Townsend   ACPI: add support...
624

9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
625
  	result = 0;
630b3aff8   Lukas Wunner   treewide: Consoli...
626
  	if (!x86_apple_machine) {
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
627
628
  		result = acpi_manager_get_info(sbs);
  		if (!result) {
61f8ff693   Chris Bainbridge   ACPI / SBS: Enabl...
629
  			sbs->manager_present = 1;
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
630
631
632
633
634
635
636
  			for (id = 0; id < MAX_SBS_BAT; ++id)
  				if ((sbs->batteries_supported & (1 << id)))
  					acpi_battery_add(sbs, id);
  		}
  	}
  
  	if (!sbs->manager_present)
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
637
  		acpi_battery_add(sbs, 0);
9faf6136f   Matthew Garrett   ACPI / SBS: Disab...
638

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
639
  	acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
3f86b8324   Rich Townsend   ACPI: add support...
640
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
641
  	if (result)
51fac8388   Rafael J. Wysocki   ACPI: Remove usel...
642
  		acpi_sbs_remove(device);
635227ee8   Len Brown   ACPI: remove func...
643
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
644
  }
51fac8388   Rafael J. Wysocki   ACPI: Remove usel...
645
  static int acpi_sbs_remove(struct acpi_device *device)
3f86b8324   Rich Townsend   ACPI: add support...
646
  {
cece90148   Len Brown   Pull style into t...
647
  	struct acpi_sbs *sbs;
3f86b8324   Rich Townsend   ACPI: add support...
648
  	int id;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
649
  	if (!device)
963497c12   Lebedev, Vladimir P   ACPI: sbs: check ...
650
  		return -EINVAL;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
651
  	sbs = acpi_driver_data(device);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
652
  	if (!sbs)
635227ee8   Len Brown   ACPI: remove func...
653
  		return -EINVAL;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
654
655
656
  	mutex_lock(&sbs->lock);
  	acpi_smbus_unregister_callback(sbs->hc);
  	for (id = 0; id < MAX_SBS_BAT; ++id)
3f86b8324   Rich Townsend   ACPI: add support...
657
  		acpi_battery_remove(sbs, id);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
658
659
660
  	acpi_charger_remove(sbs);
  	mutex_unlock(&sbs->lock);
  	mutex_destroy(&sbs->lock);
3f86b8324   Rich Townsend   ACPI: add support...
661
  	kfree(sbs);
635227ee8   Len Brown   ACPI: remove func...
662
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
663
  }
906924048   Rafael J. Wysocki   ACPI / PM: Fix un...
664
  #ifdef CONFIG_PM_SLEEP
d202f77d2   Rafael J. Wysocki   ACPI: Use struct ...
665
  static int acpi_sbs_resume(struct device *dev)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
666
667
  {
  	struct acpi_sbs *sbs;
d202f77d2   Rafael J. Wysocki   ACPI: Use struct ...
668
  	if (!dev)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
669
  		return -EINVAL;
d202f77d2   Rafael J. Wysocki   ACPI: Use struct ...
670
  	sbs = to_acpi_device(dev)->driver_data;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
671
  	acpi_sbs_callback(sbs);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
672
673
  	return 0;
  }
15029dd79   Shuah Khan   ACPI / SBS: fix S...
674
675
  #else
  #define acpi_sbs_resume NULL
906924048   Rafael J. Wysocki   ACPI / PM: Fix un...
676
  #endif
722062334   Vladimir Lebedev   ACPI: sbs: Common...
677

d202f77d2   Rafael J. Wysocki   ACPI: Use struct ...
678
  static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
679
680
681
682
683
684
685
  static struct acpi_driver acpi_sbs_driver = {
  	.name = "sbs",
  	.class = ACPI_SBS_CLASS,
  	.ids = sbs_device_ids,
  	.ops = {
  		.add = acpi_sbs_add,
  		.remove = acpi_sbs_remove,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
686
  		},
d202f77d2   Rafael J. Wysocki   ACPI: Use struct ...
687
  	.drv.pm = &acpi_sbs_pm,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
688
  };
3f86b8324   Rich Townsend   ACPI: add support...
689
690
691
  static int __init acpi_sbs_init(void)
  {
  	int result = 0;
b20d2aeb0   Len Brown   ACPI: skip smart ...
692
693
  	if (acpi_disabled)
  		return -ENODEV;
2a68b995c   Lan Tianyu   ACPI / SBS: Remov...
694

3f86b8324   Rich Townsend   ACPI: add support...
695
  	result = acpi_bus_register_driver(&acpi_sbs_driver);
2a68b995c   Lan Tianyu   ACPI / SBS: Remov...
696
  	if (result < 0)
635227ee8   Len Brown   ACPI: remove func...
697
  		return -ENODEV;
2a68b995c   Lan Tianyu   ACPI / SBS: Remov...
698

635227ee8   Len Brown   ACPI: remove func...
699
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
700
701
702
703
  }
  
  static void __exit acpi_sbs_exit(void)
  {
3f86b8324   Rich Townsend   ACPI: add support...
704
  	acpi_bus_unregister_driver(&acpi_sbs_driver);
635227ee8   Len Brown   ACPI: remove func...
705
  	return;
3f86b8324   Rich Townsend   ACPI: add support...
706
707
708
709
  }
  
  module_init(acpi_sbs_init);
  module_exit(acpi_sbs_exit);