aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2007-10-10 00:30:19 -0400
committerLen Brown <len.brown@intel.com>2007-10-10 00:30:19 -0400
commite270051d9c6e5f0b31668ec1f0d864ab9920ffca (patch)
tree49c2a5fb6ca6790f9cf070b49552388dadc7fa5b /drivers
parenta2883dfa2e4a94b24109b2bfe735561e50cc44b4 (diff)
parentd5b4a3d0efa36de31b86d5677dad6c36cb8735d7 (diff)
Pull battery-sbs-ac into release branch
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/Kconfig13
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c33
-rw-r--r--drivers/acpi/battery.c1038
-rw-r--r--drivers/acpi/bus.c23
-rw-r--r--drivers/acpi/ec.c3
-rw-r--r--drivers/acpi/sbs.c1869
-rw-r--r--drivers/acpi/sbshc.c309
-rw-r--r--drivers/acpi/sbshc.h27
9 files changed, 1365 insertions, 1951 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 9685b75898ed..b83389145f28 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -88,7 +88,7 @@ config ACPI_PROC_EVENT
88 88
89config ACPI_AC 89config ACPI_AC
90 tristate "AC Adapter" 90 tristate "AC Adapter"
91 depends on X86 91 depends on X86 && POWER_SUPPLY
92 default y 92 default y
93 help 93 help
94 This driver adds support for the AC Adapter object, which indicates 94 This driver adds support for the AC Adapter object, which indicates
@@ -97,7 +97,7 @@ config ACPI_AC
97 97
98config ACPI_BATTERY 98config ACPI_BATTERY
99 tristate "Battery" 99 tristate "Battery"
100 depends on X86 100 depends on X86 && POWER_SUPPLY
101 default y 101 default y
102 help 102 help
103 This driver adds support for battery information through 103 This driver adds support for battery information through
@@ -350,12 +350,11 @@ config ACPI_HOTPLUG_MEMORY
350 $>modprobe acpi_memhotplug 350 $>modprobe acpi_memhotplug
351 351
352config ACPI_SBS 352config ACPI_SBS
353 tristate "Smart Battery System (EXPERIMENTAL)" 353 tristate "Smart Battery System"
354 depends on X86 354 depends on X86
355 depends on EXPERIMENTAL 355 depends on POWER_SUPPLY
356 help 356 help
357 This driver adds support for the Smart Battery System. 357 This driver adds support for the Smart Battery System, another
358 A "Smart Battery" is quite old and quite rare compared 358 type of access to battery information, found on some laptops.
359 to today's ACPI "Control Method" battery.
360 359
361endif # ACPI 360endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d4336f1730e9..54e3ab0e5fc0 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
60obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o 60obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
61obj-y += cm_sbs.o 61obj-y += cm_sbs.o
62obj-$(CONFIG_ACPI_SBS) += sbs.o 62obj-$(CONFIG_ACPI_SBS) += sbs.o
63obj-$(CONFIG_ACPI_SBS) += sbshc.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 26d70702b313..e03de37a750d 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -29,6 +29,7 @@
29#include <linux/types.h> 29#include <linux/types.h>
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/power_supply.h>
32#include <acpi/acpi_bus.h> 33#include <acpi/acpi_bus.h>
33#include <acpi/acpi_drivers.h> 34#include <acpi/acpi_drivers.h>
34 35
@@ -72,16 +73,37 @@ static struct acpi_driver acpi_ac_driver = {
72}; 73};
73 74
74struct acpi_ac { 75struct acpi_ac {
76 struct power_supply charger;
75 struct acpi_device * device; 77 struct acpi_device * device;
76 unsigned long state; 78 unsigned long state;
77}; 79};
78 80
81#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
82
79static const struct file_operations acpi_ac_fops = { 83static const struct file_operations acpi_ac_fops = {
80 .open = acpi_ac_open_fs, 84 .open = acpi_ac_open_fs,
81 .read = seq_read, 85 .read = seq_read,
82 .llseek = seq_lseek, 86 .llseek = seq_lseek,
83 .release = single_release, 87 .release = single_release,
84}; 88};
89static int get_ac_property(struct power_supply *psy,
90 enum power_supply_property psp,
91 union power_supply_propval *val)
92{
93 struct acpi_ac *ac = to_acpi_ac(psy);
94 switch (psp) {
95 case POWER_SUPPLY_PROP_ONLINE:
96 val->intval = ac->state;
97 break;
98 default:
99 return -EINVAL;
100 }
101 return 0;
102}
103
104static enum power_supply_property ac_props[] = {
105 POWER_SUPPLY_PROP_ONLINE,
106};
85 107
86/* -------------------------------------------------------------------------- 108/* --------------------------------------------------------------------------
87 AC Adapter Management 109 AC Adapter Management
@@ -208,6 +230,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
208 acpi_bus_generate_netlink_event(device->pnp.device_class, 230 acpi_bus_generate_netlink_event(device->pnp.device_class,
209 device->dev.bus_id, event, 231 device->dev.bus_id, event,
210 (u32) ac->state); 232 (u32) ac->state);
233 kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
211 break; 234 break;
212 default: 235 default:
213 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 236 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -244,7 +267,12 @@ static int acpi_ac_add(struct acpi_device *device)
244 result = acpi_ac_add_fs(device); 267 result = acpi_ac_add_fs(device);
245 if (result) 268 if (result)
246 goto end; 269 goto end;
247 270 ac->charger.name = acpi_device_bid(device);
271 ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
272 ac->charger.properties = ac_props;
273 ac->charger.num_properties = ARRAY_SIZE(ac_props);
274 ac->charger.get_property = get_ac_property;
275 power_supply_register(&ac->device->dev, &ac->charger);
248 status = acpi_install_notify_handler(device->handle, 276 status = acpi_install_notify_handler(device->handle,
249 ACPI_ALL_NOTIFY, acpi_ac_notify, 277 ACPI_ALL_NOTIFY, acpi_ac_notify,
250 ac); 278 ac);
@@ -279,7 +307,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
279 307
280 status = acpi_remove_notify_handler(device->handle, 308 status = acpi_remove_notify_handler(device->handle,
281 ACPI_ALL_NOTIFY, acpi_ac_notify); 309 ACPI_ALL_NOTIFY, acpi_ac_notify);
282 310 if (ac->charger.dev)
311 power_supply_unregister(&ac->charger);
283 acpi_ac_remove_fs(device); 312 acpi_ac_remove_fs(device);
284 313
285 kfree(ac); 314 kfree(ac);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 9b2c0f74f869..681e26b56b11 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $) 2 * battery.c - ACPI Battery Driver (Revision: 2.0)
3 * 3 *
4 * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
5 * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 6 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 7 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * 8 *
@@ -27,244 +29,288 @@
27#include <linux/module.h> 29#include <linux/module.h>
28#include <linux/init.h> 30#include <linux/init.h>
29#include <linux/types.h> 31#include <linux/types.h>
32#include <linux/jiffies.h>
33
34#ifdef CONFIG_ACPI_PROCFS
30#include <linux/proc_fs.h> 35#include <linux/proc_fs.h>
31#include <linux/seq_file.h> 36#include <linux/seq_file.h>
32#include <asm/uaccess.h> 37#include <asm/uaccess.h>
38#endif
33 39
34#include <acpi/acpi_bus.h> 40#include <acpi/acpi_bus.h>
35#include <acpi/acpi_drivers.h> 41#include <acpi/acpi_drivers.h>
36 42
37#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF 43#include <linux/power_supply.h>
38 44
39#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" 45#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
40#define ACPI_BATTERY_FORMAT_BST "NNNN"
41 46
42#define ACPI_BATTERY_COMPONENT 0x00040000 47#define ACPI_BATTERY_COMPONENT 0x00040000
43#define ACPI_BATTERY_CLASS "battery" 48#define ACPI_BATTERY_CLASS "battery"
44#define ACPI_BATTERY_DEVICE_NAME "Battery" 49#define ACPI_BATTERY_DEVICE_NAME "Battery"
45#define ACPI_BATTERY_NOTIFY_STATUS 0x80 50#define ACPI_BATTERY_NOTIFY_STATUS 0x80
46#define ACPI_BATTERY_NOTIFY_INFO 0x81 51#define ACPI_BATTERY_NOTIFY_INFO 0x81
47#define ACPI_BATTERY_UNITS_WATTS "mW"
48#define ACPI_BATTERY_UNITS_AMPS "mA"
49 52
50#define _COMPONENT ACPI_BATTERY_COMPONENT 53#define _COMPONENT ACPI_BATTERY_COMPONENT
51 54
52#define ACPI_BATTERY_UPDATE_TIME 0
53
54#define ACPI_BATTERY_NONE_UPDATE 0
55#define ACPI_BATTERY_EASY_UPDATE 1
56#define ACPI_BATTERY_INIT_UPDATE 2
57
58ACPI_MODULE_NAME("battery"); 55ACPI_MODULE_NAME("battery");
59 56
60MODULE_AUTHOR("Paul Diefenbaugh"); 57MODULE_AUTHOR("Paul Diefenbaugh");
58MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
61MODULE_DESCRIPTION("ACPI Battery Driver"); 59MODULE_DESCRIPTION("ACPI Battery Driver");
62MODULE_LICENSE("GPL"); 60MODULE_LICENSE("GPL");
63 61
64static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME; 62static unsigned int cache_time = 1000;
65 63module_param(cache_time, uint, 0644);
66/* 0 - every time, > 0 - by update_time */ 64MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
67module_param(update_time, uint, 0644);
68 65
66#ifdef CONFIG_ACPI_PROCFS
69extern struct proc_dir_entry *acpi_lock_battery_dir(void); 67extern struct proc_dir_entry *acpi_lock_battery_dir(void);
70extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 68extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
71 69
72static int acpi_battery_add(struct acpi_device *device); 70enum acpi_battery_files {
73static int acpi_battery_remove(struct acpi_device *device, int type); 71 info_tag = 0,
74static int acpi_battery_resume(struct acpi_device *device); 72 state_tag,
73 alarm_tag,
74 ACPI_BATTERY_NUMFILES,
75};
76
77#endif
75 78
76static const struct acpi_device_id battery_device_ids[] = { 79static const struct acpi_device_id battery_device_ids[] = {
77 {"PNP0C0A", 0}, 80 {"PNP0C0A", 0},
78 {"", 0}, 81 {"", 0},
79}; 82};
80MODULE_DEVICE_TABLE(acpi, battery_device_ids);
81
82static struct acpi_driver acpi_battery_driver = {
83 .name = "battery",
84 .class = ACPI_BATTERY_CLASS,
85 .ids = battery_device_ids,
86 .ops = {
87 .add = acpi_battery_add,
88 .resume = acpi_battery_resume,
89 .remove = acpi_battery_remove,
90 },
91};
92 83
93struct acpi_battery_state { 84MODULE_DEVICE_TABLE(acpi, battery_device_ids);
94 acpi_integer state;
95 acpi_integer present_rate;
96 acpi_integer remaining_capacity;
97 acpi_integer present_voltage;
98};
99
100struct acpi_battery_info {
101 acpi_integer power_unit;
102 acpi_integer design_capacity;
103 acpi_integer last_full_capacity;
104 acpi_integer battery_technology;
105 acpi_integer design_voltage;
106 acpi_integer design_capacity_warning;
107 acpi_integer design_capacity_low;
108 acpi_integer battery_capacity_granularity_1;
109 acpi_integer battery_capacity_granularity_2;
110 acpi_string model_number;
111 acpi_string serial_number;
112 acpi_string battery_type;
113 acpi_string oem_info;
114};
115
116enum acpi_battery_files{
117 ACPI_BATTERY_INFO = 0,
118 ACPI_BATTERY_STATE,
119 ACPI_BATTERY_ALARM,
120 ACPI_BATTERY_NUMFILES,
121};
122 85
123struct acpi_battery_flags {
124 u8 battery_present_prev;
125 u8 alarm_present;
126 u8 init_update;
127 u8 update[ACPI_BATTERY_NUMFILES];
128 u8 power_unit;
129};
130 86
131struct acpi_battery { 87struct acpi_battery {
132 struct mutex mutex; 88 struct mutex lock;
89 struct power_supply bat;
133 struct acpi_device *device; 90 struct acpi_device *device;
134 struct acpi_battery_flags flags; 91 unsigned long update_time;
135 struct acpi_buffer bif_data; 92 int current_now;
136 struct acpi_buffer bst_data; 93 int capacity_now;
137 unsigned long alarm; 94 int voltage_now;
138 unsigned long update_time[ACPI_BATTERY_NUMFILES]; 95 int design_capacity;
96 int full_charge_capacity;
97 int technology;
98 int design_voltage;
99 int design_capacity_warning;
100 int design_capacity_low;
101 int capacity_granularity_1;
102 int capacity_granularity_2;
103 int alarm;
104 char model_number[32];
105 char serial_number[32];
106 char type[32];
107 char oem_info[32];
108 int state;
109 int power_unit;
110 u8 alarm_present;
139}; 111};
140 112
113#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
114
141inline int acpi_battery_present(struct acpi_battery *battery) 115inline int acpi_battery_present(struct acpi_battery *battery)
142{ 116{
143 return battery->device->status.battery_present; 117 return battery->device->status.battery_present;
144} 118}
145inline char *acpi_battery_power_units(struct acpi_battery *battery)
146{
147 if (battery->flags.power_unit)
148 return ACPI_BATTERY_UNITS_AMPS;
149 else
150 return ACPI_BATTERY_UNITS_WATTS;
151}
152 119
153inline acpi_handle acpi_battery_handle(struct acpi_battery *battery) 120static int acpi_battery_technology(struct acpi_battery *battery)
154{ 121{
155 return battery->device->handle; 122 if (!strcasecmp("NiCd", battery->type))
123 return POWER_SUPPLY_TECHNOLOGY_NiCd;
124 if (!strcasecmp("NiMH", battery->type))
125 return POWER_SUPPLY_TECHNOLOGY_NiMH;
126 if (!strcasecmp("LION", battery->type))
127 return POWER_SUPPLY_TECHNOLOGY_LION;
128 if (!strcasecmp("LiP", battery->type))
129 return POWER_SUPPLY_TECHNOLOGY_LIPO;
130 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
156} 131}
157 132
158/* -------------------------------------------------------------------------- 133static int acpi_battery_get_property(struct power_supply *psy,
159 Battery Management 134 enum power_supply_property psp,
160 -------------------------------------------------------------------------- */ 135 union power_supply_propval *val)
161
162static void acpi_battery_check_result(struct acpi_battery *battery, int result)
163{ 136{
164 if (!battery) 137 struct acpi_battery *battery = to_acpi_battery(psy);
165 return;
166 138
167 if (result) { 139 if ((!acpi_battery_present(battery)) &&
168 battery->flags.init_update = 1; 140 psp != POWER_SUPPLY_PROP_PRESENT)
141 return -ENODEV;
142 switch (psp) {
143 case POWER_SUPPLY_PROP_STATUS:
144 if (battery->state & 0x01)
145 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
146 else if (battery->state & 0x02)
147 val->intval = POWER_SUPPLY_STATUS_CHARGING;
148 else if (battery->state == 0)
149 val->intval = POWER_SUPPLY_STATUS_FULL;
150 break;
151 case POWER_SUPPLY_PROP_PRESENT:
152 val->intval = acpi_battery_present(battery);
153 break;
154 case POWER_SUPPLY_PROP_TECHNOLOGY:
155 val->intval = acpi_battery_technology(battery);
156 break;
157 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
158 val->intval = battery->design_voltage * 1000;
159 break;
160 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
161 val->intval = battery->voltage_now * 1000;
162 break;
163 case POWER_SUPPLY_PROP_CURRENT_NOW:
164 val->intval = battery->current_now * 1000;
165 break;
166 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
167 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
168 val->intval = battery->design_capacity * 1000;
169 break;
170 case POWER_SUPPLY_PROP_CHARGE_FULL:
171 case POWER_SUPPLY_PROP_ENERGY_FULL:
172 val->intval = battery->full_charge_capacity * 1000;
173 break;
174 case POWER_SUPPLY_PROP_CHARGE_NOW:
175 case POWER_SUPPLY_PROP_ENERGY_NOW:
176 val->intval = battery->capacity_now * 1000;
177 break;
178 case POWER_SUPPLY_PROP_MODEL_NAME:
179 val->strval = battery->model_number;
180 break;
181 case POWER_SUPPLY_PROP_MANUFACTURER:
182 val->strval = battery->oem_info;
183 break;
184 default:
185 return -EINVAL;
169 } 186 }
187 return 0;
170} 188}
171 189
172static int acpi_battery_extract_package(struct acpi_battery *battery, 190static enum power_supply_property charge_battery_props[] = {
173 union acpi_object *package, 191 POWER_SUPPLY_PROP_STATUS,
174 struct acpi_buffer *format, 192 POWER_SUPPLY_PROP_PRESENT,
175 struct acpi_buffer *data, 193 POWER_SUPPLY_PROP_TECHNOLOGY,
176 char *package_name) 194 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
195 POWER_SUPPLY_PROP_VOLTAGE_NOW,
196 POWER_SUPPLY_PROP_CURRENT_NOW,
197 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
198 POWER_SUPPLY_PROP_CHARGE_FULL,
199 POWER_SUPPLY_PROP_CHARGE_NOW,
200 POWER_SUPPLY_PROP_MODEL_NAME,
201 POWER_SUPPLY_PROP_MANUFACTURER,
202};
203
204static enum power_supply_property energy_battery_props[] = {
205 POWER_SUPPLY_PROP_STATUS,
206 POWER_SUPPLY_PROP_PRESENT,
207 POWER_SUPPLY_PROP_TECHNOLOGY,
208 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
209 POWER_SUPPLY_PROP_VOLTAGE_NOW,
210 POWER_SUPPLY_PROP_CURRENT_NOW,
211 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
212 POWER_SUPPLY_PROP_ENERGY_FULL,
213 POWER_SUPPLY_PROP_ENERGY_NOW,
214 POWER_SUPPLY_PROP_MODEL_NAME,
215 POWER_SUPPLY_PROP_MANUFACTURER,
216};
217
218#ifdef CONFIG_ACPI_PROCFS
219inline char *acpi_battery_units(struct acpi_battery *battery)
177{ 220{
178 acpi_status status = AE_OK; 221 return (battery->power_unit)?"mA":"mW";
179 struct acpi_buffer data_null = { 0, NULL }; 222}
223#endif
180 224
181 status = acpi_extract_package(package, format, &data_null); 225/* --------------------------------------------------------------------------
182 if (status != AE_BUFFER_OVERFLOW) { 226 Battery Management
183 ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s", 227 -------------------------------------------------------------------------- */
184 package_name)); 228struct acpi_offsets {
185 return -ENODEV; 229 size_t offset; /* offset inside struct acpi_sbs_battery */
186 } 230 u8 mode; /* int or string? */
231};
187 232
188 if (data_null.length != data->length) { 233static struct acpi_offsets state_offsets[] = {
189 kfree(data->pointer); 234 {offsetof(struct acpi_battery, state), 0},
190 data->pointer = kzalloc(data_null.length, GFP_KERNEL); 235 {offsetof(struct acpi_battery, current_now), 0},
191 if (!data->pointer) { 236 {offsetof(struct acpi_battery, capacity_now), 0},
192 ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); 237 {offsetof(struct acpi_battery, voltage_now), 0},
193 return -ENOMEM; 238};
194 }
195 data->length = data_null.length;
196 }
197 239
198 status = acpi_extract_package(package, format, data); 240static struct acpi_offsets info_offsets[] = {
199 if (ACPI_FAILURE(status)) { 241 {offsetof(struct acpi_battery, power_unit), 0},
200 ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", 242 {offsetof(struct acpi_battery, design_capacity), 0},
201 package_name)); 243 {offsetof(struct acpi_battery, full_charge_capacity), 0},
202 return -ENODEV; 244 {offsetof(struct acpi_battery, technology), 0},
203 } 245 {offsetof(struct acpi_battery, design_voltage), 0},
246 {offsetof(struct acpi_battery, design_capacity_warning), 0},
247 {offsetof(struct acpi_battery, design_capacity_low), 0},
248 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
249 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
250 {offsetof(struct acpi_battery, model_number), 1},
251 {offsetof(struct acpi_battery, serial_number), 1},
252 {offsetof(struct acpi_battery, type), 1},
253 {offsetof(struct acpi_battery, oem_info), 1},
254};
204 255
256static int extract_package(struct acpi_battery *battery,
257 union acpi_object *package,
258 struct acpi_offsets *offsets, int num)
259{
260 int i, *x;
261 union acpi_object *element;
262 if (package->type != ACPI_TYPE_PACKAGE)
263 return -EFAULT;
264 for (i = 0; i < num; ++i) {
265 if (package->package.count <= i)
266 return -EFAULT;
267 element = &package->package.elements[i];
268 if (offsets[i].mode) {
269 if (element->type != ACPI_TYPE_STRING &&
270 element->type != ACPI_TYPE_BUFFER)
271 return -EFAULT;
272 strncpy((u8 *)battery + offsets[i].offset,
273 element->string.pointer, 32);
274 } else {
275 if (element->type != ACPI_TYPE_INTEGER)
276 return -EFAULT;
277 x = (int *)((u8 *)battery + offsets[i].offset);
278 *x = element->integer.value;
279 }
280 }
205 return 0; 281 return 0;
206} 282}
207 283
208static int acpi_battery_get_status(struct acpi_battery *battery) 284static int acpi_battery_get_status(struct acpi_battery *battery)
209{ 285{
210 int result = 0; 286 if (acpi_bus_get_status(battery->device)) {
211
212 result = acpi_bus_get_status(battery->device);
213 if (result) {
214 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); 287 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
215 return -ENODEV; 288 return -ENODEV;
216 } 289 }
217 return result; 290 return 0;
218} 291}
219 292
220static int acpi_battery_get_info(struct acpi_battery *battery) 293static int acpi_battery_get_info(struct acpi_battery *battery)
221{ 294{
222 int result = 0; 295 int result = -EFAULT;
223 acpi_status status = 0; 296 acpi_status status = 0;
224 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 297 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
225 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
226 ACPI_BATTERY_FORMAT_BIF
227 };
228 union acpi_object *package = NULL;
229 struct acpi_buffer *data = NULL;
230 struct acpi_battery_info *bif = NULL;
231
232 battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
233 298
234 if (!acpi_battery_present(battery)) 299 if (!acpi_battery_present(battery))
235 return 0; 300 return 0;
301 mutex_lock(&battery->lock);
302 status = acpi_evaluate_object(battery->device->handle, "_BIF",
303 NULL, &buffer);
304 mutex_unlock(&battery->lock);
236 305
237 /* Evaluate _BIF */
238
239 status =
240 acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
241 &buffer);
242 if (ACPI_FAILURE(status)) { 306 if (ACPI_FAILURE(status)) {
243 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); 307 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
244 return -ENODEV; 308 return -ENODEV;
245 } 309 }
246 310
247 package = buffer.pointer; 311 result = extract_package(battery, buffer.pointer,
248 312 info_offsets, ARRAY_SIZE(info_offsets));
249 data = &battery->bif_data;
250
251 /* Extract Package Data */
252
253 result =
254 acpi_battery_extract_package(battery, package, &format, data,
255 "_BIF");
256 if (result)
257 goto end;
258
259 end:
260
261 kfree(buffer.pointer); 313 kfree(buffer.pointer);
262
263 if (!result) {
264 bif = data->pointer;
265 battery->flags.power_unit = bif->power_unit;
266 }
267
268 return result; 314 return result;
269} 315}
270 316
@@ -273,342 +319,203 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
273 int result = 0; 319 int result = 0;
274 acpi_status status = 0; 320 acpi_status status = 0;
275 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 321 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
276 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
277 ACPI_BATTERY_FORMAT_BST
278 };
279 union acpi_object *package = NULL;
280 struct acpi_buffer *data = NULL;
281
282 battery->update_time[ACPI_BATTERY_STATE] = get_seconds();
283 322
284 if (!acpi_battery_present(battery)) 323 if (!acpi_battery_present(battery))
285 return 0; 324 return 0;
286 325
287 /* Evaluate _BST */ 326 if (battery->update_time &&
327 time_before(jiffies, battery->update_time +
328 msecs_to_jiffies(cache_time)))
329 return 0;
330
331 mutex_lock(&battery->lock);
332 status = acpi_evaluate_object(battery->device->handle, "_BST",
333 NULL, &buffer);
334 mutex_unlock(&battery->lock);
288 335
289 status =
290 acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
291 &buffer);
292 if (ACPI_FAILURE(status)) { 336 if (ACPI_FAILURE(status)) {
293 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); 337 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
294 return -ENODEV; 338 return -ENODEV;
295 } 339 }
296 340
297 package = buffer.pointer; 341 result = extract_package(battery, buffer.pointer,
298 342 state_offsets, ARRAY_SIZE(state_offsets));
299 data = &battery->bst_data; 343 battery->update_time = jiffies;
300
301 /* Extract Package Data */
302
303 result =
304 acpi_battery_extract_package(battery, package, &format, data,
305 "_BST");
306 if (result)
307 goto end;
308
309 end:
310 kfree(buffer.pointer); 344 kfree(buffer.pointer);
311
312 return result; 345 return result;
313} 346}
314 347
315static int acpi_battery_get_alarm(struct acpi_battery *battery) 348static int acpi_battery_set_alarm(struct acpi_battery *battery)
316{
317 battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
318
319 return 0;
320}
321
322static int acpi_battery_set_alarm(struct acpi_battery *battery,
323 unsigned long alarm)
324{ 349{
325 acpi_status status = 0; 350 acpi_status status = 0;
326 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 351 union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
327 struct acpi_object_list arg_list = { 1, &arg0 }; 352 struct acpi_object_list arg_list = { 1, &arg0 };
328 353
329 battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); 354 if (!acpi_battery_present(battery)|| !battery->alarm_present)
330
331 if (!acpi_battery_present(battery))
332 return -ENODEV; 355 return -ENODEV;
333 356
334 if (!battery->flags.alarm_present) 357 arg0.integer.value = battery->alarm;
335 return -ENODEV;
336
337 arg0.integer.value = alarm;
338 358
339 status = 359 mutex_lock(&battery->lock);
340 acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", 360 status = acpi_evaluate_object(battery->device->handle, "_BTP",
341 &arg_list, NULL); 361 &arg_list, NULL);
362 mutex_unlock(&battery->lock);
363
342 if (ACPI_FAILURE(status)) 364 if (ACPI_FAILURE(status))
343 return -ENODEV; 365 return -ENODEV;
344 366
345 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); 367 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
346
347 battery->alarm = alarm;
348
349 return 0; 368 return 0;
350} 369}
351 370
352static int acpi_battery_init_alarm(struct acpi_battery *battery) 371static int acpi_battery_init_alarm(struct acpi_battery *battery)
353{ 372{
354 int result = 0;
355 acpi_status status = AE_OK; 373 acpi_status status = AE_OK;
356 acpi_handle handle = NULL; 374 acpi_handle handle = NULL;
357 struct acpi_battery_info *bif = battery->bif_data.pointer;
358 unsigned long alarm = battery->alarm;
359 375
360 /* See if alarms are supported, and if so, set default */ 376 /* See if alarms are supported, and if so, set default */
361 377 status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
362 status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); 378 if (ACPI_FAILURE(status)) {
363 if (ACPI_SUCCESS(status)) { 379 battery->alarm_present = 0;
364 battery->flags.alarm_present = 1; 380 return 0;
365 if (!alarm && bif) {
366 alarm = bif->design_capacity_warning;
367 }
368 result = acpi_battery_set_alarm(battery, alarm);
369 if (result)
370 goto end;
371 } else {
372 battery->flags.alarm_present = 0;
373 } 381 }
374 382 battery->alarm_present = 1;
375 end: 383 if (!battery->alarm)
376 384 battery->alarm = battery->design_capacity_warning;
377 return result; 385 return acpi_battery_set_alarm(battery);
378} 386}
379 387
380static int acpi_battery_init_update(struct acpi_battery *battery) 388static int acpi_battery_update(struct acpi_battery *battery)
381{ 389{
382 int result = 0; 390 int saved_present = acpi_battery_present(battery);
383 391 int result = acpi_battery_get_status(battery);
384 result = acpi_battery_get_status(battery); 392 if (result || !acpi_battery_present(battery))
385 if (result)
386 return result; 393 return result;
387 394 if (saved_present != acpi_battery_present(battery) ||
388 battery->flags.battery_present_prev = acpi_battery_present(battery); 395 !battery->update_time) {
389 396 battery->update_time = 0;
390 if (acpi_battery_present(battery)) {
391 result = acpi_battery_get_info(battery); 397 result = acpi_battery_get_info(battery);
392 if (result) 398 if (result)
393 return result; 399 return result;
394 result = acpi_battery_get_state(battery); 400 if (battery->power_unit) {
395 if (result) 401 battery->bat.properties = charge_battery_props;
396 return result; 402 battery->bat.num_properties =
397 403 ARRAY_SIZE(charge_battery_props);
398 acpi_battery_init_alarm(battery);
399 }
400
401 return result;
402}
403
404static int acpi_battery_update(struct acpi_battery *battery,
405 int update, int *update_result_ptr)
406{
407 int result = 0;
408 int update_result = ACPI_BATTERY_NONE_UPDATE;
409
410 if (!acpi_battery_present(battery)) {
411 update = 1;
412 }
413
414 if (battery->flags.init_update) {
415 result = acpi_battery_init_update(battery);
416 if (result)
417 goto end;
418 update_result = ACPI_BATTERY_INIT_UPDATE;
419 } else if (update) {
420 result = acpi_battery_get_status(battery);
421 if (result)
422 goto end;
423 if ((!battery->flags.battery_present_prev & acpi_battery_present(battery))
424 || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) {
425 result = acpi_battery_init_update(battery);
426 if (result)
427 goto end;
428 update_result = ACPI_BATTERY_INIT_UPDATE;
429 } else { 404 } else {
430 update_result = ACPI_BATTERY_EASY_UPDATE; 405 battery->bat.properties = energy_battery_props;
406 battery->bat.num_properties =
407 ARRAY_SIZE(energy_battery_props);
431 } 408 }
409 acpi_battery_init_alarm(battery);
432 } 410 }
433 411 return acpi_battery_get_state(battery);
434 end:
435
436 battery->flags.init_update = (result != 0);
437
438 *update_result_ptr = update_result;
439
440 return result;
441}
442
443static void acpi_battery_notify_update(struct acpi_battery *battery)
444{
445 acpi_battery_get_status(battery);
446
447 if (battery->flags.init_update) {
448 return;
449 }
450
451 if ((!battery->flags.battery_present_prev &
452 acpi_battery_present(battery)) ||
453 (battery->flags.battery_present_prev &
454 !acpi_battery_present(battery))) {
455 battery->flags.init_update = 1;
456 } else {
457 battery->flags.update[ACPI_BATTERY_INFO] = 1;
458 battery->flags.update[ACPI_BATTERY_STATE] = 1;
459 battery->flags.update[ACPI_BATTERY_ALARM] = 1;
460 }
461} 412}
462 413
463/* -------------------------------------------------------------------------- 414/* --------------------------------------------------------------------------
464 FS Interface (/proc) 415 FS Interface (/proc)
465 -------------------------------------------------------------------------- */ 416 -------------------------------------------------------------------------- */
466 417
418#ifdef CONFIG_ACPI_PROCFS
467static struct proc_dir_entry *acpi_battery_dir; 419static struct proc_dir_entry *acpi_battery_dir;
468 420
469static int acpi_battery_print_info(struct seq_file *seq, int result) 421static int acpi_battery_print_info(struct seq_file *seq, int result)
470{ 422{
471 struct acpi_battery *battery = seq->private; 423 struct acpi_battery *battery = seq->private;
472 struct acpi_battery_info *bif = NULL;
473 char *units = "?";
474 424
475 if (result) 425 if (result)
476 goto end; 426 goto end;
477 427
478 if (acpi_battery_present(battery)) 428 seq_printf(seq, "present: %s\n",
479 seq_printf(seq, "present: yes\n"); 429 acpi_battery_present(battery)?"yes":"no");
480 else { 430 if (!acpi_battery_present(battery))
481 seq_printf(seq, "present: no\n");
482 goto end;
483 }
484
485 bif = battery->bif_data.pointer;
486 if (!bif) {
487 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL"));
488 result = -ENODEV;
489 goto end; 431 goto end;
490 } 432 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
491
492 /* Battery Units */
493
494 units = acpi_battery_power_units(battery);
495
496 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
497 seq_printf(seq, "design capacity: unknown\n"); 433 seq_printf(seq, "design capacity: unknown\n");
498 else 434 else
499 seq_printf(seq, "design capacity: %d %sh\n", 435 seq_printf(seq, "design capacity: %d %sh\n",
500 (u32) bif->design_capacity, units); 436 battery->design_capacity,
437 acpi_battery_units(battery));
501 438
502 if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 439 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
503 seq_printf(seq, "last full capacity: unknown\n"); 440 seq_printf(seq, "last full capacity: unknown\n");
504 else 441 else
505 seq_printf(seq, "last full capacity: %d %sh\n", 442 seq_printf(seq, "last full capacity: %d %sh\n",
506 (u32) bif->last_full_capacity, units); 443 battery->full_charge_capacity,
444 acpi_battery_units(battery));
507 445
508 switch ((u32) bif->battery_technology) { 446 seq_printf(seq, "battery technology: %srechargeable\n",
509 case 0: 447 (!battery->technology)?"non-":"");
510 seq_printf(seq, "battery technology: non-rechargeable\n");
511 break;
512 case 1:
513 seq_printf(seq, "battery technology: rechargeable\n");
514 break;
515 default:
516 seq_printf(seq, "battery technology: unknown\n");
517 break;
518 }
519 448
520 if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) 449 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
521 seq_printf(seq, "design voltage: unknown\n"); 450 seq_printf(seq, "design voltage: unknown\n");
522 else 451 else
523 seq_printf(seq, "design voltage: %d mV\n", 452 seq_printf(seq, "design voltage: %d mV\n",
524 (u32) bif->design_voltage); 453 battery->design_voltage);
525 seq_printf(seq, "design capacity warning: %d %sh\n", 454 seq_printf(seq, "design capacity warning: %d %sh\n",
526 (u32) bif->design_capacity_warning, units); 455 battery->design_capacity_warning,
456 acpi_battery_units(battery));
527 seq_printf(seq, "design capacity low: %d %sh\n", 457 seq_printf(seq, "design capacity low: %d %sh\n",
528 (u32) bif->design_capacity_low, units); 458 battery->design_capacity_low,
459 acpi_battery_units(battery));
529 seq_printf(seq, "capacity granularity 1: %d %sh\n", 460 seq_printf(seq, "capacity granularity 1: %d %sh\n",
530 (u32) bif->battery_capacity_granularity_1, units); 461 battery->capacity_granularity_1,
462 acpi_battery_units(battery));
531 seq_printf(seq, "capacity granularity 2: %d %sh\n", 463 seq_printf(seq, "capacity granularity 2: %d %sh\n",
532 (u32) bif->battery_capacity_granularity_2, units); 464 battery->capacity_granularity_2,
533 seq_printf(seq, "model number: %s\n", bif->model_number); 465 acpi_battery_units(battery));
534 seq_printf(seq, "serial number: %s\n", bif->serial_number); 466 seq_printf(seq, "model number: %s\n", battery->model_number);
535 seq_printf(seq, "battery type: %s\n", bif->battery_type); 467 seq_printf(seq, "serial number: %s\n", battery->serial_number);
536 seq_printf(seq, "OEM info: %s\n", bif->oem_info); 468 seq_printf(seq, "battery type: %s\n", battery->type);
537 469 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
538 end: 470 end:
539
540 if (result) 471 if (result)
541 seq_printf(seq, "ERROR: Unable to read battery info\n"); 472 seq_printf(seq, "ERROR: Unable to read battery info\n");
542
543 return result; 473 return result;
544} 474}
545 475
546static int acpi_battery_print_state(struct seq_file *seq, int result) 476static int acpi_battery_print_state(struct seq_file *seq, int result)
547{ 477{
548 struct acpi_battery *battery = seq->private; 478 struct acpi_battery *battery = seq->private;
549 struct acpi_battery_state *bst = NULL;
550 char *units = "?";
551 479
552 if (result) 480 if (result)
553 goto end; 481 goto end;
554 482
555 if (acpi_battery_present(battery)) 483 seq_printf(seq, "present: %s\n",
556 seq_printf(seq, "present: yes\n"); 484 acpi_battery_present(battery)?"yes":"no");
557 else { 485 if (!acpi_battery_present(battery))
558 seq_printf(seq, "present: no\n");
559 goto end;
560 }
561
562 bst = battery->bst_data.pointer;
563 if (!bst) {
564 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL"));
565 result = -ENODEV;
566 goto end; 486 goto end;
567 }
568
569 /* Battery Units */
570
571 units = acpi_battery_power_units(battery);
572
573 if (!(bst->state & 0x04))
574 seq_printf(seq, "capacity state: ok\n");
575 else
576 seq_printf(seq, "capacity state: critical\n");
577 487
578 if ((bst->state & 0x01) && (bst->state & 0x02)) { 488 seq_printf(seq, "capacity state: %s\n",
489 (battery->state & 0x04)?"critical":"ok");
490 if ((battery->state & 0x01) && (battery->state & 0x02))
579 seq_printf(seq, 491 seq_printf(seq,
580 "charging state: charging/discharging\n"); 492 "charging state: charging/discharging\n");
581 } else if (bst->state & 0x01) 493 else if (battery->state & 0x01)
582 seq_printf(seq, "charging state: discharging\n"); 494 seq_printf(seq, "charging state: discharging\n");
583 else if (bst->state & 0x02) 495 else if (battery->state & 0x02)
584 seq_printf(seq, "charging state: charging\n"); 496 seq_printf(seq, "charging state: charging\n");
585 else { 497 else
586 seq_printf(seq, "charging state: charged\n"); 498 seq_printf(seq, "charging state: charged\n");
587 }
588 499
589 if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) 500 if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN)
590 seq_printf(seq, "present rate: unknown\n"); 501 seq_printf(seq, "present rate: unknown\n");
591 else 502 else
592 seq_printf(seq, "present rate: %d %s\n", 503 seq_printf(seq, "present rate: %d %s\n",
593 (u32) bst->present_rate, units); 504 battery->current_now, acpi_battery_units(battery));
594 505
595 if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 506 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
596 seq_printf(seq, "remaining capacity: unknown\n"); 507 seq_printf(seq, "remaining capacity: unknown\n");
597 else 508 else
598 seq_printf(seq, "remaining capacity: %d %sh\n", 509 seq_printf(seq, "remaining capacity: %d %sh\n",
599 (u32) bst->remaining_capacity, units); 510 battery->capacity_now, acpi_battery_units(battery));
600 511 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
601 if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
602 seq_printf(seq, "present voltage: unknown\n"); 512 seq_printf(seq, "present voltage: unknown\n");
603 else 513 else
604 seq_printf(seq, "present voltage: %d mV\n", 514 seq_printf(seq, "present voltage: %d mV\n",
605 (u32) bst->present_voltage); 515 battery->voltage_now);
606
607 end: 516 end:
608 517 if (result)
609 if (result) {
610 seq_printf(seq, "ERROR: Unable to read battery state\n"); 518 seq_printf(seq, "ERROR: Unable to read battery state\n");
611 }
612 519
613 return result; 520 return result;
614} 521}
@@ -616,7 +523,6 @@ static int acpi_battery_print_state(struct seq_file *seq, int result)
616static int acpi_battery_print_alarm(struct seq_file *seq, int result) 523static int acpi_battery_print_alarm(struct seq_file *seq, int result)
617{ 524{
618 struct acpi_battery *battery = seq->private; 525 struct acpi_battery *battery = seq->private;
619 char *units = "?";
620 526
621 if (result) 527 if (result)
622 goto end; 528 goto end;
@@ -625,189 +531,121 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result)
625 seq_printf(seq, "present: no\n"); 531 seq_printf(seq, "present: no\n");
626 goto end; 532 goto end;
627 } 533 }
628
629 /* Battery Units */
630
631 units = acpi_battery_power_units(battery);
632
633 seq_printf(seq, "alarm: "); 534 seq_printf(seq, "alarm: ");
634 if (!battery->alarm) 535 if (!battery->alarm)
635 seq_printf(seq, "unsupported\n"); 536 seq_printf(seq, "unsupported\n");
636 else 537 else
637 seq_printf(seq, "%lu %sh\n", battery->alarm, units); 538 seq_printf(seq, "%u %sh\n", battery->alarm,
638 539 acpi_battery_units(battery));
639 end: 540 end:
640
641 if (result) 541 if (result)
642 seq_printf(seq, "ERROR: Unable to read battery alarm\n"); 542 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
643
644 return result; 543 return result;
645} 544}
646 545
647static ssize_t 546static ssize_t acpi_battery_write_alarm(struct file *file,
648acpi_battery_write_alarm(struct file *file, 547 const char __user * buffer,
649 const char __user * buffer, 548 size_t count, loff_t * ppos)
650 size_t count, loff_t * ppos)
651{ 549{
652 int result = 0; 550 int result = 0;
653 char alarm_string[12] = { '\0' }; 551 char alarm_string[12] = { '\0' };
654 struct seq_file *m = file->private_data; 552 struct seq_file *m = file->private_data;
655 struct acpi_battery *battery = m->private; 553 struct acpi_battery *battery = m->private;
656 int update_result = ACPI_BATTERY_NONE_UPDATE;
657 554
658 if (!battery || (count > sizeof(alarm_string) - 1)) 555 if (!battery || (count > sizeof(alarm_string) - 1))
659 return -EINVAL; 556 return -EINVAL;
660
661 mutex_lock(&battery->mutex);
662
663 result = acpi_battery_update(battery, 1, &update_result);
664 if (result) { 557 if (result) {
665 result = -ENODEV; 558 result = -ENODEV;
666 goto end; 559 goto end;
667 } 560 }
668
669 if (!acpi_battery_present(battery)) { 561 if (!acpi_battery_present(battery)) {
670 result = -ENODEV; 562 result = -ENODEV;
671 goto end; 563 goto end;
672 } 564 }
673
674 if (copy_from_user(alarm_string, buffer, count)) { 565 if (copy_from_user(alarm_string, buffer, count)) {
675 result = -EFAULT; 566 result = -EFAULT;
676 goto end; 567 goto end;
677 } 568 }
678
679 alarm_string[count] = '\0'; 569 alarm_string[count] = '\0';
680 570 battery->alarm = simple_strtol(alarm_string, NULL, 0);
681 result = acpi_battery_set_alarm(battery, 571 result = acpi_battery_set_alarm(battery);
682 simple_strtoul(alarm_string, NULL, 0));
683 if (result)
684 goto end;
685
686 end: 572 end:
687
688 acpi_battery_check_result(battery, result);
689
690 if (!result) 573 if (!result)
691 result = count; 574 return count;
692
693 mutex_unlock(&battery->mutex);
694
695 return result; 575 return result;
696} 576}
697 577
698typedef int(*print_func)(struct seq_file *seq, int result); 578typedef int(*print_func)(struct seq_file *seq, int result);
699typedef int(*get_func)(struct acpi_battery *battery); 579
700 580static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
701static struct acpi_read_mux { 581 acpi_battery_print_info,
702 print_func print; 582 acpi_battery_print_state,
703 get_func get; 583 acpi_battery_print_alarm,
704} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = {
705 {.get = acpi_battery_get_info, .print = acpi_battery_print_info},
706 {.get = acpi_battery_get_state, .print = acpi_battery_print_state},
707 {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm},
708}; 584};
709 585
710static int acpi_battery_read(int fid, struct seq_file *seq) 586static int acpi_battery_read(int fid, struct seq_file *seq)
711{ 587{
712 struct acpi_battery *battery = seq->private; 588 struct acpi_battery *battery = seq->private;
713 int result = 0; 589 int result = acpi_battery_update(battery);
714 int update_result = ACPI_BATTERY_NONE_UPDATE; 590 return acpi_print_funcs[fid](seq, result);
715 int update = 0; 591}
716 592
717 mutex_lock(&battery->mutex); 593#define DECLARE_FILE_FUNCTIONS(_name) \
718 594static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
719 update = (get_seconds() - battery->update_time[fid] >= update_time); 595{ \
720 update = (update | battery->flags.update[fid]); 596 return acpi_battery_read(_name##_tag, seq); \
721 597} \
722 result = acpi_battery_update(battery, update, &update_result); 598static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
723 if (result) 599{ \
724 goto end; 600 return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
725 601}
726 if (update_result == ACPI_BATTERY_EASY_UPDATE) { 602
727 result = acpi_read_funcs[fid].get(battery); 603DECLARE_FILE_FUNCTIONS(info);
728 if (result) 604DECLARE_FILE_FUNCTIONS(state);
729 goto end; 605DECLARE_FILE_FUNCTIONS(alarm);
606
607#undef DECLARE_FILE_FUNCTIONS
608
609#define FILE_DESCRIPTION_RO(_name) \
610 { \
611 .name = __stringify(_name), \
612 .mode = S_IRUGO, \
613 .ops = { \
614 .open = acpi_battery_##_name##_open_fs, \
615 .read = seq_read, \
616 .llseek = seq_lseek, \
617 .release = single_release, \
618 .owner = THIS_MODULE, \
619 }, \
620 }
621
622#define FILE_DESCRIPTION_RW(_name) \
623 { \
624 .name = __stringify(_name), \
625 .mode = S_IFREG | S_IRUGO | S_IWUSR, \
626 .ops = { \
627 .open = acpi_battery_##_name##_open_fs, \
628 .read = seq_read, \
629 .llseek = seq_lseek, \
630 .write = acpi_battery_write_##_name, \
631 .release = single_release, \
632 .owner = THIS_MODULE, \
633 }, \
730 } 634 }
731 635
732 end:
733 result = acpi_read_funcs[fid].print(seq, result);
734 acpi_battery_check_result(battery, result);
735 battery->flags.update[fid] = result;
736 mutex_unlock(&battery->mutex);
737 return result;
738}
739
740static int acpi_battery_read_info(struct seq_file *seq, void *offset)
741{
742 return acpi_battery_read(ACPI_BATTERY_INFO, seq);
743}
744
745static int acpi_battery_read_state(struct seq_file *seq, void *offset)
746{
747 return acpi_battery_read(ACPI_BATTERY_STATE, seq);
748}
749
750static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
751{
752 return acpi_battery_read(ACPI_BATTERY_ALARM, seq);
753}
754
755static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
756{
757 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
758}
759
760static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
761{
762 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
763}
764
765static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
766{
767 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
768}
769
770static struct battery_file { 636static struct battery_file {
771 struct file_operations ops; 637 struct file_operations ops;
772 mode_t mode; 638 mode_t mode;
773 char *name; 639 char *name;
774} acpi_battery_file[] = { 640} acpi_battery_file[] = {
775 { 641 FILE_DESCRIPTION_RO(info),
776 .name = "info", 642 FILE_DESCRIPTION_RO(state),
777 .mode = S_IRUGO, 643 FILE_DESCRIPTION_RW(alarm),
778 .ops = {
779 .open = acpi_battery_info_open_fs,
780 .read = seq_read,
781 .llseek = seq_lseek,
782 .release = single_release,
783 .owner = THIS_MODULE,
784 },
785 },
786 {
787 .name = "state",
788 .mode = S_IRUGO,
789 .ops = {
790 .open = acpi_battery_state_open_fs,
791 .read = seq_read,
792 .llseek = seq_lseek,
793 .release = single_release,
794 .owner = THIS_MODULE,
795 },
796 },
797 {
798 .name = "alarm",
799 .mode = S_IFREG | S_IRUGO | S_IWUSR,
800 .ops = {
801 .open = acpi_battery_alarm_open_fs,
802 .read = seq_read,
803 .write = acpi_battery_write_alarm,
804 .llseek = seq_lseek,
805 .release = single_release,
806 .owner = THIS_MODULE,
807 },
808 },
809}; 644};
810 645
646#undef FILE_DESCRIPTION_RO
647#undef FILE_DESCRIPTION_RW
648
811static int acpi_battery_add_fs(struct acpi_device *device) 649static int acpi_battery_add_fs(struct acpi_device *device)
812{ 650{
813 struct proc_dir_entry *entry = NULL; 651 struct proc_dir_entry *entry = NULL;
@@ -832,25 +670,51 @@ static int acpi_battery_add_fs(struct acpi_device *device)
832 entry->owner = THIS_MODULE; 670 entry->owner = THIS_MODULE;
833 } 671 }
834 } 672 }
835
836 return 0; 673 return 0;
837} 674}
838 675
839static int acpi_battery_remove_fs(struct acpi_device *device) 676static void acpi_battery_remove_fs(struct acpi_device *device)
840{ 677{
841 int i; 678 int i;
842 if (acpi_device_dir(device)) { 679 if (!acpi_device_dir(device))
843 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { 680 return;
844 remove_proc_entry(acpi_battery_file[i].name, 681 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
682 remove_proc_entry(acpi_battery_file[i].name,
845 acpi_device_dir(device)); 683 acpi_device_dir(device));
846 }
847 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
848 acpi_device_dir(device) = NULL;
849 }
850 684
851 return 0; 685 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
686 acpi_device_dir(device) = NULL;
687}
688
689#endif
690
691static ssize_t acpi_battery_alarm_show(struct device *dev,
692 struct device_attribute *attr,
693 char *buf)
694{
695 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
696 return sprintf(buf, "%d\n", battery->alarm * 1000);
697}
698
699static ssize_t acpi_battery_alarm_store(struct device *dev,
700 struct device_attribute *attr,
701 const char *buf, size_t count)
702{
703 unsigned long x;
704 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
705 if (sscanf(buf, "%ld\n", &x) == 1)
706 battery->alarm = x/1000;
707 if (acpi_battery_present(battery))
708 acpi_battery_set_alarm(battery);
709 return count;
852} 710}
853 711
712static struct device_attribute alarm_attr = {
713 .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
714 .show = acpi_battery_alarm_show,
715 .store = acpi_battery_alarm_store,
716};
717
854/* -------------------------------------------------------------------------- 718/* --------------------------------------------------------------------------
855 Driver Interface 719 Driver Interface
856 -------------------------------------------------------------------------- */ 720 -------------------------------------------------------------------------- */
@@ -858,33 +722,17 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
858static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) 722static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
859{ 723{
860 struct acpi_battery *battery = data; 724 struct acpi_battery *battery = data;
861 struct acpi_device *device = NULL; 725 struct acpi_device *device;
862
863 if (!battery) 726 if (!battery)
864 return; 727 return;
865
866 device = battery->device; 728 device = battery->device;
867 729 acpi_battery_update(battery);
868 switch (event) { 730 acpi_bus_generate_proc_event(device, event,
869 case ACPI_BATTERY_NOTIFY_STATUS: 731 acpi_battery_present(battery));
870 case ACPI_BATTERY_NOTIFY_INFO: 732 acpi_bus_generate_netlink_event(device->pnp.device_class,
871 case ACPI_NOTIFY_BUS_CHECK: 733 device->dev.bus_id, event,
872 case ACPI_NOTIFY_DEVICE_CHECK:
873 device = battery->device;
874 acpi_battery_notify_update(battery);
875 acpi_bus_generate_proc_event(device, event,
876 acpi_battery_present(battery)); 734 acpi_battery_present(battery));
877 acpi_bus_generate_netlink_event(device->pnp.device_class, 735 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
878 device->dev.bus_id, event,
879 acpi_battery_present(battery));
880 break;
881 default:
882 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
883 "Unsupported event [0x%x]\n", event));
884 break;
885 }
886
887 return;
888} 736}
889 737
890static int acpi_battery_add(struct acpi_device *device) 738static int acpi_battery_add(struct acpi_device *device)
@@ -892,33 +740,27 @@ static int acpi_battery_add(struct acpi_device *device)
892 int result = 0; 740 int result = 0;
893 acpi_status status = 0; 741 acpi_status status = 0;
894 struct acpi_battery *battery = NULL; 742 struct acpi_battery *battery = NULL;
895
896 if (!device) 743 if (!device)
897 return -EINVAL; 744 return -EINVAL;
898
899 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); 745 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
900 if (!battery) 746 if (!battery)
901 return -ENOMEM; 747 return -ENOMEM;
902
903 mutex_init(&battery->mutex);
904
905 mutex_lock(&battery->mutex);
906
907 battery->device = device; 748 battery->device = device;
908 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 749 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
909 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 750 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
910 acpi_driver_data(device) = battery; 751 acpi_driver_data(device) = battery;
911 752 mutex_init(&battery->lock);
912 result = acpi_battery_get_status(battery); 753 acpi_battery_update(battery);
913 if (result) 754#ifdef CONFIG_ACPI_PROCFS
914 goto end;
915
916 battery->flags.init_update = 1;
917
918 result = acpi_battery_add_fs(device); 755 result = acpi_battery_add_fs(device);
919 if (result) 756 if (result)
920 goto end; 757 goto end;
921 758#endif
759 battery->bat.name = acpi_device_bid(device);
760 battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
761 battery->bat.get_property = acpi_battery_get_property;
762 result = power_supply_register(&battery->device->dev, &battery->bat);
763 result = device_create_file(battery->bat.dev, &alarm_attr);
922 status = acpi_install_notify_handler(device->handle, 764 status = acpi_install_notify_handler(device->handle,
923 ACPI_ALL_NOTIFY, 765 ACPI_ALL_NOTIFY,
924 acpi_battery_notify, battery); 766 acpi_battery_notify, battery);
@@ -927,20 +769,16 @@ static int acpi_battery_add(struct acpi_device *device)
927 result = -ENODEV; 769 result = -ENODEV;
928 goto end; 770 goto end;
929 } 771 }
930
931 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", 772 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
932 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), 773 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
933 device->status.battery_present ? "present" : "absent"); 774 device->status.battery_present ? "present" : "absent");
934
935 end: 775 end:
936
937 if (result) { 776 if (result) {
777#ifdef CONFIG_ACPI_PROCFS
938 acpi_battery_remove_fs(device); 778 acpi_battery_remove_fs(device);
779#endif
939 kfree(battery); 780 kfree(battery);
940 } 781 }
941
942 mutex_unlock(&battery->mutex);
943
944 return result; 782 return result;
945} 783}
946 784
@@ -951,27 +789,19 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
951 789
952 if (!device || !acpi_driver_data(device)) 790 if (!device || !acpi_driver_data(device))
953 return -EINVAL; 791 return -EINVAL;
954
955 battery = acpi_driver_data(device); 792 battery = acpi_driver_data(device);
956
957 mutex_lock(&battery->mutex);
958
959 status = acpi_remove_notify_handler(device->handle, 793 status = acpi_remove_notify_handler(device->handle,
960 ACPI_ALL_NOTIFY, 794 ACPI_ALL_NOTIFY,
961 acpi_battery_notify); 795 acpi_battery_notify);
962 796#ifdef CONFIG_ACPI_PROCFS
963 acpi_battery_remove_fs(device); 797 acpi_battery_remove_fs(device);
964 798#endif
965 kfree(battery->bif_data.pointer); 799 if (battery->bat.dev) {
966 800 device_remove_file(battery->bat.dev, &alarm_attr);
967 kfree(battery->bst_data.pointer); 801 power_supply_unregister(&battery->bat);
968 802 }
969 mutex_unlock(&battery->mutex); 803 mutex_destroy(&battery->lock);
970
971 mutex_destroy(&battery->mutex);
972
973 kfree(battery); 804 kfree(battery);
974
975 return 0; 805 return 0;
976} 806}
977 807
@@ -979,44 +809,48 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
979static int acpi_battery_resume(struct acpi_device *device) 809static int acpi_battery_resume(struct acpi_device *device)
980{ 810{
981 struct acpi_battery *battery; 811 struct acpi_battery *battery;
982
983 if (!device) 812 if (!device)
984 return -EINVAL; 813 return -EINVAL;
985 814 battery = acpi_driver_data(device);
986 battery = device->driver_data; 815 battery->update_time = 0;
987
988 battery->flags.init_update = 1;
989
990 return 0; 816 return 0;
991} 817}
992 818
819static struct acpi_driver acpi_battery_driver = {
820 .name = "battery",
821 .class = ACPI_BATTERY_CLASS,
822 .ids = battery_device_ids,
823 .ops = {
824 .add = acpi_battery_add,
825 .resume = acpi_battery_resume,
826 .remove = acpi_battery_remove,
827 },
828};
829
993static int __init acpi_battery_init(void) 830static int __init acpi_battery_init(void)
994{ 831{
995 int result;
996
997 if (acpi_disabled) 832 if (acpi_disabled)
998 return -ENODEV; 833 return -ENODEV;
999 834#ifdef CONFIG_ACPI_PROCFS
1000 acpi_battery_dir = acpi_lock_battery_dir(); 835 acpi_battery_dir = acpi_lock_battery_dir();
1001 if (!acpi_battery_dir) 836 if (!acpi_battery_dir)
1002 return -ENODEV; 837 return -ENODEV;
1003 838#endif
1004 result = acpi_bus_register_driver(&acpi_battery_driver); 839 if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
1005 if (result < 0) { 840#ifdef CONFIG_ACPI_PROCFS
1006 acpi_unlock_battery_dir(acpi_battery_dir); 841 acpi_unlock_battery_dir(acpi_battery_dir);
842#endif
1007 return -ENODEV; 843 return -ENODEV;
1008 } 844 }
1009
1010 return 0; 845 return 0;
1011} 846}
1012 847
1013static void __exit acpi_battery_exit(void) 848static void __exit acpi_battery_exit(void)
1014{ 849{
1015 acpi_bus_unregister_driver(&acpi_battery_driver); 850 acpi_bus_unregister_driver(&acpi_battery_driver);
1016 851#ifdef CONFIG_ACPI_PROCFS
1017 acpi_unlock_battery_dir(acpi_battery_dir); 852 acpi_unlock_battery_dir(acpi_battery_dir);
1018 853#endif
1019 return;
1020} 854}
1021 855
1022module_init(acpi_battery_init); 856module_init(acpi_battery_init);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9ba778a2b484..a54234d3aac1 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -284,15 +284,11 @@ DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
284 284
285extern int event_is_open; 285extern int event_is_open;
286 286
287int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) 287int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
288{ 288{
289 struct acpi_bus_event *event = NULL; 289 struct acpi_bus_event *event;
290 unsigned long flags = 0; 290 unsigned long flags = 0;
291 291
292
293 if (!device)
294 return -EINVAL;
295
296 /* drop event on the floor if no one's listening */ 292 /* drop event on the floor if no one's listening */
297 if (!event_is_open) 293 if (!event_is_open)
298 return 0; 294 return 0;
@@ -301,8 +297,8 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
301 if (!event) 297 if (!event)
302 return -ENOMEM; 298 return -ENOMEM;
303 299
304 strcpy(event->device_class, device->pnp.device_class); 300 strcpy(event->device_class, device_class);
305 strcpy(event->bus_id, device->pnp.bus_id); 301 strcpy(event->bus_id, bus_id);
306 event->type = type; 302 event->type = type;
307 event->data = data; 303 event->data = data;
308 304
@@ -313,6 +309,17 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
313 wake_up_interruptible(&acpi_bus_event_queue); 309 wake_up_interruptible(&acpi_bus_event_queue);
314 310
315 return 0; 311 return 0;
312
313}
314
315EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);
316
317int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
318{
319 if (!device)
320 return -EINVAL;
321 return acpi_bus_generate_proc_event4(device->pnp.device_class,
322 device->pnp.bus_id, type, data);
316} 323}
317 324
318EXPORT_SYMBOL(acpi_bus_generate_proc_event); 325EXPORT_SYMBOL(acpi_bus_generate_proc_event);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3f7935ab0cf5..e9a04052084b 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -425,7 +425,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
425 handler->func = func; 425 handler->func = func;
426 handler->data = data; 426 handler->data = data;
427 mutex_lock(&ec->lock); 427 mutex_lock(&ec->lock);
428 list_add_tail(&handler->node, &ec->list); 428 list_add(&handler->node, &ec->list);
429 mutex_unlock(&ec->lock); 429 mutex_unlock(&ec->lock);
430 return 0; 430 return 0;
431} 431}
@@ -440,7 +440,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
440 if (query_bit == handler->query_bit) { 440 if (query_bit == handler->query_bit) {
441 list_del(&handler->node); 441 list_del(&handler->node);
442 kfree(handler); 442 kfree(handler);
443 break;
444 } 443 }
445 } 444 }
446 mutex_unlock(&ec->lock); 445 mutex_unlock(&ec->lock);
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index a578986e3214..90fd09c65f95 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $) 2 * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
3 * 3 *
4 * Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
5 * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
4 * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> 6 * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
5 * 7 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -26,15 +28,22 @@
26#include <linux/module.h> 28#include <linux/module.h>
27#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
28#include <linux/kernel.h> 30#include <linux/kernel.h>
31
32#ifdef CONFIG_ACPI_PROCFS
29#include <linux/proc_fs.h> 33#include <linux/proc_fs.h>
30#include <linux/seq_file.h> 34#include <linux/seq_file.h>
31#include <asm/uaccess.h> 35#include <asm/uaccess.h>
36#endif
37
32#include <linux/acpi.h> 38#include <linux/acpi.h>
33#include <linux/timer.h> 39#include <linux/timer.h>
34#include <linux/jiffies.h> 40#include <linux/jiffies.h>
35#include <linux/delay.h> 41#include <linux/delay.h>
36 42
37#define ACPI_SBS_COMPONENT 0x00080000 43#include <linux/power_supply.h>
44
45#include "sbshc.h"
46
38#define ACPI_SBS_CLASS "sbs" 47#define ACPI_SBS_CLASS "sbs"
39#define ACPI_AC_CLASS "ac_adapter" 48#define ACPI_AC_CLASS "ac_adapter"
40#define ACPI_BATTERY_CLASS "battery" 49#define ACPI_BATTERY_CLASS "battery"
@@ -44,836 +53,436 @@
44#define ACPI_SBS_FILE_ALARM "alarm" 53#define ACPI_SBS_FILE_ALARM "alarm"
45#define ACPI_BATTERY_DIR_NAME "BAT%i" 54#define ACPI_BATTERY_DIR_NAME "BAT%i"
46#define ACPI_AC_DIR_NAME "AC0" 55#define ACPI_AC_DIR_NAME "AC0"
47#define ACPI_SBC_SMBUS_ADDR 0x9
48#define ACPI_SBSM_SMBUS_ADDR 0xa
49#define ACPI_SB_SMBUS_ADDR 0xb
50#define ACPI_SBS_AC_NOTIFY_STATUS 0x80
51#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
52#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81
53 56
54#define _COMPONENT ACPI_SBS_COMPONENT 57enum acpi_sbs_device_addr {
58 ACPI_SBS_CHARGER = 0x9,
59 ACPI_SBS_MANAGER = 0xa,
60 ACPI_SBS_BATTERY = 0xb,
61};
55 62
56ACPI_MODULE_NAME("sbs"); 63#define ACPI_SBS_NOTIFY_STATUS 0x80
64#define ACPI_SBS_NOTIFY_INFO 0x81
57 65
58MODULE_AUTHOR("Rich Townsend"); 66MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
59MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); 67MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
60MODULE_LICENSE("GPL"); 68MODULE_LICENSE("GPL");
61 69
62#define xmsleep(t) msleep(t) 70static unsigned int cache_time = 1000;
63 71module_param(cache_time, uint, 0644);
64#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */ 72MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
65
66#define ACPI_EC_SMB_STS 0x01 /* status */
67#define ACPI_EC_SMB_ADDR 0x02 /* address */
68#define ACPI_EC_SMB_CMD 0x03 /* command */
69#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
70#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
71
72#define ACPI_EC_SMB_STS_DONE 0x80
73#define ACPI_EC_SMB_STS_STATUS 0x1f
74
75#define ACPI_EC_SMB_PRTCL_WRITE 0x00
76#define ACPI_EC_SMB_PRTCL_READ 0x01
77#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
78#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
79
80#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
81#define ACPI_EC_SMB_ACCESS_SLEEP1 1
82#define ACPI_EC_SMB_ACCESS_SLEEP2 10
83
84#define DEF_CAPACITY_UNIT 3
85#define MAH_CAPACITY_UNIT 1
86#define MWH_CAPACITY_UNIT 2
87#define CAPACITY_UNIT DEF_CAPACITY_UNIT
88
89#define REQUEST_UPDATE_MODE 1
90#define QUEUE_UPDATE_MODE 2
91
92#define DATA_TYPE_COMMON 0
93#define DATA_TYPE_INFO 1
94#define DATA_TYPE_STATE 2
95#define DATA_TYPE_ALARM 3
96#define DATA_TYPE_AC_STATE 4
97 73
98extern struct proc_dir_entry *acpi_lock_ac_dir(void); 74extern struct proc_dir_entry *acpi_lock_ac_dir(void);
99extern struct proc_dir_entry *acpi_lock_battery_dir(void); 75extern struct proc_dir_entry *acpi_lock_battery_dir(void);
100extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 76extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
101extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 77extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
102 78
103#define MAX_SBS_BAT 4 79#define MAX_SBS_BAT 4
104#define ACPI_SBS_BLOCK_MAX 32 80#define ACPI_SBS_BLOCK_MAX 32
105 81
106#define ACPI_SBS_SMBUS_READ 1
107#define ACPI_SBS_SMBUS_WRITE 2
108
109#define ACPI_SBS_WORD_DATA 1
110#define ACPI_SBS_BLOCK_DATA 2
111
112#define UPDATE_DELAY 10
113
114/* 0 - every time, > 0 - by update_time */
115static unsigned int update_time = 120;
116
117static unsigned int capacity_mode = CAPACITY_UNIT;
118
119module_param(update_time, uint, 0644);
120module_param(capacity_mode, uint, 0444);
121
122static int acpi_sbs_add(struct acpi_device *device);
123static int acpi_sbs_remove(struct acpi_device *device, int type);
124static int acpi_sbs_resume(struct acpi_device *device);
125
126static const struct acpi_device_id sbs_device_ids[] = { 82static const struct acpi_device_id sbs_device_ids[] = {
127 {"ACPI0001", 0}, 83 {"ACPI0002", 0},
128 {"ACPI0005", 0},
129 {"", 0}, 84 {"", 0},
130}; 85};
131MODULE_DEVICE_TABLE(acpi, sbs_device_ids); 86MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
132 87
133static struct acpi_driver acpi_sbs_driver = {
134 .name = "sbs",
135 .class = ACPI_SBS_CLASS,
136 .ids = sbs_device_ids,
137 .ops = {
138 .add = acpi_sbs_add,
139 .remove = acpi_sbs_remove,
140 .resume = acpi_sbs_resume,
141 },
142};
143
144struct acpi_ac {
145 int ac_present;
146};
147
148struct acpi_battery_info {
149 int capacity_mode;
150 s16 full_charge_capacity;
151 s16 design_capacity;
152 s16 design_voltage;
153 int vscale;
154 int ipscale;
155 s16 serial_number;
156 char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3];
157 char device_name[ACPI_SBS_BLOCK_MAX + 3];
158 char device_chemistry[ACPI_SBS_BLOCK_MAX + 3];
159};
160
161struct acpi_battery_state {
162 s16 voltage;
163 s16 amperage;
164 s16 remaining_capacity;
165 s16 battery_state;
166};
167
168struct acpi_battery_alarm {
169 s16 remaining_capacity;
170};
171
172struct acpi_battery { 88struct acpi_battery {
173 int alive; 89 struct power_supply bat;
174 int id;
175 int init_state;
176 int battery_present;
177 struct acpi_sbs *sbs; 90 struct acpi_sbs *sbs;
178 struct acpi_battery_info info; 91#ifdef CONFIG_ACPI_PROCFS
179 struct acpi_battery_state state; 92 struct proc_dir_entry *proc_entry;
180 struct acpi_battery_alarm alarm; 93#endif
181 struct proc_dir_entry *battery_entry; 94 unsigned long update_time;
95 char name[8];
96 char manufacturer_name[ACPI_SBS_BLOCK_MAX];
97 char device_name[ACPI_SBS_BLOCK_MAX];
98 char device_chemistry[ACPI_SBS_BLOCK_MAX];
99 u16 alarm_capacity;
100 u16 full_charge_capacity;
101 u16 design_capacity;
102 u16 design_voltage;
103 u16 serial_number;
104 u16 cycle_count;
105 u16 temp_now;
106 u16 voltage_now;
107 s16 current_now;
108 s16 current_avg;
109 u16 capacity_now;
110 u16 state_of_charge;
111 u16 state;
112 u16 mode;
113 u16 spec;
114 u8 id;
115 u8 present:1;
182}; 116};
183 117
118#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
119
184struct acpi_sbs { 120struct acpi_sbs {
185 int base; 121 struct power_supply charger;
186 struct acpi_device *device; 122 struct acpi_device *device;
187 struct mutex mutex; 123 struct acpi_smb_hc *hc;
188 int sbsm_present; 124 struct mutex lock;
189 int sbsm_batteries_supported; 125#ifdef CONFIG_ACPI_PROCFS
190 struct proc_dir_entry *ac_entry; 126 struct proc_dir_entry *charger_entry;
191 struct acpi_ac ac; 127#endif
192 struct acpi_battery battery[MAX_SBS_BAT]; 128 struct acpi_battery battery[MAX_SBS_BAT];
193 int zombie; 129 u8 batteries_supported:4;
194 struct timer_list update_timer; 130 u8 manager_present:1;
195 int run_cnt; 131 u8 charger_present:1;
196 int update_proc_flg;
197}; 132};
198 133
199static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); 134#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
200static void acpi_sbs_update_time(void *data);
201 135
202union sbs_rw_data { 136static inline int battery_scale(int log)
203 u16 word;
204 u8 block[ACPI_SBS_BLOCK_MAX + 2];
205};
206
207static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
208 char read_write, u8 command, int size,
209 union sbs_rw_data *data);
210
211/* --------------------------------------------------------------------------
212 SMBus Communication
213 -------------------------------------------------------------------------- */
214
215static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data)
216{ 137{
217 u8 val; 138 int scale = 1;
218 int err; 139 while (log--)
219 140 scale *= 10;
220 err = ec_read(sbs->base + address, &val); 141 return scale;
221 if (!err) {
222 *data = val;
223 }
224 xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
225 return (err);
226}
227
228static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data)
229{
230 int err;
231
232 err = ec_write(sbs->base + address, data);
233 return (err);
234}
235
236static int
237acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
238 char read_write, u8 command, int size,
239 union sbs_rw_data *data)
240{
241 unsigned char protocol, len = 0, temp[2] = { 0, 0 };
242 int i;
243
244 if (read_write == ACPI_SBS_SMBUS_READ) {
245 protocol = ACPI_EC_SMB_PRTCL_READ;
246 } else {
247 protocol = ACPI_EC_SMB_PRTCL_WRITE;
248 }
249
250 switch (size) {
251
252 case ACPI_SBS_WORD_DATA:
253 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
254 if (read_write == ACPI_SBS_SMBUS_WRITE) {
255 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word);
256 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1,
257 data->word >> 8);
258 }
259 protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA;
260 break;
261 case ACPI_SBS_BLOCK_DATA:
262 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
263 if (read_write == ACPI_SBS_SMBUS_WRITE) {
264 len = min_t(u8, data->block[0], 32);
265 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len);
266 for (i = 0; i < len; i++)
267 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i,
268 data->block[i + 1]);
269 }
270 protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA;
271 break;
272 default:
273 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
274 "unsupported transaction %d", size));
275 return (-1);
276 }
277
278 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1);
279 acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol);
280
281 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
282
283 if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
284 xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1);
285 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
286 }
287 if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
288 xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
289 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
290 }
291 if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
292 || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
293 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
294 "transaction %d error", size));
295 return (-1);
296 }
297
298 if (read_write == ACPI_SBS_SMBUS_WRITE) {
299 return (0);
300 }
301
302 switch (size) {
303
304 case ACPI_SBS_WORD_DATA:
305 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp);
306 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1);
307 data->word = (temp[1] << 8) | temp[0];
308 break;
309
310 case ACPI_SBS_BLOCK_DATA:
311 len = 0;
312 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len);
313 len = min_t(u8, len, 32);
314 for (i = 0; i < len; i++)
315 acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i,
316 data->block + i + 1);
317 data->block[0] = len;
318 break;
319 default:
320 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
321 "unsupported transaction %d", size));
322 return (-1);
323 }
324
325 return (0);
326} 142}
327 143
328static int 144static inline int acpi_battery_vscale(struct acpi_battery *battery)
329acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word)
330{ 145{
331 union sbs_rw_data data; 146 return battery_scale((battery->spec & 0x0f00) >> 8);
332 int result = 0;
333
334 result = acpi_ec_sbs_access(sbs, addr,
335 ACPI_SBS_SMBUS_READ, func,
336 ACPI_SBS_WORD_DATA, &data);
337 if (result) {
338 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
339 "acpi_ec_sbs_access() failed"));
340 } else {
341 *word = data.word;
342 }
343
344 return result;
345} 147}
346 148
347static int 149static inline int acpi_battery_ipscale(struct acpi_battery *battery)
348acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str)
349{ 150{
350 union sbs_rw_data data; 151 return battery_scale((battery->spec & 0xf000) >> 12);
351 int result = 0;
352
353 result = acpi_ec_sbs_access(sbs, addr,
354 ACPI_SBS_SMBUS_READ, func,
355 ACPI_SBS_BLOCK_DATA, &data);
356 if (result) {
357 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
358 "acpi_ec_sbs_access() failed"));
359 } else {
360 strncpy(str, (const char *)data.block + 1, data.block[0]);
361 str[data.block[0]] = 0;
362 }
363
364 return result;
365} 152}
366 153
367static int 154static inline int acpi_battery_mode(struct acpi_battery *battery)
368acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word)
369{ 155{
370 union sbs_rw_data data; 156 return (battery->mode & 0x8000);
371 int result = 0;
372
373 data.word = word;
374
375 result = acpi_ec_sbs_access(sbs, addr,
376 ACPI_SBS_SMBUS_WRITE, func,
377 ACPI_SBS_WORD_DATA, &data);
378 if (result) {
379 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
380 "acpi_ec_sbs_access() failed"));
381 }
382
383 return result;
384} 157}
385 158
386static int sbs_zombie(struct acpi_sbs *sbs) 159static inline int acpi_battery_scale(struct acpi_battery *battery)
387{ 160{
388 return (sbs->zombie); 161 return (acpi_battery_mode(battery) ? 10 : 1) *
162 acpi_battery_ipscale(battery);
389} 163}
390 164
391static int sbs_mutex_lock(struct acpi_sbs *sbs) 165static int sbs_get_ac_property(struct power_supply *psy,
166 enum power_supply_property psp,
167 union power_supply_propval *val)
392{ 168{
393 if (sbs_zombie(sbs)) { 169 struct acpi_sbs *sbs = to_acpi_sbs(psy);
394 return -ENODEV; 170 switch (psp) {
171 case POWER_SUPPLY_PROP_ONLINE:
172 val->intval = sbs->charger_present;
173 break;
174 default:
175 return -EINVAL;
395 } 176 }
396 mutex_lock(&sbs->mutex);
397 return 0; 177 return 0;
398} 178}
399 179
400static void sbs_mutex_unlock(struct acpi_sbs *sbs) 180static int acpi_battery_technology(struct acpi_battery *battery)
401{ 181{
402 mutex_unlock(&sbs->mutex); 182 if (!strcasecmp("NiCd", battery->device_chemistry))
183 return POWER_SUPPLY_TECHNOLOGY_NiCd;
184 if (!strcasecmp("NiMH", battery->device_chemistry))
185 return POWER_SUPPLY_TECHNOLOGY_NiMH;
186 if (!strcasecmp("LION", battery->device_chemistry))
187 return POWER_SUPPLY_TECHNOLOGY_LION;
188 if (!strcasecmp("LiP", battery->device_chemistry))
189 return POWER_SUPPLY_TECHNOLOGY_LIPO;
190 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
403} 191}
404 192
405/* -------------------------------------------------------------------------- 193static int acpi_sbs_battery_get_property(struct power_supply *psy,
406 Smart Battery System Management 194 enum power_supply_property psp,
407 -------------------------------------------------------------------------- */ 195 union power_supply_propval *val)
408
409static int acpi_check_update_proc(struct acpi_sbs *sbs)
410{ 196{
411 acpi_status status = AE_OK; 197 struct acpi_battery *battery = to_acpi_battery(psy);
412 198
413 if (update_time == 0) { 199 if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
414 sbs->update_proc_flg = 0; 200 return -ENODEV;
415 return 0; 201 switch (psp) {
416 } 202 case POWER_SUPPLY_PROP_STATUS:
417 if (sbs->update_proc_flg == 0) { 203 if (battery->current_now < 0)
418 status = acpi_os_execute(OSL_GPE_HANDLER, 204 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
419 acpi_sbs_update_time, sbs); 205 else if (battery->current_now > 0)
420 if (status != AE_OK) { 206 val->intval = POWER_SUPPLY_STATUS_CHARGING;
421 ACPI_EXCEPTION((AE_INFO, status, 207 else
422 "acpi_os_execute() failed")); 208 val->intval = POWER_SUPPLY_STATUS_FULL;
423 return 1; 209 break;
424 } 210 case POWER_SUPPLY_PROP_PRESENT:
425 sbs->update_proc_flg = 1; 211 val->intval = battery->present;
212 break;
213 case POWER_SUPPLY_PROP_TECHNOLOGY:
214 val->intval = acpi_battery_technology(battery);
215 break;
216 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
217 val->intval = battery->design_voltage *
218 acpi_battery_vscale(battery) * 1000;
219 break;
220 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
221 val->intval = battery->voltage_now *
222 acpi_battery_vscale(battery) * 1000;
223 break;
224 case POWER_SUPPLY_PROP_CURRENT_NOW:
225 val->intval = abs(battery->current_now) *
226 acpi_battery_ipscale(battery) * 1000;
227 break;
228 case POWER_SUPPLY_PROP_CURRENT_AVG:
229 val->intval = abs(battery->current_avg) *
230 acpi_battery_ipscale(battery) * 1000;
231 break;
232 case POWER_SUPPLY_PROP_CAPACITY:
233 val->intval = battery->state_of_charge;
234 break;
235 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
236 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
237 val->intval = battery->design_capacity *
238 acpi_battery_scale(battery) * 1000;
239 break;
240 case POWER_SUPPLY_PROP_CHARGE_FULL:
241 case POWER_SUPPLY_PROP_ENERGY_FULL:
242 val->intval = battery->full_charge_capacity *
243 acpi_battery_scale(battery) * 1000;
244 break;
245 case POWER_SUPPLY_PROP_CHARGE_NOW:
246 case POWER_SUPPLY_PROP_ENERGY_NOW:
247 val->intval = battery->capacity_now *
248 acpi_battery_scale(battery) * 1000;
249 break;
250 case POWER_SUPPLY_PROP_TEMP:
251 val->intval = battery->temp_now - 2730; // dK -> dC
252 break;
253 case POWER_SUPPLY_PROP_MODEL_NAME:
254 val->strval = battery->device_name;
255 break;
256 case POWER_SUPPLY_PROP_MANUFACTURER:
257 val->strval = battery->manufacturer_name;
258 break;
259 default:
260 return -EINVAL;
426 } 261 }
427 return 0; 262 return 0;
428} 263}
429 264
430static int acpi_sbs_generate_event(struct acpi_device *device, 265static enum power_supply_property sbs_ac_props[] = {
431 int event, int state, char *bid, char *class) 266 POWER_SUPPLY_PROP_ONLINE,
432{ 267};
433 char bid_saved[5];
434 char class_saved[20];
435 int result = 0;
436
437 strcpy(bid_saved, acpi_device_bid(device));
438 strcpy(class_saved, acpi_device_class(device));
439
440 strcpy(acpi_device_bid(device), bid);
441 strcpy(acpi_device_class(device), class);
442
443 result = acpi_bus_generate_proc_event(device, event, state);
444
445 strcpy(acpi_device_bid(device), bid_saved);
446 strcpy(acpi_device_class(device), class_saved);
447
448 acpi_bus_generate_netlink_event(class, bid, event, state);
449 return result;
450}
451
452static int acpi_battery_get_present(struct acpi_battery *battery)
453{
454 s16 state;
455 int result = 0;
456 int is_present = 0;
457
458 result = acpi_sbs_read_word(battery->sbs,
459 ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
460 if (result) {
461 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
462 "acpi_sbs_read_word() failed"));
463 }
464 if (!result) {
465 is_present = (state & 0x000f) & (1 << battery->id);
466 }
467 battery->battery_present = is_present;
468
469 return result;
470}
471 268
472static int acpi_battery_select(struct acpi_battery *battery) 269static enum power_supply_property sbs_charge_battery_props[] = {
473{ 270 POWER_SUPPLY_PROP_STATUS,
474 struct acpi_sbs *sbs = battery->sbs; 271 POWER_SUPPLY_PROP_PRESENT,
475 int result = 0; 272 POWER_SUPPLY_PROP_TECHNOLOGY,
476 s16 state; 273 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
477 int foo; 274 POWER_SUPPLY_PROP_VOLTAGE_NOW,
275 POWER_SUPPLY_PROP_CURRENT_NOW,
276 POWER_SUPPLY_PROP_CURRENT_AVG,
277 POWER_SUPPLY_PROP_CAPACITY,
278 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
279 POWER_SUPPLY_PROP_CHARGE_FULL,
280 POWER_SUPPLY_PROP_CHARGE_NOW,
281 POWER_SUPPLY_PROP_TEMP,
282 POWER_SUPPLY_PROP_MODEL_NAME,
283 POWER_SUPPLY_PROP_MANUFACTURER,
284};
478 285
479 if (sbs->sbsm_present) { 286static enum power_supply_property sbs_energy_battery_props[] = {
287 POWER_SUPPLY_PROP_STATUS,
288 POWER_SUPPLY_PROP_PRESENT,
289 POWER_SUPPLY_PROP_TECHNOLOGY,
290 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
291 POWER_SUPPLY_PROP_VOLTAGE_NOW,
292 POWER_SUPPLY_PROP_CURRENT_NOW,
293 POWER_SUPPLY_PROP_CURRENT_AVG,
294 POWER_SUPPLY_PROP_CAPACITY,
295 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
296 POWER_SUPPLY_PROP_ENERGY_FULL,
297 POWER_SUPPLY_PROP_ENERGY_NOW,
298 POWER_SUPPLY_PROP_TEMP,
299 POWER_SUPPLY_PROP_MODEL_NAME,
300 POWER_SUPPLY_PROP_MANUFACTURER,
301};
480 302
481 /* Take special care not to knobble other nibbles of 303/* --------------------------------------------------------------------------
482 * state (aka selector_state), since 304 Smart Battery System Management
483 * it causes charging to halt on SBSELs */ 305 -------------------------------------------------------------------------- */
484 306
485 result = 307struct acpi_battery_reader {
486 acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state); 308 u8 command; /* command for battery */
487 if (result) { 309 u8 mode; /* word or block? */
488 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 310 size_t offset; /* offset inside struct acpi_sbs_battery */
489 "acpi_sbs_read_word() failed")); 311};
490 goto end;
491 }
492 312
493 foo = (state & 0x0fff) | (1 << (battery->id + 12)); 313static struct acpi_battery_reader info_readers[] = {
494 result = 314 {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
495 acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo); 315 {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
496 if (result) { 316 {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
497 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 317 {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
498 "acpi_sbs_write_word() failed")); 318 {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
499 goto end; 319 {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
500 } 320 {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
501 } 321 {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
322 {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
323 {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
324 {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
325};
502 326
503 end: 327static struct acpi_battery_reader state_readers[] = {
504 return result; 328 {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
505} 329 {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
330 {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)},
331 {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)},
332 {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
333 {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
334 {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
335};
506 336
507static int acpi_sbsm_get_info(struct acpi_sbs *sbs) 337static int acpi_manager_get_info(struct acpi_sbs *sbs)
508{ 338{
509 int result = 0; 339 int result = 0;
510 s16 battery_system_info; 340 u16 battery_system_info;
511
512 result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04,
513 &battery_system_info);
514 if (result) {
515 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
516 "acpi_sbs_read_word() failed"));
517 goto end;
518 }
519 sbs->sbsm_present = 1;
520 sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
521
522 end:
523 341
342 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
343 0x04, (u8 *)&battery_system_info);
344 if (!result)
345 sbs->batteries_supported = battery_system_info & 0x000f;
524 return result; 346 return result;
525} 347}
526 348
527static int acpi_battery_get_info(struct acpi_battery *battery) 349static int acpi_battery_get_info(struct acpi_battery *battery)
528{ 350{
529 struct acpi_sbs *sbs = battery->sbs; 351 int i, result = 0;
530 int result = 0; 352
531 s16 battery_mode; 353 for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
532 s16 specification_info; 354 result = acpi_smbus_read(battery->sbs->hc,
533 355 info_readers[i].mode,
534 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03, 356 ACPI_SBS_BATTERY,
535 &battery_mode); 357 info_readers[i].command,
536 if (result) { 358 (u8 *) battery +
537 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 359 info_readers[i].offset);
538 "acpi_sbs_read_word() failed")); 360 if (result)
539 goto end; 361 break;
540 }
541 battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
542
543 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10,
544 &battery->info.full_charge_capacity);
545 if (result) {
546 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
547 "acpi_sbs_read_word() failed"));
548 goto end;
549 }
550
551 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18,
552 &battery->info.design_capacity);
553
554 if (result) {
555 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
556 "acpi_sbs_read_word() failed"));
557 goto end;
558 }
559
560 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19,
561 &battery->info.design_voltage);
562 if (result) {
563 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
564 "acpi_sbs_read_word() failed"));
565 goto end;
566 } 362 }
567
568 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a,
569 &specification_info);
570 if (result) {
571 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
572 "acpi_sbs_read_word() failed"));
573 goto end;
574 }
575
576 switch ((specification_info & 0x0f00) >> 8) {
577 case 1:
578 battery->info.vscale = 10;
579 break;
580 case 2:
581 battery->info.vscale = 100;
582 break;
583 case 3:
584 battery->info.vscale = 1000;
585 break;
586 default:
587 battery->info.vscale = 1;
588 }
589
590 switch ((specification_info & 0xf000) >> 12) {
591 case 1:
592 battery->info.ipscale = 10;
593 break;
594 case 2:
595 battery->info.ipscale = 100;
596 break;
597 case 3:
598 battery->info.ipscale = 1000;
599 break;
600 default:
601 battery->info.ipscale = 1;
602 }
603
604 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c,
605 &battery->info.serial_number);
606 if (result) {
607 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
608 "acpi_sbs_read_word() failed"));
609 goto end;
610 }
611
612 result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20,
613 battery->info.manufacturer_name);
614 if (result) {
615 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
616 "acpi_sbs_read_str() failed"));
617 goto end;
618 }
619
620 result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21,
621 battery->info.device_name);
622 if (result) {
623 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
624 "acpi_sbs_read_str() failed"));
625 goto end;
626 }
627
628 result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22,
629 battery->info.device_chemistry);
630 if (result) {
631 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
632 "acpi_sbs_read_str() failed"));
633 goto end;
634 }
635
636 end:
637 return result; 363 return result;
638} 364}
639 365
640static int acpi_battery_get_state(struct acpi_battery *battery) 366static int acpi_battery_get_state(struct acpi_battery *battery)
641{ 367{
642 struct acpi_sbs *sbs = battery->sbs; 368 int i, result = 0;
643 int result = 0;
644 369
645 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09, 370 if (battery->update_time &&
646 &battery->state.voltage); 371 time_before(jiffies, battery->update_time +
647 if (result) { 372 msecs_to_jiffies(cache_time)))
648 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 373 return 0;
649 "acpi_sbs_read_word() failed")); 374 for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
650 goto end; 375 result = acpi_smbus_read(battery->sbs->hc,
651 } 376 state_readers[i].mode,
652 377 ACPI_SBS_BATTERY,
653 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a, 378 state_readers[i].command,
654 &battery->state.amperage); 379 (u8 *)battery +
655 if (result) { 380 state_readers[i].offset);
656 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 381 if (result)
657 "acpi_sbs_read_word() failed")); 382 goto end;
658 goto end;
659 }
660
661 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f,
662 &battery->state.remaining_capacity);
663 if (result) {
664 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
665 "acpi_sbs_read_word() failed"));
666 goto end;
667 }
668
669 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16,
670 &battery->state.battery_state);
671 if (result) {
672 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
673 "acpi_sbs_read_word() failed"));
674 goto end;
675 } 383 }
676
677 end: 384 end:
385 battery->update_time = jiffies;
678 return result; 386 return result;
679} 387}
680 388
681static int acpi_battery_get_alarm(struct acpi_battery *battery) 389static int acpi_battery_get_alarm(struct acpi_battery *battery)
682{ 390{
683 struct acpi_sbs *sbs = battery->sbs; 391 return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
684 int result = 0; 392 ACPI_SBS_BATTERY, 0x01,
685 393 (u8 *)&battery->alarm_capacity);
686 result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
687 &battery->alarm.remaining_capacity);
688 if (result) {
689 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
690 "acpi_sbs_read_word() failed"));
691 goto end;
692 }
693
694 end:
695
696 return result;
697} 394}
698 395
699static int acpi_battery_set_alarm(struct acpi_battery *battery, 396static int acpi_battery_set_alarm(struct acpi_battery *battery)
700 unsigned long alarm)
701{ 397{
702 struct acpi_sbs *sbs = battery->sbs; 398 struct acpi_sbs *sbs = battery->sbs;
703 int result = 0; 399 u16 value, sel = 1 << (battery->id + 12);
704 s16 battery_mode;
705 int foo;
706 400
707 result = acpi_battery_select(battery); 401 int ret;
708 if (result) {
709 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
710 "acpi_battery_select() failed"));
711 goto end;
712 }
713 402
714 /* If necessary, enable the alarm */
715 403
716 if (alarm > 0) { 404 if (sbs->manager_present) {
717 result = 405 ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
718 acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03, 406 0x01, (u8 *)&value);
719 &battery_mode); 407 if (ret)
720 if (result) {
721 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
722 "acpi_sbs_read_word() failed"));
723 goto end; 408 goto end;
724 } 409 if ((value & 0xf000) != sel) {
725 410 value &= 0x0fff;
726 result = 411 value |= sel;
727 acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, 412 ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
728 battery_mode & 0xbfff); 413 ACPI_SBS_MANAGER,
729 if (result) { 414 0x01, (u8 *)&value, 2);
730 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 415 if (ret)
731 "acpi_sbs_write_word() failed"));
732 goto end; 416 goto end;
733 } 417 }
734 } 418 }
735 419 ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
736 foo = alarm / (battery->info.capacity_mode ? 10 : 1); 420 0x01, (u8 *)&battery->alarm_capacity, 2);
737 result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo);
738 if (result) {
739 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
740 "acpi_sbs_write_word() failed"));
741 goto end;
742 }
743
744 end: 421 end:
745 422 return ret;
746 return result;
747} 423}
748 424
749static int acpi_battery_set_mode(struct acpi_battery *battery) 425static int acpi_ac_get_present(struct acpi_sbs *sbs)
750{ 426{
751 struct acpi_sbs *sbs = battery->sbs; 427 int result;
752 int result = 0; 428 u16 status;
753 s16 battery_mode;
754
755 if (capacity_mode == DEF_CAPACITY_UNIT) {
756 goto end;
757 }
758
759 result = acpi_sbs_read_word(sbs,
760 ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
761 if (result) {
762 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
763 "acpi_sbs_read_word() failed"));
764 goto end;
765 }
766
767 if (capacity_mode == MAH_CAPACITY_UNIT) {
768 battery_mode &= 0x7fff;
769 } else {
770 battery_mode |= 0x8000;
771 }
772 result = acpi_sbs_write_word(sbs,
773 ACPI_SB_SMBUS_ADDR, 0x03, battery_mode);
774 if (result) {
775 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
776 "acpi_sbs_write_word() failed"));
777 goto end;
778 }
779
780 result = acpi_sbs_read_word(sbs,
781 ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
782 if (result) {
783 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
784 "acpi_sbs_read_word() failed"));
785 goto end;
786 }
787 429
788 end: 430 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
431 0x13, (u8 *) & status);
432 if (!result)
433 sbs->charger_present = (status >> 15) & 0x1;
789 return result; 434 return result;
790} 435}
791 436
792static int acpi_battery_init(struct acpi_battery *battery) 437static ssize_t acpi_battery_alarm_show(struct device *dev,
438 struct device_attribute *attr,
439 char *buf)
793{ 440{
794 int result = 0; 441 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
795 442 acpi_battery_get_alarm(battery);
796 result = acpi_battery_select(battery); 443 return sprintf(buf, "%d\n", battery->alarm_capacity *
797 if (result) { 444 acpi_battery_scale(battery) * 1000);
798 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
799 "acpi_battery_select() failed"));
800 goto end;
801 }
802
803 result = acpi_battery_set_mode(battery);
804 if (result) {
805 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
806 "acpi_battery_set_mode() failed"));
807 goto end;
808 }
809
810 result = acpi_battery_get_info(battery);
811 if (result) {
812 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
813 "acpi_battery_get_info() failed"));
814 goto end;
815 }
816
817 result = acpi_battery_get_state(battery);
818 if (result) {
819 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
820 "acpi_battery_get_state() failed"));
821 goto end;
822 }
823
824 result = acpi_battery_get_alarm(battery);
825 if (result) {
826 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
827 "acpi_battery_get_alarm() failed"));
828 goto end;
829 }
830
831 end:
832 return result;
833} 445}
834 446
835static int acpi_ac_get_present(struct acpi_sbs *sbs) 447static ssize_t acpi_battery_alarm_store(struct device *dev,
448 struct device_attribute *attr,
449 const char *buf, size_t count)
836{ 450{
837 int result = 0; 451 unsigned long x;
838 s16 charger_status; 452 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
839 453 if (sscanf(buf, "%ld\n", &x) == 1)
840 result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13, 454 battery->alarm_capacity = x /
841 &charger_status); 455 (1000 * acpi_battery_scale(battery));
842 456 if (battery->present)
843 if (result) { 457 acpi_battery_set_alarm(battery);
844 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 458 return count;
845 "acpi_sbs_read_word() failed"));
846 goto end;
847 }
848
849 sbs->ac.ac_present = (charger_status & 0x8000) >> 15;
850
851 end:
852
853 return result;
854} 459}
855 460
461static struct device_attribute alarm_attr = {
462 .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
463 .show = acpi_battery_alarm_show,
464 .store = acpi_battery_alarm_store,
465};
466
856/* -------------------------------------------------------------------------- 467/* --------------------------------------------------------------------------
857 FS Interface (/proc/acpi) 468 FS Interface (/proc/acpi)
858 -------------------------------------------------------------------------- */ 469 -------------------------------------------------------------------------- */
859 470
471#ifdef CONFIG_ACPI_PROCFS
860/* Generic Routines */ 472/* Generic Routines */
861
862static int 473static int
863acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, 474acpi_sbs_add_fs(struct proc_dir_entry **dir,
864 struct proc_dir_entry *parent_dir, 475 struct proc_dir_entry *parent_dir,
865 char *dir_name, 476 char *dir_name,
866 struct file_operations *info_fops, 477 struct file_operations *info_fops,
867 struct file_operations *state_fops, 478 struct file_operations *state_fops,
868 struct file_operations *alarm_fops, void *data) 479 struct file_operations *alarm_fops, void *data)
869{ 480{
870 struct proc_dir_entry *entry = NULL; 481 struct proc_dir_entry *entry = NULL;
871 482
872 if (!*dir) { 483 if (!*dir) {
873 *dir = proc_mkdir(dir_name, parent_dir); 484 *dir = proc_mkdir(dir_name, parent_dir);
874 if (!*dir) { 485 if (!*dir) {
875 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
876 "proc_mkdir() failed"));
877 return -ENODEV; 486 return -ENODEV;
878 } 487 }
879 (*dir)->owner = THIS_MODULE; 488 (*dir)->owner = THIS_MODULE;
@@ -882,10 +491,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
882 /* 'info' [R] */ 491 /* 'info' [R] */
883 if (info_fops) { 492 if (info_fops) {
884 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); 493 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
885 if (!entry) { 494 if (entry) {
886 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
887 "create_proc_entry() failed"));
888 } else {
889 entry->proc_fops = info_fops; 495 entry->proc_fops = info_fops;
890 entry->data = data; 496 entry->data = data;
891 entry->owner = THIS_MODULE; 497 entry->owner = THIS_MODULE;
@@ -895,10 +501,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
895 /* 'state' [R] */ 501 /* 'state' [R] */
896 if (state_fops) { 502 if (state_fops) {
897 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); 503 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
898 if (!entry) { 504 if (entry) {
899 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
900 "create_proc_entry() failed"));
901 } else {
902 entry->proc_fops = state_fops; 505 entry->proc_fops = state_fops;
903 entry->data = data; 506 entry->data = data;
904 entry->owner = THIS_MODULE; 507 entry->owner = THIS_MODULE;
@@ -908,24 +511,19 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
908 /* 'alarm' [R/W] */ 511 /* 'alarm' [R/W] */
909 if (alarm_fops) { 512 if (alarm_fops) {
910 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); 513 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
911 if (!entry) { 514 if (entry) {
912 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
913 "create_proc_entry() failed"));
914 } else {
915 entry->proc_fops = alarm_fops; 515 entry->proc_fops = alarm_fops;
916 entry->data = data; 516 entry->data = data;
917 entry->owner = THIS_MODULE; 517 entry->owner = THIS_MODULE;
918 } 518 }
919 } 519 }
920
921 return 0; 520 return 0;
922} 521}
923 522
924static void 523static void
925acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, 524acpi_sbs_remove_fs(struct proc_dir_entry **dir,
926 struct proc_dir_entry *parent_dir) 525 struct proc_dir_entry *parent_dir)
927{ 526{
928
929 if (*dir) { 527 if (*dir) {
930 remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); 528 remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
931 remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); 529 remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
@@ -933,82 +531,52 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
933 remove_proc_entry((*dir)->name, parent_dir); 531 remove_proc_entry((*dir)->name, parent_dir);
934 *dir = NULL; 532 *dir = NULL;
935 } 533 }
936
937} 534}
938 535
939/* Smart Battery Interface */ 536/* Smart Battery Interface */
940
941static struct proc_dir_entry *acpi_battery_dir = NULL; 537static struct proc_dir_entry *acpi_battery_dir = NULL;
942 538
539static inline char *acpi_battery_units(struct acpi_battery *battery)
540{
541 return acpi_battery_mode(battery) ? " mWh" : " mAh";
542}
543
544
943static int acpi_battery_read_info(struct seq_file *seq, void *offset) 545static int acpi_battery_read_info(struct seq_file *seq, void *offset)
944{ 546{
945 struct acpi_battery *battery = seq->private; 547 struct acpi_battery *battery = seq->private;
946 struct acpi_sbs *sbs = battery->sbs; 548 struct acpi_sbs *sbs = battery->sbs;
947 int cscale;
948 int result = 0; 549 int result = 0;
949 550
950 if (sbs_mutex_lock(sbs)) { 551 mutex_lock(&sbs->lock);
951 return -ENODEV;
952 }
953
954 result = acpi_check_update_proc(sbs);
955 if (result)
956 goto end;
957
958 if (update_time == 0) {
959 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO);
960 if (result) {
961 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
962 "acpi_sbs_update_run() failed"));
963 }
964 }
965 552
966 if (battery->battery_present) { 553 seq_printf(seq, "present: %s\n",
967 seq_printf(seq, "present: yes\n"); 554 (battery->present) ? "yes" : "no");
968 } else { 555 if (!battery->present)
969 seq_printf(seq, "present: no\n");
970 goto end; 556 goto end;
971 }
972 557
973 if (battery->info.capacity_mode) {
974 cscale = battery->info.vscale * battery->info.ipscale;
975 } else {
976 cscale = battery->info.ipscale;
977 }
978 seq_printf(seq, "design capacity: %i%s\n", 558 seq_printf(seq, "design capacity: %i%s\n",
979 battery->info.design_capacity * cscale, 559 battery->design_capacity * acpi_battery_scale(battery),
980 battery->info.capacity_mode ? "0 mWh" : " mAh"); 560 acpi_battery_units(battery));
981
982 seq_printf(seq, "last full capacity: %i%s\n", 561 seq_printf(seq, "last full capacity: %i%s\n",
983 battery->info.full_charge_capacity * cscale, 562 battery->full_charge_capacity * acpi_battery_scale(battery),
984 battery->info.capacity_mode ? "0 mWh" : " mAh"); 563 acpi_battery_units(battery));
985
986 seq_printf(seq, "battery technology: rechargeable\n"); 564 seq_printf(seq, "battery technology: rechargeable\n");
987
988 seq_printf(seq, "design voltage: %i mV\n", 565 seq_printf(seq, "design voltage: %i mV\n",
989 battery->info.design_voltage * battery->info.vscale); 566 battery->design_voltage * acpi_battery_vscale(battery));
990
991 seq_printf(seq, "design capacity warning: unknown\n"); 567 seq_printf(seq, "design capacity warning: unknown\n");
992 seq_printf(seq, "design capacity low: unknown\n"); 568 seq_printf(seq, "design capacity low: unknown\n");
993 seq_printf(seq, "capacity granularity 1: unknown\n"); 569 seq_printf(seq, "capacity granularity 1: unknown\n");
994 seq_printf(seq, "capacity granularity 2: unknown\n"); 570 seq_printf(seq, "capacity granularity 2: unknown\n");
995 571 seq_printf(seq, "model number: %s\n", battery->device_name);
996 seq_printf(seq, "model number: %s\n",
997 battery->info.device_name);
998
999 seq_printf(seq, "serial number: %i\n", 572 seq_printf(seq, "serial number: %i\n",
1000 battery->info.serial_number); 573 battery->serial_number);
1001
1002 seq_printf(seq, "battery type: %s\n", 574 seq_printf(seq, "battery type: %s\n",
1003 battery->info.device_chemistry); 575 battery->device_chemistry);
1004
1005 seq_printf(seq, "OEM info: %s\n", 576 seq_printf(seq, "OEM info: %s\n",
1006 battery->info.manufacturer_name); 577 battery->manufacturer_name);
1007
1008 end: 578 end:
1009 579 mutex_unlock(&sbs->lock);
1010 sbs_mutex_unlock(sbs);
1011
1012 return result; 580 return result;
1013} 581}
1014 582
@@ -1022,73 +590,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
1022 struct acpi_battery *battery = seq->private; 590 struct acpi_battery *battery = seq->private;
1023 struct acpi_sbs *sbs = battery->sbs; 591 struct acpi_sbs *sbs = battery->sbs;
1024 int result = 0; 592 int result = 0;
1025 int cscale;
1026 int foo;
1027
1028 if (sbs_mutex_lock(sbs)) {
1029 return -ENODEV;
1030 }
1031 593
1032 result = acpi_check_update_proc(sbs); 594 mutex_lock(&sbs->lock);
1033 if (result) 595 seq_printf(seq, "present: %s\n",
596 (battery->present) ? "yes" : "no");
597 if (!battery->present)
1034 goto end; 598 goto end;
1035 599
1036 if (update_time == 0) { 600 acpi_battery_get_state(battery);
1037 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE); 601 seq_printf(seq, "capacity state: %s\n",
1038 if (result) { 602 (battery->state & 0x0010) ? "critical" : "ok");
1039 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 603 seq_printf(seq, "charging state: %s\n",
1040 "acpi_sbs_update_run() failed")); 604 (battery->current_now < 0) ? "discharging" :
1041 } 605 ((battery->current_now > 0) ? "charging" : "charged"));
1042 } 606 seq_printf(seq, "present rate: %d mA\n",
1043 607 abs(battery->current_now) * acpi_battery_ipscale(battery));
1044 if (battery->battery_present) {
1045 seq_printf(seq, "present: yes\n");
1046 } else {
1047 seq_printf(seq, "present: no\n");
1048 goto end;
1049 }
1050
1051 if (battery->info.capacity_mode) {
1052 cscale = battery->info.vscale * battery->info.ipscale;
1053 } else {
1054 cscale = battery->info.ipscale;
1055 }
1056
1057 if (battery->state.battery_state & 0x0010) {
1058 seq_printf(seq, "capacity state: critical\n");
1059 } else {
1060 seq_printf(seq, "capacity state: ok\n");
1061 }
1062
1063 foo = (s16) battery->state.amperage * battery->info.ipscale;
1064 if (battery->info.capacity_mode) {
1065 foo = foo * battery->info.design_voltage / 1000;
1066 }
1067 if (battery->state.amperage < 0) {
1068 seq_printf(seq, "charging state: discharging\n");
1069 seq_printf(seq, "present rate: %d %s\n",
1070 -foo, battery->info.capacity_mode ? "mW" : "mA");
1071 } else if (battery->state.amperage > 0) {
1072 seq_printf(seq, "charging state: charging\n");
1073 seq_printf(seq, "present rate: %d %s\n",
1074 foo, battery->info.capacity_mode ? "mW" : "mA");
1075 } else {
1076 seq_printf(seq, "charging state: charged\n");
1077 seq_printf(seq, "present rate: 0 %s\n",
1078 battery->info.capacity_mode ? "mW" : "mA");
1079 }
1080
1081 seq_printf(seq, "remaining capacity: %i%s\n", 608 seq_printf(seq, "remaining capacity: %i%s\n",
1082 battery->state.remaining_capacity * cscale, 609 battery->capacity_now * acpi_battery_scale(battery),
1083 battery->info.capacity_mode ? "0 mWh" : " mAh"); 610 acpi_battery_units(battery));
1084
1085 seq_printf(seq, "present voltage: %i mV\n", 611 seq_printf(seq, "present voltage: %i mV\n",
1086 battery->state.voltage * battery->info.vscale); 612 battery->voltage_now * acpi_battery_vscale(battery));
1087 613
1088 end: 614 end:
1089 615 mutex_unlock(&sbs->lock);
1090 sbs_mutex_unlock(sbs);
1091
1092 return result; 616 return result;
1093} 617}
1094 618
@@ -1102,48 +626,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
1102 struct acpi_battery *battery = seq->private; 626 struct acpi_battery *battery = seq->private;
1103 struct acpi_sbs *sbs = battery->sbs; 627 struct acpi_sbs *sbs = battery->sbs;
1104 int result = 0; 628 int result = 0;
1105 int cscale;
1106
1107 if (sbs_mutex_lock(sbs)) {
1108 return -ENODEV;
1109 }
1110
1111 result = acpi_check_update_proc(sbs);
1112 if (result)
1113 goto end;
1114 629
1115 if (update_time == 0) { 630 mutex_lock(&sbs->lock);
1116 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM);
1117 if (result) {
1118 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1119 "acpi_sbs_update_run() failed"));
1120 }
1121 }
1122 631
1123 if (!battery->battery_present) { 632 if (!battery->present) {
1124 seq_printf(seq, "present: no\n"); 633 seq_printf(seq, "present: no\n");
1125 goto end; 634 goto end;
1126 } 635 }
1127 636
1128 if (battery->info.capacity_mode) { 637 acpi_battery_get_alarm(battery);
1129 cscale = battery->info.vscale * battery->info.ipscale;
1130 } else {
1131 cscale = battery->info.ipscale;
1132 }
1133
1134 seq_printf(seq, "alarm: "); 638 seq_printf(seq, "alarm: ");
1135 if (battery->alarm.remaining_capacity) { 639 if (battery->alarm_capacity)
1136 seq_printf(seq, "%i%s\n", 640 seq_printf(seq, "%i%s\n",
1137 battery->alarm.remaining_capacity * cscale, 641 battery->alarm_capacity *
1138 battery->info.capacity_mode ? "0 mWh" : " mAh"); 642 acpi_battery_scale(battery),
1139 } else { 643 acpi_battery_units(battery));
644 else
1140 seq_printf(seq, "disabled\n"); 645 seq_printf(seq, "disabled\n");
1141 }
1142
1143 end: 646 end:
1144 647 mutex_unlock(&sbs->lock);
1145 sbs_mutex_unlock(sbs);
1146
1147 return result; 648 return result;
1148} 649}
1149 650
@@ -1155,59 +656,29 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
1155 struct acpi_battery *battery = seq->private; 656 struct acpi_battery *battery = seq->private;
1156 struct acpi_sbs *sbs = battery->sbs; 657 struct acpi_sbs *sbs = battery->sbs;
1157 char alarm_string[12] = { '\0' }; 658 char alarm_string[12] = { '\0' };
1158 int result, old_alarm, new_alarm; 659 int result = 0;
1159 660 mutex_lock(&sbs->lock);
1160 if (sbs_mutex_lock(sbs)) { 661 if (!battery->present) {
1161 return -ENODEV;
1162 }
1163
1164 result = acpi_check_update_proc(sbs);
1165 if (result)
1166 goto end;
1167
1168 if (!battery->battery_present) {
1169 result = -ENODEV; 662 result = -ENODEV;
1170 goto end; 663 goto end;
1171 } 664 }
1172
1173 if (count > sizeof(alarm_string) - 1) { 665 if (count > sizeof(alarm_string) - 1) {
1174 result = -EINVAL; 666 result = -EINVAL;
1175 goto end; 667 goto end;
1176 } 668 }
1177
1178 if (copy_from_user(alarm_string, buffer, count)) { 669 if (copy_from_user(alarm_string, buffer, count)) {
1179 result = -EFAULT; 670 result = -EFAULT;
1180 goto end; 671 goto end;
1181 } 672 }
1182
1183 alarm_string[count] = 0; 673 alarm_string[count] = 0;
1184 674 battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
1185 old_alarm = battery->alarm.remaining_capacity; 675 acpi_battery_scale(battery);
1186 new_alarm = simple_strtoul(alarm_string, NULL, 0); 676 acpi_battery_set_alarm(battery);
1187
1188 result = acpi_battery_set_alarm(battery, new_alarm);
1189 if (result) {
1190 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1191 "acpi_battery_set_alarm() failed"));
1192 acpi_battery_set_alarm(battery, old_alarm);
1193 goto end;
1194 }
1195 result = acpi_battery_get_alarm(battery);
1196 if (result) {
1197 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1198 "acpi_battery_get_alarm() failed"));
1199 acpi_battery_set_alarm(battery, old_alarm);
1200 goto end;
1201 }
1202
1203 end: 677 end:
1204 sbs_mutex_unlock(sbs); 678 mutex_unlock(&sbs->lock);
1205 679 if (result)
1206 if (result) {
1207 return result; 680 return result;
1208 } else { 681 return count;
1209 return count;
1210 }
1211} 682}
1212 683
1213static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 684static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
@@ -1246,26 +717,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
1246 717
1247static int acpi_ac_read_state(struct seq_file *seq, void *offset) 718static int acpi_ac_read_state(struct seq_file *seq, void *offset)
1248{ 719{
1249 struct acpi_sbs *sbs = seq->private;
1250 int result;
1251 720
1252 if (sbs_mutex_lock(sbs)) { 721 struct acpi_sbs *sbs = seq->private;
1253 return -ENODEV;
1254 }
1255 722
1256 if (update_time == 0) { 723 mutex_lock(&sbs->lock);
1257 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE);
1258 if (result) {
1259 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1260 "acpi_sbs_update_run() failed"));
1261 }
1262 }
1263 724
1264 seq_printf(seq, "state: %s\n", 725 seq_printf(seq, "state: %s\n",
1265 sbs->ac.ac_present ? "on-line" : "off-line"); 726 sbs->charger_present ? "on-line" : "off-line");
1266
1267 sbs_mutex_unlock(sbs);
1268 727
728 mutex_unlock(&sbs->lock);
1269 return 0; 729 return 0;
1270} 730}
1271 731
@@ -1282,429 +742,203 @@ static struct file_operations acpi_ac_state_fops = {
1282 .owner = THIS_MODULE, 742 .owner = THIS_MODULE,
1283}; 743};
1284 744
745#endif
746
1285/* -------------------------------------------------------------------------- 747/* --------------------------------------------------------------------------
1286 Driver Interface 748 Driver Interface
1287 -------------------------------------------------------------------------- */ 749 -------------------------------------------------------------------------- */
750static int acpi_battery_read(struct acpi_battery *battery)
751{
752 int result = 0, saved_present = battery->present;
753 u16 state;
754
755 if (battery->sbs->manager_present) {
756 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
757 ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
758 if (!result)
759 battery->present = state & (1 << battery->id);
760 state &= 0x0fff;
761 state |= 1 << (battery->id + 12);
762 acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
763 ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
764 } else if (battery->id == 0)
765 battery->present = 1;
766 if (result || !battery->present)
767 return result;
1288 768
1289/* Smart Battery */ 769 if (saved_present != battery->present) {
770 battery->update_time = 0;
771 result = acpi_battery_get_info(battery);
772 if (result)
773 return result;
774 }
775 result = acpi_battery_get_state(battery);
776 return result;
777}
1290 778
779/* Smart Battery */
1291static int acpi_battery_add(struct acpi_sbs *sbs, int id) 780static int acpi_battery_add(struct acpi_sbs *sbs, int id)
1292{ 781{
1293 int is_present; 782 struct acpi_battery *battery = &sbs->battery[id];
1294 int result; 783 int result;
1295 char dir_name[32];
1296 struct acpi_battery *battery;
1297
1298 battery = &sbs->battery[id];
1299
1300 battery->alive = 0;
1301 784
1302 battery->init_state = 0;
1303 battery->id = id; 785 battery->id = id;
1304 battery->sbs = sbs; 786 battery->sbs = sbs;
787 result = acpi_battery_read(battery);
788 if (result)
789 return result;
1305 790
1306 result = acpi_battery_select(battery); 791 sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
1307 if (result) { 792#ifdef CONFIG_ACPI_PROCFS
1308 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 793 acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
1309 "acpi_battery_select() failed")); 794 battery->name, &acpi_battery_info_fops,
1310 goto end; 795 &acpi_battery_state_fops, &acpi_battery_alarm_fops,
1311 } 796 battery);
1312 797#endif
1313 result = acpi_battery_get_present(battery); 798 battery->bat.name = battery->name;
1314 if (result) { 799 battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
1315 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 800 if (!acpi_battery_mode(battery)) {
1316 "acpi_battery_get_present() failed")); 801 battery->bat.properties = sbs_charge_battery_props;
1317 goto end; 802 battery->bat.num_properties =
1318 } 803 ARRAY_SIZE(sbs_charge_battery_props);
1319 804 } else {
1320 is_present = battery->battery_present; 805 battery->bat.properties = sbs_energy_battery_props;
1321 806 battery->bat.num_properties =
1322 if (is_present) { 807 ARRAY_SIZE(sbs_energy_battery_props);
1323 result = acpi_battery_init(battery);
1324 if (result) {
1325 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1326 "acpi_battery_init() failed"));
1327 goto end;
1328 }
1329 battery->init_state = 1;
1330 }
1331
1332 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1333
1334 result = acpi_sbs_generic_add_fs(&battery->battery_entry,
1335 acpi_battery_dir,
1336 dir_name,
1337 &acpi_battery_info_fops,
1338 &acpi_battery_state_fops,
1339 &acpi_battery_alarm_fops, battery);
1340 if (result) {
1341 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1342 "acpi_sbs_generic_add_fs() failed"));
1343 goto end;
1344 } 808 }
1345 battery->alive = 1; 809 battery->bat.get_property = acpi_sbs_battery_get_property;
1346 810 result = power_supply_register(&sbs->device->dev, &battery->bat);
811 device_create_file(battery->bat.dev, &alarm_attr);
1347 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", 812 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
1348 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name, 813 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
1349 sbs->battery->battery_present ? "present" : "absent"); 814 battery->name, sbs->battery->present ? "present" : "absent");
1350
1351 end:
1352 return result; 815 return result;
1353} 816}
1354 817
1355static void acpi_battery_remove(struct acpi_sbs *sbs, int id) 818static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
1356{ 819{
1357 820 if (sbs->battery[id].bat.dev)
1358 if (sbs->battery[id].battery_entry) { 821 device_remove_file(sbs->battery[id].bat.dev, &alarm_attr);
1359 acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry), 822 power_supply_unregister(&sbs->battery[id].bat);
1360 acpi_battery_dir); 823#ifdef CONFIG_ACPI_PROCFS
1361 } 824 if (sbs->battery[id].proc_entry) {
825 acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
826 acpi_battery_dir);
827 }
828#endif
1362} 829}
1363 830
1364static int acpi_ac_add(struct acpi_sbs *sbs) 831static int acpi_charger_add(struct acpi_sbs *sbs)
1365{ 832{
1366 int result; 833 int result;
1367 834
1368 result = acpi_ac_get_present(sbs); 835 result = acpi_ac_get_present(sbs);
1369 if (result) { 836 if (result)
1370 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1371 "acpi_ac_get_present() failed"));
1372 goto end; 837 goto end;
1373 } 838#ifdef CONFIG_ACPI_PROCFS
1374 839 result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
1375 result = acpi_sbs_generic_add_fs(&sbs->ac_entry, 840 ACPI_AC_DIR_NAME, NULL,
1376 acpi_ac_dir, 841 &acpi_ac_state_fops, NULL, sbs);
1377 ACPI_AC_DIR_NAME, 842 if (result)
1378 NULL, &acpi_ac_state_fops, NULL, sbs);
1379 if (result) {
1380 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1381 "acpi_sbs_generic_add_fs() failed"));
1382 goto end; 843 goto end;
1383 } 844#endif
1384 845 sbs->charger.name = "sbs-charger";
846 sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
847 sbs->charger.properties = sbs_ac_props;
848 sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
849 sbs->charger.get_property = sbs_get_ac_property;
850 power_supply_register(&sbs->device->dev, &sbs->charger);
1385 printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", 851 printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
1386 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), 852 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
1387 ACPI_AC_DIR_NAME, sbs->ac.ac_present ? "on-line" : "off-line"); 853 ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
1388
1389 end: 854 end:
1390
1391 return result; 855 return result;
1392} 856}
1393 857
1394static void acpi_ac_remove(struct acpi_sbs *sbs) 858static void acpi_charger_remove(struct acpi_sbs *sbs)
1395{ 859{
1396 860 if (sbs->charger.dev)
1397 if (sbs->ac_entry) { 861 power_supply_unregister(&sbs->charger);
1398 acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir); 862#ifdef CONFIG_ACPI_PROCFS
1399 } 863 if (sbs->charger_entry)
864 acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
865#endif
1400} 866}
1401 867
1402static void acpi_sbs_update_time_run(unsigned long data) 868void acpi_sbs_callback(void *context)
1403{ 869{
1404 acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data); 870 int id;
1405} 871 struct acpi_sbs *sbs = context;
1406 872 struct acpi_battery *bat;
1407static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) 873 u8 saved_charger_state = sbs->charger_present;
1408{ 874 u8 saved_battery_state;
1409 struct acpi_battery *battery; 875 acpi_ac_get_present(sbs);
1410 int result = 0, cnt; 876 if (sbs->charger_present != saved_charger_state) {
1411 int old_ac_present = -1; 877#ifdef CONFIG_ACPI_PROC_EVENT
1412 int old_battery_present = -1; 878 acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
1413 int new_ac_present = -1; 879 ACPI_SBS_NOTIFY_STATUS,
1414 int new_battery_present = -1; 880 sbs->charger_present);
1415 int id_min = 0, id_max = MAX_SBS_BAT - 1; 881#endif
1416 char dir_name[32]; 882 kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
1417 int do_battery_init = 0, do_ac_init = 0; 883 }
1418 int old_remaining_capacity = 0; 884 if (sbs->manager_present) {
1419 int update_battery = 1; 885 for (id = 0; id < MAX_SBS_BAT; ++id) {
1420 int up_tm = update_time; 886 if (!(sbs->batteries_supported & (1 << id)))
1421 887 continue;
1422 if (sbs_zombie(sbs)) { 888 bat = &sbs->battery[id];
1423 goto end; 889 saved_battery_state = bat->present;
1424 } 890 acpi_battery_read(bat);
1425 891 if (saved_battery_state == bat->present)
1426 if (id >= 0) { 892 continue;
1427 id_min = id_max = id; 893#ifdef CONFIG_ACPI_PROC_EVENT
1428 } 894 acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
1429 895 bat->name,
1430 if (data_type == DATA_TYPE_COMMON && up_tm > 0) { 896 ACPI_SBS_NOTIFY_STATUS,
1431 cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); 897 bat->present);
1432 if (sbs->run_cnt % cnt != 0) { 898#endif
1433 update_battery = 0; 899 kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
1434 }
1435 }
1436
1437 sbs->run_cnt++;
1438
1439 old_ac_present = sbs->ac.ac_present;
1440
1441 result = acpi_ac_get_present(sbs);
1442 if (result) {
1443 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1444 "acpi_ac_get_present() failed"));
1445 }
1446
1447 new_ac_present = sbs->ac.ac_present;
1448
1449 do_ac_init = (old_ac_present != new_ac_present);
1450 if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) {
1451 do_ac_init = 1;
1452 }
1453
1454 if (do_ac_init) {
1455 result = acpi_sbs_generate_event(sbs->device,
1456 ACPI_SBS_AC_NOTIFY_STATUS,
1457 new_ac_present,
1458 ACPI_AC_DIR_NAME,
1459 ACPI_AC_CLASS);
1460 if (result) {
1461 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1462 "acpi_sbs_generate_event() failed"));
1463 }
1464 }
1465
1466 if (data_type == DATA_TYPE_COMMON) {
1467 if (!do_ac_init && !update_battery) {
1468 goto end;
1469 }
1470 }
1471
1472 if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) {
1473 goto end;
1474 }
1475
1476 for (id = id_min; id <= id_max; id++) {
1477 battery = &sbs->battery[id];
1478 if (battery->alive == 0) {
1479 continue;
1480 }
1481
1482 old_remaining_capacity = battery->state.remaining_capacity;
1483
1484 old_battery_present = battery->battery_present;
1485
1486 result = acpi_battery_select(battery);
1487 if (result) {
1488 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1489 "acpi_battery_select() failed"));
1490 }
1491
1492 result = acpi_battery_get_present(battery);
1493 if (result) {
1494 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1495 "acpi_battery_get_present() failed"));
1496 }
1497
1498 new_battery_present = battery->battery_present;
1499
1500 do_battery_init = ((old_battery_present != new_battery_present)
1501 && new_battery_present);
1502 if (!new_battery_present)
1503 goto event;
1504 if (do_ac_init || do_battery_init) {
1505 result = acpi_battery_init(battery);
1506 if (result) {
1507 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1508 "acpi_battery_init() "
1509 "failed"));
1510 }
1511 }
1512 if (sbs_zombie(sbs)) {
1513 goto end;
1514 }
1515
1516 if ((data_type == DATA_TYPE_COMMON
1517 || data_type == DATA_TYPE_INFO)
1518 && new_battery_present) {
1519 result = acpi_battery_get_info(battery);
1520 if (result) {
1521 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1522 "acpi_battery_get_info() failed"));
1523 }
1524 }
1525 if (data_type == DATA_TYPE_INFO) {
1526 continue;
1527 }
1528 if (sbs_zombie(sbs)) {
1529 goto end;
1530 }
1531
1532 if ((data_type == DATA_TYPE_COMMON
1533 || data_type == DATA_TYPE_STATE)
1534 && new_battery_present) {
1535 result = acpi_battery_get_state(battery);
1536 if (result) {
1537 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1538 "acpi_battery_get_state() failed"));
1539 }
1540 }
1541 if (data_type == DATA_TYPE_STATE) {
1542 goto event;
1543 }
1544 if (sbs_zombie(sbs)) {
1545 goto end;
1546 }
1547
1548 if ((data_type == DATA_TYPE_COMMON
1549 || data_type == DATA_TYPE_ALARM)
1550 && new_battery_present) {
1551 result = acpi_battery_get_alarm(battery);
1552 if (result) {
1553 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1554 "acpi_battery_get_alarm() "
1555 "failed"));
1556 }
1557 }
1558 if (data_type == DATA_TYPE_ALARM) {
1559 continue;
1560 }
1561 if (sbs_zombie(sbs)) {
1562 goto end;
1563 }
1564
1565 event:
1566
1567 if (old_battery_present != new_battery_present || do_ac_init ||
1568 old_remaining_capacity !=
1569 battery->state.remaining_capacity) {
1570 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1571 result = acpi_sbs_generate_event(sbs->device,
1572 ACPI_SBS_BATTERY_NOTIFY_STATUS,
1573 new_battery_present,
1574 dir_name,
1575 ACPI_BATTERY_CLASS);
1576 if (result) {
1577 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1578 "acpi_sbs_generate_event() "
1579 "failed"));
1580 }
1581 } 900 }
1582 } 901 }
1583
1584 end:
1585
1586 return result;
1587} 902}
1588 903
1589static void acpi_sbs_update_time(void *data) 904static int acpi_sbs_remove(struct acpi_device *device, int type);
1590{
1591 struct acpi_sbs *sbs = data;
1592 unsigned long delay = -1;
1593 int result;
1594 unsigned int up_tm = update_time;
1595
1596 if (sbs_mutex_lock(sbs))
1597 return;
1598
1599 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON);
1600 if (result) {
1601 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1602 "acpi_sbs_update_run() failed"));
1603 }
1604
1605 if (sbs_zombie(sbs)) {
1606 goto end;
1607 }
1608
1609 if (!up_tm) {
1610 if (timer_pending(&sbs->update_timer))
1611 del_timer(&sbs->update_timer);
1612 } else {
1613 delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1614 delay = jiffies + HZ * delay;
1615 if (timer_pending(&sbs->update_timer)) {
1616 mod_timer(&sbs->update_timer, delay);
1617 } else {
1618 sbs->update_timer.data = (unsigned long)data;
1619 sbs->update_timer.function = acpi_sbs_update_time_run;
1620 sbs->update_timer.expires = delay;
1621 add_timer(&sbs->update_timer);
1622 }
1623 }
1624
1625 end:
1626
1627 sbs_mutex_unlock(sbs);
1628}
1629 905
1630static int acpi_sbs_add(struct acpi_device *device) 906static int acpi_sbs_add(struct acpi_device *device)
1631{ 907{
1632 struct acpi_sbs *sbs = NULL; 908 struct acpi_sbs *sbs;
1633 int result = 0, remove_result = 0; 909 int result = 0;
1634 int id; 910 int id;
1635 acpi_status status = AE_OK;
1636 unsigned long val;
1637
1638 status =
1639 acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
1640 if (ACPI_FAILURE(status)) {
1641 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC"));
1642 return -EIO;
1643 }
1644 911
1645 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); 912 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
1646 if (!sbs) { 913 if (!sbs) {
1647 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed"));
1648 result = -ENOMEM; 914 result = -ENOMEM;
1649 goto end; 915 goto end;
1650 } 916 }
1651 917
1652 mutex_init(&sbs->mutex); 918 mutex_init(&sbs->lock);
1653
1654 sbs_mutex_lock(sbs);
1655 919
1656 sbs->base = 0xff & (val >> 8); 920 sbs->hc = acpi_driver_data(device->parent);
1657 sbs->device = device; 921 sbs->device = device;
1658
1659 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); 922 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
1660 strcpy(acpi_device_class(device), ACPI_SBS_CLASS); 923 strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
1661 acpi_driver_data(device) = sbs; 924 acpi_driver_data(device) = sbs;
1662 925
1663 result = acpi_ac_add(sbs); 926 result = acpi_charger_add(sbs);
1664 if (result) {
1665 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
1666 goto end;
1667 }
1668
1669 acpi_sbsm_get_info(sbs);
1670
1671 if (!sbs->sbsm_present) {
1672 result = acpi_battery_add(sbs, 0);
1673 if (result) {
1674 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1675 "acpi_battery_add() failed"));
1676 goto end;
1677 }
1678 } else {
1679 for (id = 0; id < MAX_SBS_BAT; id++) {
1680 if ((sbs->sbsm_batteries_supported & (1 << id))) {
1681 result = acpi_battery_add(sbs, id);
1682 if (result) {
1683 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1684 "acpi_battery_add() failed"));
1685 goto end;
1686 }
1687 }
1688 }
1689 }
1690
1691 init_timer(&sbs->update_timer);
1692 result = acpi_check_update_proc(sbs);
1693 if (result) 927 if (result)
1694 goto end; 928 goto end;
1695 929
930 result = acpi_manager_get_info(sbs);
931 if (!result) {
932 sbs->manager_present = 1;
933 for (id = 0; id < MAX_SBS_BAT; ++id)
934 if ((sbs->batteries_supported & (1 << id)))
935 acpi_battery_add(sbs, id);
936 } else
937 acpi_battery_add(sbs, 0);
938 acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
1696 end: 939 end:
1697 940 if (result)
1698 sbs_mutex_unlock(sbs); 941 acpi_sbs_remove(device, 0);
1699
1700 if (result) {
1701 remove_result = acpi_sbs_remove(device, 0);
1702 if (remove_result) {
1703 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1704 "acpi_sbs_remove() failed"));
1705 }
1706 }
1707
1708 return result; 942 return result;
1709} 943}
1710 944
@@ -1713,39 +947,25 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
1713 struct acpi_sbs *sbs; 947 struct acpi_sbs *sbs;
1714 int id; 948 int id;
1715 949
1716 if (!device) { 950 if (!device)
1717 return -EINVAL; 951 return -EINVAL;
1718 }
1719
1720 sbs = acpi_driver_data(device); 952 sbs = acpi_driver_data(device);
1721 if (!sbs) { 953 if (!sbs)
1722 return -EINVAL; 954 return -EINVAL;
1723 } 955 mutex_lock(&sbs->lock);
1724 956 acpi_smbus_unregister_callback(sbs->hc);
1725 sbs_mutex_lock(sbs); 957 for (id = 0; id < MAX_SBS_BAT; ++id)
1726
1727 sbs->zombie = 1;
1728 del_timer_sync(&sbs->update_timer);
1729 acpi_os_wait_events_complete(NULL);
1730 del_timer_sync(&sbs->update_timer);
1731
1732 for (id = 0; id < MAX_SBS_BAT; id++) {
1733 acpi_battery_remove(sbs, id); 958 acpi_battery_remove(sbs, id);
1734 } 959 acpi_charger_remove(sbs);
1735 960 mutex_unlock(&sbs->lock);
1736 acpi_ac_remove(sbs); 961 mutex_destroy(&sbs->lock);
1737
1738 sbs_mutex_unlock(sbs);
1739
1740 mutex_destroy(&sbs->mutex);
1741
1742 kfree(sbs); 962 kfree(sbs);
1743
1744 return 0; 963 return 0;
1745} 964}
1746 965
1747static void acpi_sbs_rmdirs(void) 966static void acpi_sbs_rmdirs(void)
1748{ 967{
968#ifdef CONFIG_ACPI_PROCFS
1749 if (acpi_ac_dir) { 969 if (acpi_ac_dir) {
1750 acpi_unlock_ac_dir(acpi_ac_dir); 970 acpi_unlock_ac_dir(acpi_ac_dir);
1751 acpi_ac_dir = NULL; 971 acpi_ac_dir = NULL;
@@ -1754,69 +974,58 @@ static void acpi_sbs_rmdirs(void)
1754 acpi_unlock_battery_dir(acpi_battery_dir); 974 acpi_unlock_battery_dir(acpi_battery_dir);
1755 acpi_battery_dir = NULL; 975 acpi_battery_dir = NULL;
1756 } 976 }
977#endif
1757} 978}
1758 979
1759static int acpi_sbs_resume(struct acpi_device *device) 980static int acpi_sbs_resume(struct acpi_device *device)
1760{ 981{
1761 struct acpi_sbs *sbs; 982 struct acpi_sbs *sbs;
1762
1763 if (!device) 983 if (!device)
1764 return -EINVAL; 984 return -EINVAL;
1765
1766 sbs = device->driver_data; 985 sbs = device->driver_data;
1767 986 acpi_sbs_callback(sbs);
1768 sbs->run_cnt = 0;
1769
1770 return 0; 987 return 0;
1771} 988}
1772 989
990static struct acpi_driver acpi_sbs_driver = {
991 .name = "sbs",
992 .class = ACPI_SBS_CLASS,
993 .ids = sbs_device_ids,
994 .ops = {
995 .add = acpi_sbs_add,
996 .remove = acpi_sbs_remove,
997 .resume = acpi_sbs_resume,
998 },
999};
1000
1773static int __init acpi_sbs_init(void) 1001static int __init acpi_sbs_init(void)
1774{ 1002{
1775 int result = 0; 1003 int result = 0;
1776 1004
1777 if (acpi_disabled) 1005 if (acpi_disabled)
1778 return -ENODEV; 1006 return -ENODEV;
1779 1007#ifdef CONFIG_ACPI_PROCFS
1780 if (capacity_mode != DEF_CAPACITY_UNIT
1781 && capacity_mode != MAH_CAPACITY_UNIT
1782 && capacity_mode != MWH_CAPACITY_UNIT) {
1783 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1784 "invalid capacity_mode = %d", capacity_mode));
1785 return -EINVAL;
1786 }
1787
1788 acpi_ac_dir = acpi_lock_ac_dir(); 1008 acpi_ac_dir = acpi_lock_ac_dir();
1789 if (!acpi_ac_dir) { 1009 if (!acpi_ac_dir)
1790 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1791 "acpi_lock_ac_dir() failed"));
1792 return -ENODEV; 1010 return -ENODEV;
1793 }
1794
1795 acpi_battery_dir = acpi_lock_battery_dir(); 1011 acpi_battery_dir = acpi_lock_battery_dir();
1796 if (!acpi_battery_dir) { 1012 if (!acpi_battery_dir) {
1797 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1798 "acpi_lock_battery_dir() failed"));
1799 acpi_sbs_rmdirs(); 1013 acpi_sbs_rmdirs();
1800 return -ENODEV; 1014 return -ENODEV;
1801 } 1015 }
1802 1016#endif
1803 result = acpi_bus_register_driver(&acpi_sbs_driver); 1017 result = acpi_bus_register_driver(&acpi_sbs_driver);
1804 if (result < 0) { 1018 if (result < 0) {
1805 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1806 "acpi_bus_register_driver() failed"));
1807 acpi_sbs_rmdirs(); 1019 acpi_sbs_rmdirs();
1808 return -ENODEV; 1020 return -ENODEV;
1809 } 1021 }
1810
1811 return 0; 1022 return 0;
1812} 1023}
1813 1024
1814static void __exit acpi_sbs_exit(void) 1025static void __exit acpi_sbs_exit(void)
1815{ 1026{
1816 acpi_bus_unregister_driver(&acpi_sbs_driver); 1027 acpi_bus_unregister_driver(&acpi_sbs_driver);
1817
1818 acpi_sbs_rmdirs(); 1028 acpi_sbs_rmdirs();
1819
1820 return; 1029 return;
1821} 1030}
1822 1031
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
new file mode 100644
index 000000000000..046d7c3ed356
--- /dev/null
+++ b/drivers/acpi/sbshc.c
@@ -0,0 +1,309 @@
1/*
2 * SMBus driver for ACPI Embedded Controller (v0.1)
3 *
4 * Copyright (c) 2007 Alexey Starikovskiy
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation version 2.
9 */
10
11#include <acpi/acpi_bus.h>
12#include <acpi/acpi_drivers.h>
13#include <acpi/actypes.h>
14#include <linux/wait.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include "sbshc.h"
18
19#define ACPI_SMB_HC_CLASS "smbus_host_controller"
20#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"
21
22struct acpi_smb_hc {
23 struct acpi_ec *ec;
24 struct mutex lock;
25 wait_queue_head_t wait;
26 u8 offset;
27 u8 query_bit;
28 smbus_alarm_callback callback;
29 void *context;
30};
31
32static int acpi_smbus_hc_add(struct acpi_device *device);
33static int acpi_smbus_hc_remove(struct acpi_device *device, int type);
34
35static const struct acpi_device_id sbs_device_ids[] = {
36 {"ACPI0001", 0},
37 {"ACPI0005", 0},
38 {"", 0},
39};
40
41MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
42
43static struct acpi_driver acpi_smb_hc_driver = {
44 .name = "smbus_hc",
45 .class = ACPI_SMB_HC_CLASS,
46 .ids = sbs_device_ids,
47 .ops = {
48 .add = acpi_smbus_hc_add,
49 .remove = acpi_smbus_hc_remove,
50 },
51};
52
53union acpi_smb_status {
54 u8 raw;
55 struct {
56 u8 status:5;
57 u8 reserved:1;
58 u8 alarm:1;
59 u8 done:1;
60 } fields;
61};
62
63enum acpi_smb_status_codes {
64 SMBUS_OK = 0,
65 SMBUS_UNKNOWN_FAILURE = 0x07,
66 SMBUS_DEVICE_ADDRESS_NACK = 0x10,
67 SMBUS_DEVICE_ERROR = 0x11,
68 SMBUS_DEVICE_COMMAND_ACCESS_DENIED = 0x12,
69 SMBUS_UNKNOWN_ERROR = 0x13,
70 SMBUS_DEVICE_ACCESS_DENIED = 0x17,
71 SMBUS_TIMEOUT = 0x18,
72 SMBUS_HOST_UNSUPPORTED_PROTOCOL = 0x19,
73 SMBUS_BUSY = 0x1a,
74 SMBUS_PEC_ERROR = 0x1f,
75};
76
77enum acpi_smb_offset {
78 ACPI_SMB_PROTOCOL = 0, /* protocol, PEC */
79 ACPI_SMB_STATUS = 1, /* status */
80 ACPI_SMB_ADDRESS = 2, /* address */
81 ACPI_SMB_COMMAND = 3, /* command */
82 ACPI_SMB_DATA = 4, /* 32 data registers */
83 ACPI_SMB_BLOCK_COUNT = 0x24, /* number of data bytes */
84 ACPI_SMB_ALARM_ADDRESS = 0x25, /* alarm address */
85 ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */
86};
87
88static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
89{
90 return ec_read(hc->offset + address, data);
91}
92
93static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data)
94{
95 return ec_write(hc->offset + address, data);
96}
97
98static inline int smb_check_done(struct acpi_smb_hc *hc)
99{
100 union acpi_smb_status status = {.raw = 0};
101 smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw);
102 return status.fields.done && (status.fields.status == SMBUS_OK);
103}
104
105static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
106{
107 if (wait_event_timeout(hc->wait, smb_check_done(hc),
108 msecs_to_jiffies(timeout)))
109 return 0;
110 else
111 return -ETIME;
112}
113
114int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address,
115 u8 command, u8 *data, u8 length)
116{
117 int ret = -EFAULT, i;
118 u8 temp, sz = 0;
119
120 mutex_lock(&hc->lock);
121 if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
122 goto end;
123 if (temp) {
124 ret = -EBUSY;
125 goto end;
126 }
127 smb_hc_write(hc, ACPI_SMB_COMMAND, command);
128 smb_hc_write(hc, ACPI_SMB_COMMAND, command);
129 if (!(protocol & 0x01)) {
130 smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length);
131 for (i = 0; i < length; ++i)
132 smb_hc_write(hc, ACPI_SMB_DATA + i, data[i]);
133 }
134 smb_hc_write(hc, ACPI_SMB_ADDRESS, address << 1);
135 smb_hc_write(hc, ACPI_SMB_PROTOCOL, protocol);
136 /*
137 * Wait for completion. Save the status code, data size,
138 * and data into the return package (if required by the protocol).
139 */
140 ret = wait_transaction_complete(hc, 1000);
141 if (ret || !(protocol & 0x01))
142 goto end;
143 switch (protocol) {
144 case SMBUS_RECEIVE_BYTE:
145 case SMBUS_READ_BYTE:
146 sz = 1;
147 break;
148 case SMBUS_READ_WORD:
149 sz = 2;
150 break;
151 case SMBUS_READ_BLOCK:
152 if (smb_hc_read(hc, ACPI_SMB_BLOCK_COUNT, &sz)) {
153 ret = -EFAULT;
154 goto end;
155 }
156 sz &= 0x1f;
157 break;
158 }
159 for (i = 0; i < sz; ++i)
160 smb_hc_read(hc, ACPI_SMB_DATA + i, &data[i]);
161 end:
162 mutex_unlock(&hc->lock);
163 return ret;
164}
165
166int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
167 u8 command, u8 *data)
168{
169 return acpi_smbus_transaction(hc, protocol, address, command, data, 0);
170}
171
172EXPORT_SYMBOL_GPL(acpi_smbus_read);
173
174int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 address,
175 u8 command, u8 *data, u8 length)
176{
177 return acpi_smbus_transaction(hc, protocol, address, command, data, length);
178}
179
180EXPORT_SYMBOL_GPL(acpi_smbus_write);
181
182int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
183 smbus_alarm_callback callback, void *context)
184{
185 mutex_lock(&hc->lock);
186 hc->callback = callback;
187 hc->context = context;
188 mutex_unlock(&hc->lock);
189 return 0;
190}
191
192EXPORT_SYMBOL_GPL(acpi_smbus_register_callback);
193
194int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc)
195{
196 mutex_lock(&hc->lock);
197 hc->callback = NULL;
198 hc->context = NULL;
199 mutex_unlock(&hc->lock);
200 return 0;
201}
202
203EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback);
204
205static void acpi_smbus_callback(void *context)
206{
207 struct acpi_smb_hc *hc = context;
208
209 if (hc->callback)
210 hc->callback(hc->context);
211}
212
213static int smbus_alarm(void *context)
214{
215 struct acpi_smb_hc *hc = context;
216 union acpi_smb_status status;
217 if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
218 return 0;
219 /* Check if it is only a completion notify */
220 if (status.fields.done)
221 wake_up(&hc->wait);
222 if (!status.fields.alarm)
223 return 0;
224 mutex_lock(&hc->lock);
225 smb_hc_write(hc, ACPI_SMB_STATUS, status.raw);
226 if (hc->callback)
227 acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc);
228 mutex_unlock(&hc->lock);
229 return 0;
230}
231
232typedef int (*acpi_ec_query_func) (void *data);
233
234extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
235 acpi_handle handle, acpi_ec_query_func func,
236 void *data);
237
238static int acpi_smbus_hc_add(struct acpi_device *device)
239{
240 int status;
241 unsigned long val;
242 struct acpi_smb_hc *hc;
243
244 if (!device)
245 return -EINVAL;
246
247 status = acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
248 if (ACPI_FAILURE(status)) {
249 printk(KERN_ERR PREFIX "error obtaining _EC.\n");
250 return -EIO;
251 }
252
253 strcpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME);
254 strcpy(acpi_device_class(device), ACPI_SMB_HC_CLASS);
255
256 hc = kzalloc(sizeof(struct acpi_smb_hc), GFP_KERNEL);
257 if (!hc)
258 return -ENOMEM;
259 mutex_init(&hc->lock);
260 init_waitqueue_head(&hc->wait);
261
262 hc->ec = acpi_driver_data(device->parent);
263 hc->offset = (val >> 8) & 0xff;
264 hc->query_bit = val & 0xff;
265 acpi_driver_data(device) = hc;
266
267 acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
268 printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
269 hc->ec, hc->offset, hc->query_bit);
270
271 return 0;
272}
273
274extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
275
276static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
277{
278 struct acpi_smb_hc *hc;
279
280 if (!device)
281 return -EINVAL;
282
283 hc = acpi_driver_data(device);
284 acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
285 kfree(hc);
286 return 0;
287}
288
289static int __init acpi_smb_hc_init(void)
290{
291 int result;
292
293 result = acpi_bus_register_driver(&acpi_smb_hc_driver);
294 if (result < 0)
295 return -ENODEV;
296 return 0;
297}
298
299static void __exit acpi_smb_hc_exit(void)
300{
301 acpi_bus_unregister_driver(&acpi_smb_hc_driver);
302}
303
304module_init(acpi_smb_hc_init);
305module_exit(acpi_smb_hc_exit);
306
307MODULE_LICENSE("GPL");
308MODULE_AUTHOR("Alexey Starikovskiy");
309MODULE_DESCRIPTION("ACPI SMBus HC driver");
diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h
new file mode 100644
index 000000000000..3bda3491a97b
--- /dev/null
+++ b/drivers/acpi/sbshc.h
@@ -0,0 +1,27 @@
1struct acpi_smb_hc;
2enum acpi_smb_protocol {
3 SMBUS_WRITE_QUICK = 2,
4 SMBUS_READ_QUICK = 3,
5 SMBUS_SEND_BYTE = 4,
6 SMBUS_RECEIVE_BYTE = 5,
7 SMBUS_WRITE_BYTE = 6,
8 SMBUS_READ_BYTE = 7,
9 SMBUS_WRITE_WORD = 8,
10 SMBUS_READ_WORD = 9,
11 SMBUS_WRITE_BLOCK = 0xa,
12 SMBUS_READ_BLOCK = 0xb,
13 SMBUS_PROCESS_CALL = 0xc,
14 SMBUS_BLOCK_PROCESS_CALL = 0xd,
15};
16
17static const u8 SMBUS_PEC = 0x80;
18
19typedef void (*smbus_alarm_callback)(void *context);
20
21extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address,
22 u8 command, u8 * data);
23extern int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 slave_address,
24 u8 command, u8 * data, u8 length);
25extern int acpi_smbus_register_callback(struct acpi_smb_hc *hc,
26 smbus_alarm_callback callback, void *context);
27extern int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc);