Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
12a5a712
Commit
12a5a712
authored
Apr 28, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull sbs into release branch
parents
14d21785
439a8888
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
682 additions
and
1040 deletions
+682
-1040
drivers/acpi/Kconfig
drivers/acpi/Kconfig
+1
-2
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-1
drivers/acpi/i2c_ec.c
drivers/acpi/i2c_ec.c
+0
-403
drivers/acpi/i2c_ec.h
drivers/acpi/i2c_ec.h
+0
-23
drivers/acpi/sbs.c
drivers/acpi/sbs.c
+680
-611
No files found.
drivers/acpi/Kconfig
View file @
12a5a712
...
...
@@ -351,11 +351,10 @@ config ACPI_HOTPLUG_MEMORY
config ACPI_SBS
tristate "Smart Battery System (EXPERIMENTAL)"
depends on X86
&& I2C
depends on X86
depends on EXPERIMENTAL
help
This driver adds support for the Smart Battery System.
Depends on I2C (Device Drivers ---> I2C support)
A "Smart Battery" is quite old and quite rare compared
to today's ACPI "Control Method" battery.
...
...
drivers/acpi/Makefile
View file @
12a5a712
...
...
@@ -59,4 +59,4 @@ obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA)
+=
toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)
+=
acpi_memhotplug.o
obj-y
+=
cm_sbs.o
obj-$(CONFIG_ACPI_SBS)
+=
i2c_ec.o
sbs.o
obj-$(CONFIG_ACPI_SBS)
+=
sbs.o
drivers/acpi/i2c_ec.c
deleted
100644 → 0
View file @
14d21785
/*
* SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $)
*
* Copyright (c) 2002, 2005 Ducrot Bruno
* Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
*
* 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 version 2.
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/delay.h>
#include "i2c_ec.h"
#define xudelay(t) udelay(t)
#define xmsleep(t) msleep(t)
#define ACPI_EC_HC_COMPONENT 0x00080000
#define ACPI_EC_HC_CLASS "ec_hc_smbus"
#define ACPI_EC_HC_HID "ACPI0001"
#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
#define _COMPONENT ACPI_EC_HC_COMPONENT
ACPI_MODULE_NAME
(
"i2c_ec"
);
static
int
acpi_ec_hc_add
(
struct
acpi_device
*
device
);
static
int
acpi_ec_hc_remove
(
struct
acpi_device
*
device
,
int
type
);
static
struct
acpi_driver
acpi_ec_hc_driver
=
{
.
name
=
"i2c_ec"
,
.
class
=
ACPI_EC_HC_CLASS
,
.
ids
=
ACPI_EC_HC_HID
,
.
ops
=
{
.
add
=
acpi_ec_hc_add
,
.
remove
=
acpi_ec_hc_remove
,
},
};
/* Various bit mask for EC_SC (R) */
#define OBF 0x01
#define IBF 0x02
#define CMD 0x08
#define BURST 0x10
#define SCI_EVT 0x20
#define SMI_EVT 0x40
/* Commands for EC_SC (W) */
#define RD_EC 0x80
#define WR_EC 0x81
#define BE_EC 0x82
#define BD_EC 0x83
#define QR_EC 0x84
/*
* ACPI 2.0 chapter 13 SMBus 2.0 EC register model
*/
#define ACPI_EC_SMB_PRTCL 0x00
/* protocol, PEC */
#define ACPI_EC_SMB_STS 0x01
/* status */
#define ACPI_EC_SMB_ADDR 0x02
/* address */
#define ACPI_EC_SMB_CMD 0x03
/* command */
#define ACPI_EC_SMB_DATA 0x04
/* 32 data registers */
#define ACPI_EC_SMB_BCNT 0x24
/* number of data bytes */
#define ACPI_EC_SMB_ALRM_A 0x25
/* alarm address */
#define ACPI_EC_SMB_ALRM_D 0x26
/* 2 bytes alarm data */
#define ACPI_EC_SMB_STS_DONE 0x80
#define ACPI_EC_SMB_STS_ALRM 0x40
#define ACPI_EC_SMB_STS_RES 0x20
#define ACPI_EC_SMB_STS_STATUS 0x1f
#define ACPI_EC_SMB_STATUS_OK 0x00
#define ACPI_EC_SMB_STATUS_FAIL 0x07
#define ACPI_EC_SMB_STATUS_DNAK 0x10
#define ACPI_EC_SMB_STATUS_DERR 0x11
#define ACPI_EC_SMB_STATUS_CMD_DENY 0x12
#define ACPI_EC_SMB_STATUS_UNKNOWN 0x13
#define ACPI_EC_SMB_STATUS_ACC_DENY 0x17
#define ACPI_EC_SMB_STATUS_TIMEOUT 0x18
#define ACPI_EC_SMB_STATUS_NOTSUP 0x19
#define ACPI_EC_SMB_STATUS_BUSY 0x1A
#define ACPI_EC_SMB_STATUS_PEC 0x1F
#define ACPI_EC_SMB_PRTCL_WRITE 0x00
#define ACPI_EC_SMB_PRTCL_READ 0x01
#define ACPI_EC_SMB_PRTCL_QUICK 0x02
#define ACPI_EC_SMB_PRTCL_BYTE 0x04
#define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06
#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
#define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c
#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define ACPI_EC_SMB_PRTCL_PEC 0x80
/* Length of pre/post transaction sleep (msec) */
#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
#define ACPI_EC_SMB_ACCESS_SLEEP1 1
#define ACPI_EC_SMB_ACCESS_SLEEP2 10
static
int
acpi_ec_smb_read
(
struct
acpi_ec_smbus
*
smbus
,
u8
address
,
u8
*
data
)
{
u8
val
;
int
err
;
err
=
ec_read
(
smbus
->
base
+
address
,
&
val
);
if
(
!
err
)
{
*
data
=
val
;
}
xmsleep
(
ACPI_EC_SMB_TRANSACTION_SLEEP
);
return
(
err
);
}
static
int
acpi_ec_smb_write
(
struct
acpi_ec_smbus
*
smbus
,
u8
address
,
u8
data
)
{
int
err
;
err
=
ec_write
(
smbus
->
base
+
address
,
data
);
return
(
err
);
}
static
int
acpi_ec_smb_access
(
struct
i2c_adapter
*
adap
,
u16
addr
,
unsigned
short
flags
,
char
read_write
,
u8
command
,
int
size
,
union
i2c_smbus_data
*
data
)
{
struct
acpi_ec_smbus
*
smbus
=
adap
->
algo_data
;
unsigned
char
protocol
,
len
=
0
,
pec
,
temp
[
2
]
=
{
0
,
0
};
int
i
;
if
(
read_write
==
I2C_SMBUS_READ
)
{
protocol
=
ACPI_EC_SMB_PRTCL_READ
;
}
else
{
protocol
=
ACPI_EC_SMB_PRTCL_WRITE
;
}
pec
=
(
flags
&
I2C_CLIENT_PEC
)
?
ACPI_EC_SMB_PRTCL_PEC
:
0
;
switch
(
size
)
{
case
I2C_SMBUS_QUICK
:
protocol
|=
ACPI_EC_SMB_PRTCL_QUICK
;
read_write
=
I2C_SMBUS_WRITE
;
break
;
case
I2C_SMBUS_BYTE
:
if
(
read_write
==
I2C_SMBUS_WRITE
)
{
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
,
data
->
byte
);
}
protocol
|=
ACPI_EC_SMB_PRTCL_BYTE
;
break
;
case
I2C_SMBUS_BYTE_DATA
:
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_CMD
,
command
);
if
(
read_write
==
I2C_SMBUS_WRITE
)
{
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
,
data
->
byte
);
}
protocol
|=
ACPI_EC_SMB_PRTCL_BYTE_DATA
;
break
;
case
I2C_SMBUS_WORD_DATA
:
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_CMD
,
command
);
if
(
read_write
==
I2C_SMBUS_WRITE
)
{
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
,
data
->
word
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
+
1
,
data
->
word
>>
8
);
}
protocol
|=
ACPI_EC_SMB_PRTCL_WORD_DATA
|
pec
;
break
;
case
I2C_SMBUS_BLOCK_DATA
:
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_CMD
,
command
);
if
(
read_write
==
I2C_SMBUS_WRITE
)
{
len
=
min_t
(
u8
,
data
->
block
[
0
],
32
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_BCNT
,
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
+
i
,
data
->
block
[
i
+
1
]);
}
protocol
|=
ACPI_EC_SMB_PRTCL_BLOCK_DATA
|
pec
;
break
;
case
I2C_SMBUS_I2C_BLOCK_DATA
:
len
=
min_t
(
u8
,
data
->
block
[
0
],
32
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_CMD
,
command
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_BCNT
,
len
);
if
(
read_write
==
I2C_SMBUS_WRITE
)
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
+
i
,
data
->
block
[
i
+
1
]);
}
}
protocol
|=
ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA
;
break
;
case
I2C_SMBUS_PROC_CALL
:
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_CMD
,
command
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
,
data
->
word
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
+
1
,
data
->
word
>>
8
);
protocol
=
ACPI_EC_SMB_PRTCL_PROC_CALL
|
pec
;
read_write
=
I2C_SMBUS_READ
;
break
;
case
I2C_SMBUS_BLOCK_PROC_CALL
:
protocol
|=
pec
;
len
=
min_t
(
u8
,
data
->
block
[
0
],
31
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_CMD
,
command
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_BCNT
,
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_DATA
+
i
,
data
->
block
[
i
+
1
]);
protocol
=
ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL
|
pec
;
read_write
=
I2C_SMBUS_READ
;
break
;
default:
ACPI_DEBUG_PRINT
((
ACPI_DB_WARN
,
"EC SMBus adapter: "
"Unsupported transaction %d
\n
"
,
size
));
return
(
-
1
);
}
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_ADDR
,
addr
<<
1
);
acpi_ec_smb_write
(
smbus
,
ACPI_EC_SMB_PRTCL
,
protocol
);
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_STS
,
temp
+
0
);
if
(
~
temp
[
0
]
&
ACPI_EC_SMB_STS_DONE
)
{
xudelay
(
500
);
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_STS
,
temp
+
0
);
}
if
(
~
temp
[
0
]
&
ACPI_EC_SMB_STS_DONE
)
{
xmsleep
(
ACPI_EC_SMB_ACCESS_SLEEP2
);
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_STS
,
temp
+
0
);
}
if
((
~
temp
[
0
]
&
ACPI_EC_SMB_STS_DONE
)
||
(
temp
[
0
]
&
ACPI_EC_SMB_STS_STATUS
))
{
return
(
-
1
);
}
if
(
read_write
==
I2C_SMBUS_WRITE
)
{
return
(
0
);
}
switch
(
size
)
{
case
I2C_SMBUS_BYTE
:
case
I2C_SMBUS_BYTE_DATA
:
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_DATA
,
&
data
->
byte
);
break
;
case
I2C_SMBUS_WORD_DATA
:
case
I2C_SMBUS_PROC_CALL
:
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_DATA
,
temp
+
0
);
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_DATA
+
1
,
temp
+
1
);
data
->
word
=
(
temp
[
1
]
<<
8
)
|
temp
[
0
];
break
;
case
I2C_SMBUS_BLOCK_DATA
:
case
I2C_SMBUS_BLOCK_PROC_CALL
:
len
=
0
;
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_BCNT
,
&
len
);
len
=
min_t
(
u8
,
len
,
32
);
case
I2C_SMBUS_I2C_BLOCK_DATA
:
for
(
i
=
0
;
i
<
len
;
i
++
)
acpi_ec_smb_read
(
smbus
,
ACPI_EC_SMB_DATA
+
i
,
data
->
block
+
i
+
1
);
data
->
block
[
0
]
=
len
;
break
;
}
return
(
0
);
}
static
u32
acpi_ec_smb_func
(
struct
i2c_adapter
*
adapter
)
{
return
(
I2C_FUNC_SMBUS_QUICK
|
I2C_FUNC_SMBUS_BYTE
|
I2C_FUNC_SMBUS_BYTE_DATA
|
I2C_FUNC_SMBUS_WORD_DATA
|
I2C_FUNC_SMBUS_BLOCK_DATA
|
I2C_FUNC_SMBUS_PROC_CALL
|
I2C_FUNC_SMBUS_BLOCK_PROC_CALL
|
I2C_FUNC_SMBUS_I2C_BLOCK
|
I2C_FUNC_SMBUS_HWPEC_CALC
);
}
static
const
struct
i2c_algorithm
acpi_ec_smbus_algorithm
=
{
.
smbus_xfer
=
acpi_ec_smb_access
,
.
functionality
=
acpi_ec_smb_func
,
};
static
int
acpi_ec_hc_add
(
struct
acpi_device
*
device
)
{
int
status
;
unsigned
long
val
;
struct
acpi_ec_hc
*
ec_hc
;
struct
acpi_ec_smbus
*
smbus
;
if
(
!
device
)
{
return
-
EINVAL
;
}
ec_hc
=
kzalloc
(
sizeof
(
struct
acpi_ec_hc
),
GFP_KERNEL
);
if
(
!
ec_hc
)
{
return
-
ENOMEM
;
}
smbus
=
kzalloc
(
sizeof
(
struct
acpi_ec_smbus
),
GFP_KERNEL
);
if
(
!
smbus
)
{
kfree
(
ec_hc
);
return
-
ENOMEM
;
}
ec_hc
->
handle
=
device
->
handle
;
strcpy
(
acpi_device_name
(
device
),
ACPI_EC_HC_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_EC_HC_CLASS
);
acpi_driver_data
(
device
)
=
ec_hc
;
status
=
acpi_evaluate_integer
(
ec_hc
->
handle
,
"_EC"
,
NULL
,
&
val
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_WARN
,
"Error obtaining _EC
\n
"
));
kfree
(
ec_hc
);
kfree
(
smbus
);
return
-
EIO
;
}
smbus
->
ec
=
acpi_driver_data
(
device
->
parent
);
smbus
->
base
=
(
val
&
0xff00ull
)
>>
8
;
smbus
->
alert
=
val
&
0xffull
;
smbus
->
adapter
.
owner
=
THIS_MODULE
;
smbus
->
adapter
.
algo
=
&
acpi_ec_smbus_algorithm
;
smbus
->
adapter
.
algo_data
=
smbus
;
smbus
->
adapter
.
dev
.
parent
=
&
device
->
dev
;
if
(
i2c_add_adapter
(
&
smbus
->
adapter
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_WARN
,
"EC SMBus adapter: Failed to register adapter
\n
"
));
kfree
(
smbus
);
kfree
(
ec_hc
);
return
-
EIO
;
}
ec_hc
->
smbus
=
smbus
;
printk
(
KERN_INFO
PREFIX
"%s [%s]
\n
"
,
acpi_device_name
(
device
),
acpi_device_bid
(
device
));
return
AE_OK
;
}
static
int
acpi_ec_hc_remove
(
struct
acpi_device
*
device
,
int
type
)
{
struct
acpi_ec_hc
*
ec_hc
;
if
(
!
device
)
{
return
-
EINVAL
;
}
ec_hc
=
acpi_driver_data
(
device
);
i2c_del_adapter
(
&
ec_hc
->
smbus
->
adapter
);
kfree
(
ec_hc
->
smbus
);
kfree
(
ec_hc
);
return
AE_OK
;
}
static
int
__init
acpi_ec_hc_init
(
void
)
{
int
result
;
result
=
acpi_bus_register_driver
(
&
acpi_ec_hc_driver
);
if
(
result
<
0
)
{
return
-
ENODEV
;
}
return
0
;
}
static
void
__exit
acpi_ec_hc_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
acpi_ec_hc_driver
);
}
struct
acpi_ec_hc
*
acpi_get_ec_hc
(
struct
acpi_device
*
device
)
{
return
acpi_driver_data
(
device
->
parent
);
}
EXPORT_SYMBOL
(
acpi_get_ec_hc
);
module_init
(
acpi_ec_hc_init
);
module_exit
(
acpi_ec_hc_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Ducrot Bruno"
);
MODULE_DESCRIPTION
(
"ACPI EC SMBus driver"
);
drivers/acpi/i2c_ec.h
deleted
100644 → 0
View file @
14d21785
/*
* SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
*
* Copyright (c) 2002, 2005 Ducrot Bruno
*
* 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 version 2.
*/
struct
acpi_ec_smbus
{
struct
i2c_adapter
adapter
;
union
acpi_ec
*
ec
;
int
base
;
int
alert
;
};
struct
acpi_ec_hc
{
acpi_handle
handle
;
struct
acpi_ec_smbus
*
smbus
;
};
struct
acpi_ec_hc
*
acpi_get_ec_hc
(
struct
acpi_device
*
device
);
drivers/acpi/sbs.c
View file @
12a5a712
...
...
@@ -30,30 +30,10 @@
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include "i2c_ec.h"
#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 ACPI_SBS_COMPONENT 0x00080000
#define ACPI_SBS_CLASS "sbs"
#define ACPI_AC_CLASS "ac_adapter"
...
...
@@ -74,39 +54,75 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
#define _COMPONENT ACPI_SBS_COMPONENT
#define MAX_SBS_BAT 4
#define MAX_SMBUS_ERR 1
ACPI_MODULE_NAME
(
"sbs"
);
MODULE_AUTHOR
(
"Rich Townsend"
);
MODULE_DESCRIPTION
(
"Smart Battery System ACPI interface driver"
);
MODULE_LICENSE
(
"GPL"
);
static
struct
semaphore
sbs_sem
;
#define xmsleep(t) msleep(t)
#define ACPI_EC_SMB_PRTCL 0x00
/* protocol, PEC */
#define ACPI_EC_SMB_STS 0x01
/* status */
#define ACPI_EC_SMB_ADDR 0x02
/* address */
#define ACPI_EC_SMB_CMD 0x03
/* command */
#define ACPI_EC_SMB_DATA 0x04
/* 32 data registers */
#define ACPI_EC_SMB_BCNT 0x24
/* number of data bytes */
#define UPDATE_MODE QUEUE_UPDATE_MODE
/* REQUEST_UPDATE_MODE QUEUE_UPDATE_MODE */
#define UPDATE_INFO_MODE 0
#define UPDATE_TIME 60
#define UPDATE_TIME2 0
#define ACPI_EC_SMB_STS_DONE 0x80
#define ACPI_EC_SMB_STS_STATUS 0x1f
static
int
capacity_mode
=
CAPACITY_UNIT
;
static
int
update_mode
=
UPDATE_MODE
;
static
int
update_info_mode
=
UPDATE_INFO_MODE
;
static
int
update_time
=
UPDATE_TIME
;
static
int
update_time2
=
UPDATE_TIME2
;
#define ACPI_EC_SMB_PRTCL_WRITE 0x00
#define ACPI_EC_SMB_PRTCL_READ 0x01
#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
module_param
(
capacity_mode
,
int
,
0
);
module_param
(
update_mode
,
int
,
0
);
module_param
(
update_info_mode
,
int
,
0
);
module_param
(
update_time
,
int
,
0
);
module_param
(
update_time2
,
int
,
0
);
#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
#define ACPI_EC_SMB_ACCESS_SLEEP1 1
#define ACPI_EC_SMB_ACCESS_SLEEP2 10
#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
#define ACPI_SBS_SMBUS_READ 1
#define ACPI_SBS_SMBUS_WRITE 2
#define ACPI_SBS_WORD_DATA 1
#define ACPI_SBS_BLOCK_DATA 2
#define UPDATE_DELAY 10
/* 0 - every time, > 0 - by update_time */
static
unsigned
int
update_time
=
120
;
static
unsigned
int
capacity_mode
=
CAPACITY_UNIT
;
module_param
(
update_time
,
uint
,
0644
);
module_param
(
capacity_mode
,
uint
,
0444
);
static
int
acpi_sbs_add
(
struct
acpi_device
*
device
);
static
int
acpi_sbs_remove
(
struct
acpi_device
*
device
,
int
type
);
static
void
acpi_battery_smbus_err_handler
(
struct
acpi_ec_smbus
*
smbus
);
static
void
acpi_sbs_update_queue
(
void
*
data
);
static
int
acpi_sbs_resume
(
struct
acpi_device
*
device
);
static
struct
acpi_driver
acpi_sbs_driver
=
{
.
name
=
"sbs"
,
...
...
@@ -115,9 +131,14 @@ static struct acpi_driver acpi_sbs_driver = {
.
ops
=
{
.
add
=
acpi_sbs_add
,
.
remove
=
acpi_sbs_remove
,
.
resume
=
acpi_sbs_resume
,
},
};
struct
acpi_ac
{
int
ac_present
;
};
struct
acpi_battery_info
{
int
capacity_mode
;
s16
full_charge_capacity
;
...
...
@@ -126,18 +147,16 @@ struct acpi_battery_info {
int
vscale
;
int
ipscale
;
s16
serial_number
;
char
manufacturer_name
[
I2C_SMBU
S_BLOCK_MAX
+
3
];
char
device_name
[
I2C_SMBU
S_BLOCK_MAX
+
3
];
char
device_chemistry
[
I2C_SMBU
S_BLOCK_MAX
+
3
];
char
manufacturer_name
[
ACPI_SB
S_BLOCK_MAX
+
3
];
char
device_name
[
ACPI_SB
S_BLOCK_MAX
+
3
];
char
device_chemistry
[
ACPI_SB
S_BLOCK_MAX
+
3
];
};
struct
acpi_battery_state
{
s16
voltage
;
s16
amperage
;
s16
remaining_capacity
;
s16
average_time_to_empty
;
s16
average_time_to_full
;
s16
battery_status
;
s16
battery_state
;
};
struct
acpi_battery_alarm
{
...
...
@@ -146,9 +165,9 @@ struct acpi_battery_alarm {
struct
acpi_battery
{
int
alive
;
int
battery_present
;
int
id
;
int
init_state
;
int
battery_present
;
struct
acpi_sbs
*
sbs
;
struct
acpi_battery_info
info
;
struct
acpi_battery_state
state
;
...
...
@@ -158,186 +177,251 @@ struct acpi_battery {
struct
acpi_sbs
{
acpi_handle
handle
;
int
base
;
struct
acpi_device
*
device
;
struct
acpi_ec_smbus
*
smbus
;
struct
mutex
mutex
;
int
sbsm_present
;
int
sbsm_batteries_supported
;
int
ac_present
;
struct
proc_dir_entry
*
ac_entry
;
struct
acpi_ac
ac
;
struct
acpi_battery
battery
[
MAX_SBS_BAT
];
int
update_info_mode
;
int
zombie
;
int
update_time
;
int
update_time2
;
struct
timer_list
update_timer
;
int
run_cnt
;
int
update_proc_flg
;
};
static
void
acpi_update_delay
(
struct
acpi_sbs
*
sbs
);
static
int
acpi_sbs_update_run
(
struct
acpi_sbs
*
sbs
,
int
data_type
);
static
int
acpi_sbs_update_run
(
struct
acpi_sbs
*
sbs
,
int
id
,
int
data_type
);
static
void
acpi_sbs_update_time
(
void
*
data
);
union
sbs_rw_data
{
u16
word
;
u8
block
[
ACPI_SBS_BLOCK_MAX
+
2
];
};
static
int
acpi_ec_sbs_access
(
struct
acpi_sbs
*
sbs
,
u16
addr
,
char
read_write
,
u8
command
,
int
size
,
union
sbs_rw_data
*
data
);
/* --------------------------------------------------------------------------
SMBus Communication
-------------------------------------------------------------------------- */
static
void
acpi_battery_smbus_err_handler
(
struct
acpi_ec_smbus
*
smbus
)
static
int
acpi_ec_sbs_read
(
struct
acpi_sbs
*
sbs
,
u8
address
,
u8
*
data
)
{
union
i2c_smbus_data
data
;
int
result
=
0
;
char
*
err_str
;
int
err_number
;
u8
val
;
int
err
;
data
.
word
=
0
;
err
=
ec_read
(
sbs
->
base
+
address
,
&
val
);
if
(
!
err
)
{
*
data
=
val
;
}
xmsleep
(
ACPI_EC_SMB_TRANSACTION_SLEEP
);
return
(
err
);
}
result
=
smbus
->
adapter
.
algo
->
smbus_xfer
(
&
smbus
->
adapter
,
ACPI_SB_SMBUS_ADDR
,
0
,
I2C_SMBUS_READ
,
0x16
,
I2C_SMBUS_BLOCK_DATA
,
&
data
);
static
int
acpi_ec_sbs_write
(
struct
acpi_sbs
*
sbs
,
u8
address
,
u8
data
)
{
int
err
;
err_number
=
(
data
.
word
&
0x000f
);
err
=
ec_write
(
sbs
->
base
+
address
,
data
);
return
(
err
);
}
switch
(
data
.
word
&
0x000f
)
{
case
0x0000
:
err_str
=
"unexpected bus error"
;
break
;
case
0x0001
:
err_str
=
"busy"
;
break
;
case
0x0002
:
err_str
=
"reserved command"
;
break
;
case
0x0003
:
err_str
=
"unsupported command"
;
break
;
case
0x0004
:
err_str
=
"access denied"
;
static
int
acpi_ec_sbs_access
(
struct
acpi_sbs
*
sbs
,
u16
addr
,
char
read_write
,
u8
command
,
int
size
,
union
sbs_rw_data
*
data
)
{
unsigned
char
protocol
,
len
=
0
,
temp
[
2
]
=
{
0
,
0
};
int
i
;
if
(
read_write
==
ACPI_SBS_SMBUS_READ
)
{
protocol
=
ACPI_EC_SMB_PRTCL_READ
;
}
else
{
protocol
=
ACPI_EC_SMB_PRTCL_WRITE
;
}
switch
(
size
)
{
case
ACPI_SBS_WORD_DATA
:
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_CMD
,
command
);
if
(
read_write
==
ACPI_SBS_SMBUS_WRITE
)
{
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_DATA
,
data
->
word
);
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_DATA
+
1
,
data
->
word
>>
8
);
}
protocol
|=
ACPI_EC_SMB_PRTCL_WORD_DATA
;
break
;
case
0x0005
:
err_str
=
"overflow/underflow"
;
case
ACPI_SBS_BLOCK_DATA
:
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_CMD
,
command
);
if
(
read_write
==
ACPI_SBS_SMBUS_WRITE
)
{
len
=
min_t
(
u8
,
data
->
block
[
0
],
32
);
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_BCNT
,
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_DATA
+
i
,
data
->
block
[
i
+
1
]);
}
protocol
|=
ACPI_EC_SMB_PRTCL_BLOCK_DATA
;
break
;
case
0x0006
:
err_str
=
"bad size"
;
default:
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"unsupported transaction %d"
,
size
));
return
(
-
1
);
}
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_ADDR
,
addr
<<
1
);
acpi_ec_sbs_write
(
sbs
,
ACPI_EC_SMB_PRTCL
,
protocol
);
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_STS
,
temp
);
if
(
~
temp
[
0
]
&
ACPI_EC_SMB_STS_DONE
)
{
xmsleep
(
ACPI_EC_SMB_ACCESS_SLEEP1
);
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_STS
,
temp
);
}
if
(
~
temp
[
0
]
&
ACPI_EC_SMB_STS_DONE
)
{
xmsleep
(
ACPI_EC_SMB_ACCESS_SLEEP2
);
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_STS
,
temp
);
}
if
((
~
temp
[
0
]
&
ACPI_EC_SMB_STS_DONE
)
||
(
temp
[
0
]
&
ACPI_EC_SMB_STS_STATUS
))
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"transaction %d error"
,
size
));
return
(
-
1
);
}
if
(
read_write
==
ACPI_SBS_SMBUS_WRITE
)
{
return
(
0
);
}
switch
(
size
)
{
case
ACPI_SBS_WORD_DATA
:
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_DATA
,
temp
);
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_DATA
+
1
,
temp
+
1
);
data
->
word
=
(
temp
[
1
]
<<
8
)
|
temp
[
0
];
break
;
case
0x0007
:
err_str
=
"unknown error"
;
case
ACPI_SBS_BLOCK_DATA
:
len
=
0
;
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_BCNT
,
&
len
);
len
=
min_t
(
u8
,
len
,
32
);
for
(
i
=
0
;
i
<
len
;
i
++
)
acpi_ec_sbs_read
(
sbs
,
ACPI_EC_SMB_DATA
+
i
,
data
->
block
+
i
+
1
);
data
->
block
[
0
]
=
len
;
break
;
default:
err_str
=
"unrecognized error"
;
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"unsupported transaction %d"
,
size
));
return
(
-
1
);
}
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"%s: ret %i, err %i
\n
"
,
err_str
,
result
,
err_number
)
);
return
(
0
);
}
static
int
acpi_sbs_smbus_read_word
(
struct
acpi_ec_smbus
*
smbus
,
int
addr
,
int
func
,
u16
*
word
,
void
(
*
err_handler
)
(
struct
acpi_ec_smbus
*
smbus
))
acpi_sbs_read_word
(
struct
acpi_sbs
*
sbs
,
int
addr
,
int
func
,
u16
*
word
)
{
union
i2c_smbus
_data
data
;
union
sbs_rw
_data
data
;
int
result
=
0
;
int
i
;
if
(
err_handler
==
NULL
)
{
err_handler
=
acpi_battery_smbus_err_handler
;
}
for
(
i
=
0
;
i
<
MAX_SMBUS_ERR
;
i
++
)
{
result
=
smbus
->
adapter
.
algo
->
smbus_xfer
(
&
smbus
->
adapter
,
addr
,
0
,
I2C_SMBUS_READ
,
func
,
I2C_SMBUS_WORD_DATA
,
&
data
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"try %i: smbus->adapter.algo->smbus_xfer() failed
\n
"
,
i
));
if
(
err_handler
)
{
err_handler
(
smbus
);
}
}
else
{
*
word
=
data
.
word
;
break
;
}
result
=
acpi_ec_sbs_access
(
sbs
,
addr
,
ACPI_SBS_SMBUS_READ
,
func
,
ACPI_SBS_WORD_DATA
,
&
data
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ec_sbs_access() failed"
));
}
else
{
*
word
=
data
.
word
;
}
return
result
;
}
static
int
acpi_sbs_smbus_read_str
(
struct
acpi_ec_smbus
*
smbus
,
int
addr
,
int
func
,
char
*
str
,
void
(
*
err_handler
)
(
struct
acpi_ec_smbus
*
smbus
))
acpi_sbs_read_str
(
struct
acpi_sbs
*
sbs
,
int
addr
,
int
func
,
char
*
str
)
{
union
i2c_smbus
_data
data
;
union
sbs_rw
_data
data
;
int
result
=
0
;
int
i
;
if
(
err_handler
==
NULL
)
{
err_handler
=
acpi_battery_smbus_err_handler
;
}
for
(
i
=
0
;
i
<
MAX_SMBUS_ERR
;
i
++
)
{
result
=
smbus
->
adapter
.
algo
->
smbus_xfer
(
&
smbus
->
adapter
,
addr
,
0
,
I2C_SMBUS_READ
,
func
,
I2C_SMBUS_BLOCK_DATA
,
&
data
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"try %i: smbus->adapter.algo->smbus_xfer() failed
\n
"
,
i
));
if
(
err_handler
)
{
err_handler
(
smbus
);
}
}
else
{
strncpy
(
str
,
(
const
char
*
)
data
.
block
+
1
,
data
.
block
[
0
]);
str
[
data
.
block
[
0
]]
=
0
;
break
;
}
result
=
acpi_ec_sbs_access
(
sbs
,
addr
,
ACPI_SBS_SMBUS_READ
,
func
,
ACPI_SBS_BLOCK_DATA
,
&
data
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ec_sbs_access() failed"
));
}
else
{
strncpy
(
str
,
(
const
char
*
)
data
.
block
+
1
,
data
.
block
[
0
]);
str
[
data
.
block
[
0
]]
=
0
;
}
return
result
;
}
static
int
acpi_sbs_smbus_write_word
(
struct
acpi_ec_smbus
*
smbus
,
int
addr
,
int
func
,
int
word
,
void
(
*
err_handler
)
(
struct
acpi_ec_smbus
*
smbus
))
acpi_sbs_write_word
(
struct
acpi_sbs
*
sbs
,
int
addr
,
int
func
,
int
word
)
{
union
i2c_smbus
_data
data
;
union
sbs_rw
_data
data
;
int
result
=
0
;
int
i
;
if
(
err_handler
==
NULL
)
{
err_handler
=
acpi_battery_smbus_err_handler
;
}
data
.
word
=
word
;
for
(
i
=
0
;
i
<
MAX_SMBUS_ERR
;
i
++
)
{
result
=
smbus
->
adapter
.
algo
->
smbus_xfer
(
&
smbus
->
adapter
,
addr
,
0
,
I2C_SMBUS_WRITE
,
func
,
I2C_SMBUS_WORD_DATA
,
&
data
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"try %i: smbus->adapter.algo"
"->smbus_xfer() failed
\n
"
,
i
));
if
(
err_handler
)
{
err_handler
(
smbus
);
}
}
else
{
break
;
}
result
=
acpi_ec_sbs_access
(
sbs
,
addr
,
ACPI_SBS_SMBUS_WRITE
,
func
,
ACPI_SBS_WORD_DATA
,
&
data
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ec_sbs_access() failed"
));
}
return
result
;
}
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
);
}
/* --------------------------------------------------------------------------
Smart Battery System Management
-------------------------------------------------------------------------- */
/* Smart Battery */
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
;
}
static
int
acpi_sbs_generate_event
(
struct
acpi_device
*
device
,
int
event
,
int
state
,
char
*
bid
,
char
*
class
)
...
...
@@ -366,12 +450,11 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
int
result
=
0
;
int
is_present
=
0
;
result
=
acpi_sbs_smbus_read_word
(
battery
->
sbs
->
smbus
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
&
state
,
NULL
);
result
=
acpi_sbs_read_word
(
battery
->
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
&
state
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbu
s_read_word() failed"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sb
s_read_word() failed"
));
}
if
(
!
result
)
{
is_present
=
(
state
&
0x000f
)
&
(
1
<<
battery
->
id
);
...
...
@@ -381,45 +464,33 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
return
result
;
}
static
int
acpi_battery_is_present
(
struct
acpi_battery
*
battery
)
{
return
(
battery
->
battery_present
);
}
static
int
acpi_ac_is_present
(
struct
acpi_sbs
*
sbs
)
{
return
(
sbs
->
ac_present
);
}
static
int
acpi_battery_select
(
struct
acpi_battery
*
battery
)
{
struct
acpi_
ec_smbus
*
smbus
=
battery
->
sbs
->
smbu
s
;
struct
acpi_
sbs
*
sbs
=
battery
->
sb
s
;
int
result
=
0
;
s16
state
;
int
foo
;
if
(
battery
->
sbs
->
sbsm_present
)
{
if
(
sbs
->
sbsm_present
)
{
/* Take special care not to knobble other nibbles of
* state (aka selector_state), since
* it causes charging to halt on SBSELs */
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
&
state
,
NULL
);
acpi_sbs_read_word
(
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
&
state
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
foo
=
(
state
&
0x0fff
)
|
(
1
<<
(
battery
->
id
+
12
));
result
=
acpi_sbs_smbus_write_word
(
smbus
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
foo
,
NULL
);
acpi_sbs_write_word
(
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
foo
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_write_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_write_word() failed
"
));
goto
end
;
}
}
...
...
@@ -430,15 +501,14 @@ static int acpi_battery_select(struct acpi_battery *battery)
static
int
acpi_sbsm_get_info
(
struct
acpi_sbs
*
sbs
)
{
struct
acpi_ec_smbus
*
smbus
=
sbs
->
smbus
;
int
result
=
0
;
s16
battery_system_info
;
result
=
acpi_sbs_
smbus_read_word
(
smbu
s
,
ACPI_SBSM_SMBUS_ADDR
,
0x04
,
&
battery_system_info
,
NULL
);
result
=
acpi_sbs_
read_word
(
sb
s
,
ACPI_SBSM_SMBUS_ADDR
,
0x04
,
&
battery_system_info
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
...
...
@@ -451,53 +521,50 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
)
{
struct
acpi_
ec_smbus
*
smbus
=
battery
->
sbs
->
smbu
s
;
struct
acpi_
sbs
*
sbs
=
battery
->
sb
s
;
int
result
=
0
;
s16
battery_mode
;
s16
specification_info
;
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
battery
->
info
.
capacity_mode
=
(
battery_mode
&
0x8000
)
>>
15
;
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x10
,
&
battery
->
info
.
full_charge_capacity
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x10
,
&
battery
->
info
.
full_charge_capacity
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x18
,
&
battery
->
info
.
design_capacity
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x18
,
&
battery
->
info
.
design_capacity
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x19
,
&
battery
->
info
.
design_voltage
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x19
,
&
battery
->
info
.
design_voltage
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x1a
,
&
specification_info
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x1a
,
&
specification_info
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
...
...
@@ -529,37 +596,35 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
battery
->
info
.
ipscale
=
1
;
}
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x1c
,
&
battery
->
info
.
serial_number
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x1c
,
&
battery
->
info
.
serial_number
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_str
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x20
,
battery
->
info
.
manufacturer_name
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_str
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x20
,
battery
->
info
.
manufacturer_name
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_str() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_str() failed
"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_str
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x21
,
battery
->
info
.
device_name
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_str
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x21
,
battery
->
info
.
device_name
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_str() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_str() failed
"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_str
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x22
,
battery
->
info
.
device_chemistry
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_str
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x22
,
battery
->
info
.
device_chemistry
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_str() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_str() failed
"
));
goto
end
;
}
...
...
@@ -567,103 +632,60 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
return
result
;
}
static
void
acpi_update_delay
(
struct
acpi_sbs
*
sbs
)
{
if
(
sbs
->
zombie
)
{
return
;
}
if
(
sbs
->
update_time2
>
0
)
{
msleep
(
sbs
->
update_time2
*
1000
);
}
}
static
int
acpi_battery_get_state
(
struct
acpi_battery
*
battery
)
{
struct
acpi_
ec_smbus
*
smbus
=
battery
->
sbs
->
smbu
s
;
struct
acpi_
sbs
*
sbs
=
battery
->
sb
s
;
int
result
=
0
;
acpi_update_delay
(
battery
->
sbs
);
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x09
,
&
battery
->
state
.
voltage
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x09
,
&
battery
->
state
.
voltage
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x0a
,
&
battery
->
state
.
amperage
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x0a
,
&
battery
->
state
.
amperage
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x0f
,
&
battery
->
state
.
remaining_capacity
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x0f
,
&
battery
->
state
.
remaining_capacity
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x12
,
&
battery
->
state
.
average_time_to_empty
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x16
,
&
battery
->
state
.
battery_state
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x13
,
&
battery
->
state
.
average_time_to_full
,
&
acpi_battery_smbus_err_handler
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x16
,
&
battery
->
state
.
battery_status
,
&
acpi_battery_smbus_err_handler
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
end:
return
result
;
}
static
int
acpi_battery_get_alarm
(
struct
acpi_battery
*
battery
)
{
struct
acpi_
ec_smbus
*
smbus
=
battery
->
sbs
->
smbu
s
;
struct
acpi_
sbs
*
sbs
=
battery
->
sb
s
;
int
result
=
0
;
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
&
battery
->
alarm
.
remaining_capacity
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
&
battery
->
alarm
.
remaining_capacity
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
acpi_update_delay
(
battery
->
sbs
);
end:
return
result
;
...
...
@@ -672,15 +694,15 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery)
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
,
unsigned
long
alarm
)
{
struct
acpi_
ec_smbus
*
smbus
=
battery
->
sbs
->
smbu
s
;
struct
acpi_
sbs
*
sbs
=
battery
->
sb
s
;
int
result
=
0
;
s16
battery_mode
;
int
foo
;
result
=
acpi_battery_select
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_select() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_select() failed
"
));
goto
end
;
}
...
...
@@ -688,33 +710,29 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
if
(
alarm
>
0
)
{
result
=
acpi_sbs_smbus_read_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
,
&
acpi_battery_smbus_err_handler
);
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
result
=
acpi_sbs_smbus_write_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
battery_mode
&
0xbfff
,
&
acpi_battery_smbus_err_handler
);
acpi_sbs_write_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
battery_mode
&
0xbfff
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_write_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_write_word() failed
"
));
goto
end
;
}
}
foo
=
alarm
/
(
battery
->
info
.
capacity_mode
?
10
:
1
);
result
=
acpi_sbs_smbus_write_word
(
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
foo
,
&
acpi_battery_smbus_err_handler
);
result
=
acpi_sbs_write_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
foo
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_write_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_write_word() failed
"
));
goto
end
;
}
...
...
@@ -725,6 +743,7 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
static
int
acpi_battery_set_mode
(
struct
acpi_battery
*
battery
)
{
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
=
0
;
s16
battery_mode
;
...
...
@@ -732,12 +751,11 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
goto
end
;
}
result
=
acpi_sbs_smbus_read_word
(
battery
->
sbs
->
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
,
NULL
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
...
...
@@ -746,21 +764,19 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
}
else
{
battery_mode
|=
0x8000
;
}
result
=
acpi_sbs_smbus_write_word
(
battery
->
sbs
->
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
battery_mode
,
NULL
);
result
=
acpi_sbs_write_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
battery_mode
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_write_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_write_word() failed
"
));
goto
end
;
}
result
=
acpi_sbs_smbus_read_word
(
battery
->
sbs
->
smbus
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
,
NULL
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
...
...
@@ -774,36 +790,36 @@ static int acpi_battery_init(struct acpi_battery *battery)
result
=
acpi_battery_select
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_init() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_select() failed
"
));
goto
end
;
}
result
=
acpi_battery_set_mode
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_set_mode() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_set_mode() failed
"
));
goto
end
;
}
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_get_info() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_get_info() failed
"
));
goto
end
;
}
result
=
acpi_battery_get_state
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_get_state() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_get_state() failed
"
));
goto
end
;
}
result
=
acpi_battery_get_alarm
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_get_alarm() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_get_alarm() failed
"
));
goto
end
;
}
...
...
@@ -813,20 +829,19 @@ static int acpi_battery_init(struct acpi_battery *battery)
static
int
acpi_ac_get_present
(
struct
acpi_sbs
*
sbs
)
{
struct
acpi_ec_smbus
*
smbus
=
sbs
->
smbus
;
int
result
=
0
;
s16
charger_status
;
result
=
acpi_sbs_
smbus_read_word
(
smbu
s
,
ACPI_SBC_SMBUS_ADDR
,
0x13
,
&
charger_status
,
NULL
);
result
=
acpi_sbs_
read_word
(
sb
s
,
ACPI_SBC_SMBUS_ADDR
,
0x13
,
&
charger_status
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_smbus_read_word() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_read_word() failed
"
));
goto
end
;
}
sbs
->
ac_present
=
(
charger_status
&
0x8000
)
>>
15
;
sbs
->
ac
.
ac
_present
=
(
charger_status
&
0x8000
)
>>
15
;
end:
...
...
@@ -852,8 +867,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
if
(
!*
dir
)
{
*
dir
=
proc_mkdir
(
dir_name
,
parent_dir
);
if
(
!*
dir
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"proc_mkdir() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"proc_mkdir() failed
"
));
return
-
ENODEV
;
}
(
*
dir
)
->
owner
=
THIS_MODULE
;
...
...
@@ -863,8 +878,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
if
(
info_fops
)
{
entry
=
create_proc_entry
(
ACPI_SBS_FILE_INFO
,
S_IRUGO
,
*
dir
);
if
(
!
entry
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"create_proc_entry() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"create_proc_entry() failed
"
));
}
else
{
entry
->
proc_fops
=
info_fops
;
entry
->
data
=
data
;
...
...
@@ -876,8 +891,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
if
(
state_fops
)
{
entry
=
create_proc_entry
(
ACPI_SBS_FILE_STATE
,
S_IRUGO
,
*
dir
);
if
(
!
entry
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"create_proc_entry() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"create_proc_entry() failed
"
));
}
else
{
entry
->
proc_fops
=
state_fops
;
entry
->
data
=
data
;
...
...
@@ -889,8 +904,8 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
if
(
alarm_fops
)
{
entry
=
create_proc_entry
(
ACPI_SBS_FILE_ALARM
,
S_IRUGO
,
*
dir
);
if
(
!
entry
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"create_proc_entry() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"create_proc_entry() failed
"
));
}
else
{
entry
->
proc_fops
=
alarm_fops
;
entry
->
data
=
data
;
...
...
@@ -923,24 +938,27 @@ static struct proc_dir_entry *acpi_battery_dir = NULL;
static
int
acpi_battery_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
cscale
;
int
result
=
0
;
if
(
battery
->
sbs
->
zombie
)
{
if
(
sbs_mutex_lock
(
sbs
)
)
{
return
-
ENODEV
;
}
down
(
&
sbs_sem
);
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
if
(
update_
mode
==
REQUEST_UPDATE_MODE
)
{
result
=
acpi_sbs_update_run
(
battery
->
sbs
,
DATA_TYPE_INFO
);
if
(
update_
time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
battery
->
id
,
DATA_TYPE_INFO
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_update_run() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_update_run() failed
"
));
}
}
if
(
acpi_battery_is_present
(
battery
)
)
{
if
(
battery
->
battery_present
)
{
seq_printf
(
seq
,
"present: yes
\n
"
);
}
else
{
seq_printf
(
seq
,
"present: no
\n
"
);
...
...
@@ -952,13 +970,13 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
}
else
{
cscale
=
battery
->
info
.
ipscale
;
}
seq_printf
(
seq
,
"design capacity: %i%s"
,
seq_printf
(
seq
,
"design capacity: %i%s
\n
"
,
battery
->
info
.
design_capacity
*
cscale
,
battery
->
info
.
capacity_mode
?
"0 mWh
\n
"
:
" mAh
\n
"
);
battery
->
info
.
capacity_mode
?
"0 mWh
"
:
" mAh
"
);
seq_printf
(
seq
,
"last full capacity: %i%s"
,
seq_printf
(
seq
,
"last full capacity: %i%s
\n
"
,
battery
->
info
.
full_charge_capacity
*
cscale
,
battery
->
info
.
capacity_mode
?
"0 mWh
\n
"
:
" mAh
\n
"
);
battery
->
info
.
capacity_mode
?
"0 mWh
"
:
" mAh
"
);
seq_printf
(
seq
,
"battery technology: rechargeable
\n
"
);
...
...
@@ -984,7 +1002,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
end:
up
(
&
sbs_sem
);
sbs_mutex_unlock
(
sbs
);
return
result
;
}
...
...
@@ -996,26 +1014,29 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
static
int
acpi_battery_read_state
(
struct
seq_file
*
seq
,
void
*
offset
)
{
struct
acpi_battery
*
battery
=
(
struct
acpi_battery
*
)
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
=
0
;
int
cscale
;
int
foo
;
if
(
battery
->
sbs
->
zombie
)
{
if
(
sbs_mutex_lock
(
sbs
)
)
{
return
-
ENODEV
;
}
down
(
&
sbs_sem
);
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
if
(
update_
mode
==
REQUEST_UPDATE_MODE
)
{
result
=
acpi_sbs_update_run
(
battery
->
sbs
,
DATA_TYPE_STATE
);
if
(
update_
time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
battery
->
id
,
DATA_TYPE_STATE
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_update_run() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_update_run() failed
"
));
}
}
if
(
acpi_battery_is_present
(
battery
)
)
{
if
(
battery
->
battery_present
)
{
seq_printf
(
seq
,
"present: yes
\n
"
);
}
else
{
seq_printf
(
seq
,
"present: no
\n
"
);
...
...
@@ -1028,7 +1049,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
cscale
=
battery
->
info
.
ipscale
;
}
if
(
battery
->
state
.
battery_stat
us
&
0x0010
)
{
if
(
battery
->
state
.
battery_stat
e
&
0x0010
)
{
seq_printf
(
seq
,
"capacity state: critical
\n
"
);
}
else
{
seq_printf
(
seq
,
"capacity state: ok
\n
"
);
...
...
@@ -1052,16 +1073,16 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
battery
->
info
.
capacity_mode
?
"mW"
:
"mA"
);
}
seq_printf
(
seq
,
"remaining capacity: %i%s"
,
seq_printf
(
seq
,
"remaining capacity: %i%s
\n
"
,
battery
->
state
.
remaining_capacity
*
cscale
,
battery
->
info
.
capacity_mode
?
"0 mWh
\n
"
:
" mAh
\n
"
);
battery
->
info
.
capacity_mode
?
"0 mWh
"
:
" mAh
"
);
seq_printf
(
seq
,
"present voltage: %i mV
\n
"
,
battery
->
state
.
voltage
*
battery
->
info
.
vscale
);
end:
up
(
&
sbs_sem
);
sbs_mutex_unlock
(
sbs
);
return
result
;
}
...
...
@@ -1074,24 +1095,27 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
static
int
acpi_battery_read_alarm
(
struct
seq_file
*
seq
,
void
*
offset
)
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
=
0
;
int
cscale
;
if
(
battery
->
sbs
->
zombie
)
{
if
(
sbs_mutex_lock
(
sbs
)
)
{
return
-
ENODEV
;
}
down
(
&
sbs_sem
);
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
if
(
update_
mode
==
REQUEST_UPDATE_MODE
)
{
result
=
acpi_sbs_update_run
(
battery
->
sbs
,
DATA_TYPE_ALARM
);
if
(
update_
time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
battery
->
id
,
DATA_TYPE_ALARM
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_update_run() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_update_run() failed
"
));
}
}
if
(
!
acpi_battery_is_present
(
battery
)
)
{
if
(
!
battery
->
battery_present
)
{
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
}
...
...
@@ -1104,16 +1128,16 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
seq_printf
(
seq
,
"alarm: "
);
if
(
battery
->
alarm
.
remaining_capacity
)
{
seq_printf
(
seq
,
"%i%s"
,
seq_printf
(
seq
,
"%i%s
\n
"
,
battery
->
alarm
.
remaining_capacity
*
cscale
,
battery
->
info
.
capacity_mode
?
"0 mWh
\n
"
:
" mAh
\n
"
);
battery
->
info
.
capacity_mode
?
"0 mWh
"
:
" mAh
"
);
}
else
{
seq_printf
(
seq
,
"disabled
\n
"
);
}
end:
up
(
&
sbs_sem
);
sbs_mutex_unlock
(
sbs
);
return
result
;
}
...
...
@@ -1124,16 +1148,19 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
{
struct
seq_file
*
seq
=
file
->
private_data
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
char
alarm_string
[
12
]
=
{
'\0'
};
int
result
,
old_alarm
,
new_alarm
;
if
(
battery
->
sbs
->
zombie
)
{
if
(
sbs_mutex_lock
(
sbs
)
)
{
return
-
ENODEV
;
}
down
(
&
sbs_sem
);
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
if
(
!
acpi_battery_is_present
(
battery
)
)
{
if
(
!
battery
->
battery_present
)
{
result
=
-
ENODEV
;
goto
end
;
}
...
...
@@ -1155,21 +1182,21 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
result
=
acpi_battery_set_alarm
(
battery
,
new_alarm
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_set_alarm() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_set_alarm() failed
"
));
acpi_battery_set_alarm
(
battery
,
old_alarm
);
goto
end
;
}
result
=
acpi_battery_get_alarm
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_get_alarm() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_get_alarm() failed
"
));
acpi_battery_set_alarm
(
battery
,
old_alarm
);
goto
end
;
}
end:
up
(
&
sbs_sem
);
sbs_mutex_unlock
(
sbs
);
if
(
result
)
{
return
result
;
...
...
@@ -1217,24 +1244,22 @@ static int acpi_ac_read_state(struct seq_file *seq, void *offset)
struct
acpi_sbs
*
sbs
=
seq
->
private
;
int
result
;
if
(
sbs
->
zombie
)
{
if
(
sbs
_mutex_lock
(
sbs
)
)
{
return
-
ENODEV
;
}
down
(
&
sbs_sem
);
if
(
update_mode
==
REQUEST_UPDATE_MODE
)
{
result
=
acpi_sbs_update_run
(
sbs
,
DATA_TYPE_AC_STATE
);
if
(
update_time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
-
1
,
DATA_TYPE_AC_STATE
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_update_run() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_update_run() failed
"
));
}
}
seq_printf
(
seq
,
"state: %s
\n
"
,
sbs
->
ac_present
?
"on-line"
:
"off-line"
);
sbs
->
ac
.
ac
_present
?
"on-line"
:
"off-line"
);
up
(
&
sbs_sem
);
sbs_mutex_unlock
(
sbs
);
return
0
;
}
...
...
@@ -1275,25 +1300,25 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
result
=
acpi_battery_select
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_select() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_select() failed
"
));
goto
end
;
}
result
=
acpi_battery_get_present
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_get_present() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_get_present() failed
"
));
goto
end
;
}
is_present
=
acpi_battery_is_present
(
battery
)
;
is_present
=
battery
->
battery_present
;
if
(
is_present
)
{
result
=
acpi_battery_init
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_init() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_init() failed
"
));
goto
end
;
}
battery
->
init_state
=
1
;
...
...
@@ -1308,12 +1333,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
&
acpi_battery_state_fops
,
&
acpi_battery_alarm_fops
,
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_generic_add_fs() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_generic_add_fs() failed
"
));
goto
end
;
}
battery
->
alive
=
1
;
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"
);
end:
return
result
;
}
...
...
@@ -1333,8 +1362,8 @@ static int acpi_ac_add(struct acpi_sbs *sbs)
result
=
acpi_ac_get_present
(
sbs
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_ac_get_present() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_ac_get_present() failed
"
));
goto
end
;
}
...
...
@@ -1343,11 +1372,15 @@ static int acpi_ac_add(struct acpi_sbs *sbs)
ACPI_AC_DIR_NAME
,
NULL
,
&
acpi_ac_state_fops
,
NULL
,
sbs
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_generic_add_fs() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_generic_add_fs() failed
"
));
goto
end
;
}
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"
);
end:
return
result
;
...
...
@@ -1361,45 +1394,85 @@ static void acpi_ac_remove(struct acpi_sbs *sbs)
}
}
static
void
acpi_sbs_update_
queu
e_run
(
unsigned
long
data
)
static
void
acpi_sbs_update_
tim
e_run
(
unsigned
long
data
)
{
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_sbs_update_
queu
e
,
(
void
*
)
data
);
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_sbs_update_
tim
e
,
(
void
*
)
data
);
}
static
int
acpi_sbs_update_run
(
struct
acpi_sbs
*
sbs
,
int
data_type
)
static
int
acpi_sbs_update_run
(
struct
acpi_sbs
*
sbs
,
int
id
,
int
data_type
)
{
struct
acpi_battery
*
battery
;
int
result
=
0
;
int
old_ac_present
;
int
old_battery_present
;
int
new_ac_present
;
int
new_battery_present
;
int
id
;
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
;
char
dir_name
[
32
];
int
do_battery_init
,
do_ac_init
;
s16
old_remaining_capacity
;
int
do_battery_init
=
0
,
do_ac_init
=
0
;
int
old_remaining_capacity
=
0
;
int
update_ac
=
1
,
update_battery
=
1
;
int
up_tm
=
update_time
;
if
(
sbs
->
zombie
)
{
if
(
sbs
_zombie
(
sbs
)
)
{
goto
end
;
}
old_ac_present
=
acpi_ac_is_present
(
sbs
);
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
++
;
if
(
!
update_ac
&&
!
update_battery
)
{
goto
end
;
}
old_ac_present
=
sbs
->
ac
.
ac_present
;
result
=
acpi_ac_get_present
(
sbs
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_ac_get_present() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_ac_get_present() failed
"
));
}
new_ac_present
=
acpi_ac_is_present
(
sbs
)
;
new_ac_present
=
sbs
->
ac
.
ac_present
;
do_ac_init
=
(
old_ac_present
!=
new_ac_present
);
if
(
sbs
->
run_cnt
==
1
&&
data_type
==
DATA_TYPE_COMMON
)
{
do_ac_init
=
1
;
}
if
(
data_type
==
DATA_TYPE_AC_STATE
)
{
if
(
do_ac_init
)
{
result
=
acpi_sbs_generate_event
(
sbs
->
device
,
ACPI_SBS_AC_NOTIFY_STATUS
,
new_ac_present
,
ACPI_AC_DIR_NAME
,
ACPI_AC_CLASS
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_generate_event() failed"
));
}
}
if
(
data_type
==
DATA_TYPE_COMMON
)
{
if
(
!
do_ac_init
&&
!
update_battery
)
{
goto
end
;
}
}
if
(
data_type
==
DATA_TYPE_AC_STATE
&&
!
do_ac_init
)
{
goto
end
;
}
for
(
id
=
0
;
id
<
MAX_SBS_BAT
;
id
++
)
{
for
(
id
=
id_min
;
id
<=
id_max
;
id
++
)
{
battery
=
&
sbs
->
battery
[
id
];
if
(
battery
->
alive
==
0
)
{
continue
;
...
...
@@ -1407,94 +1480,92 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
old_remaining_capacity
=
battery
->
state
.
remaining_capacity
;
old_battery_present
=
acpi_battery_is_present
(
battery
)
;
old_battery_present
=
battery
->
battery_present
;
result
=
acpi_battery_select
(
battery
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_battery_select() failed
\n
"
));
}
if
(
sbs
->
zombie
)
{
goto
end
;
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_select() failed"
));
}
result
=
acpi_battery_get_present
(
battery
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_battery_get_present() failed
\n
"
));
}
if
(
sbs
->
zombie
)
{
goto
end
;
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_present() failed"
));
}
new_battery_present
=
acpi_battery_is_present
(
battery
)
;
new_battery_present
=
battery
->
battery_present
;
do_battery_init
=
((
old_battery_present
!=
new_battery_present
)
&&
new_battery_present
);
if
(
sbs
->
zombie
)
{
if
(
!
new_battery_present
)
goto
event
;
if
(
do_ac_init
||
do_battery_init
)
{
result
=
acpi_battery_init
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_init() "
"failed"
));
}
}
if
(
sbs_zombie
(
sbs
))
{
goto
end
;
}
if
(
do_ac_init
||
do_battery_init
||
update_info_mode
||
sbs
->
update_info_mode
)
{
if
(
sbs
->
update_info_mode
)
{
sbs
->
update_info_mode
=
0
;
}
else
{
sbs
->
update_info_mode
=
1
;
}
result
=
acpi_battery_init
(
battery
);
if
((
data_type
==
DATA_TYPE_COMMON
||
data_type
==
DATA_TYPE_INFO
)
&&
new_battery_present
)
{
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_battery_init() "
"failed
\n
"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_info() failed"
));
}
}
if
(
data_type
==
DATA_TYPE_INFO
)
{
continue
;
}
if
(
sbs
->
zombie
)
{
if
(
sbs_zombie
(
sbs
))
{
goto
end
;
}
if
(
new_battery_present
)
{
result
=
acpi_battery_get_alarm
(
battery
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_battery_get_alarm() "
"failed
\n
"
));
}
if
(
data_type
==
DATA_TYPE_ALARM
)
{
continue
;
}
if
((
data_type
==
DATA_TYPE_COMMON
||
data_type
==
DATA_TYPE_STATE
)
&&
new_battery_present
)
{
result
=
acpi_battery_get_state
(
battery
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_battery_get_state() "
"failed
\n
"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_state() failed"
));
}
}
if
(
sbs
->
zombie
)
{
goto
e
nd
;
if
(
data_type
==
DATA_TYPE_STATE
)
{
goto
e
vent
;
}
if
(
data_type
!=
DATA_TYPE_COMMON
)
{
continue
;
if
(
sbs_zombie
(
sbs
)
)
{
goto
end
;
}
if
(
old_battery_present
!=
new_battery_present
)
{
sprintf
(
dir_name
,
ACPI_BATTERY_DIR_NAME
,
id
);
result
=
acpi_sbs_generate_event
(
sbs
->
device
,
ACPI_SBS_BATTERY_NOTIFY_STATUS
,
new_battery_present
,
dir_name
,
ACPI_BATTERY_CLASS
);
if
((
data_type
==
DATA_TYPE_COMMON
||
data_type
==
DATA_TYPE_ALARM
)
&&
new_battery_present
)
{
result
=
acpi_battery_get_alarm
(
battery
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_generate_event
() "
"failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_get_alarm
() "
"failed
"
));
}
}
if
(
old_remaining_capacity
!=
battery
->
state
.
remaining_capacity
)
{
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
)
{
sprintf
(
dir_name
,
ACPI_BATTERY_DIR_NAME
,
id
);
result
=
acpi_sbs_generate_event
(
sbs
->
device
,
ACPI_SBS_BATTERY_NOTIFY_STATUS
,
...
...
@@ -1502,138 +1573,120 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
dir_name
,
ACPI_BATTERY_CLASS
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_sbs_generate_event() failed
\n
"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_generate_event() "
"failed"
));
}
}
}
if
(
sbs
->
zombie
)
{
goto
end
;
}
if
(
data_type
!=
DATA_TYPE_COMMON
)
{
goto
end
;
}
if
(
old_ac_present
!=
new_ac_present
)
{
result
=
acpi_sbs_generate_event
(
sbs
->
device
,
ACPI_SBS_AC_NOTIFY_STATUS
,
new_ac_present
,
ACPI_AC_DIR_NAME
,
ACPI_AC_CLASS
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_sbs_generate_event() failed
\n
"
));
}
}
end:
return
result
;
}
static
void
acpi_sbs_update_
queu
e
(
void
*
data
)
static
void
acpi_sbs_update_
tim
e
(
void
*
data
)
{
struct
acpi_sbs
*
sbs
=
data
;
unsigned
long
delay
=
-
1
;
int
result
;
unsigned
int
up_tm
=
update_time
;
if
(
sbs
->
zombie
)
{
goto
end
;
}
if
(
sbs_mutex_lock
(
sbs
))
return
;
result
=
acpi_sbs_update_run
(
sbs
,
DATA_TYPE_COMMON
);
result
=
acpi_sbs_update_run
(
sbs
,
-
1
,
DATA_TYPE_COMMON
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_update_run() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_update_run() failed
"
));
}
if
(
sbs
->
zombie
)
{
if
(
sbs
_zombie
(
sbs
)
)
{
goto
end
;
}
if
(
update_mode
==
REQUEST_UPDATE_MODE
)
{
goto
end
;
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
);
}
}
delay
=
jiffies
+
HZ
*
update_time
;
sbs
->
update_timer
.
data
=
(
unsigned
long
)
data
;
sbs
->
update_timer
.
function
=
acpi_sbs_update_queue_run
;
sbs
->
update_timer
.
expires
=
delay
;
add_timer
(
&
sbs
->
update_timer
);
end:
;
sbs_mutex_unlock
(
sbs
);
}
static
int
acpi_sbs_add
(
struct
acpi_device
*
device
)
{
struct
acpi_sbs
*
sbs
=
NULL
;
struct
acpi_ec_hc
*
ec_hc
=
NULL
;
int
result
,
remove_result
=
0
;
int
result
=
0
,
remove_result
=
0
;
unsigned
long
sbs_obj
;
int
id
,
cnt
;
int
id
;
acpi_status
status
=
AE_OK
;
unsigned
long
val
;
status
=
acpi_evaluate_integer
(
device
->
parent
->
handle
,
"_EC"
,
NULL
,
&
val
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"Error obtaining _EC"
));
return
-
EIO
;
}
sbs
=
kzalloc
(
sizeof
(
struct
acpi_sbs
),
GFP_KERNEL
);
if
(
!
sbs
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"kmalloc() failed
\n
"
));
return
-
ENOMEM
;
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"kzalloc() failed"
));
result
=
-
ENOMEM
;
goto
end
;
}
cnt
=
0
;
while
(
cnt
<
10
)
{
cnt
++
;
ec_hc
=
acpi_get_ec_hc
(
device
);
if
(
ec_hc
)
{
break
;
}
msleep
(
1000
);
}
mutex_init
(
&
sbs
->
mutex
);
if
(
!
ec_hc
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_get_ec_hc() failed: "
"NO driver found for EC HC SMBus
\n
"
));
result
=
-
ENODEV
;
goto
end
;
}
sbs_mutex_lock
(
sbs
);
sbs
->
base
=
(
val
&
0xff00ull
)
>>
8
;
sbs
->
device
=
device
;
sbs
->
smbus
=
ec_hc
->
smbus
;
strcpy
(
acpi_device_name
(
device
),
ACPI_SBS_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_SBS_CLASS
);
acpi_driver_data
(
device
)
=
sbs
;
sbs
->
update_time
=
0
;
sbs
->
update_time2
=
0
;
result
=
acpi_ac_add
(
sbs
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_ac_add() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ac_add() failed
"
));
goto
end
;
}
result
=
acpi_evaluate_integer
(
device
->
handle
,
"_SBS"
,
NULL
,
&
sbs_obj
);
if
(
ACPI_FAILURE
(
result
)
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_evaluate_integer() failed
\n
"
));
status
=
acpi_evaluate_integer
(
device
->
handle
,
"_SBS"
,
NULL
,
&
sbs_obj
);
if
(
status
)
{
ACPI_
EXCEPTION
((
AE_INFO
,
status
,
"acpi_evaluate_integer() failed
"
));
result
=
-
EIO
;
goto
end
;
}
if
(
sbs_obj
>
0
)
{
result
=
acpi_sbsm_get_info
(
sbs
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbsm_get_info() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbsm_get_info() failed
"
));
goto
end
;
}
sbs
->
sbsm_present
=
1
;
}
if
(
sbs
->
sbsm_present
==
0
)
{
result
=
acpi_battery_add
(
sbs
,
0
);
if
(
result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_battery_add() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_battery_add() failed
"
));
goto
end
;
}
}
else
{
...
...
@@ -1641,9 +1694,8 @@ static int acpi_sbs_add(struct acpi_device *device)
if
((
sbs
->
sbsm_batteries_supported
&
(
1
<<
id
)))
{
result
=
acpi_battery_add
(
sbs
,
id
);
if
(
result
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_battery_add() "
"failed
\n
"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_add() failed"
));
goto
end
;
}
}
...
...
@@ -1653,33 +1705,26 @@ static int acpi_sbs_add(struct acpi_device *device)
sbs
->
handle
=
device
->
handle
;
init_timer
(
&
sbs
->
update_timer
);
if
(
update_mode
==
QUEUE_UPDATE_MODE
)
{
status
=
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_sbs_update_queue
,
sbs
);
if
(
status
!=
AE_OK
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_os_execute() failed
\n
"
));
}
}
sbs
->
update_time
=
update_time
;
sbs
->
update_time2
=
update_time2
;
printk
(
KERN_INFO
PREFIX
"%s [%s]
\n
"
,
acpi_device_name
(
device
),
acpi_device_bid
(
device
));
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
end:
sbs_mutex_unlock
(
sbs
);
if
(
result
)
{
remove_result
=
acpi_sbs_remove
(
device
,
0
);
if
(
remove_result
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_sbs_remove() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_sbs_remove() failed
"
));
}
}
return
result
;
}
int
acpi_sbs_remove
(
struct
acpi_device
*
device
,
int
type
)
static
int
acpi_sbs_remove
(
struct
acpi_device
*
device
,
int
type
)
{
struct
acpi_sbs
*
sbs
;
int
id
;
...
...
@@ -1688,15 +1733,14 @@ int acpi_sbs_remove(struct acpi_device *device, int type)
return
-
EINVAL
;
}
sbs
=
(
struct
acpi_sbs
*
)
acpi_driver_data
(
device
);
sbs
=
acpi_driver_data
(
device
);
if
(
!
sbs
)
{
return
-
EINVAL
;
}
sbs_mutex_lock
(
sbs
);
sbs
->
zombie
=
1
;
sbs
->
update_time
=
0
;
sbs
->
update_time2
=
0
;
del_timer_sync
(
&
sbs
->
update_timer
);
acpi_os_wait_events_complete
(
NULL
);
del_timer_sync
(
&
sbs
->
update_timer
);
...
...
@@ -1707,11 +1751,41 @@ int acpi_sbs_remove(struct acpi_device *device, int type)
acpi_ac_remove
(
sbs
);
sbs_mutex_unlock
(
sbs
);
mutex_destroy
(
&
sbs
->
mutex
);
kfree
(
sbs
);
return
0
;
}
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
;
}
static
int
__init
acpi_sbs_init
(
void
)
{
int
result
=
0
;
...
...
@@ -1719,35 +1793,34 @@ static int __init acpi_sbs_init(void)
if
(
acpi_disabled
)
return
-
ENODEV
;
init_MUTEX
(
&
sbs_sem
);
if
(
capacity_mode
!=
DEF_CAPACITY_UNIT
&&
capacity_mode
!=
MAH_CAPACITY_UNIT
&&
capacity_mode
!=
MWH_CAPACITY_UNIT
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_sbs_init: "
"invalid capacity_mode = %d
\n
"
,
capacity_mode
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"invalid capacity_mode = %d"
,
capacity_mode
));
return
-
EINVAL
;
}
acpi_ac_dir
=
acpi_lock_ac_dir
();
if
(
!
acpi_ac_dir
)
{
ACPI_
DEBUG_PRINT
((
ACPI_DB
_ERROR
,
"acpi_lock_ac_dir() failed
\n
"
));
ACPI_
EXCEPTION
((
AE_INFO
,
AE
_ERROR
,
"acpi_lock_ac_dir() failed
"
));
return
-
ENODEV
;
}
acpi_battery_dir
=
acpi_lock_battery_dir
();
if
(
!
acpi_battery_dir
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_lock_battery_dir() failed
\n
"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_lock_battery_dir() failed"
));
acpi_sbs_rmdirs
();
return
-
ENODEV
;
}
result
=
acpi_bus_register_driver
(
&
acpi_sbs_driver
);
if
(
result
<
0
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"acpi_bus_register_driver() failed
\n
"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_bus_register_driver() failed"
));
acpi_sbs_rmdirs
();
return
-
ENODEV
;
}
...
...
@@ -1756,13 +1829,9 @@ static int __init acpi_sbs_init(void)
static
void
__exit
acpi_sbs_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
acpi_sbs_driver
);
acpi_unlock_ac_dir
(
acpi_ac_dir
);
acpi_ac_dir
=
NULL
;
acpi_unlock_battery_dir
(
acpi_battery_dir
);
acpi_battery_dir
=
NULL
;
acpi_sbs_rmdirs
();
return
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment