2006-07-01 11:36:54 -04:00
/*
* acpi_sbs . c - ACPI Smart Battery System Driver ( $ Revision : 1.16 $ )
*
* Copyright ( c ) 2005 Rich Townsend < rhdt @ bartol . udel . edu >
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or ( at
* your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA .
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/kernel.h>
# include <linux/proc_fs.h>
# include <linux/seq_file.h>
# include <asm/uaccess.h>
# include <linux/acpi.h>
2007-03-19 17:45:50 +03:00
# include <linux/timer.h>
2007-03-19 17:45:50 +03:00
# include <linux/jiffies.h>
2006-07-01 11:36:54 -04:00
# include <linux/delay.h>
2007-09-26 19:43:28 +04:00
# include "sbshc.h"
2006-07-01 11:36:54 -04:00
# define ACPI_SBS_COMPONENT 0x00080000
# define ACPI_SBS_CLASS "sbs"
# define ACPI_AC_CLASS "ac_adapter"
# define ACPI_BATTERY_CLASS "battery"
# define ACPI_SBS_DEVICE_NAME "Smart Battery System"
# define ACPI_SBS_FILE_INFO "info"
# define ACPI_SBS_FILE_STATE "state"
# define ACPI_SBS_FILE_ALARM "alarm"
# define ACPI_BATTERY_DIR_NAME "BAT%i"
# define ACPI_AC_DIR_NAME "AC0"
# define ACPI_SBC_SMBUS_ADDR 0x9
# define ACPI_SBSM_SMBUS_ADDR 0xa
# define ACPI_SB_SMBUS_ADDR 0xb
# define ACPI_SBS_AC_NOTIFY_STATUS 0x80
# define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
# define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81
# define _COMPONENT ACPI_SBS_COMPONENT
2007-02-12 22:42:12 -05:00
ACPI_MODULE_NAME ( " sbs " ) ;
2006-07-01 11:36:54 -04:00
MODULE_AUTHOR ( " Rich Townsend " ) ;
MODULE_DESCRIPTION ( " Smart Battery System ACPI interface driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
2007-03-19 17:45:50 +03:00
# define DEF_CAPACITY_UNIT 3
# define MAH_CAPACITY_UNIT 1
# define MWH_CAPACITY_UNIT 2
# define CAPACITY_UNIT DEF_CAPACITY_UNIT
# define REQUEST_UPDATE_MODE 1
# define QUEUE_UPDATE_MODE 2
# define DATA_TYPE_COMMON 0
# define DATA_TYPE_INFO 1
# define DATA_TYPE_STATE 2
# define DATA_TYPE_ALARM 3
# define DATA_TYPE_AC_STATE 4
extern struct proc_dir_entry * acpi_lock_ac_dir ( void ) ;
extern struct proc_dir_entry * acpi_lock_battery_dir ( void ) ;
extern void acpi_unlock_ac_dir ( struct proc_dir_entry * acpi_ac_dir ) ;
extern void acpi_unlock_battery_dir ( struct proc_dir_entry * acpi_battery_dir ) ;
# define MAX_SBS_BAT 4
# define ACPI_SBS_BLOCK_MAX 32
2007-03-19 17:45:50 +03:00
# define UPDATE_DELAY 10
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
/* 0 - every time, > 0 - by update_time */
static unsigned int update_time = 120 ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
static unsigned int capacity_mode = CAPACITY_UNIT ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
module_param ( update_time , uint , 0644 ) ;
module_param ( capacity_mode , uint , 0444 ) ;
2006-07-01 11:36:54 -04:00
static int acpi_sbs_add ( struct acpi_device * device ) ;
static int acpi_sbs_remove ( struct acpi_device * device , int type ) ;
2007-03-19 17:45:50 +03:00
static int acpi_sbs_resume ( struct acpi_device * device ) ;
2006-07-01 11:36:54 -04:00
2007-07-23 14:44:41 +02:00
static const struct acpi_device_id sbs_device_ids [ ] = {
2007-09-26 19:43:28 +04:00
{ " ACPI0002 " , 0 } ,
2007-07-23 14:44:41 +02:00
{ " " , 0 } ,
} ;
MODULE_DEVICE_TABLE ( acpi , sbs_device_ids ) ;
2006-07-01 11:36:54 -04:00
static struct acpi_driver acpi_sbs_driver = {
2007-02-12 23:33:40 -05:00
. name = " sbs " ,
2006-07-01 11:36:54 -04:00
. class = ACPI_SBS_CLASS ,
2007-07-23 14:44:41 +02:00
. ids = sbs_device_ids ,
2006-07-01 11:36:54 -04:00
. ops = {
. add = acpi_sbs_add ,
. remove = acpi_sbs_remove ,
2007-03-19 17:45:50 +03:00
. resume = acpi_sbs_resume ,
2006-07-01 11:36:54 -04:00
} ,
} ;
2007-03-19 17:45:50 +03:00
struct acpi_ac {
int ac_present ;
} ;
2006-07-01 11:36:54 -04:00
struct acpi_battery_info {
int capacity_mode ;
s16 full_charge_capacity ;
s16 design_capacity ;
s16 design_voltage ;
int vscale ;
int ipscale ;
s16 serial_number ;
2007-03-19 17:45:50 +03:00
char manufacturer_name [ ACPI_SBS_BLOCK_MAX + 3 ] ;
char device_name [ ACPI_SBS_BLOCK_MAX + 3 ] ;
char device_chemistry [ ACPI_SBS_BLOCK_MAX + 3 ] ;
2006-07-01 11:36:54 -04:00
} ;
struct acpi_battery_state {
s16 voltage ;
s16 amperage ;
s16 remaining_capacity ;
2007-03-19 17:45:50 +03:00
s16 battery_state ;
2006-07-01 11:36:54 -04:00
} ;
struct acpi_battery_alarm {
s16 remaining_capacity ;
} ;
struct acpi_battery {
int alive ;
int id ;
int init_state ;
2007-03-19 17:45:50 +03:00
int battery_present ;
2006-07-01 11:36:54 -04:00
struct acpi_sbs * sbs ;
struct acpi_battery_info info ;
struct acpi_battery_state state ;
struct acpi_battery_alarm alarm ;
struct proc_dir_entry * battery_entry ;
} ;
struct acpi_sbs {
struct acpi_device * device ;
2007-09-26 19:43:28 +04:00
struct acpi_smb_hc * hc ;
2007-03-19 17:45:50 +03:00
struct mutex mutex ;
2006-07-01 11:36:54 -04:00
int sbsm_present ;
int sbsm_batteries_supported ;
struct proc_dir_entry * ac_entry ;
2007-03-19 17:45:50 +03:00
struct acpi_ac ac ;
2006-07-01 11:36:54 -04:00
struct acpi_battery battery [ MAX_SBS_BAT ] ;
int zombie ;
struct timer_list update_timer ;
2007-03-19 17:45:50 +03:00
int run_cnt ;
int update_proc_flg ;
2006-07-01 11:36:54 -04:00
} ;
2007-03-19 17:45:50 +03:00
static int acpi_sbs_update_run ( struct acpi_sbs * sbs , int id , int data_type ) ;
static void acpi_sbs_update_time ( void * data ) ;
static int sbs_zombie ( struct acpi_sbs * sbs )
{
return ( sbs - > zombie ) ;
}
static int sbs_mutex_lock ( struct acpi_sbs * sbs )
{
if ( sbs_zombie ( sbs ) ) {
return - ENODEV ;
}
mutex_lock ( & sbs - > mutex ) ;
return 0 ;
}
static void sbs_mutex_unlock ( struct acpi_sbs * sbs )
{
mutex_unlock ( & sbs - > mutex ) ;
}
2006-07-01 11:36:54 -04:00
/* --------------------------------------------------------------------------
Smart Battery System Management
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2007-03-19 17:45:50 +03:00
static int acpi_check_update_proc ( struct acpi_sbs * sbs )
{
acpi_status status = AE_OK ;
if ( update_time = = 0 ) {
sbs - > update_proc_flg = 0 ;
return 0 ;
}
if ( sbs - > update_proc_flg = = 0 ) {
status = acpi_os_execute ( OSL_GPE_HANDLER ,
acpi_sbs_update_time , sbs ) ;
if ( status ! = AE_OK ) {
ACPI_EXCEPTION ( ( AE_INFO , status ,
" acpi_os_execute() failed " ) ) ;
return 1 ;
}
sbs - > update_proc_flg = 1 ;
}
return 0 ;
}
2006-07-01 11:36:54 -04:00
static int acpi_battery_get_present ( struct acpi_battery * battery )
{
s16 state ;
int result = 0 ;
int is_present = 0 ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD ,
ACPI_SBSM_SMBUS_ADDR , 0x01 , ( u8 * ) & state ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
if ( ! result ) {
is_present = ( state & 0x000f ) & ( 1 < < battery - > id ) ;
}
battery - > battery_present = is_present ;
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_select ( struct acpi_battery * battery )
{
2007-03-19 17:45:50 +03:00
struct acpi_sbs * sbs = battery - > sbs ;
2006-07-01 11:36:54 -04:00
int result = 0 ;
s16 state ;
int foo ;
2007-03-19 17:45:50 +03:00
if ( sbs - > sbsm_present ) {
2006-07-01 11:36:54 -04:00
/* Take special care not to knobble other nibbles of
* state ( aka selector_state ) , since
* it causes charging to halt on SBSELs */
result =
2007-09-26 19:43:28 +04:00
acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SBSM_SMBUS_ADDR , 0x01 , ( u8 * ) & state ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
foo = ( state & 0x0fff ) | ( 1 < < ( battery - > id + 12 ) ) ;
result =
2007-09-26 19:43:28 +04:00
acpi_smbus_write ( battery - > sbs - > hc , SMBUS_WRITE_WORD , ACPI_SBSM_SMBUS_ADDR , 0x01 , ( u8 * ) & foo , 2 ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_write() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_sbsm_get_info ( struct acpi_sbs * sbs )
{
int result = 0 ;
s16 battery_system_info ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( sbs - > hc , SMBUS_READ_WORD , ACPI_SBSM_SMBUS_ADDR , 0x04 ,
( u8 * ) & battery_system_info ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-06-23 16:24:48 -04:00
sbs - > sbsm_present = 1 ;
2006-07-01 11:36:54 -04:00
sbs - > sbsm_batteries_supported = battery_system_info & 0x000f ;
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_get_info ( struct acpi_battery * battery )
{
int result = 0 ;
s16 battery_mode ;
s16 specification_info ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x03 ,
( u8 * ) & battery_mode ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
battery - > info . capacity_mode = ( battery_mode & 0x8000 ) > > 15 ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x10 ,
( u8 * ) & battery - > info . full_charge_capacity ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x18 ,
( u8 * ) & battery - > info . design_capacity ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x19 ,
( u8 * ) & battery - > info . design_voltage ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x1a ,
( u8 * ) & specification_info ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
switch ( ( specification_info & 0x0f00 ) > > 8 ) {
case 1 :
battery - > info . vscale = 10 ;
break ;
case 2 :
battery - > info . vscale = 100 ;
break ;
case 3 :
battery - > info . vscale = 1000 ;
break ;
default :
battery - > info . vscale = 1 ;
}
switch ( ( specification_info & 0xf000 ) > > 12 ) {
case 1 :
battery - > info . ipscale = 10 ;
break ;
case 2 :
battery - > info . ipscale = 100 ;
break ;
case 3 :
battery - > info . ipscale = 1000 ;
break ;
default :
battery - > info . ipscale = 1 ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x1c ,
( u8 * ) & battery - > info . serial_number ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_BLOCK , ACPI_SB_SMBUS_ADDR , 0x20 ,
( u8 * ) battery - > info . manufacturer_name ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_read_str() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_BLOCK , ACPI_SB_SMBUS_ADDR , 0x21 ,
( u8 * ) battery - > info . device_name ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_read_str() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_BLOCK , ACPI_SB_SMBUS_ADDR , 0x22 ,
( u8 * ) battery - > info . device_chemistry ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_read_str() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_get_state ( struct acpi_battery * battery )
{
int result = 0 ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x09 ,
( u8 * ) & battery - > state . voltage ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x0a ,
( u8 * ) & battery - > state . amperage ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x0f ,
( u8 * ) & battery - > state . remaining_capacity ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x16 ,
( u8 * ) & battery - > state . battery_state ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_get_alarm ( struct acpi_battery * battery )
{
int result = 0 ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x01 ,
( u8 * ) & battery - > alarm . remaining_capacity ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_set_alarm ( struct acpi_battery * battery ,
unsigned long alarm )
{
int result = 0 ;
s16 battery_mode ;
int foo ;
result = acpi_battery_select ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_select() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
/* If necessary, enable the alarm */
if ( alarm > 0 ) {
result =
2007-09-26 19:43:28 +04:00
acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x03 ,
( u8 * ) & battery_mode ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
battery_mode & = 0xbfff ;
2006-07-01 11:36:54 -04:00
result =
2007-09-26 19:43:28 +04:00
acpi_smbus_write ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x01 ,
( u8 * ) & battery_mode , 2 ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_write() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
}
foo = alarm / ( battery - > info . capacity_mode ? 10 : 1 ) ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_write ( battery - > sbs - > hc , SMBUS_READ_WORD , ACPI_SB_SMBUS_ADDR , 0x01 , ( u8 * ) & foo , 2 ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_write() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_set_mode ( struct acpi_battery * battery )
{
int result = 0 ;
s16 battery_mode ;
if ( capacity_mode = = DEF_CAPACITY_UNIT ) {
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD ,
ACPI_SB_SMBUS_ADDR , 0x03 , ( u8 * ) & battery_mode ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
if ( capacity_mode = = MAH_CAPACITY_UNIT ) {
battery_mode & = 0x7fff ;
} else {
battery_mode | = 0x8000 ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_write ( battery - > sbs - > hc , SMBUS_READ_WORD ,
ACPI_SB_SMBUS_ADDR , 0x03 , ( u8 * ) & battery_mode , 2 ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_write() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( battery - > sbs - > hc , SMBUS_READ_WORD ,
ACPI_SB_SMBUS_ADDR , 0x03 , ( u8 * ) & battery_mode ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_init ( struct acpi_battery * battery )
{
int result = 0 ;
result = acpi_battery_select ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-03-19 17:45:50 +03:00
" acpi_battery_select() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_battery_set_mode ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_set_mode() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_battery_get_info ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_get_info() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_battery_get_state ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_get_state() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_battery_get_alarm ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_get_alarm() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_ac_get_present ( struct acpi_sbs * sbs )
{
int result = 0 ;
s16 charger_status ;
2007-09-26 19:43:28 +04:00
result = acpi_smbus_read ( sbs - > hc , SMBUS_READ_WORD , ACPI_SBC_SMBUS_ADDR , 0x13 ,
( u8 * ) & charger_status ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:28 +04:00
" acpi_smbus_read() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
sbs - > ac . ac_present = ( charger_status & 0x8000 ) > > 15 ;
2006-07-01 11:36:54 -04:00
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
/* --------------------------------------------------------------------------
FS Interface ( / proc / acpi )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Generic Routines */
static int
acpi_sbs_generic_add_fs ( struct proc_dir_entry * * dir ,
struct proc_dir_entry * parent_dir ,
char * dir_name ,
struct file_operations * info_fops ,
struct file_operations * state_fops ,
struct file_operations * alarm_fops , void * data )
{
struct proc_dir_entry * entry = NULL ;
if ( ! * dir ) {
* dir = proc_mkdir ( dir_name , parent_dir ) ;
if ( ! * dir ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" proc_mkdir() failed " ) ) ;
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
( * dir ) - > owner = THIS_MODULE ;
}
/* 'info' [R] */
if ( info_fops ) {
entry = create_proc_entry ( ACPI_SBS_FILE_INFO , S_IRUGO , * dir ) ;
if ( ! entry ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" create_proc_entry() failed " ) ) ;
2006-07-01 11:36:54 -04:00
} else {
entry - > proc_fops = info_fops ;
entry - > data = data ;
entry - > owner = THIS_MODULE ;
}
}
/* 'state' [R] */
if ( state_fops ) {
entry = create_proc_entry ( ACPI_SBS_FILE_STATE , S_IRUGO , * dir ) ;
if ( ! entry ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" create_proc_entry() failed " ) ) ;
2006-07-01 11:36:54 -04:00
} else {
entry - > proc_fops = state_fops ;
entry - > data = data ;
entry - > owner = THIS_MODULE ;
}
}
/* 'alarm' [R/W] */
if ( alarm_fops ) {
entry = create_proc_entry ( ACPI_SBS_FILE_ALARM , S_IRUGO , * dir ) ;
if ( ! entry ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" create_proc_entry() failed " ) ) ;
2006-07-01 11:36:54 -04:00
} else {
entry - > proc_fops = alarm_fops ;
entry - > data = data ;
entry - > owner = THIS_MODULE ;
}
}
2006-07-01 16:48:23 -04:00
return 0 ;
2006-07-01 11:36:54 -04:00
}
static void
acpi_sbs_generic_remove_fs ( struct proc_dir_entry * * dir ,
struct proc_dir_entry * parent_dir )
{
if ( * dir ) {
remove_proc_entry ( ACPI_SBS_FILE_INFO , * dir ) ;
remove_proc_entry ( ACPI_SBS_FILE_STATE , * dir ) ;
remove_proc_entry ( ACPI_SBS_FILE_ALARM , * dir ) ;
remove_proc_entry ( ( * dir ) - > name , parent_dir ) ;
* dir = NULL ;
}
}
/* Smart Battery Interface */
static struct proc_dir_entry * acpi_battery_dir = NULL ;
static int acpi_battery_read_info ( struct seq_file * seq , void * offset )
{
2006-10-01 00:28:50 +02:00
struct acpi_battery * battery = seq - > private ;
2007-03-19 17:45:50 +03:00
struct acpi_sbs * sbs = battery - > sbs ;
2006-07-01 11:36:54 -04:00
int cscale ;
int result = 0 ;
2007-03-19 17:45:50 +03:00
if ( sbs_mutex_lock ( sbs ) ) {
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
result = acpi_check_update_proc ( sbs ) ;
if ( result )
goto end ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( update_time = = 0 ) {
result = acpi_sbs_update_run ( sbs , battery - > id , DATA_TYPE_INFO ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_update_run() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
2007-03-19 17:45:50 +03:00
if ( battery - > battery_present ) {
2006-07-01 11:36:54 -04:00
seq_printf ( seq , " present: yes \n " ) ;
} else {
seq_printf ( seq , " present: no \n " ) ;
goto end ;
}
if ( battery - > info . capacity_mode ) {
cscale = battery - > info . vscale * battery - > info . ipscale ;
} else {
cscale = battery - > info . ipscale ;
}
2007-03-19 17:45:50 +03:00
seq_printf ( seq , " design capacity: %i%s \n " ,
2006-07-01 11:36:54 -04:00
battery - > info . design_capacity * cscale ,
2007-03-19 17:45:50 +03:00
battery - > info . capacity_mode ? " 0 mWh " : " mAh " ) ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
seq_printf ( seq , " last full capacity: %i%s \n " ,
2006-07-01 11:36:54 -04:00
battery - > info . full_charge_capacity * cscale ,
2007-03-19 17:45:50 +03:00
battery - > info . capacity_mode ? " 0 mWh " : " mAh " ) ;
2006-07-01 11:36:54 -04:00
seq_printf ( seq , " battery technology: rechargeable \n " ) ;
seq_printf ( seq , " design voltage: %i mV \n " ,
battery - > info . design_voltage * battery - > info . vscale ) ;
seq_printf ( seq , " design capacity warning: unknown \n " ) ;
seq_printf ( seq , " design capacity low: unknown \n " ) ;
seq_printf ( seq , " capacity granularity 1: unknown \n " ) ;
seq_printf ( seq , " capacity granularity 2: unknown \n " ) ;
seq_printf ( seq , " model number: %s \n " ,
battery - > info . device_name ) ;
seq_printf ( seq , " serial number: %i \n " ,
battery - > info . serial_number ) ;
seq_printf ( seq , " battery type: %s \n " ,
battery - > info . device_chemistry ) ;
seq_printf ( seq , " OEM info: %s \n " ,
battery - > info . manufacturer_name ) ;
end :
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_info_open_fs ( struct inode * inode , struct file * file )
{
return single_open ( file , acpi_battery_read_info , PDE ( inode ) - > data ) ;
}
static int acpi_battery_read_state ( struct seq_file * seq , void * offset )
{
2007-03-19 17:45:50 +03:00
struct acpi_battery * battery = seq - > private ;
struct acpi_sbs * sbs = battery - > sbs ;
2006-07-01 11:36:54 -04:00
int result = 0 ;
int cscale ;
int foo ;
2007-03-19 17:45:50 +03:00
if ( sbs_mutex_lock ( sbs ) ) {
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
result = acpi_check_update_proc ( sbs ) ;
if ( result )
goto end ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( update_time = = 0 ) {
result = acpi_sbs_update_run ( sbs , battery - > id , DATA_TYPE_STATE ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_update_run() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
2007-03-19 17:45:50 +03:00
if ( battery - > battery_present ) {
2006-07-01 11:36:54 -04:00
seq_printf ( seq , " present: yes \n " ) ;
} else {
seq_printf ( seq , " present: no \n " ) ;
goto end ;
}
if ( battery - > info . capacity_mode ) {
cscale = battery - > info . vscale * battery - > info . ipscale ;
} else {
cscale = battery - > info . ipscale ;
}
2007-03-19 17:45:50 +03:00
if ( battery - > state . battery_state & 0x0010 ) {
2006-07-01 11:36:54 -04:00
seq_printf ( seq , " capacity state: critical \n " ) ;
} else {
seq_printf ( seq , " capacity state: ok \n " ) ;
}
2007-02-10 01:51:13 -05:00
foo = ( s16 ) battery - > state . amperage * battery - > info . ipscale ;
if ( battery - > info . capacity_mode ) {
foo = foo * battery - > info . design_voltage / 1000 ;
}
2006-07-01 11:36:54 -04:00
if ( battery - > state . amperage < 0 ) {
seq_printf ( seq , " charging state: discharging \n " ) ;
2007-02-10 01:51:13 -05:00
seq_printf ( seq , " present rate: %d %s \n " ,
- foo , battery - > info . capacity_mode ? " mW " : " mA " ) ;
2006-07-01 11:36:54 -04:00
} else if ( battery - > state . amperage > 0 ) {
seq_printf ( seq , " charging state: charging \n " ) ;
2007-02-10 01:51:13 -05:00
seq_printf ( seq , " present rate: %d %s \n " ,
foo , battery - > info . capacity_mode ? " mW " : " mA " ) ;
2006-07-01 11:36:54 -04:00
} else {
seq_printf ( seq , " charging state: charged \n " ) ;
seq_printf ( seq , " present rate: 0 %s \n " ,
battery - > info . capacity_mode ? " mW " : " mA " ) ;
}
2007-03-19 17:45:50 +03:00
seq_printf ( seq , " remaining capacity: %i%s \n " ,
2006-07-01 11:36:54 -04:00
battery - > state . remaining_capacity * cscale ,
2007-03-19 17:45:50 +03:00
battery - > info . capacity_mode ? " 0 mWh " : " mAh " ) ;
2006-07-01 11:36:54 -04:00
seq_printf ( seq , " present voltage: %i mV \n " ,
battery - > state . voltage * battery - > info . vscale ) ;
end :
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static int acpi_battery_state_open_fs ( struct inode * inode , struct file * file )
{
return single_open ( file , acpi_battery_read_state , PDE ( inode ) - > data ) ;
}
static int acpi_battery_read_alarm ( struct seq_file * seq , void * offset )
{
2006-10-01 00:28:50 +02:00
struct acpi_battery * battery = seq - > private ;
2007-03-19 17:45:50 +03:00
struct acpi_sbs * sbs = battery - > sbs ;
2006-07-01 11:36:54 -04:00
int result = 0 ;
int cscale ;
2007-03-19 17:45:50 +03:00
if ( sbs_mutex_lock ( sbs ) ) {
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
result = acpi_check_update_proc ( sbs ) ;
if ( result )
goto end ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( update_time = = 0 ) {
result = acpi_sbs_update_run ( sbs , battery - > id , DATA_TYPE_ALARM ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_update_run() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
2007-03-19 17:45:50 +03:00
if ( ! battery - > battery_present ) {
2006-07-01 11:36:54 -04:00
seq_printf ( seq , " present: no \n " ) ;
goto end ;
}
if ( battery - > info . capacity_mode ) {
cscale = battery - > info . vscale * battery - > info . ipscale ;
} else {
cscale = battery - > info . ipscale ;
}
seq_printf ( seq , " alarm: " ) ;
if ( battery - > alarm . remaining_capacity ) {
2007-03-19 17:45:50 +03:00
seq_printf ( seq , " %i%s \n " ,
2006-07-01 11:36:54 -04:00
battery - > alarm . remaining_capacity * cscale ,
2007-03-19 17:45:50 +03:00
battery - > info . capacity_mode ? " 0 mWh " : " mAh " ) ;
2006-07-01 11:36:54 -04:00
} else {
seq_printf ( seq , " disabled \n " ) ;
}
end :
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static ssize_t
acpi_battery_write_alarm ( struct file * file , const char __user * buffer ,
size_t count , loff_t * ppos )
{
2006-10-01 00:28:50 +02:00
struct seq_file * seq = file - > private_data ;
struct acpi_battery * battery = seq - > private ;
2007-03-19 17:45:50 +03:00
struct acpi_sbs * sbs = battery - > sbs ;
2006-07-01 11:36:54 -04:00
char alarm_string [ 12 ] = { ' \0 ' } ;
int result , old_alarm , new_alarm ;
2007-03-19 17:45:50 +03:00
if ( sbs_mutex_lock ( sbs ) ) {
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
result = acpi_check_update_proc ( sbs ) ;
if ( result )
goto end ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( ! battery - > battery_present ) {
2006-07-01 11:36:54 -04:00
result = - ENODEV ;
goto end ;
}
if ( count > sizeof ( alarm_string ) - 1 ) {
result = - EINVAL ;
goto end ;
}
if ( copy_from_user ( alarm_string , buffer , count ) ) {
result = - EFAULT ;
goto end ;
}
alarm_string [ count ] = 0 ;
old_alarm = battery - > alarm . remaining_capacity ;
new_alarm = simple_strtoul ( alarm_string , NULL , 0 ) ;
result = acpi_battery_set_alarm ( battery , new_alarm ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_set_alarm() failed " ) ) ;
2006-10-01 00:28:50 +02:00
acpi_battery_set_alarm ( battery , old_alarm ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_battery_get_alarm ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_get_alarm() failed " ) ) ;
2006-10-01 00:28:50 +02:00
acpi_battery_set_alarm ( battery , old_alarm ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
end :
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
} else {
2006-07-01 16:48:23 -04:00
return count ;
2006-07-01 11:36:54 -04:00
}
}
static int acpi_battery_alarm_open_fs ( struct inode * inode , struct file * file )
{
return single_open ( file , acpi_battery_read_alarm , PDE ( inode ) - > data ) ;
}
static struct file_operations acpi_battery_info_fops = {
. open = acpi_battery_info_open_fs ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static struct file_operations acpi_battery_state_fops = {
. open = acpi_battery_state_open_fs ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
static struct file_operations acpi_battery_alarm_fops = {
. open = acpi_battery_alarm_open_fs ,
. read = seq_read ,
. write = acpi_battery_write_alarm ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
/* Legacy AC Adapter Interface */
static struct proc_dir_entry * acpi_ac_dir = NULL ;
static int acpi_ac_read_state ( struct seq_file * seq , void * offset )
{
2006-10-01 00:28:50 +02:00
struct acpi_sbs * sbs = seq - > private ;
2006-07-01 11:36:54 -04:00
int result ;
2007-03-19 17:45:50 +03:00
if ( sbs_mutex_lock ( sbs ) ) {
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
if ( update_time = = 0 ) {
result = acpi_sbs_update_run ( sbs , - 1 , DATA_TYPE_AC_STATE ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_update_run() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
seq_printf ( seq , " state: %s \n " ,
2007-03-19 17:45:50 +03:00
sbs - > ac . ac_present ? " on-line " : " off-line " ) ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
2006-07-01 16:48:23 -04:00
return 0 ;
2006-07-01 11:36:54 -04:00
}
static int acpi_ac_state_open_fs ( struct inode * inode , struct file * file )
{
return single_open ( file , acpi_ac_read_state , PDE ( inode ) - > data ) ;
}
static struct file_operations acpi_ac_state_fops = {
. open = acpi_ac_state_open_fs ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. owner = THIS_MODULE ,
} ;
/* --------------------------------------------------------------------------
Driver Interface
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Smart Battery */
static int acpi_battery_add ( struct acpi_sbs * sbs , int id )
{
int is_present ;
int result ;
char dir_name [ 32 ] ;
struct acpi_battery * battery ;
battery = & sbs - > battery [ id ] ;
battery - > alive = 0 ;
battery - > init_state = 0 ;
battery - > id = id ;
battery - > sbs = sbs ;
result = acpi_battery_select ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_select() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_battery_get_present ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_get_present() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
is_present = battery - > battery_present ;
2006-07-01 11:36:54 -04:00
if ( is_present ) {
result = acpi_battery_init ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_init() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
battery - > init_state = 1 ;
}
2006-10-01 00:28:50 +02:00
sprintf ( dir_name , ACPI_BATTERY_DIR_NAME , id ) ;
2006-07-01 11:36:54 -04:00
result = acpi_sbs_generic_add_fs ( & battery - > battery_entry ,
acpi_battery_dir ,
dir_name ,
& acpi_battery_info_fops ,
& acpi_battery_state_fops ,
& acpi_battery_alarm_fops , battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_generic_add_fs() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
battery - > alive = 1 ;
2007-03-19 17:45:50 +03:00
printk ( KERN_INFO PREFIX " %s [%s]: Battery Slot [%s] (battery %s) \n " ,
ACPI_SBS_DEVICE_NAME , acpi_device_bid ( sbs - > device ) , dir_name ,
sbs - > battery - > battery_present ? " present " : " absent " ) ;
2006-07-01 11:36:54 -04:00
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static void acpi_battery_remove ( struct acpi_sbs * sbs , int id )
{
if ( sbs - > battery [ id ] . battery_entry ) {
acpi_sbs_generic_remove_fs ( & ( sbs - > battery [ id ] . battery_entry ) ,
acpi_battery_dir ) ;
}
}
static int acpi_ac_add ( struct acpi_sbs * sbs )
{
int result ;
result = acpi_ac_get_present ( sbs ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_ac_get_present() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
result = acpi_sbs_generic_add_fs ( & sbs - > ac_entry ,
acpi_ac_dir ,
ACPI_AC_DIR_NAME ,
NULL , & acpi_ac_state_fops , NULL , sbs ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_generic_add_fs() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
printk ( KERN_INFO PREFIX " %s [%s]: AC Adapter [%s] (%s) \n " ,
ACPI_SBS_DEVICE_NAME , acpi_device_bid ( sbs - > device ) ,
ACPI_AC_DIR_NAME , sbs - > ac . ac_present ? " on-line " : " off-line " ) ;
2006-07-01 11:36:54 -04:00
end :
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
static void acpi_ac_remove ( struct acpi_sbs * sbs )
{
if ( sbs - > ac_entry ) {
acpi_sbs_generic_remove_fs ( & sbs - > ac_entry , acpi_ac_dir ) ;
}
}
2007-03-19 17:45:50 +03:00
static void acpi_sbs_update_time_run ( unsigned long data )
2006-07-01 11:36:54 -04:00
{
2007-03-19 17:45:50 +03:00
acpi_os_execute ( OSL_GPE_HANDLER , acpi_sbs_update_time , ( void * ) data ) ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
static int acpi_sbs_update_run ( struct acpi_sbs * sbs , int id , int data_type )
2006-07-01 11:36:54 -04:00
{
struct acpi_battery * battery ;
2007-03-19 17:45:50 +03:00
int result = 0 , cnt ;
int old_ac_present = - 1 ;
int old_battery_present = - 1 ;
int new_ac_present = - 1 ;
int new_battery_present = - 1 ;
int id_min = 0 , id_max = MAX_SBS_BAT - 1 ;
2006-07-01 11:36:54 -04:00
char dir_name [ 32 ] ;
2007-03-19 17:45:50 +03:00
int do_battery_init = 0 , do_ac_init = 0 ;
int old_remaining_capacity = 0 ;
2007-07-09 11:33:15 -07:00
int update_battery = 1 ;
2007-03-19 17:45:50 +03:00
int up_tm = update_time ;
if ( sbs_zombie ( sbs ) ) {
goto end ;
}
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( id > = 0 ) {
id_min = id_max = id ;
}
if ( data_type = = DATA_TYPE_COMMON & & up_tm > 0 ) {
cnt = up_tm / ( up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm ) ;
if ( sbs - > run_cnt % cnt ! = 0 ) {
update_battery = 0 ;
}
}
sbs - > run_cnt + + ;
old_ac_present = sbs - > ac . ac_present ;
2006-07-01 11:36:54 -04:00
result = acpi_ac_get_present ( sbs ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_ac_get_present() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
new_ac_present = sbs - > ac . ac_present ;
2006-07-01 11:36:54 -04:00
do_ac_init = ( old_ac_present ! = new_ac_present ) ;
2007-03-19 17:45:50 +03:00
if ( sbs - > run_cnt = = 1 & & data_type = = DATA_TYPE_COMMON ) {
do_ac_init = 1 ;
}
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( do_ac_init ) {
2007-09-26 19:43:16 +04:00
result = acpi_bus_generate_proc_event4 ( ACPI_AC_CLASS ,
2007-03-19 17:45:50 +03:00
ACPI_AC_DIR_NAME ,
2007-09-26 19:43:16 +04:00
ACPI_SBS_AC_NOTIFY_STATUS ,
new_ac_present ) ;
2007-03-19 17:45:50 +03:00
if ( result ) {
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:16 +04:00
" acpi_bus_generate_event4() failed " ) ) ;
2007-03-19 17:45:50 +03:00
}
2007-09-26 19:43:16 +04:00
acpi_bus_generate_netlink_event ( ACPI_AC_CLASS , ACPI_AC_DIR_NAME ,
ACPI_SBS_AC_NOTIFY_STATUS ,
new_ac_present ) ;
2007-03-19 17:45:50 +03:00
}
if ( data_type = = DATA_TYPE_COMMON ) {
if ( ! do_ac_init & & ! update_battery ) {
goto end ;
}
}
if ( data_type = = DATA_TYPE_AC_STATE & & ! do_ac_init ) {
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
for ( id = id_min ; id < = id_max ; id + + ) {
2006-07-01 11:36:54 -04:00
battery = & sbs - > battery [ id ] ;
if ( battery - > alive = = 0 ) {
continue ;
}
old_remaining_capacity = battery - > state . remaining_capacity ;
2007-03-19 17:45:50 +03:00
old_battery_present = battery - > battery_present ;
2006-07-01 11:36:54 -04:00
result = acpi_battery_select ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_select() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
result = acpi_battery_get_present ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_get_present() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
new_battery_present = battery - > battery_present ;
2006-07-01 11:36:54 -04:00
do_battery_init = ( ( old_battery_present ! = new_battery_present )
& & new_battery_present ) ;
2007-03-19 17:45:50 +03:00
if ( ! new_battery_present )
goto event ;
if ( do_ac_init | | do_battery_init ) {
2006-07-01 11:36:54 -04:00
result = acpi_battery_init ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_init() "
" failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
2007-03-19 17:45:50 +03:00
if ( sbs_zombie ( sbs ) ) {
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
if ( ( data_type = = DATA_TYPE_COMMON
| | data_type = = DATA_TYPE_INFO )
& & new_battery_present ) {
result = acpi_battery_get_info ( battery ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-03-19 17:45:50 +03:00
" acpi_battery_get_info() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
}
if ( data_type = = DATA_TYPE_INFO ) {
continue ;
}
if ( sbs_zombie ( sbs ) ) {
goto end ;
}
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( ( data_type = = DATA_TYPE_COMMON
| | data_type = = DATA_TYPE_STATE )
& & new_battery_present ) {
2006-07-01 11:36:54 -04:00
result = acpi_battery_get_state ( battery ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-03-19 17:45:50 +03:00
" acpi_battery_get_state() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
2007-03-19 17:45:50 +03:00
if ( data_type = = DATA_TYPE_STATE ) {
goto event ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
if ( sbs_zombie ( sbs ) ) {
goto end ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
if ( ( data_type = = DATA_TYPE_COMMON
| | data_type = = DATA_TYPE_ALARM )
& & new_battery_present ) {
result = acpi_battery_get_alarm ( battery ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-03-19 17:45:50 +03:00
" acpi_battery_get_alarm() "
2007-03-19 17:45:50 +03:00
" failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
2007-03-19 17:45:50 +03:00
if ( data_type = = DATA_TYPE_ALARM ) {
continue ;
}
if ( sbs_zombie ( sbs ) ) {
goto end ;
}
event :
if ( old_battery_present ! = new_battery_present | | do_ac_init | |
old_remaining_capacity ! =
battery - > state . remaining_capacity ) {
2006-10-01 00:28:50 +02:00
sprintf ( dir_name , ACPI_BATTERY_DIR_NAME , id ) ;
2007-09-26 19:43:16 +04:00
result = acpi_bus_generate_proc_event4 ( ACPI_BATTERY_CLASS ,
2006-07-01 11:36:54 -04:00
dir_name ,
2007-09-26 19:43:16 +04:00
ACPI_SBS_BATTERY_NOTIFY_STATUS ,
new_battery_present ) ;
acpi_bus_generate_netlink_event ( ACPI_BATTERY_CLASS , dir_name ,
ACPI_SBS_BATTERY_NOTIFY_STATUS ,
new_battery_present ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-09-26 19:43:16 +04:00
" acpi_bus_generate_proc_event4() "
2007-03-19 17:45:50 +03:00
" failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
}
}
end :
2007-03-19 17:45:50 +03:00
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
static void acpi_sbs_update_time ( void * data )
2006-07-01 11:36:54 -04:00
{
struct acpi_sbs * sbs = data ;
unsigned long delay = - 1 ;
int result ;
2007-03-19 17:45:50 +03:00
unsigned int up_tm = update_time ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
if ( sbs_mutex_lock ( sbs ) )
return ;
2006-07-01 11:36:54 -04:00
2007-03-19 17:45:50 +03:00
result = acpi_sbs_update_run ( sbs , - 1 , DATA_TYPE_COMMON ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_update_run() failed " ) ) ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
if ( sbs_zombie ( sbs ) ) {
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
if ( ! up_tm ) {
if ( timer_pending ( & sbs - > update_timer ) )
del_timer ( & sbs - > update_timer ) ;
} else {
delay = ( up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm ) ;
delay = jiffies + HZ * delay ;
if ( timer_pending ( & sbs - > update_timer ) ) {
mod_timer ( & sbs - > update_timer , delay ) ;
} else {
sbs - > update_timer . data = ( unsigned long ) data ;
sbs - > update_timer . function = acpi_sbs_update_time_run ;
sbs - > update_timer . expires = delay ;
add_timer ( & sbs - > update_timer ) ;
}
2006-07-01 11:36:54 -04:00
}
end :
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
}
static int acpi_sbs_add ( struct acpi_device * device )
{
struct acpi_sbs * sbs = NULL ;
2007-03-19 17:45:50 +03:00
int result = 0 , remove_result = 0 ;
2007-03-19 17:45:50 +03:00
int id ;
2006-07-01 11:36:54 -04:00
2006-12-19 12:56:11 -08:00
sbs = kzalloc ( sizeof ( struct acpi_sbs ) , GFP_KERNEL ) ;
2006-07-01 11:36:54 -04:00
if ( ! sbs ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR , " kzalloc() failed " ) ) ;
result = - ENOMEM ;
goto end ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
mutex_init ( & sbs - > mutex ) ;
sbs_mutex_lock ( sbs ) ;
2006-07-01 11:36:54 -04:00
sbs - > device = device ;
2007-09-26 19:43:28 +04:00
sbs - > hc = acpi_driver_data ( device - > parent ) ;
2006-07-01 11:36:54 -04:00
strcpy ( acpi_device_name ( device ) , ACPI_SBS_DEVICE_NAME ) ;
strcpy ( acpi_device_class ( device ) , ACPI_SBS_CLASS ) ;
acpi_driver_data ( device ) = sbs ;
result = acpi_ac_add ( sbs ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR , " acpi_ac_add() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
2007-03-19 17:45:50 +03:00
2007-06-23 16:24:48 -04:00
acpi_sbsm_get_info ( sbs ) ;
if ( ! sbs - > sbsm_present ) {
2006-07-01 11:36:54 -04:00
result = acpi_battery_add ( sbs , 0 ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_battery_add() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
} else {
for ( id = 0 ; id < MAX_SBS_BAT ; id + + ) {
if ( ( sbs - > sbsm_batteries_supported & ( 1 < < id ) ) ) {
result = acpi_battery_add ( sbs , id ) ;
if ( result ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-03-19 17:45:50 +03:00
" acpi_battery_add() failed " ) ) ;
2006-07-01 11:36:54 -04:00
goto end ;
}
}
}
}
init_timer ( & sbs - > update_timer ) ;
2007-03-19 17:45:50 +03:00
result = acpi_check_update_proc ( sbs ) ;
if ( result )
goto end ;
2006-07-01 11:36:54 -04:00
end :
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
2006-07-01 11:36:54 -04:00
if ( result ) {
2007-03-19 17:45:50 +03:00
remove_result = acpi_sbs_remove ( device , 0 ) ;
if ( remove_result ) {
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_sbs_remove() failed " ) ) ;
}
2006-07-01 11:36:54 -04:00
}
2006-07-01 16:48:23 -04:00
return result ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
static int acpi_sbs_remove ( struct acpi_device * device , int type )
2006-07-01 11:36:54 -04:00
{
2006-12-16 01:04:27 -05:00
struct acpi_sbs * sbs ;
2006-07-01 11:36:54 -04:00
int id ;
2006-09-05 19:49:13 +04:00
if ( ! device ) {
return - EINVAL ;
}
2007-03-19 17:45:50 +03:00
sbs = acpi_driver_data ( device ) ;
2006-09-05 19:49:13 +04:00
if ( ! sbs ) {
2006-07-01 16:48:23 -04:00
return - EINVAL ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
sbs_mutex_lock ( sbs ) ;
2006-07-01 11:36:54 -04:00
sbs - > zombie = 1 ;
del_timer_sync ( & sbs - > update_timer ) ;
acpi_os_wait_events_complete ( NULL ) ;
del_timer_sync ( & sbs - > update_timer ) ;
for ( id = 0 ; id < MAX_SBS_BAT ; id + + ) {
acpi_battery_remove ( sbs , id ) ;
}
acpi_ac_remove ( sbs ) ;
2007-03-19 17:45:50 +03:00
sbs_mutex_unlock ( sbs ) ;
mutex_destroy ( & sbs - > mutex ) ;
2007-03-19 17:45:50 +03:00
2006-07-01 11:36:54 -04:00
kfree ( sbs ) ;
2006-07-01 16:48:23 -04:00
return 0 ;
2006-07-01 11:36:54 -04:00
}
2007-03-19 17:45:50 +03:00
static void acpi_sbs_rmdirs ( void )
{
if ( acpi_ac_dir ) {
acpi_unlock_ac_dir ( acpi_ac_dir ) ;
acpi_ac_dir = NULL ;
}
if ( acpi_battery_dir ) {
acpi_unlock_battery_dir ( acpi_battery_dir ) ;
acpi_battery_dir = NULL ;
}
}
static int acpi_sbs_resume ( struct acpi_device * device )
{
struct acpi_sbs * sbs ;
if ( ! device )
return - EINVAL ;
sbs = device - > driver_data ;
sbs - > run_cnt = 0 ;
return 0 ;
}
2006-07-01 11:36:54 -04:00
static int __init acpi_sbs_init ( void )
{
int result = 0 ;
2006-08-15 23:21:37 -04:00
if ( acpi_disabled )
return - ENODEV ;
2006-07-01 11:36:54 -04:00
if ( capacity_mode ! = DEF_CAPACITY_UNIT
& & capacity_mode ! = MAH_CAPACITY_UNIT
& & capacity_mode ! = MWH_CAPACITY_UNIT ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
2007-03-19 17:45:50 +03:00
" invalid capacity_mode = %d " , capacity_mode ) ) ;
2006-07-01 16:48:23 -04:00
return - EINVAL ;
2006-07-01 11:36:54 -04:00
}
acpi_ac_dir = acpi_lock_ac_dir ( ) ;
if ( ! acpi_ac_dir ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_lock_ac_dir() failed " ) ) ;
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
acpi_battery_dir = acpi_lock_battery_dir ( ) ;
if ( ! acpi_battery_dir ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_lock_battery_dir() failed " ) ) ;
2007-03-19 17:45:50 +03:00
acpi_sbs_rmdirs ( ) ;
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
result = acpi_bus_register_driver ( & acpi_sbs_driver ) ;
if ( result < 0 ) {
2007-03-19 17:45:50 +03:00
ACPI_EXCEPTION ( ( AE_INFO , AE_ERROR ,
" acpi_bus_register_driver() failed " ) ) ;
2007-03-19 17:45:50 +03:00
acpi_sbs_rmdirs ( ) ;
2006-07-01 16:48:23 -04:00
return - ENODEV ;
2006-07-01 11:36:54 -04:00
}
2006-07-01 16:48:23 -04:00
return 0 ;
2006-07-01 11:36:54 -04:00
}
static void __exit acpi_sbs_exit ( void )
{
acpi_bus_unregister_driver ( & acpi_sbs_driver ) ;
2007-03-19 17:45:50 +03:00
acpi_sbs_rmdirs ( ) ;
2006-07-01 11:36:54 -04:00
2006-07-01 16:48:23 -04:00
return ;
2006-07-01 11:36:54 -04:00
}
module_init ( acpi_sbs_init ) ;
module_exit ( acpi_sbs_exit ) ;