Pull smart-battery into release branch

Len Brown 309b0f12 d0e5f39f

+2355 -14
+12
drivers/acpi/Kconfig
··· 352 352 If one selects "m," this driver can be loaded using the following 353 353 command: 354 354 $>modprobe acpi_memhotplug 355 + 356 + config ACPI_SBS 357 + tristate "Smart Battery System (EXPERIMENTAL)" 358 + depends on X86 && I2C 359 + depends on EXPERIMENTAL 360 + default y 361 + help 362 + This driver adds support for the Smart Battery System. 363 + Depends on I2C (Device Drivers ---> I2C support) 364 + A "Smart Battery" is quite old and quite rare compared 365 + to today's ACPI "Control Method" battery. 366 + 355 367 endif # ACPI 356 368 357 369 endmenu
+2
drivers/acpi/Makefile
··· 58 58 obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 59 59 obj-y += scan.o motherboard.o 60 60 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o 61 + obj-y += cm_sbs.o 62 + obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o
+7 -5
drivers/acpi/ac.c
··· 50 50 MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); 51 51 MODULE_LICENSE("GPL"); 52 52 53 + extern struct proc_dir_entry *acpi_lock_ac_dir(void); 54 + extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 55 + 53 56 static int acpi_ac_add(struct acpi_device *device); 54 57 static int acpi_ac_remove(struct acpi_device *device, int type); 55 58 static int acpi_ac_open_fs(struct inode *inode, struct file *file); ··· 283 280 284 281 static int __init acpi_ac_init(void) 285 282 { 286 - int result = 0; 283 + int result; 287 284 288 285 289 - acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); 286 + acpi_ac_dir = acpi_lock_ac_dir(); 290 287 if (!acpi_ac_dir) 291 288 return -ENODEV; 292 - acpi_ac_dir->owner = THIS_MODULE; 293 289 294 290 result = acpi_bus_register_driver(&acpi_ac_driver); 295 291 if (result < 0) { 296 - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); 292 + acpi_unlock_ac_dir(acpi_ac_dir); 297 293 return -ENODEV; 298 294 } 299 295 ··· 304 302 305 303 acpi_bus_unregister_driver(&acpi_ac_driver); 306 304 307 - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); 305 + acpi_unlock_ac_dir(acpi_ac_dir); 308 306 309 307 return; 310 308 }
+7 -6
drivers/acpi/battery.c
··· 59 59 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); 60 60 MODULE_LICENSE("GPL"); 61 61 62 + extern struct proc_dir_entry *acpi_lock_battery_dir(void); 63 + extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 64 + 62 65 static int acpi_battery_add(struct acpi_device *device); 63 66 static int acpi_battery_remove(struct acpi_device *device, int type); 64 67 ··· 755 752 756 753 static int __init acpi_battery_init(void) 757 754 { 758 - int result = 0; 755 + int result; 759 756 760 - 761 - acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); 757 + acpi_battery_dir = acpi_lock_battery_dir(); 762 758 if (!acpi_battery_dir) 763 759 return -ENODEV; 764 - acpi_battery_dir->owner = THIS_MODULE; 765 760 766 761 result = acpi_bus_register_driver(&acpi_battery_driver); 767 762 if (result < 0) { 768 - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); 763 + acpi_unlock_battery_dir(acpi_battery_dir); 769 764 return -ENODEV; 770 765 } 771 766 ··· 775 774 776 775 acpi_bus_unregister_driver(&acpi_battery_driver); 777 776 778 - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); 777 + acpi_unlock_battery_dir(acpi_battery_dir); 779 778 780 779 return; 781 780 }
+131
drivers/acpi/cm_sbs.c
··· 1 + /* 2 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or (at 7 + * your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, but 10 + * WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License along 15 + * with this program; if not, write to the Free Software Foundation, Inc., 16 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 17 + * 18 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 + */ 20 + 21 + #include <linux/kernel.h> 22 + #include <linux/module.h> 23 + #include <linux/init.h> 24 + #include <linux/acpi.h> 25 + #include <linux/types.h> 26 + #include <linux/proc_fs.h> 27 + #include <linux/seq_file.h> 28 + #include <acpi/acpi_bus.h> 29 + #include <acpi/acpi_drivers.h> 30 + #include <acpi/acmacros.h> 31 + #include <acpi/actypes.h> 32 + #include <acpi/acutils.h> 33 + 34 + ACPI_MODULE_NAME("cm_sbs") 35 + #define ACPI_AC_CLASS "ac_adapter" 36 + #define ACPI_BATTERY_CLASS "battery" 37 + #define ACPI_SBS_COMPONENT 0x00080000 38 + #define _COMPONENT ACPI_SBS_COMPONENT 39 + static struct proc_dir_entry *acpi_ac_dir; 40 + static struct proc_dir_entry *acpi_battery_dir; 41 + 42 + static struct semaphore cm_sbs_sem; 43 + 44 + static int lock_ac_dir_cnt = 0; 45 + static int lock_battery_dir_cnt = 0; 46 + 47 + struct proc_dir_entry *acpi_lock_ac_dir(void) 48 + { 49 + 50 + down(&cm_sbs_sem); 51 + if (!acpi_ac_dir) { 52 + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); 53 + } 54 + if (acpi_ac_dir) { 55 + lock_ac_dir_cnt++; 56 + } else { 57 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 58 + "Cannot create %s\n", ACPI_AC_CLASS)); 59 + } 60 + up(&cm_sbs_sem); 61 + return acpi_ac_dir; 62 + } 63 + 64 + EXPORT_SYMBOL(acpi_lock_ac_dir); 65 + 66 + void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param) 67 + { 68 + 69 + down(&cm_sbs_sem); 70 + if (acpi_ac_dir_param) { 71 + lock_ac_dir_cnt--; 72 + } 73 + if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) { 74 + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); 75 + acpi_ac_dir = 0; 76 + } 77 + up(&cm_sbs_sem); 78 + } 79 + 80 + EXPORT_SYMBOL(acpi_unlock_ac_dir); 81 + 82 + struct proc_dir_entry *acpi_lock_battery_dir(void) 83 + { 84 + 85 + down(&cm_sbs_sem); 86 + if (!acpi_battery_dir) { 87 + acpi_battery_dir = 88 + proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); 89 + } 90 + if (acpi_battery_dir) { 91 + lock_battery_dir_cnt++; 92 + } else { 93 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 94 + "Cannot create %s\n", ACPI_BATTERY_CLASS)); 95 + } 96 + up(&cm_sbs_sem); 97 + return acpi_battery_dir; 98 + } 99 + 100 + EXPORT_SYMBOL(acpi_lock_battery_dir); 101 + 102 + void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) 103 + { 104 + 105 + down(&cm_sbs_sem); 106 + if (acpi_battery_dir_param) { 107 + lock_battery_dir_cnt--; 108 + } 109 + if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param 110 + && acpi_battery_dir) { 111 + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); 112 + acpi_battery_dir = 0; 113 + } 114 + up(&cm_sbs_sem); 115 + return; 116 + } 117 + 118 + EXPORT_SYMBOL(acpi_unlock_battery_dir); 119 + 120 + static int __init acpi_cm_sbs_init(void) 121 + { 122 + 123 + if (acpi_disabled) 124 + return 0; 125 + 126 + init_MUTEX(&cm_sbs_sem); 127 + 128 + return 0; 129 + } 130 + 131 + subsys_initcall(acpi_cm_sbs_init);
+406
drivers/acpi/i2c_ec.c
··· 1 + /* 2 + * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $) 3 + * 4 + * Copyright (c) 2002, 2005 Ducrot Bruno 5 + * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks) 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation version 2. 10 + */ 11 + 12 + #include <linux/version.h> 13 + #include <linux/module.h> 14 + #include <linux/slab.h> 15 + #include <linux/kernel.h> 16 + #include <linux/stddef.h> 17 + #include <linux/sched.h> 18 + #include <linux/init.h> 19 + #include <linux/i2c.h> 20 + #include <linux/acpi.h> 21 + #include <linux/delay.h> 22 + 23 + #include "i2c_ec.h" 24 + 25 + #define xudelay(t) udelay(t) 26 + #define xmsleep(t) msleep(t) 27 + 28 + #define ACPI_EC_HC_COMPONENT 0x00080000 29 + #define ACPI_EC_HC_CLASS "ec_hc_smbus" 30 + #define ACPI_EC_HC_HID "ACPI0001" 31 + #define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver" 32 + #define ACPI_EC_HC_DEVICE_NAME "EC HC smbus" 33 + 34 + #define _COMPONENT ACPI_EC_HC_COMPONENT 35 + 36 + ACPI_MODULE_NAME("acpi_smbus") 37 + 38 + static int acpi_ec_hc_add(struct acpi_device *device); 39 + static int acpi_ec_hc_remove(struct acpi_device *device, int type); 40 + 41 + static struct acpi_driver acpi_ec_hc_driver = { 42 + .name = ACPI_EC_HC_DRIVER_NAME, 43 + .class = ACPI_EC_HC_CLASS, 44 + .ids = ACPI_EC_HC_HID, 45 + .ops = { 46 + .add = acpi_ec_hc_add, 47 + .remove = acpi_ec_hc_remove, 48 + }, 49 + }; 50 + 51 + /* Various bit mask for EC_SC (R) */ 52 + #define OBF 0x01 53 + #define IBF 0x02 54 + #define CMD 0x08 55 + #define BURST 0x10 56 + #define SCI_EVT 0x20 57 + #define SMI_EVT 0x40 58 + 59 + /* Commands for EC_SC (W) */ 60 + #define RD_EC 0x80 61 + #define WR_EC 0x81 62 + #define BE_EC 0x82 63 + #define BD_EC 0x83 64 + #define QR_EC 0x84 65 + 66 + /* 67 + * ACPI 2.0 chapter 13 SMBus 2.0 EC register model 68 + */ 69 + 70 + #define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */ 71 + #define ACPI_EC_SMB_STS 0x01 /* status */ 72 + #define ACPI_EC_SMB_ADDR 0x02 /* address */ 73 + #define ACPI_EC_SMB_CMD 0x03 /* command */ 74 + #define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */ 75 + #define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */ 76 + #define ACPI_EC_SMB_ALRM_A 0x25 /* alarm address */ 77 + #define ACPI_EC_SMB_ALRM_D 0x26 /* 2 bytes alarm data */ 78 + 79 + #define ACPI_EC_SMB_STS_DONE 0x80 80 + #define ACPI_EC_SMB_STS_ALRM 0x40 81 + #define ACPI_EC_SMB_STS_RES 0x20 82 + #define ACPI_EC_SMB_STS_STATUS 0x1f 83 + 84 + #define ACPI_EC_SMB_STATUS_OK 0x00 85 + #define ACPI_EC_SMB_STATUS_FAIL 0x07 86 + #define ACPI_EC_SMB_STATUS_DNAK 0x10 87 + #define ACPI_EC_SMB_STATUS_DERR 0x11 88 + #define ACPI_EC_SMB_STATUS_CMD_DENY 0x12 89 + #define ACPI_EC_SMB_STATUS_UNKNOWN 0x13 90 + #define ACPI_EC_SMB_STATUS_ACC_DENY 0x17 91 + #define ACPI_EC_SMB_STATUS_TIMEOUT 0x18 92 + #define ACPI_EC_SMB_STATUS_NOTSUP 0x19 93 + #define ACPI_EC_SMB_STATUS_BUSY 0x1A 94 + #define ACPI_EC_SMB_STATUS_PEC 0x1F 95 + 96 + #define ACPI_EC_SMB_PRTCL_WRITE 0x00 97 + #define ACPI_EC_SMB_PRTCL_READ 0x01 98 + #define ACPI_EC_SMB_PRTCL_QUICK 0x02 99 + #define ACPI_EC_SMB_PRTCL_BYTE 0x04 100 + #define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06 101 + #define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08 102 + #define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a 103 + #define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c 104 + #define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d 105 + #define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a 106 + #define ACPI_EC_SMB_PRTCL_PEC 0x80 107 + 108 + /* Length of pre/post transaction sleep (msec) */ 109 + #define ACPI_EC_SMB_TRANSACTION_SLEEP 1 110 + #define ACPI_EC_SMB_ACCESS_SLEEP1 1 111 + #define ACPI_EC_SMB_ACCESS_SLEEP2 10 112 + 113 + static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data) 114 + { 115 + u8 val; 116 + int err; 117 + 118 + err = ec_read(smbus->base + address, &val); 119 + if (!err) { 120 + *data = val; 121 + } 122 + xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP); 123 + return (err); 124 + } 125 + 126 + static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data) 127 + { 128 + int err; 129 + 130 + err = ec_write(smbus->base + address, data); 131 + return (err); 132 + } 133 + 134 + static int 135 + acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, 136 + char read_write, u8 command, int size, 137 + union i2c_smbus_data *data) 138 + { 139 + struct acpi_ec_smbus *smbus = adap->algo_data; 140 + unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 }; 141 + int i; 142 + 143 + if (read_write == I2C_SMBUS_READ) { 144 + protocol = ACPI_EC_SMB_PRTCL_READ; 145 + } else { 146 + protocol = ACPI_EC_SMB_PRTCL_WRITE; 147 + } 148 + pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0; 149 + 150 + switch (size) { 151 + 152 + case I2C_SMBUS_QUICK: 153 + protocol |= ACPI_EC_SMB_PRTCL_QUICK; 154 + read_write = I2C_SMBUS_WRITE; 155 + break; 156 + 157 + case I2C_SMBUS_BYTE: 158 + if (read_write == I2C_SMBUS_WRITE) { 159 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte); 160 + } 161 + protocol |= ACPI_EC_SMB_PRTCL_BYTE; 162 + break; 163 + 164 + case I2C_SMBUS_BYTE_DATA: 165 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 166 + if (read_write == I2C_SMBUS_WRITE) { 167 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte); 168 + } 169 + protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA; 170 + break; 171 + 172 + case I2C_SMBUS_WORD_DATA: 173 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 174 + if (read_write == I2C_SMBUS_WRITE) { 175 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word); 176 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, 177 + data->word >> 8); 178 + } 179 + protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec; 180 + break; 181 + 182 + case I2C_SMBUS_BLOCK_DATA: 183 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 184 + if (read_write == I2C_SMBUS_WRITE) { 185 + len = min_t(u8, data->block[0], 32); 186 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); 187 + for (i = 0; i < len; i++) 188 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, 189 + data->block[i + 1]); 190 + } 191 + protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec; 192 + break; 193 + 194 + case I2C_SMBUS_I2C_BLOCK_DATA: 195 + len = min_t(u8, data->block[0], 32); 196 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 197 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); 198 + if (read_write == I2C_SMBUS_WRITE) { 199 + for (i = 0; i < len; i++) { 200 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, 201 + data->block[i + 1]); 202 + } 203 + } 204 + protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA; 205 + break; 206 + 207 + case I2C_SMBUS_PROC_CALL: 208 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 209 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word); 210 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8); 211 + protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec; 212 + read_write = I2C_SMBUS_READ; 213 + break; 214 + 215 + case I2C_SMBUS_BLOCK_PROC_CALL: 216 + protocol |= pec; 217 + len = min_t(u8, data->block[0], 31); 218 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); 219 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); 220 + for (i = 0; i < len; i++) 221 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, 222 + data->block[i + 1]); 223 + protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec; 224 + read_write = I2C_SMBUS_READ; 225 + break; 226 + 227 + default: 228 + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: " 229 + "Unsupported transaction %d\n", size)); 230 + return (-1); 231 + } 232 + 233 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1); 234 + acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol); 235 + 236 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); 237 + 238 + if (~temp[0] & ACPI_EC_SMB_STS_DONE) { 239 + xudelay(500); 240 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); 241 + } 242 + if (~temp[0] & ACPI_EC_SMB_STS_DONE) { 243 + xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2); 244 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); 245 + } 246 + if ((~temp[0] & ACPI_EC_SMB_STS_DONE) 247 + || (temp[0] & ACPI_EC_SMB_STS_STATUS)) { 248 + return (-1); 249 + } 250 + 251 + if (read_write == I2C_SMBUS_WRITE) { 252 + return (0); 253 + } 254 + 255 + switch (size) { 256 + 257 + case I2C_SMBUS_BYTE: 258 + case I2C_SMBUS_BYTE_DATA: 259 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte); 260 + break; 261 + 262 + case I2C_SMBUS_WORD_DATA: 263 + case I2C_SMBUS_PROC_CALL: 264 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0); 265 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1); 266 + data->word = (temp[1] << 8) | temp[0]; 267 + break; 268 + 269 + case I2C_SMBUS_BLOCK_DATA: 270 + case I2C_SMBUS_BLOCK_PROC_CALL: 271 + len = 0; 272 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len); 273 + len = min_t(u8, len, 32); 274 + case I2C_SMBUS_I2C_BLOCK_DATA: 275 + for (i = 0; i < len; i++) 276 + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i, 277 + data->block + i + 1); 278 + data->block[0] = len; 279 + break; 280 + } 281 + 282 + return (0); 283 + } 284 + 285 + static u32 acpi_ec_smb_func(struct i2c_adapter *adapter) 286 + { 287 + 288 + return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 289 + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 290 + I2C_FUNC_SMBUS_BLOCK_DATA | 291 + I2C_FUNC_SMBUS_PROC_CALL | 292 + I2C_FUNC_SMBUS_BLOCK_PROC_CALL | 293 + I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC); 294 + } 295 + 296 + static struct i2c_algorithm acpi_ec_smbus_algorithm = { 297 + .smbus_xfer = acpi_ec_smb_access, 298 + .functionality = acpi_ec_smb_func, 299 + }; 300 + 301 + static int acpi_ec_hc_add(struct acpi_device *device) 302 + { 303 + int status; 304 + unsigned long val; 305 + struct acpi_ec_hc *ec_hc; 306 + struct acpi_ec_smbus *smbus; 307 + 308 + if (!device) { 309 + return -EINVAL; 310 + } 311 + 312 + ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL); 313 + if (!ec_hc) { 314 + return -ENOMEM; 315 + } 316 + memset(ec_hc, 0, sizeof(struct acpi_ec_hc)); 317 + 318 + smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL); 319 + if (!smbus) { 320 + kfree(ec_hc); 321 + return -ENOMEM; 322 + } 323 + memset(smbus, 0, sizeof(struct acpi_ec_smbus)); 324 + 325 + ec_hc->handle = device->handle; 326 + strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME); 327 + strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS); 328 + acpi_driver_data(device) = ec_hc; 329 + 330 + status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val); 331 + if (ACPI_FAILURE(status)) { 332 + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n")); 333 + kfree(ec_hc->smbus); 334 + kfree(smbus); 335 + return -EIO; 336 + } 337 + 338 + smbus->ec = acpi_driver_data(device->parent); 339 + smbus->base = (val & 0xff00ull) >> 8; 340 + smbus->alert = val & 0xffull; 341 + 342 + smbus->adapter.owner = THIS_MODULE; 343 + smbus->adapter.algo = &acpi_ec_smbus_algorithm; 344 + smbus->adapter.algo_data = smbus; 345 + 346 + if (i2c_add_adapter(&smbus->adapter)) { 347 + ACPI_DEBUG_PRINT((ACPI_DB_WARN, 348 + "EC SMBus adapter: Failed to register adapter\n")); 349 + kfree(smbus); 350 + kfree(ec_hc); 351 + return -EIO; 352 + } 353 + 354 + ec_hc->smbus = smbus; 355 + 356 + printk(KERN_INFO PREFIX "%s [%s]\n", 357 + acpi_device_name(device), acpi_device_bid(device)); 358 + 359 + return AE_OK; 360 + } 361 + 362 + static int acpi_ec_hc_remove(struct acpi_device *device, int type) 363 + { 364 + struct acpi_ec_hc *ec_hc; 365 + 366 + if (!device) { 367 + return -EINVAL; 368 + } 369 + ec_hc = acpi_driver_data(device); 370 + 371 + i2c_del_adapter(&ec_hc->smbus->adapter); 372 + kfree(ec_hc->smbus); 373 + kfree(ec_hc); 374 + 375 + return AE_OK; 376 + } 377 + 378 + static int __init acpi_ec_hc_init(void) 379 + { 380 + int result; 381 + 382 + result = acpi_bus_register_driver(&acpi_ec_hc_driver); 383 + if (result < 0) { 384 + return -ENODEV; 385 + } 386 + return 0; 387 + } 388 + 389 + static void __exit acpi_ec_hc_exit(void) 390 + { 391 + acpi_bus_unregister_driver(&acpi_ec_hc_driver); 392 + } 393 + 394 + struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device) 395 + { 396 + return ((struct acpi_ec_hc *)acpi_driver_data(device->parent)); 397 + } 398 + 399 + EXPORT_SYMBOL(acpi_get_ec_hc); 400 + 401 + module_init(acpi_ec_hc_init); 402 + module_exit(acpi_ec_hc_exit); 403 + 404 + MODULE_LICENSE("GPL"); 405 + MODULE_AUTHOR("Ducrot Bruno"); 406 + MODULE_DESCRIPTION("ACPI EC SMBus driver");
+23
drivers/acpi/i2c_ec.h
··· 1 + /* 2 + * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $) 3 + * 4 + * Copyright (c) 2002, 2005 Ducrot Bruno 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 + struct acpi_ec_smbus { 12 + struct i2c_adapter adapter; 13 + union acpi_ec *ec; 14 + int base; 15 + int alert; 16 + }; 17 + 18 + struct acpi_ec_hc { 19 + acpi_handle handle; 20 + struct acpi_ec_smbus *smbus; 21 + }; 22 + 23 + struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
+1 -3
drivers/acpi/numa.c
··· 259 259 { 260 260 int pxm, node = -1; 261 261 262 - ACPI_FUNCTION_TRACE("acpi_get_node"); 263 - 264 262 pxm = acpi_get_pxm(handle); 265 263 if (pxm >= 0) 266 264 node = acpi_map_pxm_to_node(pxm); 267 265 268 - return_VALUE(node); 266 + return node; 269 267 } 270 268 EXPORT_SYMBOL(acpi_get_node);
+1766
drivers/acpi/sbs.c
··· 1 + /* 2 + * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $) 3 + * 4 + * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> 5 + * 6 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or (at 11 + * your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, but 14 + * WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 + * General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License along 19 + * with this program; if not, write to the Free Software Foundation, Inc., 20 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 21 + * 22 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 + */ 24 + 25 + #include <linux/init.h> 26 + #include <linux/module.h> 27 + #include <linux/moduleparam.h> 28 + #include <linux/kernel.h> 29 + #include <linux/proc_fs.h> 30 + #include <linux/seq_file.h> 31 + #include <asm/uaccess.h> 32 + #include <linux/acpi.h> 33 + #include <linux/i2c.h> 34 + #include <linux/delay.h> 35 + 36 + #include "i2c_ec.h" 37 + 38 + #define DEF_CAPACITY_UNIT 3 39 + #define MAH_CAPACITY_UNIT 1 40 + #define MWH_CAPACITY_UNIT 2 41 + #define CAPACITY_UNIT DEF_CAPACITY_UNIT 42 + 43 + #define REQUEST_UPDATE_MODE 1 44 + #define QUEUE_UPDATE_MODE 2 45 + 46 + #define DATA_TYPE_COMMON 0 47 + #define DATA_TYPE_INFO 1 48 + #define DATA_TYPE_STATE 2 49 + #define DATA_TYPE_ALARM 3 50 + #define DATA_TYPE_AC_STATE 4 51 + 52 + extern struct proc_dir_entry *acpi_lock_ac_dir(void); 53 + extern struct proc_dir_entry *acpi_lock_battery_dir(void); 54 + extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 55 + extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 56 + 57 + #define ACPI_SBS_COMPONENT 0x00080000 58 + #define ACPI_SBS_CLASS "sbs" 59 + #define ACPI_AC_CLASS "ac_adapter" 60 + #define ACPI_BATTERY_CLASS "battery" 61 + #define ACPI_SBS_HID "ACPI0002" 62 + #define ACPI_SBS_DRIVER_NAME "ACPI Smart Battery System Driver" 63 + #define ACPI_SBS_DEVICE_NAME "Smart Battery System" 64 + #define ACPI_SBS_FILE_INFO "info" 65 + #define ACPI_SBS_FILE_STATE "state" 66 + #define ACPI_SBS_FILE_ALARM "alarm" 67 + #define ACPI_BATTERY_DIR_NAME "BAT%i" 68 + #define ACPI_AC_DIR_NAME "AC0" 69 + #define ACPI_SBC_SMBUS_ADDR 0x9 70 + #define ACPI_SBSM_SMBUS_ADDR 0xa 71 + #define ACPI_SB_SMBUS_ADDR 0xb 72 + #define ACPI_SBS_AC_NOTIFY_STATUS 0x80 73 + #define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80 74 + #define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81 75 + 76 + #define _COMPONENT ACPI_SBS_COMPONENT 77 + 78 + #define MAX_SBS_BAT 4 79 + #define MAX_SMBUS_ERR 1 80 + 81 + ACPI_MODULE_NAME("acpi_sbs"); 82 + 83 + MODULE_AUTHOR("Rich Townsend"); 84 + MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); 85 + MODULE_LICENSE("GPL"); 86 + 87 + static struct semaphore sbs_sem; 88 + 89 + #define UPDATE_MODE QUEUE_UPDATE_MODE 90 + /* REQUEST_UPDATE_MODE QUEUE_UPDATE_MODE */ 91 + #define UPDATE_INFO_MODE 0 92 + #define UPDATE_TIME 60 93 + #define UPDATE_TIME2 0 94 + 95 + static int capacity_mode = CAPACITY_UNIT; 96 + static int update_mode = UPDATE_MODE; 97 + static int update_info_mode = UPDATE_INFO_MODE; 98 + static int update_time = UPDATE_TIME; 99 + static int update_time2 = UPDATE_TIME2; 100 + 101 + module_param(capacity_mode, int, CAPACITY_UNIT); 102 + module_param(update_mode, int, UPDATE_MODE); 103 + module_param(update_info_mode, int, UPDATE_INFO_MODE); 104 + module_param(update_time, int, UPDATE_TIME); 105 + module_param(update_time2, int, UPDATE_TIME2); 106 + 107 + static int acpi_sbs_add(struct acpi_device *device); 108 + static int acpi_sbs_remove(struct acpi_device *device, int type); 109 + static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus); 110 + static void acpi_sbs_update_queue(void *data); 111 + 112 + static struct acpi_driver acpi_sbs_driver = { 113 + .name = ACPI_SBS_DRIVER_NAME, 114 + .class = ACPI_SBS_CLASS, 115 + .ids = ACPI_SBS_HID, 116 + .ops = { 117 + .add = acpi_sbs_add, 118 + .remove = acpi_sbs_remove, 119 + }, 120 + }; 121 + 122 + struct acpi_battery_info { 123 + int capacity_mode; 124 + s16 full_charge_capacity; 125 + s16 design_capacity; 126 + s16 design_voltage; 127 + int vscale; 128 + int ipscale; 129 + s16 serial_number; 130 + char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3]; 131 + char device_name[I2C_SMBUS_BLOCK_MAX + 3]; 132 + char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3]; 133 + }; 134 + 135 + struct acpi_battery_state { 136 + s16 voltage; 137 + s16 amperage; 138 + s16 remaining_capacity; 139 + s16 average_time_to_empty; 140 + s16 average_time_to_full; 141 + s16 battery_status; 142 + }; 143 + 144 + struct acpi_battery_alarm { 145 + s16 remaining_capacity; 146 + }; 147 + 148 + struct acpi_battery { 149 + int alive; 150 + int battery_present; 151 + int id; 152 + int init_state; 153 + struct acpi_sbs *sbs; 154 + struct acpi_battery_info info; 155 + struct acpi_battery_state state; 156 + struct acpi_battery_alarm alarm; 157 + struct proc_dir_entry *battery_entry; 158 + }; 159 + 160 + struct acpi_sbs { 161 + acpi_handle handle; 162 + struct acpi_device *device; 163 + struct acpi_ec_smbus *smbus; 164 + int sbsm_present; 165 + int sbsm_batteries_supported; 166 + int ac_present; 167 + struct proc_dir_entry *ac_entry; 168 + struct acpi_battery battery[MAX_SBS_BAT]; 169 + int update_info_mode; 170 + int zombie; 171 + int update_time; 172 + int update_time2; 173 + struct timer_list update_timer; 174 + }; 175 + 176 + static void acpi_update_delay(struct acpi_sbs *sbs); 177 + static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type); 178 + 179 + /* -------------------------------------------------------------------------- 180 + SMBus Communication 181 + -------------------------------------------------------------------------- */ 182 + 183 + static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus) 184 + { 185 + union i2c_smbus_data data; 186 + int result = 0; 187 + char *err_str; 188 + int err_number; 189 + 190 + data.word = 0; 191 + 192 + result = smbus->adapter.algo-> 193 + smbus_xfer(&smbus->adapter, 194 + ACPI_SB_SMBUS_ADDR, 195 + 0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data); 196 + 197 + err_number = (data.word & 0x000f); 198 + 199 + switch (data.word & 0x000f) { 200 + case 0x0000: 201 + err_str = "unexpected bus error"; 202 + break; 203 + case 0x0001: 204 + err_str = "busy"; 205 + break; 206 + case 0x0002: 207 + err_str = "reserved command"; 208 + break; 209 + case 0x0003: 210 + err_str = "unsupported command"; 211 + break; 212 + case 0x0004: 213 + err_str = "access denied"; 214 + break; 215 + case 0x0005: 216 + err_str = "overflow/underflow"; 217 + break; 218 + case 0x0006: 219 + err_str = "bad size"; 220 + break; 221 + case 0x0007: 222 + err_str = "unknown error"; 223 + break; 224 + default: 225 + err_str = "unrecognized error"; 226 + } 227 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 228 + "%s: ret %i, err %i\n", err_str, result, err_number)); 229 + } 230 + 231 + static int 232 + acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func, 233 + u16 * word, 234 + void (*err_handler) (struct acpi_ec_smbus * smbus)) 235 + { 236 + union i2c_smbus_data data; 237 + int result = 0; 238 + int i; 239 + 240 + if (err_handler == NULL) { 241 + err_handler = acpi_battery_smbus_err_handler; 242 + } 243 + 244 + for (i = 0; i < MAX_SMBUS_ERR; i++) { 245 + result = 246 + smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, 247 + I2C_SMBUS_READ, func, 248 + I2C_SMBUS_WORD_DATA, &data); 249 + if (result) { 250 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 251 + "try %i: smbus->adapter.algo->smbus_xfer() failed\n", 252 + i)); 253 + if (err_handler) { 254 + err_handler(smbus); 255 + } 256 + } else { 257 + *word = data.word; 258 + break; 259 + } 260 + } 261 + 262 + return result; 263 + } 264 + 265 + static int 266 + acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func, 267 + char *str, 268 + void (*err_handler) (struct acpi_ec_smbus * smbus)) 269 + { 270 + union i2c_smbus_data data; 271 + int result = 0; 272 + int i; 273 + 274 + if (err_handler == NULL) { 275 + err_handler = acpi_battery_smbus_err_handler; 276 + } 277 + 278 + for (i = 0; i < MAX_SMBUS_ERR; i++) { 279 + result = 280 + smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, 281 + I2C_SMBUS_READ, func, 282 + I2C_SMBUS_BLOCK_DATA, 283 + &data); 284 + if (result) { 285 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 286 + "try %i: smbus->adapter.algo->smbus_xfer() failed\n", 287 + i)); 288 + if (err_handler) { 289 + err_handler(smbus); 290 + } 291 + } else { 292 + strncpy(str, (const char *)data.block + 1, 293 + data.block[0]); 294 + str[data.block[0]] = 0; 295 + break; 296 + } 297 + } 298 + 299 + return result; 300 + } 301 + 302 + static int 303 + acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func, 304 + int word, 305 + void (*err_handler) (struct acpi_ec_smbus * smbus)) 306 + { 307 + union i2c_smbus_data data; 308 + int result = 0; 309 + int i; 310 + 311 + if (err_handler == NULL) { 312 + err_handler = acpi_battery_smbus_err_handler; 313 + } 314 + 315 + data.word = word; 316 + 317 + for (i = 0; i < MAX_SMBUS_ERR; i++) { 318 + result = 319 + smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, 320 + I2C_SMBUS_WRITE, func, 321 + I2C_SMBUS_WORD_DATA, &data); 322 + if (result) { 323 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 324 + "try %i: smbus->adapter.algo" 325 + "->smbus_xfer() failed\n", i)); 326 + if (err_handler) { 327 + err_handler(smbus); 328 + } 329 + } else { 330 + break; 331 + } 332 + } 333 + 334 + return result; 335 + } 336 + 337 + /* -------------------------------------------------------------------------- 338 + Smart Battery System Management 339 + -------------------------------------------------------------------------- */ 340 + 341 + /* Smart Battery */ 342 + 343 + static int acpi_sbs_generate_event(struct acpi_device *device, 344 + int event, int state, char *bid, char *class) 345 + { 346 + char bid_saved[5]; 347 + char class_saved[20]; 348 + int result = 0; 349 + 350 + strcpy(bid_saved, acpi_device_bid(device)); 351 + strcpy(class_saved, acpi_device_class(device)); 352 + 353 + strcpy(acpi_device_bid(device), bid); 354 + strcpy(acpi_device_class(device), class); 355 + 356 + result = acpi_bus_generate_event(device, event, state); 357 + 358 + strcpy(acpi_device_bid(device), bid_saved); 359 + strcpy(acpi_device_class(device), class_saved); 360 + 361 + return result; 362 + } 363 + 364 + static int acpi_battery_get_present(struct acpi_battery *battery) 365 + { 366 + s16 state; 367 + int result = 0; 368 + int is_present = 0; 369 + 370 + result = acpi_sbs_smbus_read_word(battery->sbs->smbus, 371 + ACPI_SBSM_SMBUS_ADDR, 0x01, 372 + &state, NULL); 373 + if (result) { 374 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 375 + "acpi_sbs_smbus_read_word() failed")); 376 + } 377 + if (!result) { 378 + is_present = (state & 0x000f) & (1 << battery->id); 379 + } 380 + battery->battery_present = is_present; 381 + 382 + return result; 383 + } 384 + 385 + static int acpi_battery_is_present(struct acpi_battery *battery) 386 + { 387 + return (battery->battery_present); 388 + } 389 + 390 + static int acpi_ac_is_present(struct acpi_sbs *sbs) 391 + { 392 + return (sbs->ac_present); 393 + } 394 + 395 + static int acpi_battery_select(struct acpi_battery *battery) 396 + { 397 + struct acpi_ec_smbus *smbus = battery->sbs->smbus; 398 + int result = 0; 399 + s16 state; 400 + int foo; 401 + 402 + if (battery->sbs->sbsm_present) { 403 + 404 + /* Take special care not to knobble other nibbles of 405 + * state (aka selector_state), since 406 + * it causes charging to halt on SBSELs */ 407 + 408 + result = 409 + acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, 410 + &state, NULL); 411 + if (result) { 412 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 413 + "acpi_sbs_smbus_read_word() failed\n")); 414 + goto end; 415 + } 416 + 417 + foo = (state & 0x0fff) | (1 << (battery->id + 12)); 418 + result = 419 + acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, 420 + foo, NULL); 421 + if (result) { 422 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 423 + "acpi_sbs_smbus_write_word() failed\n")); 424 + goto end; 425 + } 426 + } 427 + 428 + end: 429 + return result; 430 + } 431 + 432 + static int acpi_sbsm_get_info(struct acpi_sbs *sbs) 433 + { 434 + struct acpi_ec_smbus *smbus = sbs->smbus; 435 + int result = 0; 436 + s16 battery_system_info; 437 + 438 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04, 439 + &battery_system_info, NULL); 440 + if (result) { 441 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 442 + "acpi_sbs_smbus_read_word() failed\n")); 443 + goto end; 444 + } 445 + 446 + sbs->sbsm_batteries_supported = battery_system_info & 0x000f; 447 + 448 + end: 449 + 450 + return result; 451 + } 452 + 453 + static int acpi_battery_get_info(struct acpi_battery *battery) 454 + { 455 + struct acpi_ec_smbus *smbus = battery->sbs->smbus; 456 + int result = 0; 457 + s16 battery_mode; 458 + s16 specification_info; 459 + 460 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, 461 + &battery_mode, 462 + &acpi_battery_smbus_err_handler); 463 + if (result) { 464 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 465 + "acpi_sbs_smbus_read_word() failed\n")); 466 + goto end; 467 + } 468 + battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; 469 + 470 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10, 471 + &battery->info.full_charge_capacity, 472 + &acpi_battery_smbus_err_handler); 473 + if (result) { 474 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 475 + "acpi_sbs_smbus_read_word() failed\n")); 476 + goto end; 477 + } 478 + 479 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18, 480 + &battery->info.design_capacity, 481 + &acpi_battery_smbus_err_handler); 482 + 483 + if (result) { 484 + goto end; 485 + } 486 + 487 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19, 488 + &battery->info.design_voltage, 489 + &acpi_battery_smbus_err_handler); 490 + if (result) { 491 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 492 + "acpi_sbs_smbus_read_word() failed\n")); 493 + goto end; 494 + } 495 + 496 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a, 497 + &specification_info, 498 + &acpi_battery_smbus_err_handler); 499 + if (result) { 500 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 501 + "acpi_sbs_smbus_read_word() failed\n")); 502 + goto end; 503 + } 504 + 505 + switch ((specification_info & 0x0f00) >> 8) { 506 + case 1: 507 + battery->info.vscale = 10; 508 + break; 509 + case 2: 510 + battery->info.vscale = 100; 511 + break; 512 + case 3: 513 + battery->info.vscale = 1000; 514 + break; 515 + default: 516 + battery->info.vscale = 1; 517 + } 518 + 519 + switch ((specification_info & 0xf000) >> 12) { 520 + case 1: 521 + battery->info.ipscale = 10; 522 + break; 523 + case 2: 524 + battery->info.ipscale = 100; 525 + break; 526 + case 3: 527 + battery->info.ipscale = 1000; 528 + break; 529 + default: 530 + battery->info.ipscale = 1; 531 + } 532 + 533 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c, 534 + &battery->info.serial_number, 535 + &acpi_battery_smbus_err_handler); 536 + if (result) { 537 + goto end; 538 + } 539 + 540 + result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20, 541 + battery->info.manufacturer_name, 542 + &acpi_battery_smbus_err_handler); 543 + if (result) { 544 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 545 + "acpi_sbs_smbus_read_str() failed\n")); 546 + goto end; 547 + } 548 + 549 + result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21, 550 + battery->info.device_name, 551 + &acpi_battery_smbus_err_handler); 552 + if (result) { 553 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 554 + "acpi_sbs_smbus_read_str() failed\n")); 555 + goto end; 556 + } 557 + 558 + result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22, 559 + battery->info.device_chemistry, 560 + &acpi_battery_smbus_err_handler); 561 + if (result) { 562 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 563 + "acpi_sbs_smbus_read_str() failed\n")); 564 + goto end; 565 + } 566 + 567 + end: 568 + return result; 569 + } 570 + 571 + static void acpi_update_delay(struct acpi_sbs *sbs) 572 + { 573 + if (sbs->zombie) { 574 + return; 575 + } 576 + if (sbs->update_time2 > 0) { 577 + msleep(sbs->update_time2 * 1000); 578 + } 579 + } 580 + 581 + static int acpi_battery_get_state(struct acpi_battery *battery) 582 + { 583 + struct acpi_ec_smbus *smbus = battery->sbs->smbus; 584 + int result = 0; 585 + 586 + acpi_update_delay(battery->sbs); 587 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09, 588 + &battery->state.voltage, 589 + &acpi_battery_smbus_err_handler); 590 + if (result) { 591 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 592 + "acpi_sbs_smbus_read_word() failed\n")); 593 + goto end; 594 + } 595 + 596 + acpi_update_delay(battery->sbs); 597 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a, 598 + &battery->state.amperage, 599 + &acpi_battery_smbus_err_handler); 600 + if (result) { 601 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 602 + "acpi_sbs_smbus_read_word() failed\n")); 603 + goto end; 604 + } 605 + 606 + acpi_update_delay(battery->sbs); 607 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f, 608 + &battery->state.remaining_capacity, 609 + &acpi_battery_smbus_err_handler); 610 + if (result) { 611 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 612 + "acpi_sbs_smbus_read_word() failed\n")); 613 + goto end; 614 + } 615 + 616 + acpi_update_delay(battery->sbs); 617 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12, 618 + &battery->state.average_time_to_empty, 619 + &acpi_battery_smbus_err_handler); 620 + if (result) { 621 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 622 + "acpi_sbs_smbus_read_word() failed\n")); 623 + goto end; 624 + } 625 + 626 + acpi_update_delay(battery->sbs); 627 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13, 628 + &battery->state.average_time_to_full, 629 + &acpi_battery_smbus_err_handler); 630 + if (result) { 631 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 632 + "acpi_sbs_smbus_read_word() failed\n")); 633 + goto end; 634 + } 635 + 636 + acpi_update_delay(battery->sbs); 637 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16, 638 + &battery->state.battery_status, 639 + &acpi_battery_smbus_err_handler); 640 + if (result) { 641 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 642 + "acpi_sbs_smbus_read_word() failed\n")); 643 + goto end; 644 + } 645 + 646 + acpi_update_delay(battery->sbs); 647 + 648 + end: 649 + return result; 650 + } 651 + 652 + static int acpi_battery_get_alarm(struct acpi_battery *battery) 653 + { 654 + struct acpi_ec_smbus *smbus = battery->sbs->smbus; 655 + int result = 0; 656 + 657 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, 658 + &battery->alarm.remaining_capacity, 659 + &acpi_battery_smbus_err_handler); 660 + if (result) { 661 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 662 + "acpi_sbs_smbus_read_word() failed\n")); 663 + goto end; 664 + } 665 + 666 + acpi_update_delay(battery->sbs); 667 + 668 + end: 669 + 670 + return result; 671 + } 672 + 673 + static int acpi_battery_set_alarm(struct acpi_battery *battery, 674 + unsigned long alarm) 675 + { 676 + struct acpi_ec_smbus *smbus = battery->sbs->smbus; 677 + int result = 0; 678 + s16 battery_mode; 679 + int foo; 680 + 681 + result = acpi_battery_select(battery); 682 + if (result) { 683 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 684 + "acpi_battery_select() failed\n")); 685 + goto end; 686 + } 687 + 688 + /* If necessary, enable the alarm */ 689 + 690 + if (alarm > 0) { 691 + result = 692 + acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, 693 + &battery_mode, 694 + &acpi_battery_smbus_err_handler); 695 + if (result) { 696 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 697 + "acpi_sbs_smbus_read_word() failed\n")); 698 + goto end; 699 + } 700 + 701 + result = 702 + acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, 703 + battery_mode & 0xbfff, 704 + &acpi_battery_smbus_err_handler); 705 + if (result) { 706 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 707 + "acpi_sbs_smbus_write_word() failed\n")); 708 + goto end; 709 + } 710 + } 711 + 712 + foo = alarm / (battery->info.capacity_mode ? 10 : 1); 713 + result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, 714 + foo, 715 + &acpi_battery_smbus_err_handler); 716 + if (result) { 717 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 718 + "acpi_sbs_smbus_write_word() failed\n")); 719 + goto end; 720 + } 721 + 722 + end: 723 + 724 + return result; 725 + } 726 + 727 + static int acpi_battery_set_mode(struct acpi_battery *battery) 728 + { 729 + int result = 0; 730 + s16 battery_mode; 731 + 732 + if (capacity_mode == DEF_CAPACITY_UNIT) { 733 + goto end; 734 + } 735 + 736 + result = acpi_sbs_smbus_read_word(battery->sbs->smbus, 737 + ACPI_SB_SMBUS_ADDR, 0x03, 738 + &battery_mode, NULL); 739 + if (result) { 740 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 741 + "acpi_sbs_smbus_read_word() failed\n")); 742 + goto end; 743 + } 744 + 745 + if (capacity_mode == MAH_CAPACITY_UNIT) { 746 + battery_mode &= 0x7fff; 747 + } else { 748 + battery_mode |= 0x8000; 749 + } 750 + result = acpi_sbs_smbus_write_word(battery->sbs->smbus, 751 + ACPI_SB_SMBUS_ADDR, 0x03, 752 + battery_mode, NULL); 753 + if (result) { 754 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 755 + "acpi_sbs_smbus_write_word() failed\n")); 756 + goto end; 757 + } 758 + 759 + result = acpi_sbs_smbus_read_word(battery->sbs->smbus, 760 + ACPI_SB_SMBUS_ADDR, 0x03, 761 + &battery_mode, NULL); 762 + if (result) { 763 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 764 + "acpi_sbs_smbus_read_word() failed\n")); 765 + goto end; 766 + } 767 + 768 + end: 769 + return result; 770 + } 771 + 772 + static int acpi_battery_init(struct acpi_battery *battery) 773 + { 774 + int result = 0; 775 + 776 + result = acpi_battery_select(battery); 777 + if (result) { 778 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 779 + "acpi_battery_init() failed\n")); 780 + goto end; 781 + } 782 + 783 + result = acpi_battery_set_mode(battery); 784 + if (result) { 785 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 786 + "acpi_battery_set_mode() failed\n")); 787 + goto end; 788 + } 789 + 790 + result = acpi_battery_get_info(battery); 791 + if (result) { 792 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 793 + "acpi_battery_get_info() failed\n")); 794 + goto end; 795 + } 796 + 797 + result = acpi_battery_get_state(battery); 798 + if (result) { 799 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 800 + "acpi_battery_get_state() failed\n")); 801 + goto end; 802 + } 803 + 804 + result = acpi_battery_get_alarm(battery); 805 + if (result) { 806 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 807 + "acpi_battery_get_alarm() failed\n")); 808 + goto end; 809 + } 810 + 811 + end: 812 + return result; 813 + } 814 + 815 + static int acpi_ac_get_present(struct acpi_sbs *sbs) 816 + { 817 + struct acpi_ec_smbus *smbus = sbs->smbus; 818 + int result = 0; 819 + s16 charger_status; 820 + 821 + result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13, 822 + &charger_status, NULL); 823 + 824 + if (result) { 825 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 826 + "acpi_sbs_smbus_read_word() failed\n")); 827 + goto end; 828 + } 829 + 830 + sbs->ac_present = (charger_status & 0x8000) >> 15; 831 + 832 + end: 833 + 834 + return result; 835 + } 836 + 837 + /* -------------------------------------------------------------------------- 838 + FS Interface (/proc/acpi) 839 + -------------------------------------------------------------------------- */ 840 + 841 + /* Generic Routines */ 842 + 843 + static int 844 + acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, 845 + struct proc_dir_entry *parent_dir, 846 + char *dir_name, 847 + struct file_operations *info_fops, 848 + struct file_operations *state_fops, 849 + struct file_operations *alarm_fops, void *data) 850 + { 851 + struct proc_dir_entry *entry = NULL; 852 + 853 + if (!*dir) { 854 + *dir = proc_mkdir(dir_name, parent_dir); 855 + if (!*dir) { 856 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 857 + "proc_mkdir() failed\n")); 858 + return -ENODEV; 859 + } 860 + (*dir)->owner = THIS_MODULE; 861 + } 862 + 863 + /* 'info' [R] */ 864 + if (info_fops) { 865 + entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); 866 + if (!entry) { 867 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 868 + "create_proc_entry() failed\n")); 869 + } else { 870 + entry->proc_fops = info_fops; 871 + entry->data = data; 872 + entry->owner = THIS_MODULE; 873 + } 874 + } 875 + 876 + /* 'state' [R] */ 877 + if (state_fops) { 878 + entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); 879 + if (!entry) { 880 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 881 + "create_proc_entry() failed\n")); 882 + } else { 883 + entry->proc_fops = state_fops; 884 + entry->data = data; 885 + entry->owner = THIS_MODULE; 886 + } 887 + } 888 + 889 + /* 'alarm' [R/W] */ 890 + if (alarm_fops) { 891 + entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); 892 + if (!entry) { 893 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 894 + "create_proc_entry() failed\n")); 895 + } else { 896 + entry->proc_fops = alarm_fops; 897 + entry->data = data; 898 + entry->owner = THIS_MODULE; 899 + } 900 + } 901 + 902 + return 0; 903 + } 904 + 905 + static void 906 + acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, 907 + struct proc_dir_entry *parent_dir) 908 + { 909 + 910 + if (*dir) { 911 + remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); 912 + remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); 913 + remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir); 914 + remove_proc_entry((*dir)->name, parent_dir); 915 + *dir = NULL; 916 + } 917 + 918 + } 919 + 920 + /* Smart Battery Interface */ 921 + 922 + static struct proc_dir_entry *acpi_battery_dir = NULL; 923 + 924 + static int acpi_battery_read_info(struct seq_file *seq, void *offset) 925 + { 926 + struct acpi_battery *battery = (struct acpi_battery *)seq->private; 927 + int cscale; 928 + int result = 0; 929 + 930 + if (battery->sbs->zombie) { 931 + return -ENODEV; 932 + } 933 + 934 + down(&sbs_sem); 935 + 936 + if (update_mode == REQUEST_UPDATE_MODE) { 937 + result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO); 938 + if (result) { 939 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 940 + "acpi_sbs_update_run() failed\n")); 941 + } 942 + } 943 + 944 + if (acpi_battery_is_present(battery)) { 945 + seq_printf(seq, "present: yes\n"); 946 + } else { 947 + seq_printf(seq, "present: no\n"); 948 + goto end; 949 + } 950 + 951 + if (battery->info.capacity_mode) { 952 + cscale = battery->info.vscale * battery->info.ipscale; 953 + } else { 954 + cscale = battery->info.ipscale; 955 + } 956 + seq_printf(seq, "design capacity: %i%s", 957 + battery->info.design_capacity * cscale, 958 + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 959 + 960 + seq_printf(seq, "last full capacity: %i%s", 961 + battery->info.full_charge_capacity * cscale, 962 + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 963 + 964 + seq_printf(seq, "battery technology: rechargeable\n"); 965 + 966 + seq_printf(seq, "design voltage: %i mV\n", 967 + battery->info.design_voltage * battery->info.vscale); 968 + 969 + seq_printf(seq, "design capacity warning: unknown\n"); 970 + seq_printf(seq, "design capacity low: unknown\n"); 971 + seq_printf(seq, "capacity granularity 1: unknown\n"); 972 + seq_printf(seq, "capacity granularity 2: unknown\n"); 973 + 974 + seq_printf(seq, "model number: %s\n", 975 + battery->info.device_name); 976 + 977 + seq_printf(seq, "serial number: %i\n", 978 + battery->info.serial_number); 979 + 980 + seq_printf(seq, "battery type: %s\n", 981 + battery->info.device_chemistry); 982 + 983 + seq_printf(seq, "OEM info: %s\n", 984 + battery->info.manufacturer_name); 985 + 986 + end: 987 + 988 + up(&sbs_sem); 989 + 990 + return result; 991 + } 992 + 993 + static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 994 + { 995 + return single_open(file, acpi_battery_read_info, PDE(inode)->data); 996 + } 997 + 998 + static int acpi_battery_read_state(struct seq_file *seq, void *offset) 999 + { 1000 + struct acpi_battery *battery = (struct acpi_battery *)seq->private; 1001 + int result = 0; 1002 + int cscale; 1003 + int foo; 1004 + 1005 + if (battery->sbs->zombie) { 1006 + return -ENODEV; 1007 + } 1008 + 1009 + down(&sbs_sem); 1010 + 1011 + if (update_mode == REQUEST_UPDATE_MODE) { 1012 + result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE); 1013 + if (result) { 1014 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1015 + "acpi_sbs_update_run() failed\n")); 1016 + } 1017 + } 1018 + 1019 + if (acpi_battery_is_present(battery)) { 1020 + seq_printf(seq, "present: yes\n"); 1021 + } else { 1022 + seq_printf(seq, "present: no\n"); 1023 + goto end; 1024 + } 1025 + 1026 + if (battery->info.capacity_mode) { 1027 + cscale = battery->info.vscale * battery->info.ipscale; 1028 + } else { 1029 + cscale = battery->info.ipscale; 1030 + } 1031 + 1032 + if (battery->state.battery_status & 0x0010) { 1033 + seq_printf(seq, "capacity state: critical\n"); 1034 + } else { 1035 + seq_printf(seq, "capacity state: ok\n"); 1036 + } 1037 + if (battery->state.amperage < 0) { 1038 + seq_printf(seq, "charging state: discharging\n"); 1039 + foo = battery->state.remaining_capacity * cscale * 60 / 1040 + (battery->state.average_time_to_empty == 0 ? 1 : 1041 + battery->state.average_time_to_empty); 1042 + seq_printf(seq, "present rate: %i%s\n", 1043 + foo, battery->info.capacity_mode ? "0 mW" : " mA"); 1044 + } else if (battery->state.amperage > 0) { 1045 + seq_printf(seq, "charging state: charging\n"); 1046 + foo = (battery->info.full_charge_capacity - 1047 + battery->state.remaining_capacity) * cscale * 60 / 1048 + (battery->state.average_time_to_full == 0 ? 1 : 1049 + battery->state.average_time_to_full); 1050 + seq_printf(seq, "present rate: %i%s\n", 1051 + foo, battery->info.capacity_mode ? "0 mW" : " mA"); 1052 + } else { 1053 + seq_printf(seq, "charging state: charged\n"); 1054 + seq_printf(seq, "present rate: 0 %s\n", 1055 + battery->info.capacity_mode ? "mW" : "mA"); 1056 + } 1057 + 1058 + seq_printf(seq, "remaining capacity: %i%s", 1059 + battery->state.remaining_capacity * cscale, 1060 + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 1061 + 1062 + seq_printf(seq, "present voltage: %i mV\n", 1063 + battery->state.voltage * battery->info.vscale); 1064 + 1065 + end: 1066 + 1067 + up(&sbs_sem); 1068 + 1069 + return result; 1070 + } 1071 + 1072 + static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 1073 + { 1074 + return single_open(file, acpi_battery_read_state, PDE(inode)->data); 1075 + } 1076 + 1077 + static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 1078 + { 1079 + struct acpi_battery *battery = (struct acpi_battery *)seq->private; 1080 + int result = 0; 1081 + int cscale; 1082 + 1083 + if (battery->sbs->zombie) { 1084 + return -ENODEV; 1085 + } 1086 + 1087 + down(&sbs_sem); 1088 + 1089 + if (update_mode == REQUEST_UPDATE_MODE) { 1090 + result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM); 1091 + if (result) { 1092 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1093 + "acpi_sbs_update_run() failed\n")); 1094 + } 1095 + } 1096 + 1097 + if (!acpi_battery_is_present(battery)) { 1098 + seq_printf(seq, "present: no\n"); 1099 + goto end; 1100 + } 1101 + 1102 + if (battery->info.capacity_mode) { 1103 + cscale = battery->info.vscale * battery->info.ipscale; 1104 + } else { 1105 + cscale = battery->info.ipscale; 1106 + } 1107 + 1108 + seq_printf(seq, "alarm: "); 1109 + if (battery->alarm.remaining_capacity) { 1110 + seq_printf(seq, "%i%s", 1111 + battery->alarm.remaining_capacity * cscale, 1112 + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); 1113 + } else { 1114 + seq_printf(seq, "disabled\n"); 1115 + } 1116 + 1117 + end: 1118 + 1119 + up(&sbs_sem); 1120 + 1121 + return result; 1122 + } 1123 + 1124 + static ssize_t 1125 + acpi_battery_write_alarm(struct file *file, const char __user * buffer, 1126 + size_t count, loff_t * ppos) 1127 + { 1128 + struct seq_file *seq = (struct seq_file *)file->private_data; 1129 + struct acpi_battery *battery = (struct acpi_battery *)seq->private; 1130 + char alarm_string[12] = { '\0' }; 1131 + int result, old_alarm, new_alarm; 1132 + 1133 + if (battery->sbs->zombie) { 1134 + return -ENODEV; 1135 + } 1136 + 1137 + down(&sbs_sem); 1138 + 1139 + if (!acpi_battery_is_present(battery)) { 1140 + result = -ENODEV; 1141 + goto end; 1142 + } 1143 + 1144 + if (count > sizeof(alarm_string) - 1) { 1145 + result = -EINVAL; 1146 + goto end; 1147 + } 1148 + 1149 + if (copy_from_user(alarm_string, buffer, count)) { 1150 + result = -EFAULT; 1151 + goto end; 1152 + } 1153 + 1154 + alarm_string[count] = 0; 1155 + 1156 + old_alarm = battery->alarm.remaining_capacity; 1157 + new_alarm = simple_strtoul(alarm_string, NULL, 0); 1158 + 1159 + result = acpi_battery_set_alarm(battery, new_alarm); 1160 + if (result) { 1161 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1162 + "acpi_battery_set_alarm() failed\n")); 1163 + (void)acpi_battery_set_alarm(battery, old_alarm); 1164 + goto end; 1165 + } 1166 + result = acpi_battery_get_alarm(battery); 1167 + if (result) { 1168 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1169 + "acpi_battery_get_alarm() failed\n")); 1170 + (void)acpi_battery_set_alarm(battery, old_alarm); 1171 + goto end; 1172 + } 1173 + 1174 + end: 1175 + up(&sbs_sem); 1176 + 1177 + if (result) { 1178 + return result; 1179 + } else { 1180 + return count; 1181 + } 1182 + } 1183 + 1184 + static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 1185 + { 1186 + return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); 1187 + } 1188 + 1189 + static struct file_operations acpi_battery_info_fops = { 1190 + .open = acpi_battery_info_open_fs, 1191 + .read = seq_read, 1192 + .llseek = seq_lseek, 1193 + .release = single_release, 1194 + .owner = THIS_MODULE, 1195 + }; 1196 + 1197 + static struct file_operations acpi_battery_state_fops = { 1198 + .open = acpi_battery_state_open_fs, 1199 + .read = seq_read, 1200 + .llseek = seq_lseek, 1201 + .release = single_release, 1202 + .owner = THIS_MODULE, 1203 + }; 1204 + 1205 + static struct file_operations acpi_battery_alarm_fops = { 1206 + .open = acpi_battery_alarm_open_fs, 1207 + .read = seq_read, 1208 + .write = acpi_battery_write_alarm, 1209 + .llseek = seq_lseek, 1210 + .release = single_release, 1211 + .owner = THIS_MODULE, 1212 + }; 1213 + 1214 + /* Legacy AC Adapter Interface */ 1215 + 1216 + static struct proc_dir_entry *acpi_ac_dir = NULL; 1217 + 1218 + static int acpi_ac_read_state(struct seq_file *seq, void *offset) 1219 + { 1220 + struct acpi_sbs *sbs = (struct acpi_sbs *)seq->private; 1221 + int result; 1222 + 1223 + if (sbs->zombie) { 1224 + return -ENODEV; 1225 + } 1226 + 1227 + down(&sbs_sem); 1228 + 1229 + if (update_mode == REQUEST_UPDATE_MODE) { 1230 + result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE); 1231 + if (result) { 1232 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1233 + "acpi_sbs_update_run() failed\n")); 1234 + } 1235 + } 1236 + 1237 + seq_printf(seq, "state: %s\n", 1238 + sbs->ac_present ? "on-line" : "off-line"); 1239 + 1240 + up(&sbs_sem); 1241 + 1242 + return 0; 1243 + } 1244 + 1245 + static int acpi_ac_state_open_fs(struct inode *inode, struct file *file) 1246 + { 1247 + return single_open(file, acpi_ac_read_state, PDE(inode)->data); 1248 + } 1249 + 1250 + static struct file_operations acpi_ac_state_fops = { 1251 + .open = acpi_ac_state_open_fs, 1252 + .read = seq_read, 1253 + .llseek = seq_lseek, 1254 + .release = single_release, 1255 + .owner = THIS_MODULE, 1256 + }; 1257 + 1258 + /* -------------------------------------------------------------------------- 1259 + Driver Interface 1260 + -------------------------------------------------------------------------- */ 1261 + 1262 + /* Smart Battery */ 1263 + 1264 + static int acpi_battery_add(struct acpi_sbs *sbs, int id) 1265 + { 1266 + int is_present; 1267 + int result; 1268 + char dir_name[32]; 1269 + struct acpi_battery *battery; 1270 + 1271 + battery = &sbs->battery[id]; 1272 + 1273 + battery->alive = 0; 1274 + 1275 + battery->init_state = 0; 1276 + battery->id = id; 1277 + battery->sbs = sbs; 1278 + 1279 + result = acpi_battery_select(battery); 1280 + if (result) { 1281 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1282 + "acpi_battery_select() failed\n")); 1283 + goto end; 1284 + } 1285 + 1286 + result = acpi_battery_get_present(battery); 1287 + if (result) { 1288 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1289 + "acpi_battery_get_present() failed\n")); 1290 + goto end; 1291 + } 1292 + 1293 + is_present = acpi_battery_is_present(battery); 1294 + 1295 + if (is_present) { 1296 + result = acpi_battery_init(battery); 1297 + if (result) { 1298 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1299 + "acpi_battery_init() failed\n")); 1300 + goto end; 1301 + } 1302 + battery->init_state = 1; 1303 + } 1304 + 1305 + (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); 1306 + 1307 + result = acpi_sbs_generic_add_fs(&battery->battery_entry, 1308 + acpi_battery_dir, 1309 + dir_name, 1310 + &acpi_battery_info_fops, 1311 + &acpi_battery_state_fops, 1312 + &acpi_battery_alarm_fops, battery); 1313 + if (result) { 1314 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1315 + "acpi_sbs_generic_add_fs() failed\n")); 1316 + goto end; 1317 + } 1318 + battery->alive = 1; 1319 + 1320 + end: 1321 + return result; 1322 + } 1323 + 1324 + static void acpi_battery_remove(struct acpi_sbs *sbs, int id) 1325 + { 1326 + 1327 + if (sbs->battery[id].battery_entry) { 1328 + acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry), 1329 + acpi_battery_dir); 1330 + } 1331 + } 1332 + 1333 + static int acpi_ac_add(struct acpi_sbs *sbs) 1334 + { 1335 + int result; 1336 + 1337 + result = acpi_ac_get_present(sbs); 1338 + if (result) { 1339 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1340 + "acpi_ac_get_present() failed\n")); 1341 + goto end; 1342 + } 1343 + 1344 + result = acpi_sbs_generic_add_fs(&sbs->ac_entry, 1345 + acpi_ac_dir, 1346 + ACPI_AC_DIR_NAME, 1347 + NULL, &acpi_ac_state_fops, NULL, sbs); 1348 + if (result) { 1349 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1350 + "acpi_sbs_generic_add_fs() failed\n")); 1351 + goto end; 1352 + } 1353 + 1354 + end: 1355 + 1356 + return result; 1357 + } 1358 + 1359 + static void acpi_ac_remove(struct acpi_sbs *sbs) 1360 + { 1361 + 1362 + if (sbs->ac_entry) { 1363 + acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir); 1364 + } 1365 + } 1366 + 1367 + static void acpi_sbs_update_queue_run(unsigned long data) 1368 + { 1369 + acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data); 1370 + } 1371 + 1372 + static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) 1373 + { 1374 + struct acpi_battery *battery; 1375 + int result = 0; 1376 + int old_ac_present; 1377 + int old_battery_present; 1378 + int new_ac_present; 1379 + int new_battery_present; 1380 + int id; 1381 + char dir_name[32]; 1382 + int do_battery_init, do_ac_init; 1383 + s16 old_remaining_capacity; 1384 + 1385 + if (sbs->zombie) { 1386 + goto end; 1387 + } 1388 + 1389 + old_ac_present = acpi_ac_is_present(sbs); 1390 + 1391 + result = acpi_ac_get_present(sbs); 1392 + if (result) { 1393 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1394 + "acpi_ac_get_present() failed\n")); 1395 + } 1396 + 1397 + new_ac_present = acpi_ac_is_present(sbs); 1398 + 1399 + do_ac_init = (old_ac_present != new_ac_present); 1400 + 1401 + if (data_type == DATA_TYPE_AC_STATE) { 1402 + goto end; 1403 + } 1404 + 1405 + for (id = 0; id < MAX_SBS_BAT; id++) { 1406 + battery = &sbs->battery[id]; 1407 + if (battery->alive == 0) { 1408 + continue; 1409 + } 1410 + 1411 + old_remaining_capacity = battery->state.remaining_capacity; 1412 + 1413 + old_battery_present = acpi_battery_is_present(battery); 1414 + 1415 + result = acpi_battery_select(battery); 1416 + if (result) { 1417 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1418 + "acpi_battery_select() failed\n")); 1419 + } 1420 + if (sbs->zombie) { 1421 + goto end; 1422 + } 1423 + 1424 + result = acpi_battery_get_present(battery); 1425 + if (result) { 1426 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1427 + "acpi_battery_get_present() failed\n")); 1428 + } 1429 + if (sbs->zombie) { 1430 + goto end; 1431 + } 1432 + 1433 + new_battery_present = acpi_battery_is_present(battery); 1434 + 1435 + do_battery_init = ((old_battery_present != new_battery_present) 1436 + && new_battery_present); 1437 + 1438 + if (sbs->zombie) { 1439 + goto end; 1440 + } 1441 + if (do_ac_init || do_battery_init || 1442 + update_info_mode || sbs->update_info_mode) { 1443 + if (sbs->update_info_mode) { 1444 + sbs->update_info_mode = 0; 1445 + } else { 1446 + sbs->update_info_mode = 1; 1447 + } 1448 + result = acpi_battery_init(battery); 1449 + if (result) { 1450 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1451 + "acpi_battery_init() " 1452 + "failed\n")); 1453 + } 1454 + } 1455 + if (data_type == DATA_TYPE_INFO) { 1456 + continue; 1457 + } 1458 + 1459 + if (sbs->zombie) { 1460 + goto end; 1461 + } 1462 + if (new_battery_present) { 1463 + result = acpi_battery_get_alarm(battery); 1464 + if (result) { 1465 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1466 + "acpi_battery_get_alarm() " 1467 + "failed\n")); 1468 + } 1469 + if (data_type == DATA_TYPE_ALARM) { 1470 + continue; 1471 + } 1472 + 1473 + result = acpi_battery_get_state(battery); 1474 + if (result) { 1475 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1476 + "acpi_battery_get_state() " 1477 + "failed\n")); 1478 + } 1479 + } 1480 + if (sbs->zombie) { 1481 + goto end; 1482 + } 1483 + if (data_type != DATA_TYPE_COMMON) { 1484 + continue; 1485 + } 1486 + 1487 + if (old_battery_present != new_battery_present) { 1488 + (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); 1489 + result = acpi_sbs_generate_event(sbs->device, 1490 + ACPI_SBS_BATTERY_NOTIFY_STATUS, 1491 + new_battery_present, 1492 + dir_name, 1493 + ACPI_BATTERY_CLASS); 1494 + if (result) { 1495 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1496 + "acpi_sbs_generate_event() " 1497 + "failed\n")); 1498 + } 1499 + } 1500 + if (old_remaining_capacity != battery->state.remaining_capacity) { 1501 + (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); 1502 + result = acpi_sbs_generate_event(sbs->device, 1503 + ACPI_SBS_BATTERY_NOTIFY_STATUS, 1504 + new_battery_present, 1505 + dir_name, 1506 + ACPI_BATTERY_CLASS); 1507 + if (result) { 1508 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1509 + "acpi_sbs_generate_event() failed\n")); 1510 + } 1511 + } 1512 + 1513 + } 1514 + if (sbs->zombie) { 1515 + goto end; 1516 + } 1517 + if (data_type != DATA_TYPE_COMMON) { 1518 + goto end; 1519 + } 1520 + 1521 + if (old_ac_present != new_ac_present) { 1522 + result = acpi_sbs_generate_event(sbs->device, 1523 + ACPI_SBS_AC_NOTIFY_STATUS, 1524 + new_ac_present, 1525 + ACPI_AC_DIR_NAME, 1526 + ACPI_AC_CLASS); 1527 + if (result) { 1528 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1529 + "acpi_sbs_generate_event() failed\n")); 1530 + } 1531 + } 1532 + 1533 + end: 1534 + return result; 1535 + } 1536 + 1537 + static void acpi_sbs_update_queue(void *data) 1538 + { 1539 + struct acpi_sbs *sbs = data; 1540 + unsigned long delay = -1; 1541 + int result; 1542 + 1543 + if (sbs->zombie) { 1544 + goto end; 1545 + } 1546 + 1547 + result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON); 1548 + if (result) { 1549 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1550 + "acpi_sbs_update_run() failed\n")); 1551 + } 1552 + 1553 + if (sbs->zombie) { 1554 + goto end; 1555 + } 1556 + 1557 + if (update_mode == REQUEST_UPDATE_MODE) { 1558 + goto end; 1559 + } 1560 + 1561 + delay = jiffies + HZ * update_time; 1562 + sbs->update_timer.data = (unsigned long)data; 1563 + sbs->update_timer.function = acpi_sbs_update_queue_run; 1564 + sbs->update_timer.expires = delay; 1565 + add_timer(&sbs->update_timer); 1566 + end: 1567 + ; 1568 + } 1569 + 1570 + static int acpi_sbs_add(struct acpi_device *device) 1571 + { 1572 + struct acpi_sbs *sbs = NULL; 1573 + struct acpi_ec_hc *ec_hc = NULL; 1574 + int result, remove_result = 0; 1575 + unsigned long sbs_obj; 1576 + int id, cnt; 1577 + acpi_status status = AE_OK; 1578 + 1579 + sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL); 1580 + if (!sbs) { 1581 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n")); 1582 + return -ENOMEM; 1583 + } 1584 + memset(sbs, 0, sizeof(struct acpi_sbs)); 1585 + 1586 + cnt = 0; 1587 + while (cnt < 10) { 1588 + cnt++; 1589 + ec_hc = acpi_get_ec_hc(device); 1590 + if (ec_hc) { 1591 + break; 1592 + } 1593 + msleep(1000); 1594 + } 1595 + 1596 + if (!ec_hc) { 1597 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1598 + "acpi_get_ec_hc() failed: " 1599 + "NO driver found for EC HC SMBus\n")); 1600 + result = -ENODEV; 1601 + goto end; 1602 + } 1603 + 1604 + sbs->device = device; 1605 + sbs->smbus = ec_hc->smbus; 1606 + 1607 + strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); 1608 + strcpy(acpi_device_class(device), ACPI_SBS_CLASS); 1609 + acpi_driver_data(device) = sbs; 1610 + 1611 + sbs->update_time = 0; 1612 + sbs->update_time2 = 0; 1613 + 1614 + result = acpi_ac_add(sbs); 1615 + if (result) { 1616 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_ac_add() failed\n")); 1617 + goto end; 1618 + } 1619 + result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); 1620 + if (ACPI_FAILURE(result)) { 1621 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1622 + "acpi_evaluate_integer() failed\n")); 1623 + result = -EIO; 1624 + goto end; 1625 + } 1626 + 1627 + if (sbs_obj > 0) { 1628 + result = acpi_sbsm_get_info(sbs); 1629 + if (result) { 1630 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1631 + "acpi_sbsm_get_info() failed\n")); 1632 + goto end; 1633 + } 1634 + sbs->sbsm_present = 1; 1635 + } 1636 + if (sbs->sbsm_present == 0) { 1637 + result = acpi_battery_add(sbs, 0); 1638 + if (result) { 1639 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1640 + "acpi_battery_add() failed\n")); 1641 + goto end; 1642 + } 1643 + } else { 1644 + for (id = 0; id < MAX_SBS_BAT; id++) { 1645 + if ((sbs->sbsm_batteries_supported & (1 << id))) { 1646 + result = acpi_battery_add(sbs, id); 1647 + if (result) { 1648 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1649 + "acpi_battery_add() " 1650 + "failed\n")); 1651 + goto end; 1652 + } 1653 + } 1654 + } 1655 + } 1656 + 1657 + sbs->handle = device->handle; 1658 + 1659 + init_timer(&sbs->update_timer); 1660 + if (update_mode == QUEUE_UPDATE_MODE) { 1661 + status = acpi_os_execute(OSL_GPE_HANDLER, 1662 + acpi_sbs_update_queue, (void *)sbs); 1663 + if (status != AE_OK) { 1664 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1665 + "acpi_os_execute() failed\n")); 1666 + } 1667 + } 1668 + sbs->update_time = update_time; 1669 + sbs->update_time2 = update_time2; 1670 + 1671 + printk(KERN_INFO PREFIX "%s [%s]\n", 1672 + acpi_device_name(device), acpi_device_bid(device)); 1673 + 1674 + end: 1675 + if (result) { 1676 + remove_result = acpi_sbs_remove(device, 0); 1677 + if (remove_result) { 1678 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1679 + "acpi_sbs_remove() failed\n")); 1680 + } 1681 + } 1682 + 1683 + return result; 1684 + } 1685 + 1686 + int acpi_sbs_remove(struct acpi_device *device, int type) 1687 + { 1688 + struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device); 1689 + int id; 1690 + 1691 + if (!device || !sbs) { 1692 + return -EINVAL; 1693 + } 1694 + 1695 + sbs->zombie = 1; 1696 + sbs->update_time = 0; 1697 + sbs->update_time2 = 0; 1698 + del_timer_sync(&sbs->update_timer); 1699 + acpi_os_wait_events_complete(NULL); 1700 + del_timer_sync(&sbs->update_timer); 1701 + 1702 + for (id = 0; id < MAX_SBS_BAT; id++) { 1703 + acpi_battery_remove(sbs, id); 1704 + } 1705 + 1706 + acpi_ac_remove(sbs); 1707 + 1708 + kfree(sbs); 1709 + 1710 + return 0; 1711 + } 1712 + 1713 + static int __init acpi_sbs_init(void) 1714 + { 1715 + int result = 0; 1716 + 1717 + init_MUTEX(&sbs_sem); 1718 + 1719 + if (capacity_mode != DEF_CAPACITY_UNIT 1720 + && capacity_mode != MAH_CAPACITY_UNIT 1721 + && capacity_mode != MWH_CAPACITY_UNIT) { 1722 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_sbs_init: " 1723 + "invalid capacity_mode = %d\n", 1724 + capacity_mode)); 1725 + return -EINVAL; 1726 + } 1727 + 1728 + acpi_ac_dir = acpi_lock_ac_dir(); 1729 + if (!acpi_ac_dir) { 1730 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1731 + "acpi_lock_ac_dir() failed\n")); 1732 + return -ENODEV; 1733 + } 1734 + 1735 + acpi_battery_dir = acpi_lock_battery_dir(); 1736 + if (!acpi_battery_dir) { 1737 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1738 + "acpi_lock_battery_dir() failed\n")); 1739 + return -ENODEV; 1740 + } 1741 + 1742 + result = acpi_bus_register_driver(&acpi_sbs_driver); 1743 + if (result < 0) { 1744 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1745 + "acpi_bus_register_driver() failed\n")); 1746 + return -ENODEV; 1747 + } 1748 + 1749 + return 0; 1750 + } 1751 + 1752 + static void __exit acpi_sbs_exit(void) 1753 + { 1754 + 1755 + acpi_bus_unregister_driver(&acpi_sbs_driver); 1756 + 1757 + acpi_unlock_ac_dir(acpi_ac_dir); 1758 + acpi_ac_dir = NULL; 1759 + acpi_unlock_battery_dir(acpi_battery_dir); 1760 + acpi_battery_dir = NULL; 1761 + 1762 + return; 1763 + } 1764 + 1765 + module_init(acpi_sbs_init); 1766 + module_exit(acpi_sbs_exit);