13f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend/* 2db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $) 33f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 4db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy * Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de> 5db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com> 63f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> 73f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 83f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 93f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 103f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * This program is free software; you can redistribute it and/or modify 113f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * it under the terms of the GNU General Public License as published by 123f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * the Free Software Foundation; either version 2 of the License, or (at 133f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * your option) any later version. 143f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 153f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * This program is distributed in the hope that it will be useful, but 163f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * WITHOUT ANY WARRANTY; without even the implied warranty of 173f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 183f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * General Public License for more details. 193f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 203f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * You should have received a copy of the GNU General Public License along 213f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * with this program; if not, write to the Free Software Foundation, Inc., 223f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 233f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * 243f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 253f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend */ 263f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 273f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/init.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/module.h> 303f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/moduleparam.h> 313f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/kernel.h> 3294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 33fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 343f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/proc_fs.h> 353f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/seq_file.h> 363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <asm/uaccess.h> 3766e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 3894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 393f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/acpi.h> 406d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedev#include <linux/timer.h> 41722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev#include <linux/jiffies.h> 423f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#include <linux/delay.h> 4394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy#include <linux/power_supply.h> 4494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 4591087dfa51a29b3c190e99339c4c32eb13646c51Alexey Starikovskiy#include "sbshc.h" 4691087dfa51a29b3c190e99339c4c32eb13646c51Alexey Starikovskiy 47a192a9580bcc41692be1f36b77c3b681827f566aLen Brown#define PREFIX "ACPI: " 48a192a9580bcc41692be1f36b77c3b681827f566aLen Brown 493f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_SBS_CLASS "sbs" 503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_AC_CLASS "ac_adapter" 513f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_BATTERY_CLASS "battery" 523f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_SBS_DEVICE_NAME "Smart Battery System" 533f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_SBS_FILE_INFO "info" 543f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_SBS_FILE_STATE "state" 553f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_SBS_FILE_ALARM "alarm" 563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_BATTERY_DIR_NAME "BAT%i" 573f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend#define ACPI_AC_DIR_NAME "AC0" 583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 59db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy#define ACPI_SBS_NOTIFY_STATUS 0x80 60db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy#define ACPI_SBS_NOTIFY_INFO 0x81 613f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 62db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey StarikovskiyMODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>"); 633f86b83243d59bb50caf5938d284d22e10d082a4Rich TownsendMODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); 643f86b83243d59bb50caf5938d284d22e10d082a4Rich TownsendMODULE_LICENSE("GPL"); 653f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 66db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic unsigned int cache_time = 1000; 67db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiymodule_param(cache_time, uint, 0644); 68db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey StarikovskiyMODULE_PARM_DESC(cache_time, "cache time in milliseconds"); 696d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedev 706d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedevextern struct proc_dir_entry *acpi_lock_ac_dir(void); 716d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedevextern struct proc_dir_entry *acpi_lock_battery_dir(void); 726d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedevextern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 736d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedevextern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 746d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedev 75db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy#define MAX_SBS_BAT 4 766d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedev#define ACPI_SBS_BLOCK_MAX 32 776d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedev 781ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renningerstatic const struct acpi_device_id sbs_device_ids[] = { 7991087dfa51a29b3c190e99339c4c32eb13646c51Alexey Starikovskiy {"ACPI0002", 0}, 801ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"", 0}, 811ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger}; 821ba90e3a87c46500623afdc3898573e4a5ebb21bThomas RenningerMODULE_DEVICE_TABLE(acpi, sbs_device_ids); 831ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger 843f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstruct acpi_battery { 8594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy struct power_supply bat; 863f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend struct acpi_sbs *sbs; 87fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 8889862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy struct proc_dir_entry *proc_entry; 8966e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 90db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy unsigned long update_time; 91db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy char name[8]; 9289862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy char manufacturer_name[ACPI_SBS_BLOCK_MAX]; 9389862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy char device_name[ACPI_SBS_BLOCK_MAX]; 9489862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy char device_chemistry[ACPI_SBS_BLOCK_MAX]; 9594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy u16 alarm_capacity; 9689862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 full_charge_capacity; 9789862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 design_capacity; 9889862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 design_voltage; 9989862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 serial_number; 100db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 cycle_count; 101db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 temp_now; 10289862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 voltage_now; 1037faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy s16 rate_now; 1047faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy s16 rate_avg; 10589862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 capacity_now; 106db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 state_of_charge; 10789862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 state; 10889862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u16 mode; 109db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 spec; 11089862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u8 id; 11189862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u8 present:1; 112037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik u8 have_sysfs_alarm:1; 1133f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend}; 1143f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 115497888cf69bf607ac1fe061a6437e0a670b0022fPhil Carmody#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat) 11694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 1173f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstruct acpi_sbs { 11894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy struct power_supply charger; 1193f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend struct acpi_device *device; 12091087dfa51a29b3c190e99339c4c32eb13646c51Alexey Starikovskiy struct acpi_smb_hc *hc; 121db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct mutex lock; 122fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 123db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct proc_dir_entry *charger_entry; 12466e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 1253f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend struct acpi_battery battery[MAX_SBS_BAT]; 126db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u8 batteries_supported:4; 12789862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u8 manager_present:1; 12889862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy u8 charger_present:1; 1293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend}; 1303f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 13194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) 13294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 1331dd5c715e5b7524da8c1030f5cf1ea903e45c457Lan Tianyustatic int acpi_sbs_remove(struct acpi_device *device, int type); 1341dd5c715e5b7524da8c1030f5cf1ea903e45c457Lan Tianyustatic int acpi_battery_get_state(struct acpi_battery *battery); 1351dd5c715e5b7524da8c1030f5cf1ea903e45c457Lan Tianyu 136db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic inline int battery_scale(int log) 137722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev{ 138db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int scale = 1; 139db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy while (log--) 140db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy scale *= 10; 141db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return scale; 142722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev} 143722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev 144db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic inline int acpi_battery_vscale(struct acpi_battery *battery) 145722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev{ 146db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return battery_scale((battery->spec & 0x0f00) >> 8); 147722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev} 148722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev 149db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic inline int acpi_battery_ipscale(struct acpi_battery *battery) 150722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev{ 151db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return battery_scale((battery->spec & 0xf000) >> 12); 152722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev} 153722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev 154db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic inline int acpi_battery_mode(struct acpi_battery *battery) 155722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev{ 156db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return (battery->mode & 0x8000); 157722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev} 1583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 159db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic inline int acpi_battery_scale(struct acpi_battery *battery) 1603f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 161db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return (acpi_battery_mode(battery) ? 10 : 1) * 162db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_ipscale(battery); 1633f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 1643f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 16594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic int sbs_get_ac_property(struct power_supply *psy, 16694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy enum power_supply_property psp, 16794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy union power_supply_propval *val) 16894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy{ 16994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy struct acpi_sbs *sbs = to_acpi_sbs(psy); 17094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy switch (psp) { 17194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_ONLINE: 17294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = sbs->charger_present; 17394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 17494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy default: 17594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return -EINVAL; 17694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy } 17794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return 0; 17894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy} 17994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 18094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic int acpi_battery_technology(struct acpi_battery *battery) 18194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy{ 18294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (!strcasecmp("NiCd", battery->device_chemistry)) 18394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return POWER_SUPPLY_TECHNOLOGY_NiCd; 18494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (!strcasecmp("NiMH", battery->device_chemistry)) 18594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return POWER_SUPPLY_TECHNOLOGY_NiMH; 18694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (!strcasecmp("LION", battery->device_chemistry)) 18794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return POWER_SUPPLY_TECHNOLOGY_LION; 18894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (!strcasecmp("LiP", battery->device_chemistry)) 18994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return POWER_SUPPLY_TECHNOLOGY_LIPO; 19094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 19194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy} 19294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 19394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic int acpi_sbs_battery_get_property(struct power_supply *psy, 19494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy enum power_supply_property psp, 19594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy union power_supply_propval *val) 19694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy{ 19794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy struct acpi_battery *battery = to_acpi_battery(psy); 19894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 19994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT) 20094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return -ENODEV; 2011dd5c715e5b7524da8c1030f5cf1ea903e45c457Lan Tianyu 2021dd5c715e5b7524da8c1030f5cf1ea903e45c457Lan Tianyu acpi_battery_get_state(battery); 20394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy switch (psp) { 20494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_STATUS: 2057faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy if (battery->rate_now < 0) 20694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 2077faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy else if (battery->rate_now > 0) 20894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = POWER_SUPPLY_STATUS_CHARGING; 20994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy else 21094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = POWER_SUPPLY_STATUS_FULL; 21194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 21294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_PRESENT: 21394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->present; 21494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 21594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_TECHNOLOGY: 21694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = acpi_battery_technology(battery); 21794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 21816698857fba1b10af4890055272975adf5686e83Alexey Starikovskiy case POWER_SUPPLY_PROP_CYCLE_COUNT: 21916698857fba1b10af4890055272975adf5686e83Alexey Starikovskiy val->intval = battery->cycle_count; 22016698857fba1b10af4890055272975adf5686e83Alexey Starikovskiy break; 22194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 22294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->design_voltage * 22394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_vscale(battery) * 1000; 22494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 22594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_VOLTAGE_NOW: 22694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->voltage_now * 22794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_vscale(battery) * 1000; 22894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 22994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_CURRENT_NOW: 2307faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy case POWER_SUPPLY_PROP_POWER_NOW: 2317faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy val->intval = abs(battery->rate_now) * 23294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_ipscale(battery) * 1000; 233e4108292cc5b5ca07abc83af31a78338362810caLan Tianyu val->intval *= (acpi_battery_mode(battery)) ? 234e4108292cc5b5ca07abc83af31a78338362810caLan Tianyu (battery->voltage_now * 235e4108292cc5b5ca07abc83af31a78338362810caLan Tianyu acpi_battery_vscale(battery) / 1000) : 1; 23694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 23794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_CURRENT_AVG: 2387faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy case POWER_SUPPLY_PROP_POWER_AVG: 2397faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy val->intval = abs(battery->rate_avg) * 24094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_ipscale(battery) * 1000; 241e4108292cc5b5ca07abc83af31a78338362810caLan Tianyu val->intval *= (acpi_battery_mode(battery)) ? 242e4108292cc5b5ca07abc83af31a78338362810caLan Tianyu (battery->voltage_now * 243e4108292cc5b5ca07abc83af31a78338362810caLan Tianyu acpi_battery_vscale(battery) / 1000) : 1; 24494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 24594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_CAPACITY: 24694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->state_of_charge; 24794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 24894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 24994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 25094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->design_capacity * 25194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_scale(battery) * 1000; 25294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 25394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_CHARGE_FULL: 25494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_ENERGY_FULL: 25594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->full_charge_capacity * 25694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_scale(battery) * 1000; 25794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 25894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_CHARGE_NOW: 25994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_ENERGY_NOW: 26094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->capacity_now * 26194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_scale(battery) * 1000; 26294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 26394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_TEMP: 26494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->intval = battery->temp_now - 2730; // dK -> dC 26594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 26694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_MODEL_NAME: 26794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->strval = battery->device_name; 26894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 26994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy case POWER_SUPPLY_PROP_MANUFACTURER: 27094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy val->strval = battery->manufacturer_name; 27194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy break; 27294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy default: 27394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return -EINVAL; 27494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy } 27594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return 0; 27694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy} 27794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 27894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic enum power_supply_property sbs_ac_props[] = { 27994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_ONLINE, 28094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy}; 28194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 28294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic enum power_supply_property sbs_charge_battery_props[] = { 28394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_STATUS, 28494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_PRESENT, 28594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_TECHNOLOGY, 28616698857fba1b10af4890055272975adf5686e83Alexey Starikovskiy POWER_SUPPLY_PROP_CYCLE_COUNT, 28794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 28894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_VOLTAGE_NOW, 28994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CURRENT_NOW, 29094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CURRENT_AVG, 29194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CAPACITY, 29294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 29394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CHARGE_FULL, 29494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CHARGE_NOW, 29594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_TEMP, 29694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_MODEL_NAME, 29794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_MANUFACTURER, 29894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy}; 29994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 30094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic enum power_supply_property sbs_energy_battery_props[] = { 30194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_STATUS, 30294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_PRESENT, 30394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_TECHNOLOGY, 30494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 30594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_VOLTAGE_NOW, 30694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CURRENT_NOW, 30794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CURRENT_AVG, 3087faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy POWER_SUPPLY_PROP_POWER_NOW, 3097faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy POWER_SUPPLY_PROP_POWER_AVG, 31094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_CAPACITY, 31194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 31294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_ENERGY_FULL, 31394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_ENERGY_NOW, 31494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_TEMP, 31594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_MODEL_NAME, 31694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy POWER_SUPPLY_PROP_MANUFACTURER, 31794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy}; 3187faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy 31994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 320db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy/* -------------------------------------------------------------------------- 321db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy Smart Battery System Management 322db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy -------------------------------------------------------------------------- */ 3233f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 324db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystruct acpi_battery_reader { 325db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u8 command; /* command for battery */ 326db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u8 mode; /* word or block? */ 327db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy size_t offset; /* offset inside struct acpi_sbs_battery */ 328db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy}; 3293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 330db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic struct acpi_battery_reader info_readers[] = { 331db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)}, 332db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)}, 333db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)}, 334db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)}, 335db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)}, 336db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)}, 337db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)}, 338db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)}, 339db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)}, 340db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)}, 341db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)}, 342db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy}; 3433f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 344db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic struct acpi_battery_reader state_readers[] = { 345db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)}, 346db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)}, 3477faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)}, 3487faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)}, 349db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)}, 350db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)}, 351db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)}, 352db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy}; 3533f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 354db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic int acpi_manager_get_info(struct acpi_sbs *sbs) 3553f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 3563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result = 0; 357db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 battery_system_info; 3583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 359db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, 36094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 0x04, (u8 *)&battery_system_info); 361db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!result) 362db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy sbs->batteries_supported = battery_system_info & 0x000f; 363635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 3643f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 3653f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 3663f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_get_info(struct acpi_battery *battery) 3673f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 368db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int i, result = 0; 3693f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 370db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy for (i = 0; i < ARRAY_SIZE(info_readers); ++i) { 37194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy result = acpi_smbus_read(battery->sbs->hc, 37294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy info_readers[i].mode, 37394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ACPI_SBS_BATTERY, 37494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy info_readers[i].command, 37594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy (u8 *) battery + 37694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy info_readers[i].offset); 377db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 378db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy break; 3793f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 380635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 3813f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 3823f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 3833f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_get_state(struct acpi_battery *battery) 3843f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 385db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int i, result = 0; 3863f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 38794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (battery->update_time && 38894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy time_before(jiffies, battery->update_time + 389db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy msecs_to_jiffies(cache_time))) 390db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return 0; 391db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy for (i = 0; i < ARRAY_SIZE(state_readers); ++i) { 392db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_smbus_read(battery->sbs->hc, 393db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy state_readers[i].mode, 394db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_BATTERY, 395db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy state_readers[i].command, 396db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy (u8 *)battery + 397db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy state_readers[i].offset); 398db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 3993f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 4003f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 4013f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 402db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->update_time = jiffies; 403635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 4043f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 4053f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 406db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic int acpi_battery_get_alarm(struct acpi_battery *battery) 4073f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 408db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, 409db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_BATTERY, 0x01, 41094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy (u8 *)&battery->alarm_capacity); 4113f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 4123f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 413db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic int acpi_battery_set_alarm(struct acpi_battery *battery) 4143f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 415db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct acpi_sbs *sbs = battery->sbs; 41694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy u16 value, sel = 1 << (battery->id + 12); 41794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 41894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy int ret; 41994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 4203f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 421db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (sbs->manager_present) { 42294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, 423db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy 0x01, (u8 *)&value); 42494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (ret) 42594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy goto end; 42694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if ((value & 0xf000) != sel) { 42794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy value &= 0x0fff; 42894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy value |= sel; 42994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, 43094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ACPI_SBS_MANAGER, 43194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 0x01, (u8 *)&value, 2); 43294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (ret) 43394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy goto end; 43494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy } 4353f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 43694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 43794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 0x01, (u8 *)&battery->alarm_capacity, 2); 43894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy end: 43994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy return ret; 4403f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 4413f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 4423f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_ac_get_present(struct acpi_sbs *sbs) 4433f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 444db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int result; 445db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 status; 4463f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 447db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, 448db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy 0x13, (u8 *) & status); 449db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!result) 450db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy sbs->charger_present = (status >> 15) & 0x1; 451635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 4523f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 4533f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 4548bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiystatic ssize_t acpi_battery_alarm_show(struct device *dev, 4558bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy struct device_attribute *attr, 4568bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy char *buf) 4578bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy{ 4588bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); 4598bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy acpi_battery_get_alarm(battery); 4608bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy return sprintf(buf, "%d\n", battery->alarm_capacity * 4618bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy acpi_battery_scale(battery) * 1000); 4628bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy} 4638bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy 4648bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiystatic ssize_t acpi_battery_alarm_store(struct device *dev, 4658bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy struct device_attribute *attr, 4668bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy const char *buf, size_t count) 4678bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy{ 4688bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy unsigned long x; 4698bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); 4708bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy if (sscanf(buf, "%ld\n", &x) == 1) 4718bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy battery->alarm_capacity = x / 4728bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy (1000 * acpi_battery_scale(battery)); 4738bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy if (battery->present) 4748bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy acpi_battery_set_alarm(battery); 4758bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy return count; 4768bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy} 4778bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy 4788bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiystatic struct device_attribute alarm_attr = { 47901e8ef11bc1a74e65678ed55795f59266d4add01Parag Warudkar .attr = {.name = "alarm", .mode = 0644}, 4808bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy .show = acpi_battery_alarm_show, 4818bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy .store = acpi_battery_alarm_store, 4828bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy}; 4838bd955320661cfd03ab8d5574d96aa684acd38f6Alexey Starikovskiy 4843f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend/* -------------------------------------------------------------------------- 4853f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend FS Interface (/proc/acpi) 4863f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend -------------------------------------------------------------------------- */ 4873f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 488fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 4893f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend/* Generic Routines */ 4903f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int 491db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiyacpi_sbs_add_fs(struct proc_dir_entry **dir, 49294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy struct proc_dir_entry *parent_dir, 49394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy char *dir_name, 494070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardt const struct file_operations *info_fops, 495070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardt const struct file_operations *state_fops, 496070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardt const struct file_operations *alarm_fops, void *data) 4973f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 4986d855fcdd24d2491455527c4999b4d04363f1980Zhang Rui printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded," 4996d855fcdd24d2491455527c4999b4d04363f1980Zhang Rui " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); 5003f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (!*dir) { 5013f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend *dir = proc_mkdir(dir_name, parent_dir); 5023f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (!*dir) { 503635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return -ENODEV; 5043f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 5053f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 5063f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5073f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend /* 'info' [R] */ 508cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev if (info_fops) 509cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir, 510cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev info_fops, data); 5113f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5123f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend /* 'state' [R] */ 513cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev if (state_fops) 514cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir, 515cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev state_fops, data); 5163f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5173f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend /* 'alarm' [R/W] */ 518cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev if (alarm_fops) 519cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir, 520cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev alarm_fops, data); 521635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return 0; 5223f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 5233f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5243f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic void 525db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiyacpi_sbs_remove_fs(struct proc_dir_entry **dir, 5263f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend struct proc_dir_entry *parent_dir) 5273f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 5283f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (*dir) { 5293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); 5303f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); 5313f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir); 5323f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend remove_proc_entry((*dir)->name, parent_dir); 5333f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend *dir = NULL; 5343f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 5353f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 5363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5373f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend/* Smart Battery Interface */ 5383f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic struct proc_dir_entry *acpi_battery_dir = NULL; 5393f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 540db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic inline char *acpi_battery_units(struct acpi_battery *battery) 541db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy{ 5425a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy return acpi_battery_mode(battery) ? " mW" : " mA"; 543db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy} 544db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy 545db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy 5463f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_read_info(struct seq_file *seq, void *offset) 5473f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 54850dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_battery *battery = seq->private; 549722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev struct acpi_sbs *sbs = battery->sbs; 5503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result = 0; 5513f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 552db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_lock(&sbs->lock); 5533f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 554db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy seq_printf(seq, "present: %s\n", 555db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy (battery->present) ? "yes" : "no"); 556db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!battery->present) 557722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev goto end; 5583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5595a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy seq_printf(seq, "design capacity: %i%sh\n", 560db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->design_capacity * acpi_battery_scale(battery), 561db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_units(battery)); 5625a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy seq_printf(seq, "last full capacity: %i%sh\n", 563db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->full_charge_capacity * acpi_battery_scale(battery), 564db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_units(battery)); 5653f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "battery technology: rechargeable\n"); 5663f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "design voltage: %i mV\n", 567db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->design_voltage * acpi_battery_vscale(battery)); 5683f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "design capacity warning: unknown\n"); 5693f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "design capacity low: unknown\n"); 57016698857fba1b10af4890055272975adf5686e83Alexey Starikovskiy seq_printf(seq, "cycle count: %i\n", battery->cycle_count); 5713f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "capacity granularity 1: unknown\n"); 5723f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "capacity granularity 2: unknown\n"); 573db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy seq_printf(seq, "model number: %s\n", battery->device_name); 5743f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "serial number: %i\n", 57589862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy battery->serial_number); 5763f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "battery type: %s\n", 57789862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy battery->device_chemistry); 5783f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "OEM info: %s\n", 57989862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy battery->manufacturer_name); 5803f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 581db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_unlock(&sbs->lock); 582635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 5833f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 5843f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5853f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 5863f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 5873f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend return single_open(file, acpi_battery_read_info, PDE(inode)->data); 5883f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 5893f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 5903f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_read_state(struct seq_file *seq, void *offset) 5913f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 592722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev struct acpi_battery *battery = seq->private; 593722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev struct acpi_sbs *sbs = battery->sbs; 5945a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy int rate; 5953f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 596db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_lock(&sbs->lock); 597db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy seq_printf(seq, "present: %s\n", 598db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy (battery->present) ? "yes" : "no"); 599db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!battery->present) 6003f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 6013f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 602db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_get_state(battery); 603db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy seq_printf(seq, "capacity state: %s\n", 604db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy (battery->state & 0x0010) ? "critical" : "ok"); 605db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy seq_printf(seq, "charging state: %s\n", 6067faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy (battery->rate_now < 0) ? "discharging" : 6077faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy ((battery->rate_now > 0) ? "charging" : "charged")); 6087faa144a518c456e2057918f030f50100144ccc6Alexey Starikovskiy rate = abs(battery->rate_now) * acpi_battery_ipscale(battery); 6095a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy rate *= (acpi_battery_mode(battery))?(battery->voltage_now * 6105a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy acpi_battery_vscale(battery)/1000):1; 6115a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy seq_printf(seq, "present rate: %d%s\n", rate, 6125a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy acpi_battery_units(battery)); 6135a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy seq_printf(seq, "remaining capacity: %i%sh\n", 614db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->capacity_now * acpi_battery_scale(battery), 615db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_units(battery)); 6163f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "present voltage: %i mV\n", 617db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->voltage_now * acpi_battery_vscale(battery)); 6183f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 6193f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 620db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_unlock(&sbs->lock); 6215a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy return 0; 6223f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 6233f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 6243f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 6253f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 6263f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend return single_open(file, acpi_battery_read_state, PDE(inode)->data); 6273f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 6283f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 6293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 6303f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 63150dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_battery *battery = seq->private; 632722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev struct acpi_sbs *sbs = battery->sbs; 6333f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result = 0; 6343f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 635db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_lock(&sbs->lock); 6363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 63789862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy if (!battery->present) { 6383f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "present: no\n"); 6393f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 6403f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 6413f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 642db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_get_alarm(battery); 6433f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "alarm: "); 644db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (battery->alarm_capacity) 6455a21e4fe587ebb793bf3a1c02755f8a845170328Alexey Starikovskiy seq_printf(seq, "%i%sh\n", 646db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->alarm_capacity * 647db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_scale(battery), 648db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_units(battery)); 649db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy else 6503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "disabled\n"); 6513f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 652db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_unlock(&sbs->lock); 653635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 6543f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 6553f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 6563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic ssize_t 6573f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendacpi_battery_write_alarm(struct file *file, const char __user * buffer, 6583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend size_t count, loff_t * ppos) 6593f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 66050dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct seq_file *seq = file->private_data; 66150dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_battery *battery = seq->private; 662722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev struct acpi_sbs *sbs = battery->sbs; 6633f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend char alarm_string[12] = { '\0' }; 664db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int result = 0; 665db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_lock(&sbs->lock); 66689862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy if (!battery->present) { 6673f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend result = -ENODEV; 6683f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 6693f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 6703f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (count > sizeof(alarm_string) - 1) { 6713f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend result = -EINVAL; 6723f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 6733f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 6743f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (copy_from_user(alarm_string, buffer, count)) { 6753f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend result = -EFAULT; 6763f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 6773f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 6783f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend alarm_string[count] = 0; 67994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) / 68094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy acpi_battery_scale(battery); 681db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_set_alarm(battery); 6823f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 683db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_unlock(&sbs->lock); 684db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 685635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 686db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return count; 6873f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 6883f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 6893f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 6903f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 6913f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); 6923f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 6933f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 694070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardtstatic const struct file_operations acpi_battery_info_fops = { 6953f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .open = acpi_battery_info_open_fs, 6963f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .read = seq_read, 6973f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .llseek = seq_lseek, 6983f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .release = single_release, 6993f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .owner = THIS_MODULE, 7003f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend}; 7013f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 702070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardtstatic const struct file_operations acpi_battery_state_fops = { 7033f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .open = acpi_battery_state_open_fs, 7043f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .read = seq_read, 7053f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .llseek = seq_lseek, 7063f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .release = single_release, 7073f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .owner = THIS_MODULE, 7083f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend}; 7093f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 710070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardtstatic const struct file_operations acpi_battery_alarm_fops = { 7113f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .open = acpi_battery_alarm_open_fs, 7123f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .read = seq_read, 7133f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .write = acpi_battery_write_alarm, 7143f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .llseek = seq_lseek, 7153f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .release = single_release, 7163f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .owner = THIS_MODULE, 7173f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend}; 7183f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 7193f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend/* Legacy AC Adapter Interface */ 7203f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 7213f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic struct proc_dir_entry *acpi_ac_dir = NULL; 7223f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 7233f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_ac_read_state(struct seq_file *seq, void *offset) 7243f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 7253f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 726db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct acpi_sbs *sbs = seq->private; 7273f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 728db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_lock(&sbs->lock); 7293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 7303f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend seq_printf(seq, "state: %s\n", 73189862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy sbs->charger_present ? "on-line" : "off-line"); 7323f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 733db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_unlock(&sbs->lock); 734635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return 0; 7353f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 7363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 7373f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_ac_state_open_fs(struct inode *inode, struct file *file) 7383f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 7393f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend return single_open(file, acpi_ac_read_state, PDE(inode)->data); 7403f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 7413f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 742070d8eb1f6b789206486ea6a4a1bb7745d86d314Jan Engelhardtstatic const struct file_operations acpi_ac_state_fops = { 7433f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .open = acpi_ac_state_open_fs, 7443f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .read = seq_read, 7453f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .llseek = seq_lseek, 7463f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .release = single_release, 7473f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend .owner = THIS_MODULE, 7483f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend}; 7493f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 75066e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 75166e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy 7523f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend/* -------------------------------------------------------------------------- 7533f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend Driver Interface 7543f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend -------------------------------------------------------------------------- */ 755db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic int acpi_battery_read(struct acpi_battery *battery) 7563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 757db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int result = 0, saved_present = battery->present; 758db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u16 state; 7593f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 760db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (battery->sbs->manager_present) { 761db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, 762db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_MANAGER, 0x01, (u8 *)&state); 763db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!result) 764db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->present = state & (1 << battery->id); 765db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy state &= 0x0fff; 766db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy state |= 1 << (battery->id + 12); 767db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, 768db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); 769db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy } else if (battery->id == 0) 770db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->present = 1; 771db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result || !battery->present) 772db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return result; 7733f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 774db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (saved_present != battery->present) { 775db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->update_time = 0; 776db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_battery_get_info(battery); 777db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 778db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return result; 779db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy } 780db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_battery_get_state(battery); 781db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return result; 782db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy} 7833f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 78494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy/* Smart Battery */ 785db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic int acpi_battery_add(struct acpi_sbs *sbs, int id) 786db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy{ 787db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct acpi_battery *battery = &sbs->battery[id]; 78894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy int result; 78994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 7903f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend battery->id = id; 7913f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend battery->sbs = sbs; 792db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_battery_read(battery); 793db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 794db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy return result; 7953f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 796db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); 797fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 798db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, 799db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery->name, &acpi_battery_info_fops, 800db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy &acpi_battery_state_fops, &acpi_battery_alarm_fops, 801db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy battery); 80266e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 80394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.name = battery->name; 80494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; 80594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (!acpi_battery_mode(battery)) { 80694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.properties = sbs_charge_battery_props; 80794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.num_properties = 80894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ARRAY_SIZE(sbs_charge_battery_props); 80994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy } else { 81094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.properties = sbs_energy_battery_props; 81194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.num_properties = 81294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy ARRAY_SIZE(sbs_energy_battery_props); 81394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy } 81494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy battery->bat.get_property = acpi_sbs_battery_get_property; 81594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy result = power_supply_register(&sbs->device->dev, &battery->bat); 816037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik if (result) 817037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik goto end; 818037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik result = device_create_file(battery->bat.dev, &alarm_attr); 819037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik if (result) 820037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik goto end; 821037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik battery->have_sysfs_alarm = 1; 822037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik end: 823722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", 824db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), 825bbafbecb24190959d77a8fee7bd23798b81e25c2Alexey Starikovskiy battery->name, battery->present ? "present" : "absent"); 826635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 8273f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 8283f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 8293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic void acpi_battery_remove(struct acpi_sbs *sbs, int id) 8303f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 831037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik struct acpi_battery *battery = &sbs->battery[id]; 832c19bdb6126a5e1f43b4a4fc3c4b09c926667e5efRakib Mullick 833037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik if (battery->bat.dev) { 834037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik if (battery->have_sysfs_alarm) 835037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik device_remove_file(battery->bat.dev, &alarm_attr); 836037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik power_supply_unregister(&battery->bat); 8373f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 838c2e46d2e2a8e6ed17fac6154ac7e5fa7fe4efb28Len Brown#ifdef CONFIG_ACPI_PROCFS_POWER 839037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik if (battery->proc_entry) 840037cbc63fd83162a8ee0c69680207ce4609adbeaJeff Garzik acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); 84166e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 8423f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 8433f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 844db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic int acpi_charger_add(struct acpi_sbs *sbs) 8453f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 8463f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result; 8473f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 8483f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend result = acpi_ac_get_present(sbs); 849db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 8503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 851fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 852db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, 853db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_AC_DIR_NAME, NULL, 854db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy &acpi_ac_state_fops, NULL, sbs); 855db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 8563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend goto end; 85766e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 85894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy sbs->charger.name = "sbs-charger"; 85994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; 86094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy sbs->charger.properties = sbs_ac_props; 86194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); 86294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy sbs->charger.get_property = sbs_get_ac_property; 86394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy power_supply_register(&sbs->device->dev, &sbs->charger); 864722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", 865722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), 86689862e3be1ba387c738fc2c3a5875cfd7e51c5a8Alexey Starikovskiy ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); 8673f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 868635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 8693f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 8703f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 871db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiystatic void acpi_charger_remove(struct acpi_sbs *sbs) 8723f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 87394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (sbs->charger.dev) 87494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy power_supply_unregister(&sbs->charger); 875fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 876db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (sbs->charger_entry) 877db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); 87866e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 8793f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 8803f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 881e5685b9d35c2cc0a98425b05df30cb837dd1e632Adrian Bunkstatic void acpi_sbs_callback(void *context) 8823f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 883db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int id; 884db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct acpi_sbs *sbs = context; 885db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct acpi_battery *bat; 886db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u8 saved_charger_state = sbs->charger_present; 887db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy u8 saved_battery_state; 888db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_ac_get_present(sbs); 889db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (sbs->charger_present != saved_charger_state) { 89094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy#ifdef CONFIG_ACPI_PROC_EVENT 891db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, 892db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_NOTIFY_STATUS, 893db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy sbs->charger_present); 89494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy#endif 89594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); 8963f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 897db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (sbs->manager_present) { 898db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy for (id = 0; id < MAX_SBS_BAT; ++id) { 899db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!(sbs->batteries_supported & (1 << id))) 900db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy continue; 901db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy bat = &sbs->battery[id]; 902db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy saved_battery_state = bat->present; 903db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_read(bat); 904db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (saved_battery_state == bat->present) 905db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy continue; 90694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy#ifdef CONFIG_ACPI_PROC_EVENT 907db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, 908db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy bat->name, 909db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy ACPI_SBS_NOTIFY_STATUS, 910db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy bat->present); 91194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy#endif 91294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); 9133f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 9143f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 9153f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 9163f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 9173f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int acpi_sbs_add(struct acpi_device *device) 9183f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 919db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy struct acpi_sbs *sbs; 920db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy int result = 0; 9216d15702cc07503b74494dc4f1ddb15f354987b14Vladimir Lebedev int id; 9223f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 92336bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); 9243f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (!sbs) { 925722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev result = -ENOMEM; 926722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev goto end; 9273f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 9283f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 929db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_init(&sbs->lock); 930722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev 93191087dfa51a29b3c190e99339c4c32eb13646c51Alexey Starikovskiy sbs->hc = acpi_driver_data(device->parent); 932db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy sbs->device = device; 9333f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); 9343f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend strcpy(acpi_device_class(device), ACPI_SBS_CLASS); 935db89b4f0dbab837d0f3de2c3e9427a8d5393afa3Pavel Machek device->driver_data = sbs; 9363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 937db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_charger_add(sbs); 938722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev if (result) 939722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev goto end; 9403f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 941db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy result = acpi_manager_get_info(sbs); 942db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!result) { 943db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy sbs->manager_present = 1; 944db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy for (id = 0; id < MAX_SBS_BAT; ++id) 945db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if ((sbs->batteries_supported & (1 << id))) 946db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_add(sbs, id); 947db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy } else 948db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_battery_add(sbs, 0); 949db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); 9503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend end: 951db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (result) 952db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_sbs_remove(device, 0); 953635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return result; 9543f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 9553f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 956722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedevstatic int acpi_sbs_remove(struct acpi_device *device, int type) 9573f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 958cece901481bafbf14de8cbd3a89ae869ea881055Len Brown struct acpi_sbs *sbs; 9593f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int id; 9603f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 961db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!device) 962963497c12acb4d43caa9751b9291b014eea51a1aLebedev, Vladimir P return -EINVAL; 963722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev sbs = acpi_driver_data(device); 964db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy if (!sbs) 965635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return -EINVAL; 966db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_lock(&sbs->lock); 967db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_smbus_unregister_callback(sbs->hc); 968db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy for (id = 0; id < MAX_SBS_BAT; ++id) 9693f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_battery_remove(sbs, id); 970db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_charger_remove(sbs); 971db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_unlock(&sbs->lock); 972db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy mutex_destroy(&sbs->lock); 9733f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend kfree(sbs); 974635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return 0; 9753f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 9763f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 977722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedevstatic void acpi_sbs_rmdirs(void) 978722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev{ 979fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 980722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev if (acpi_ac_dir) { 981722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_unlock_ac_dir(acpi_ac_dir); 982722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_ac_dir = NULL; 983722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev } 984722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev if (acpi_battery_dir) { 985722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_unlock_battery_dir(acpi_battery_dir); 986722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_battery_dir = NULL; 987722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev } 98866e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 989722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev} 990722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev 991722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedevstatic int acpi_sbs_resume(struct acpi_device *device) 992722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev{ 993722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev struct acpi_sbs *sbs; 994722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev if (!device) 995722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev return -EINVAL; 996722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev sbs = device->driver_data; 997db1c291af7ad748777371f25b9ff92e3e5aba38eAlexey Starikovskiy acpi_sbs_callback(sbs); 998722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev return 0; 999722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev} 1000722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev 100194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiystatic struct acpi_driver acpi_sbs_driver = { 100294f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .name = "sbs", 100394f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .class = ACPI_SBS_CLASS, 100494f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .ids = sbs_device_ids, 100594f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .ops = { 100694f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .add = acpi_sbs_add, 100794f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .remove = acpi_sbs_remove, 100894f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy .resume = acpi_sbs_resume, 100994f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy }, 101094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy}; 101194f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy 10123f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic int __init acpi_sbs_init(void) 10133f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 10143f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result = 0; 10153f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 1016b20d2aeb0ad322cbe7fd9120acae6118231b17a3Len Brown if (acpi_disabled) 1017b20d2aeb0ad322cbe7fd9120acae6118231b17a3Len Brown return -ENODEV; 1018fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 10193f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_ac_dir = acpi_lock_ac_dir(); 102094f6c0860139da9219255b8ff45ad42117dda859Alexey Starikovskiy if (!acpi_ac_dir) 1021635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return -ENODEV; 10223f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_battery_dir = acpi_lock_battery_dir(); 10233f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (!acpi_battery_dir) { 1024722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_sbs_rmdirs(); 1025635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return -ENODEV; 10263f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 102766e4b72bfa7347fd1017b9b82dce77a410f2e4a1Alexey Starikovskiy#endif 10283f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend result = acpi_bus_register_driver(&acpi_sbs_driver); 10293f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend if (result < 0) { 1030722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_sbs_rmdirs(); 1031635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return -ENODEV; 10323f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend } 1033635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return 0; 10343f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 10353f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 10363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendstatic void __exit acpi_sbs_exit(void) 10373f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend{ 10383f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_bus_unregister_driver(&acpi_sbs_driver); 1039722062334b972c31a3b83dbf7e9b5a58bb2707ddVladimir Lebedev acpi_sbs_rmdirs(); 1040635227ee89929a6e2920fc8aa1cd48f7225d3d93Len Brown return; 10413f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend} 10423f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 10433f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendmodule_init(acpi_sbs_init); 10443f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendmodule_exit(acpi_sbs_exit); 1045