Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e270051d
Commit
e270051d
authored
Oct 10, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull battery-sbs-ac into release branch
parents
a2883dfa
d5b4a3d0
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1366 additions
and
1951 deletions
+1366
-1951
drivers/acpi/Kconfig
drivers/acpi/Kconfig
+6
-7
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-0
drivers/acpi/ac.c
drivers/acpi/ac.c
+31
-2
drivers/acpi/battery.c
drivers/acpi/battery.c
+436
-602
drivers/acpi/bus.c
drivers/acpi/bus.c
+15
-8
drivers/acpi/ec.c
drivers/acpi/ec.c
+1
-2
drivers/acpi/sbs.c
drivers/acpi/sbs.c
+539
-1330
drivers/acpi/sbshc.c
drivers/acpi/sbshc.c
+309
-0
drivers/acpi/sbshc.h
drivers/acpi/sbshc.h
+27
-0
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+1
-0
No files found.
drivers/acpi/Kconfig
View file @
e270051d
...
@@ -88,7 +88,7 @@ config ACPI_PROC_EVENT
...
@@ -88,7 +88,7 @@ config ACPI_PROC_EVENT
config ACPI_AC
config ACPI_AC
tristate "AC Adapter"
tristate "AC Adapter"
depends on X86
depends on X86
&& POWER_SUPPLY
default y
default y
help
help
This driver adds support for the AC Adapter object, which indicates
This driver adds support for the AC Adapter object, which indicates
...
@@ -97,7 +97,7 @@ config ACPI_AC
...
@@ -97,7 +97,7 @@ config ACPI_AC
config ACPI_BATTERY
config ACPI_BATTERY
tristate "Battery"
tristate "Battery"
depends on X86
depends on X86
&& POWER_SUPPLY
default y
default y
help
help
This driver adds support for battery information through
This driver adds support for battery information through
...
@@ -350,12 +350,11 @@ config ACPI_HOTPLUG_MEMORY
...
@@ -350,12 +350,11 @@ config ACPI_HOTPLUG_MEMORY
$>modprobe acpi_memhotplug
$>modprobe acpi_memhotplug
config ACPI_SBS
config ACPI_SBS
tristate "Smart Battery System
(EXPERIMENTAL)
"
tristate "Smart Battery System"
depends on X86
depends on X86
depends on
EXPERIMENTAL
depends on
POWER_SUPPLY
help
help
This driver adds support for the Smart Battery System.
This driver adds support for the Smart Battery System, another
A "Smart Battery" is quite old and quite rare compared
type of access to battery information, found on some laptops.
to today's ACPI "Control Method" battery.
endif # ACPI
endif # ACPI
drivers/acpi/Makefile
View file @
e270051d
...
@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
...
@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)
+=
acpi_memhotplug.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)
+=
acpi_memhotplug.o
obj-y
+=
cm_sbs.o
obj-y
+=
cm_sbs.o
obj-$(CONFIG_ACPI_SBS)
+=
sbs.o
obj-$(CONFIG_ACPI_SBS)
+=
sbs.o
obj-$(CONFIG_ACPI_SBS)
+=
sbshc.o
drivers/acpi/ac.c
View file @
e270051d
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
#include <linux/types.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include <linux/power_supply.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_drivers.h>
...
@@ -72,16 +73,37 @@ static struct acpi_driver acpi_ac_driver = {
...
@@ -72,16 +73,37 @@ static struct acpi_driver acpi_ac_driver = {
};
};
struct
acpi_ac
{
struct
acpi_ac
{
struct
power_supply
charger
;
struct
acpi_device
*
device
;
struct
acpi_device
*
device
;
unsigned
long
state
;
unsigned
long
state
;
};
};
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
static
const
struct
file_operations
acpi_ac_fops
=
{
static
const
struct
file_operations
acpi_ac_fops
=
{
.
open
=
acpi_ac_open_fs
,
.
open
=
acpi_ac_open_fs
,
.
read
=
seq_read
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
release
=
single_release
,
};
};
static
int
get_ac_property
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
acpi_ac
*
ac
=
to_acpi_ac
(
psy
);
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_ONLINE
:
val
->
intval
=
ac
->
state
;
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
static
enum
power_supply_property
ac_props
[]
=
{
POWER_SUPPLY_PROP_ONLINE
,
};
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
AC Adapter Management
AC Adapter Management
...
@@ -208,6 +230,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
...
@@ -208,6 +230,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
acpi_bus_generate_netlink_event
(
device
->
pnp
.
device_class
,
acpi_bus_generate_netlink_event
(
device
->
pnp
.
device_class
,
device
->
dev
.
bus_id
,
event
,
device
->
dev
.
bus_id
,
event
,
(
u32
)
ac
->
state
);
(
u32
)
ac
->
state
);
kobject_uevent
(
&
ac
->
charger
.
dev
->
kobj
,
KOBJ_CHANGE
);
break
;
break
;
default:
default:
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
...
@@ -244,7 +267,12 @@ static int acpi_ac_add(struct acpi_device *device)
...
@@ -244,7 +267,12 @@ static int acpi_ac_add(struct acpi_device *device)
result
=
acpi_ac_add_fs
(
device
);
result
=
acpi_ac_add_fs
(
device
);
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
ac
->
charger
.
name
=
acpi_device_bid
(
device
);
ac
->
charger
.
type
=
POWER_SUPPLY_TYPE_MAINS
;
ac
->
charger
.
properties
=
ac_props
;
ac
->
charger
.
num_properties
=
ARRAY_SIZE
(
ac_props
);
ac
->
charger
.
get_property
=
get_ac_property
;
power_supply_register
(
&
ac
->
device
->
dev
,
&
ac
->
charger
);
status
=
acpi_install_notify_handler
(
device
->
handle
,
status
=
acpi_install_notify_handler
(
device
->
handle
,
ACPI_ALL_NOTIFY
,
acpi_ac_notify
,
ACPI_ALL_NOTIFY
,
acpi_ac_notify
,
ac
);
ac
);
...
@@ -279,7 +307,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
...
@@ -279,7 +307,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
status
=
acpi_remove_notify_handler
(
device
->
handle
,
status
=
acpi_remove_notify_handler
(
device
->
handle
,
ACPI_ALL_NOTIFY
,
acpi_ac_notify
);
ACPI_ALL_NOTIFY
,
acpi_ac_notify
);
if
(
ac
->
charger
.
dev
)
power_supply_unregister
(
&
ac
->
charger
);
acpi_ac_remove_fs
(
device
);
acpi_ac_remove_fs
(
device
);
kfree
(
ac
);
kfree
(
ac
);
...
...
drivers/acpi/battery.c
View file @
e270051d
/*
/*
*
acpi_battery.c - ACPI Battery Driver ($Revision: 37 $
)
*
battery.c - ACPI Battery Driver (Revision: 2.0
)
*
*
* Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
* Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
*
...
@@ -27,244 +29,288 @@
...
@@ -27,244 +29,288 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/jiffies.h>
#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#endif
#include <acpi/acpi_bus.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_drivers.h>
#
define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
#
include <linux/power_supply.h>
#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
#define ACPI_BATTERY_FORMAT_BST "NNNN"
#define ACPI_BATTERY_COMPONENT 0x00040000
#define ACPI_BATTERY_COMPONENT 0x00040000
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
#define ACPI_BATTERY_NOTIFY_INFO 0x81
#define ACPI_BATTERY_NOTIFY_INFO 0x81
#define ACPI_BATTERY_UNITS_WATTS "mW"
#define ACPI_BATTERY_UNITS_AMPS "mA"
#define _COMPONENT ACPI_BATTERY_COMPONENT
#define _COMPONENT ACPI_BATTERY_COMPONENT
#define ACPI_BATTERY_UPDATE_TIME 0
#define ACPI_BATTERY_NONE_UPDATE 0
#define ACPI_BATTERY_EASY_UPDATE 1
#define ACPI_BATTERY_INIT_UPDATE 2
ACPI_MODULE_NAME
(
"battery"
);
ACPI_MODULE_NAME
(
"battery"
);
MODULE_AUTHOR
(
"Paul Diefenbaugh"
);
MODULE_AUTHOR
(
"Paul Diefenbaugh"
);
MODULE_AUTHOR
(
"Alexey Starikovskiy <astarikovskiy@suse.de>"
);
MODULE_DESCRIPTION
(
"ACPI Battery Driver"
);
MODULE_DESCRIPTION
(
"ACPI Battery Driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
static
unsigned
int
update_time
=
ACPI_BATTERY_UPDATE_TIME
;
static
unsigned
int
cache_time
=
1000
;
module_param
(
cache_time
,
uint
,
0644
);
/* 0 - every time, > 0 - by update_time */
MODULE_PARM_DESC
(
cache_time
,
"cache time in milliseconds"
);
module_param
(
update_time
,
uint
,
0644
);
#ifdef CONFIG_ACPI_PROCFS
extern
struct
proc_dir_entry
*
acpi_lock_battery_dir
(
void
);
extern
struct
proc_dir_entry
*
acpi_lock_battery_dir
(
void
);
extern
void
*
acpi_unlock_battery_dir
(
struct
proc_dir_entry
*
acpi_battery_dir
);
extern
void
*
acpi_unlock_battery_dir
(
struct
proc_dir_entry
*
acpi_battery_dir
);
static
int
acpi_battery_add
(
struct
acpi_device
*
device
);
enum
acpi_battery_files
{
static
int
acpi_battery_remove
(
struct
acpi_device
*
device
,
int
type
);
info_tag
=
0
,
static
int
acpi_battery_resume
(
struct
acpi_device
*
device
);
state_tag
,
alarm_tag
,
ACPI_BATTERY_NUMFILES
,
};
#endif
static
const
struct
acpi_device_id
battery_device_ids
[]
=
{
static
const
struct
acpi_device_id
battery_device_ids
[]
=
{
{
"PNP0C0A"
,
0
},
{
"PNP0C0A"
,
0
},
{
""
,
0
},
{
""
,
0
},
};
};
MODULE_DEVICE_TABLE
(
acpi
,
battery_device_ids
);
static
struct
acpi_driver
acpi_battery_driver
=
{
.
name
=
"battery"
,
.
class
=
ACPI_BATTERY_CLASS
,
.
ids
=
battery_device_ids
,
.
ops
=
{
.
add
=
acpi_battery_add
,
.
resume
=
acpi_battery_resume
,
.
remove
=
acpi_battery_remove
,
},
};
struct
acpi_battery_state
{
MODULE_DEVICE_TABLE
(
acpi
,
battery_device_ids
);
acpi_integer
state
;
acpi_integer
present_rate
;
acpi_integer
remaining_capacity
;
acpi_integer
present_voltage
;
};
struct
acpi_battery_info
{
acpi_integer
power_unit
;
acpi_integer
design_capacity
;
acpi_integer
last_full_capacity
;
acpi_integer
battery_technology
;
acpi_integer
design_voltage
;
acpi_integer
design_capacity_warning
;
acpi_integer
design_capacity_low
;
acpi_integer
battery_capacity_granularity_1
;
acpi_integer
battery_capacity_granularity_2
;
acpi_string
model_number
;
acpi_string
serial_number
;
acpi_string
battery_type
;
acpi_string
oem_info
;
};
enum
acpi_battery_files
{
ACPI_BATTERY_INFO
=
0
,
ACPI_BATTERY_STATE
,
ACPI_BATTERY_ALARM
,
ACPI_BATTERY_NUMFILES
,
};
struct
acpi_battery_flags
{
u8
battery_present_prev
;
u8
alarm_present
;
u8
init_update
;
u8
update
[
ACPI_BATTERY_NUMFILES
];
u8
power_unit
;
};
struct
acpi_battery
{
struct
acpi_battery
{
struct
mutex
mutex
;
struct
mutex
lock
;
struct
power_supply
bat
;
struct
acpi_device
*
device
;
struct
acpi_device
*
device
;
struct
acpi_battery_flags
flags
;
unsigned
long
update_time
;
struct
acpi_buffer
bif_data
;
int
current_now
;
struct
acpi_buffer
bst_data
;
int
capacity_now
;
unsigned
long
alarm
;
int
voltage_now
;
unsigned
long
update_time
[
ACPI_BATTERY_NUMFILES
];
int
design_capacity
;
int
full_charge_capacity
;
int
technology
;
int
design_voltage
;
int
design_capacity_warning
;
int
design_capacity_low
;
int
capacity_granularity_1
;
int
capacity_granularity_2
;
int
alarm
;
char
model_number
[
32
];
char
serial_number
[
32
];
char
type
[
32
];
char
oem_info
[
32
];
int
state
;
int
power_unit
;
u8
alarm_present
;
};
};
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
inline
int
acpi_battery_present
(
struct
acpi_battery
*
battery
)
inline
int
acpi_battery_present
(
struct
acpi_battery
*
battery
)
{
{
return
battery
->
device
->
status
.
battery_present
;
return
battery
->
device
->
status
.
battery_present
;
}
}
inline
char
*
acpi_battery_power_units
(
struct
acpi_battery
*
battery
)
{
if
(
battery
->
flags
.
power_unit
)
return
ACPI_BATTERY_UNITS_AMPS
;
else
return
ACPI_BATTERY_UNITS_WATTS
;
}
inline
acpi_handle
acpi_battery_handle
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_technology
(
struct
acpi_battery
*
battery
)
{
{
return
battery
->
device
->
handle
;
if
(
!
strcasecmp
(
"NiCd"
,
battery
->
type
))
return
POWER_SUPPLY_TECHNOLOGY_NiCd
;
if
(
!
strcasecmp
(
"NiMH"
,
battery
->
type
))
return
POWER_SUPPLY_TECHNOLOGY_NiMH
;
if
(
!
strcasecmp
(
"LION"
,
battery
->
type
))
return
POWER_SUPPLY_TECHNOLOGY_LION
;
if
(
!
strcasecmp
(
"LiP"
,
battery
->
type
))
return
POWER_SUPPLY_TECHNOLOGY_LIPO
;
return
POWER_SUPPLY_TECHNOLOGY_UNKNOWN
;
}
}
/* --------------------------------------------------------------------------
static
int
acpi_battery_get_property
(
struct
power_supply
*
psy
,
Battery Management
enum
power_supply_property
psp
,
-------------------------------------------------------------------------- */
union
power_supply_propval
*
val
)
static
void
acpi_battery_check_result
(
struct
acpi_battery
*
battery
,
int
result
)
{
{
if
(
!
battery
)
struct
acpi_battery
*
battery
=
to_acpi_battery
(
psy
);
return
;
if
(
result
)
{
if
((
!
acpi_battery_present
(
battery
))
&&
battery
->
flags
.
init_update
=
1
;
psp
!=
POWER_SUPPLY_PROP_PRESENT
)
return
-
ENODEV
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_STATUS
:
if
(
battery
->
state
&
0x01
)
val
->
intval
=
POWER_SUPPLY_STATUS_DISCHARGING
;
else
if
(
battery
->
state
&
0x02
)
val
->
intval
=
POWER_SUPPLY_STATUS_CHARGING
;
else
if
(
battery
->
state
==
0
)
val
->
intval
=
POWER_SUPPLY_STATUS_FULL
;
break
;
case
POWER_SUPPLY_PROP_PRESENT
:
val
->
intval
=
acpi_battery_present
(
battery
);
break
;
case
POWER_SUPPLY_PROP_TECHNOLOGY
:
val
->
intval
=
acpi_battery_technology
(
battery
);
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
val
->
intval
=
battery
->
design_voltage
*
1000
;
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_NOW
:
val
->
intval
=
battery
->
voltage_now
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CURRENT_NOW
:
val
->
intval
=
battery
->
current_now
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
:
case
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN
:
val
->
intval
=
battery
->
design_capacity
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_FULL
:
case
POWER_SUPPLY_PROP_ENERGY_FULL
:
val
->
intval
=
battery
->
full_charge_capacity
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_NOW
:
case
POWER_SUPPLY_PROP_ENERGY_NOW
:
val
->
intval
=
battery
->
capacity_now
*
1000
;
break
;
case
POWER_SUPPLY_PROP_MODEL_NAME
:
val
->
strval
=
battery
->
model_number
;
break
;
case
POWER_SUPPLY_PROP_MANUFACTURER
:
val
->
strval
=
battery
->
oem_info
;
break
;
default:
return
-
EINVAL
;
}
}
return
0
;
}
}
static
int
acpi_battery_extract_package
(
struct
acpi_battery
*
battery
,
static
enum
power_supply_property
charge_battery_props
[]
=
{
union
acpi_object
*
package
,
POWER_SUPPLY_PROP_STATUS
,
struct
acpi_buffer
*
format
,
POWER_SUPPLY_PROP_PRESENT
,
struct
acpi_buffer
*
data
,
POWER_SUPPLY_PROP_TECHNOLOGY
,
char
*
package_name
)
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_CURRENT_NOW
,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
,
POWER_SUPPLY_PROP_CHARGE_FULL
,
POWER_SUPPLY_PROP_CHARGE_NOW
,
POWER_SUPPLY_PROP_MODEL_NAME
,
POWER_SUPPLY_PROP_MANUFACTURER
,
};
static
enum
power_supply_property
energy_battery_props
[]
=
{
POWER_SUPPLY_PROP_STATUS
,
POWER_SUPPLY_PROP_PRESENT
,
POWER_SUPPLY_PROP_TECHNOLOGY
,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_CURRENT_NOW
,
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN
,
POWER_SUPPLY_PROP_ENERGY_FULL
,
POWER_SUPPLY_PROP_ENERGY_NOW
,
POWER_SUPPLY_PROP_MODEL_NAME
,
POWER_SUPPLY_PROP_MANUFACTURER
,
};
#ifdef CONFIG_ACPI_PROCFS
inline
char
*
acpi_battery_units
(
struct
acpi_battery
*
battery
)
{
{
acpi_status
status
=
AE_OK
;
return
(
battery
->
power_unit
)
?
"mA"
:
"mW"
;
struct
acpi_buffer
data_null
=
{
0
,
NULL
};
}
#endif
status
=
acpi_extract_package
(
package
,
format
,
&
data_null
);
/* --------------------------------------------------------------------------
if
(
status
!=
AE_BUFFER_OVERFLOW
)
{
Battery Management
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting size %s"
,
-------------------------------------------------------------------------- */
package_name
));
struct
acpi_offsets
{
return
-
ENODEV
;
size_t
offset
;
/* offset inside struct acpi_sbs_battery */
}
u8
mode
;
/* int or string? */
};
if
(
data_null
.
length
!=
data
->
length
)
{
static
struct
acpi_offsets
state_offsets
[]
=
{
kfree
(
data
->
pointer
);
{
offsetof
(
struct
acpi_battery
,
state
),
0
},
data
->
pointer
=
kzalloc
(
data_null
.
length
,
GFP_KERNEL
);
{
offsetof
(
struct
acpi_battery
,
current_now
),
0
},
if
(
!
data
->
pointer
)
{
{
offsetof
(
struct
acpi_battery
,
capacity_now
),
0
},
ACPI_EXCEPTION
((
AE_INFO
,
AE_NO_MEMORY
,
"kzalloc()"
));
{
offsetof
(
struct
acpi_battery
,
voltage_now
),
0
},
return
-
ENOMEM
;
};
}
data
->
length
=
data_null
.
length
;
}
status
=
acpi_extract_package
(
package
,
format
,
data
);
static
struct
acpi_offsets
info_offsets
[]
=
{
if
(
ACPI_FAILURE
(
status
))
{
{
offsetof
(
struct
acpi_battery
,
power_unit
),
0
},
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Extracting %s"
,
{
offsetof
(
struct
acpi_battery
,
design_capacity
),
0
},
package_name
));
{
offsetof
(
struct
acpi_battery
,
full_charge_capacity
),
0
},
return
-
ENODEV
;
{
offsetof
(
struct
acpi_battery
,
technology
),
0
},
}
{
offsetof
(
struct
acpi_battery
,
design_voltage
),
0
},
{
offsetof
(
struct
acpi_battery
,
design_capacity_warning
),
0
},
{
offsetof
(
struct
acpi_battery
,
design_capacity_low
),
0
},
{
offsetof
(
struct
acpi_battery
,
capacity_granularity_1
),
0
},
{
offsetof
(
struct
acpi_battery
,
capacity_granularity_2
),
0
},
{
offsetof
(
struct
acpi_battery
,
model_number
),
1
},
{
offsetof
(
struct
acpi_battery
,
serial_number
),
1
},
{
offsetof
(
struct
acpi_battery
,
type
),
1
},
{
offsetof
(
struct
acpi_battery
,
oem_info
),
1
},
};
static
int
extract_package
(
struct
acpi_battery
*
battery
,
union
acpi_object
*
package
,
struct
acpi_offsets
*
offsets
,
int
num
)
{
int
i
,
*
x
;
union
acpi_object
*
element
;
if
(
package
->
type
!=
ACPI_TYPE_PACKAGE
)
return
-
EFAULT
;
for
(
i
=
0
;
i
<
num
;
++
i
)
{
if
(
package
->
package
.
count
<=
i
)
return
-
EFAULT
;
element
=
&
package
->
package
.
elements
[
i
];
if
(
offsets
[
i
].
mode
)
{
if
(
element
->
type
!=
ACPI_TYPE_STRING
&&
element
->
type
!=
ACPI_TYPE_BUFFER
)
return
-
EFAULT
;
strncpy
((
u8
*
)
battery
+
offsets
[
i
].
offset
,
element
->
string
.
pointer
,
32
);
}
else
{
if
(
element
->
type
!=
ACPI_TYPE_INTEGER
)
return
-
EFAULT
;
x
=
(
int
*
)((
u8
*
)
battery
+
offsets
[
i
].
offset
);
*
x
=
element
->
integer
.
value
;
}
}
return
0
;
return
0
;
}
}
static
int
acpi_battery_get_status
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_get_status
(
struct
acpi_battery
*
battery
)
{
{
int
result
=
0
;
if
(
acpi_bus_get_status
(
battery
->
device
))
{
result
=
acpi_bus_get_status
(
battery
->
device
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"Evaluating _STA"
));
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"Evaluating _STA"
));
return
-
ENODEV
;
return
-
ENODEV
;
}
}
return
result
;
return
0
;
}
}
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
)
{
{
int
result
=
0
;
int
result
=
-
EFAULT
;
acpi_status
status
=
0
;
acpi_status
status
=
0
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
struct
acpi_buffer
format
=
{
sizeof
(
ACPI_BATTERY_FORMAT_BIF
),
ACPI_BATTERY_FORMAT_BIF
};
union
acpi_object
*
package
=
NULL
;
struct
acpi_buffer
*
data
=
NULL
;
struct
acpi_battery_info
*
bif
=
NULL
;
battery
->
update_time
[
ACPI_BATTERY_INFO
]
=
get_seconds
();
if
(
!
acpi_battery_present
(
battery
))
if
(
!
acpi_battery_present
(
battery
))
return
0
;
return
0
;
mutex_lock
(
&
battery
->
lock
);
status
=
acpi_evaluate_object
(
battery
->
device
->
handle
,
"_BIF"
,
NULL
,
&
buffer
);
mutex_unlock
(
&
battery
->
lock
);
/* Evaluate _BIF */
status
=
acpi_evaluate_object
(
acpi_battery_handle
(
battery
),
"_BIF"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Evaluating _BIF"
));
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Evaluating _BIF"
));
return
-
ENODEV
;
return
-
ENODEV
;
}
}
package
=
buffer
.
pointer
;
result
=
extract_package
(
battery
,
buffer
.
pointer
,
info_offsets
,
ARRAY_SIZE
(
info_offsets
));
data
=
&
battery
->
bif_data
;
/* Extract Package Data */
result
=
acpi_battery_extract_package
(
battery
,
package
,
&
format
,
data
,
"_BIF"
);
if
(
result
)
goto
end
;
end:
kfree
(
buffer
.
pointer
);
kfree
(
buffer
.
pointer
);
if
(
!
result
)
{
bif
=
data
->
pointer
;
battery
->
flags
.
power_unit
=
bif
->
power_unit
;
}
return
result
;
return
result
;
}
}
...
@@ -273,342 +319,203 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
...
@@ -273,342 +319,203 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
int
result
=
0
;
int
result
=
0
;
acpi_status
status
=
0
;
acpi_status
status
=
0
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
struct
acpi_buffer
format
=
{
sizeof
(
ACPI_BATTERY_FORMAT_BST
),
ACPI_BATTERY_FORMAT_BST
};
union
acpi_object
*
package
=
NULL
;
struct
acpi_buffer
*
data
=
NULL
;
battery
->
update_time
[
ACPI_BATTERY_STATE
]
=
get_seconds
();
if
(
!
acpi_battery_present
(
battery
))
if
(
!
acpi_battery_present
(
battery
))
return
0
;
return
0
;
/* Evaluate _BST */
if
(
battery
->
update_time
&&
time_before
(
jiffies
,
battery
->
update_time
+
msecs_to_jiffies
(
cache_time
)))
return
0
;
mutex_lock
(
&
battery
->
lock
);
status
=
acpi_evaluate_object
(
battery
->
device
->
handle
,
"_BST"
,
NULL
,
&
buffer
);
mutex_unlock
(
&
battery
->
lock
);
status
=
acpi_evaluate_object
(
acpi_battery_handle
(
battery
),
"_BST"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Evaluating _BST"
));
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Evaluating _BST"
));
return
-
ENODEV
;
return
-
ENODEV
;
}
}
package
=
buffer
.
pointer
;
result
=
extract_package
(
battery
,
buffer
.
pointer
,
state_offsets
,
ARRAY_SIZE
(
state_offsets
));
data
=
&
battery
->
bst_data
;
battery
->
update_time
=
jiffies
;
/* Extract Package Data */
result
=
acpi_battery_extract_package
(
battery
,
package
,
&
format
,
data
,
"_BST"
);
if
(
result
)
goto
end
;
end:
kfree
(
buffer
.
pointer
);
kfree
(
buffer
.
pointer
);
return
result
;
return
result
;
}
}
static
int
acpi_battery_get_alarm
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
)
{
battery
->
update_time
[
ACPI_BATTERY_ALARM
]
=
get_seconds
();
return
0
;
}
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
,
unsigned
long
alarm
)
{
{
acpi_status
status
=
0
;
acpi_status
status
=
0
;
union
acpi_object
arg0
=
{
ACPI_TYPE_INTEGER
};
union
acpi_object
arg0
=
{
.
type
=
ACPI_TYPE_INTEGER
};
struct
acpi_object_list
arg_list
=
{
1
,
&
arg0
};
struct
acpi_object_list
arg_list
=
{
1
,
&
arg0
};
battery
->
update_time
[
ACPI_BATTERY_ALARM
]
=
get_seconds
();
if
(
!
acpi_battery_present
(
battery
)
||
!
battery
->
alarm_present
)
if
(
!
acpi_battery_present
(
battery
))
return
-
ENODEV
;
return
-
ENODEV
;
if
(
!
battery
->
flags
.
alarm_present
)
arg0
.
integer
.
value
=
battery
->
alarm
;
return
-
ENODEV
;
arg0
.
integer
.
value
=
alarm
;
status
=
mutex_lock
(
&
battery
->
lock
);
acpi_evaluate_object
(
acpi_battery_handle
(
battery
)
,
"_BTP"
,
status
=
acpi_evaluate_object
(
battery
->
device
->
handle
,
"_BTP"
,
&
arg_list
,
NULL
);
&
arg_list
,
NULL
);
mutex_unlock
(
&
battery
->
lock
);
if
(
ACPI_FAILURE
(
status
))
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
return
-
ENODEV
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Alarm set to %d
\n
"
,
(
u32
)
alarm
));
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Alarm set to %d
\n
"
,
battery
->
alarm
));
battery
->
alarm
=
alarm
;
return
0
;
return
0
;
}
}
static
int
acpi_battery_init_alarm
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_init_alarm
(
struct
acpi_battery
*
battery
)
{
{
int
result
=
0
;
acpi_status
status
=
AE_OK
;
acpi_status
status
=
AE_OK
;
acpi_handle
handle
=
NULL
;
acpi_handle
handle
=
NULL
;
struct
acpi_battery_info
*
bif
=
battery
->
bif_data
.
pointer
;
unsigned
long
alarm
=
battery
->
alarm
;
/* See if alarms are supported, and if so, set default */
/* See if alarms are supported, and if so, set default */
status
=
acpi_get_handle
(
battery
->
device
->
handle
,
"_BTP"
,
&
handle
);
status
=
acpi_get_handle
(
acpi_battery_handle
(
battery
),
"_BTP"
,
&
handle
);
if
(
ACPI_FAILURE
(
status
))
{
if
(
ACPI_SUCCESS
(
status
))
{
battery
->
alarm_present
=
0
;
battery
->
flags
.
alarm_present
=
1
;
return
0
;
if
(
!
alarm
&&
bif
)
{
alarm
=
bif
->
design_capacity_warning
;
}
result
=
acpi_battery_set_alarm
(
battery
,
alarm
);
if
(
result
)
goto
end
;
}
else
{
battery
->
flags
.
alarm_present
=
0
;
}
}
battery
->
alarm_present
=
1
;
end:
if
(
!
battery
->
alarm
)
battery
->
alarm
=
battery
->
design_capacity_warning
;
return
result
;
return
acpi_battery_set_alarm
(
battery
)
;
}
}
static
int
acpi_battery_
init_
update
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_update
(
struct
acpi_battery
*
battery
)
{
{
int
result
=
0
;
int
saved_present
=
acpi_battery_present
(
battery
);
int
result
=
acpi_battery_get_status
(
battery
);
result
=
acpi_battery_get_status
(
battery
);
if
(
result
||
!
acpi_battery_present
(
battery
))
if
(
result
)
return
result
;
return
result
;
if
(
saved_present
!=
acpi_battery_present
(
battery
)
||
battery
->
flags
.
battery_present_prev
=
acpi_battery_present
(
battery
);
!
battery
->
update_time
)
{
battery
->
update_time
=
0
;
if
(
acpi_battery_present
(
battery
))
{
result
=
acpi_battery_get_info
(
battery
);
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
if
(
result
)
return
result
;
return
result
;
result
=
acpi_battery_get_state
(
battery
);
if
(
battery
->
power_unit
)
{
if
(
result
)
battery
->
bat
.
properties
=
charge_battery_props
;
return
result
;
battery
->
bat
.
num_properties
=
ARRAY_SIZE
(
charge_battery_props
);
acpi_battery_init_alarm
(
battery
);
}
return
result
;
}
static
int
acpi_battery_update
(
struct
acpi_battery
*
battery
,
int
update
,
int
*
update_result_ptr
)
{
int
result
=
0
;
int
update_result
=
ACPI_BATTERY_NONE_UPDATE
;
if
(
!
acpi_battery_present
(
battery
))
{
update
=
1
;
}
if
(
battery
->
flags
.
init_update
)
{
result
=
acpi_battery_init_update
(
battery
);
if
(
result
)
goto
end
;
update_result
=
ACPI_BATTERY_INIT_UPDATE
;
}
else
if
(
update
)
{
result
=
acpi_battery_get_status
(
battery
);
if
(
result
)
goto
end
;
if
((
!
battery
->
flags
.
battery_present_prev
&
acpi_battery_present
(
battery
))
||
(
battery
->
flags
.
battery_present_prev
&
!
acpi_battery_present
(
battery
)))
{
result
=
acpi_battery_init_update
(
battery
);
if
(
result
)
goto
end
;
update_result
=
ACPI_BATTERY_INIT_UPDATE
;
}
else
{
}
else
{
update_result
=
ACPI_BATTERY_EASY_UPDATE
;
battery
->
bat
.
properties
=
energy_battery_props
;
battery
->
bat
.
num_properties
=
ARRAY_SIZE
(
energy_battery_props
);
}
}
acpi_battery_init_alarm
(
battery
);
}
}
return
acpi_battery_get_state
(
battery
);
end:
battery
->
flags
.
init_update
=
(
result
!=
0
);
*
update_result_ptr
=
update_result
;
return
result
;
}
static
void
acpi_battery_notify_update
(
struct
acpi_battery
*
battery
)
{
acpi_battery_get_status
(
battery
);
if
(
battery
->
flags
.
init_update
)
{
return
;
}
if
((
!
battery
->
flags
.
battery_present_prev
&
acpi_battery_present
(
battery
))
||
(
battery
->
flags
.
battery_present_prev
&
!
acpi_battery_present
(
battery
)))
{
battery
->
flags
.
init_update
=
1
;
}
else
{
battery
->
flags
.
update
[
ACPI_BATTERY_INFO
]
=
1
;
battery
->
flags
.
update
[
ACPI_BATTERY_STATE
]
=
1
;
battery
->
flags
.
update
[
ACPI_BATTERY_ALARM
]
=
1
;
}
}
}
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
FS Interface (/proc)
FS Interface (/proc)
-------------------------------------------------------------------------- */
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS
static
struct
proc_dir_entry
*
acpi_battery_dir
;
static
struct
proc_dir_entry
*
acpi_battery_dir
;
static
int
acpi_battery_print_info
(
struct
seq_file
*
seq
,
int
result
)
static
int
acpi_battery_print_info
(
struct
seq_file
*
seq
,
int
result
)
{
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery_info
*
bif
=
NULL
;
char
*
units
=
"?"
;
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
if
(
acpi_battery_present
(
battery
))
seq_printf
(
seq
,
"present: %s
\n
"
,
seq_printf
(
seq
,
"present: yes
\n
"
);
acpi_battery_present
(
battery
)
?
"yes"
:
"no"
);
else
{
if
(
!
acpi_battery_present
(
battery
))
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
}
bif
=
battery
->
bif_data
.
pointer
;
if
(
!
bif
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"BIF buffer is NULL"
));
result
=
-
ENODEV
;
goto
end
;
goto
end
;
}
if
(
battery
->
design_capacity
==
ACPI_BATTERY_VALUE_UNKNOWN
)
/* Battery Units */
units
=
acpi_battery_power_units
(
battery
);
if
(
bif
->
design_capacity
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"design capacity: unknown
\n
"
);
seq_printf
(
seq
,
"design capacity: unknown
\n
"
);
else
else
seq_printf
(
seq
,
"design capacity: %d %sh
\n
"
,
seq_printf
(
seq
,
"design capacity: %d %sh
\n
"
,
(
u32
)
bif
->
design_capacity
,
units
);
battery
->
design_capacity
,
acpi_battery_units
(
battery
));
if
(
b
if
->
last_full
_capacity
==
ACPI_BATTERY_VALUE_UNKNOWN
)
if
(
b
attery
->
full_charge
_capacity
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"last full capacity: unknown
\n
"
);
seq_printf
(
seq
,
"last full capacity: unknown
\n
"
);
else
else
seq_printf
(
seq
,
"last full capacity: %d %sh
\n
"
,
seq_printf
(
seq
,
"last full capacity: %d %sh
\n
"
,
(
u32
)
bif
->
last_full_capacity
,
units
);
battery
->
full_charge_capacity
,
acpi_battery_units
(
battery
));
switch
((
u32
)
bif
->
battery_technology
)
{
seq_printf
(
seq
,
"battery technology: %srechargeable
\n
"
,
case
0
:
(
!
battery
->
technology
)
?
"non-"
:
""
);
seq_printf
(
seq
,
"battery technology: non-rechargeable
\n
"
);
break
;
case
1
:
seq_printf
(
seq
,
"battery technology: rechargeable
\n
"
);
break
;
default:
seq_printf
(
seq
,
"battery technology: unknown
\n
"
);
break
;
}
if
(
b
if
->
design_voltage
==
ACPI_BATTERY_VALUE_UNKNOWN
)
if
(
b
attery
->
design_voltage
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"design voltage: unknown
\n
"
);
seq_printf
(
seq
,
"design voltage: unknown
\n
"
);
else
else
seq_printf
(
seq
,
"design voltage: %d mV
\n
"
,
seq_printf
(
seq
,
"design voltage: %d mV
\n
"
,
(
u32
)
bif
->
design_voltage
);
battery
->
design_voltage
);
seq_printf
(
seq
,
"design capacity warning: %d %sh
\n
"
,
seq_printf
(
seq
,
"design capacity warning: %d %sh
\n
"
,
(
u32
)
bif
->
design_capacity_warning
,
units
);
battery
->
design_capacity_warning
,
acpi_battery_units
(
battery
));
seq_printf
(
seq
,
"design capacity low: %d %sh
\n
"
,
seq_printf
(
seq
,
"design capacity low: %d %sh
\n
"
,
(
u32
)
bif
->
design_capacity_low
,
units
);
battery
->
design_capacity_low
,
acpi_battery_units
(
battery
));
seq_printf
(
seq
,
"capacity granularity 1: %d %sh
\n
"
,
seq_printf
(
seq
,
"capacity granularity 1: %d %sh
\n
"
,
(
u32
)
bif
->
battery_capacity_granularity_1
,
units
);
battery
->
capacity_granularity_1
,
acpi_battery_units
(
battery
));
seq_printf
(
seq
,
"capacity granularity 2: %d %sh
\n
"
,
seq_printf
(
seq
,
"capacity granularity 2: %d %sh
\n
"
,
(
u32
)
bif
->
battery_capacity_granularity_2
,
units
);
battery
->
capacity_granularity_2
,
seq_printf
(
seq
,
"model number: %s
\n
"
,
bif
->
model_number
);
acpi_battery_units
(
battery
)
);
seq_printf
(
seq
,
"
serial number: %s
\n
"
,
bif
->
seria
l_number
);
seq_printf
(
seq
,
"
model number: %s
\n
"
,
battery
->
mode
l_number
);
seq_printf
(
seq
,
"
battery type: %s
\n
"
,
bif
->
battery_type
);
seq_printf
(
seq
,
"
serial number: %s
\n
"
,
battery
->
serial_number
);
seq_printf
(
seq
,
"
OEM info: %s
\n
"
,
bif
->
oem_info
);
seq_printf
(
seq
,
"
battery type: %s
\n
"
,
battery
->
type
);
seq_printf
(
seq
,
"OEM info: %s
\n
"
,
battery
->
oem_info
);
end:
end:
if
(
result
)
if
(
result
)
seq_printf
(
seq
,
"ERROR: Unable to read battery info
\n
"
);
seq_printf
(
seq
,
"ERROR: Unable to read battery info
\n
"
);
return
result
;
return
result
;
}
}
static
int
acpi_battery_print_state
(
struct
seq_file
*
seq
,
int
result
)
static
int
acpi_battery_print_state
(
struct
seq_file
*
seq
,
int
result
)
{
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery_state
*
bst
=
NULL
;
char
*
units
=
"?"
;
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
if
(
acpi_battery_present
(
battery
))
seq_printf
(
seq
,
"present: %s
\n
"
,
seq_printf
(
seq
,
"present: yes
\n
"
);
acpi_battery_present
(
battery
)
?
"yes"
:
"no"
);
else
{
if
(
!
acpi_battery_present
(
battery
))
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
}
bst
=
battery
->
bst_data
.
pointer
;
if
(
!
bst
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"BST buffer is NULL"
));
result
=
-
ENODEV
;
goto
end
;
goto
end
;
}
/* Battery Units */
units
=
acpi_battery_power_units
(
battery
);
if
(
!
(
bst
->
state
&
0x04
))
seq_printf
(
seq
,
"capacity state: ok
\n
"
);
else
seq_printf
(
seq
,
"capacity state: critical
\n
"
);
if
((
bst
->
state
&
0x01
)
&&
(
bst
->
state
&
0x02
))
{
seq_printf
(
seq
,
"capacity state: %s
\n
"
,
(
battery
->
state
&
0x04
)
?
"critical"
:
"ok"
);
if
((
battery
->
state
&
0x01
)
&&
(
battery
->
state
&
0x02
))
seq_printf
(
seq
,
seq_printf
(
seq
,
"charging state: charging/discharging
\n
"
);
"charging state: charging/discharging
\n
"
);
}
else
if
(
bst
->
state
&
0x01
)
else
if
(
battery
->
state
&
0x01
)
seq_printf
(
seq
,
"charging state: discharging
\n
"
);
seq_printf
(
seq
,
"charging state: discharging
\n
"
);
else
if
(
b
st
->
state
&
0x02
)
else
if
(
b
attery
->
state
&
0x02
)
seq_printf
(
seq
,
"charging state: charging
\n
"
);
seq_printf
(
seq
,
"charging state: charging
\n
"
);
else
{
else
seq_printf
(
seq
,
"charging state: charged
\n
"
);
seq_printf
(
seq
,
"charging state: charged
\n
"
);
}
if
(
b
st
->
present_rate
==
ACPI_BATTERY_VALUE_UNKNOWN
)
if
(
b
attery
->
current_now
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"present rate: unknown
\n
"
);
seq_printf
(
seq
,
"present rate: unknown
\n
"
);
else
else
seq_printf
(
seq
,
"present rate: %d %s
\n
"
,
seq_printf
(
seq
,
"present rate: %d %s
\n
"
,
(
u32
)
bst
->
present_rate
,
units
);
battery
->
current_now
,
acpi_battery_units
(
battery
)
);
if
(
b
st
->
remaining_capacity
==
ACPI_BATTERY_VALUE_UNKNOWN
)
if
(
b
attery
->
capacity_now
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"remaining capacity: unknown
\n
"
);
seq_printf
(
seq
,
"remaining capacity: unknown
\n
"
);
else
else
seq_printf
(
seq
,
"remaining capacity: %d %sh
\n
"
,
seq_printf
(
seq
,
"remaining capacity: %d %sh
\n
"
,
(
u32
)
bst
->
remaining_capacity
,
units
);
battery
->
capacity_now
,
acpi_battery_units
(
battery
));
if
(
battery
->
voltage_now
==
ACPI_BATTERY_VALUE_UNKNOWN
)
if
(
bst
->
present_voltage
==
ACPI_BATTERY_VALUE_UNKNOWN
)
seq_printf
(
seq
,
"present voltage: unknown
\n
"
);
seq_printf
(
seq
,
"present voltage: unknown
\n
"
);
else
else
seq_printf
(
seq
,
"present voltage: %d mV
\n
"
,
seq_printf
(
seq
,
"present voltage: %d mV
\n
"
,
(
u32
)
bst
->
present_voltage
);
battery
->
voltage_now
);
end:
end:
if
(
result
)
if
(
result
)
{
seq_printf
(
seq
,
"ERROR: Unable to read battery state
\n
"
);
seq_printf
(
seq
,
"ERROR: Unable to read battery state
\n
"
);
}
return
result
;
return
result
;
}
}
...
@@ -616,7 +523,6 @@ static int acpi_battery_print_state(struct seq_file *seq, int result)
...
@@ -616,7 +523,6 @@ static int acpi_battery_print_state(struct seq_file *seq, int result)
static
int
acpi_battery_print_alarm
(
struct
seq_file
*
seq
,
int
result
)
static
int
acpi_battery_print_alarm
(
struct
seq_file
*
seq
,
int
result
)
{
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
char
*
units
=
"?"
;
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
...
@@ -625,189 +531,121 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result)
...
@@ -625,189 +531,121 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result)
seq_printf
(
seq
,
"present: no
\n
"
);
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
goto
end
;
}
}
/* Battery Units */
units
=
acpi_battery_power_units
(
battery
);
seq_printf
(
seq
,
"alarm: "
);
seq_printf
(
seq
,
"alarm: "
);
if
(
!
battery
->
alarm
)
if
(
!
battery
->
alarm
)
seq_printf
(
seq
,
"unsupported
\n
"
);
seq_printf
(
seq
,
"unsupported
\n
"
);
else
else
seq_printf
(
seq
,
"%
lu %sh
\n
"
,
battery
->
alarm
,
units
);
seq_printf
(
seq
,
"%
u %sh
\n
"
,
battery
->
alarm
,
acpi_battery_units
(
battery
));
end:
end:
if
(
result
)
if
(
result
)
seq_printf
(
seq
,
"ERROR: Unable to read battery alarm
\n
"
);
seq_printf
(
seq
,
"ERROR: Unable to read battery alarm
\n
"
);
return
result
;
return
result
;
}
}
static
ssize_t
static
ssize_t
acpi_battery_write_alarm
(
struct
file
*
file
,
acpi_battery_write_alarm
(
struct
file
*
file
,
const
char
__user
*
buffer
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
)
{
{
int
result
=
0
;
int
result
=
0
;
char
alarm_string
[
12
]
=
{
'\0'
};
char
alarm_string
[
12
]
=
{
'\0'
};
struct
seq_file
*
m
=
file
->
private_data
;
struct
seq_file
*
m
=
file
->
private_data
;
struct
acpi_battery
*
battery
=
m
->
private
;
struct
acpi_battery
*
battery
=
m
->
private
;
int
update_result
=
ACPI_BATTERY_NONE_UPDATE
;
if
(
!
battery
||
(
count
>
sizeof
(
alarm_string
)
-
1
))
if
(
!
battery
||
(
count
>
sizeof
(
alarm_string
)
-
1
))
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
battery
->
mutex
);
result
=
acpi_battery_update
(
battery
,
1
,
&
update_result
);
if
(
result
)
{
if
(
result
)
{
result
=
-
ENODEV
;
result
=
-
ENODEV
;
goto
end
;
goto
end
;
}
}
if
(
!
acpi_battery_present
(
battery
))
{
if
(
!
acpi_battery_present
(
battery
))
{
result
=
-
ENODEV
;
result
=
-
ENODEV
;
goto
end
;
goto
end
;
}
}
if
(
copy_from_user
(
alarm_string
,
buffer
,
count
))
{
if
(
copy_from_user
(
alarm_string
,
buffer
,
count
))
{
result
=
-
EFAULT
;
result
=
-
EFAULT
;
goto
end
;
goto
end
;
}
}
alarm_string
[
count
]
=
'\0'
;
alarm_string
[
count
]
=
'\0'
;
battery
->
alarm
=
simple_strtol
(
alarm_string
,
NULL
,
0
);
result
=
acpi_battery_set_alarm
(
battery
,
result
=
acpi_battery_set_alarm
(
battery
);
simple_strtoul
(
alarm_string
,
NULL
,
0
));
if
(
result
)
goto
end
;
end:
end:
acpi_battery_check_result
(
battery
,
result
);
if
(
!
result
)
if
(
!
result
)
result
=
count
;
return
count
;
mutex_unlock
(
&
battery
->
mutex
);
return
result
;
return
result
;
}
}
typedef
int
(
*
print_func
)(
struct
seq_file
*
seq
,
int
result
);
typedef
int
(
*
print_func
)(
struct
seq_file
*
seq
,
int
result
);
typedef
int
(
*
get_func
)(
struct
acpi_battery
*
battery
);
static
print_func
acpi_print_funcs
[
ACPI_BATTERY_NUMFILES
]
=
{
static
struct
acpi_read_mux
{
acpi_battery_print_info
,
print_func
print
;
acpi_battery_print_state
,
get_func
get
;
acpi_battery_print_alarm
,
}
acpi_read_funcs
[
ACPI_BATTERY_NUMFILES
]
=
{
{.
get
=
acpi_battery_get_info
,
.
print
=
acpi_battery_print_info
},
{.
get
=
acpi_battery_get_state
,
.
print
=
acpi_battery_print_state
},
{.
get
=
acpi_battery_get_alarm
,
.
print
=
acpi_battery_print_alarm
},
};
};
static
int
acpi_battery_read
(
int
fid
,
struct
seq_file
*
seq
)
static
int
acpi_battery_read
(
int
fid
,
struct
seq_file
*
seq
)
{
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
int
result
=
0
;
int
result
=
acpi_battery_update
(
battery
);
int
update_result
=
ACPI_BATTERY_NONE_UPDATE
;
return
acpi_print_funcs
[
fid
](
seq
,
result
);
int
update
=
0
;
}
mutex_lock
(
&
battery
->
mutex
);
#define DECLARE_FILE_FUNCTIONS(_name) \
static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
update
=
(
get_seconds
()
-
battery
->
update_time
[
fid
]
>=
update_time
);
{ \
update
=
(
update
|
battery
->
flags
.
update
[
fid
]);
return acpi_battery_read(_name##_tag, seq); \
} \
result
=
acpi_battery_update
(
battery
,
update
,
&
update_result
);
static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
if
(
result
)
{ \
goto
end
;
return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
}
if
(
update_result
==
ACPI_BATTERY_EASY_UPDATE
)
{
result
=
acpi_read_funcs
[
fid
].
get
(
battery
);
DECLARE_FILE_FUNCTIONS
(
info
);
if
(
result
)
DECLARE_FILE_FUNCTIONS
(
state
);
goto
end
;
DECLARE_FILE_FUNCTIONS
(
alarm
);
#undef DECLARE_FILE_FUNCTIONS
#define FILE_DESCRIPTION_RO(_name) \
{ \
.name = __stringify(_name), \
.mode = S_IRUGO, \
.ops = { \
.open = acpi_battery_##_name##_open_fs, \
.read = seq_read, \
.llseek = seq_lseek, \
.release = single_release, \
.owner = THIS_MODULE, \
}, \
}
#define FILE_DESCRIPTION_RW(_name) \
{ \
.name = __stringify(_name), \
.mode = S_IFREG | S_IRUGO | S_IWUSR, \
.ops = { \
.open = acpi_battery_##_name##_open_fs, \
.read = seq_read, \
.llseek = seq_lseek, \
.write = acpi_battery_write_##_name, \
.release = single_release, \
.owner = THIS_MODULE, \
}, \
}
}
end:
result
=
acpi_read_funcs
[
fid
].
print
(
seq
,
result
);
acpi_battery_check_result
(
battery
,
result
);
battery
->
flags
.
update
[
fid
]
=
result
;
mutex_unlock
(
&
battery
->
mutex
);
return
result
;
}
static
int
acpi_battery_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
{
return
acpi_battery_read
(
ACPI_BATTERY_INFO
,
seq
);
}
static
int
acpi_battery_read_state
(
struct
seq_file
*
seq
,
void
*
offset
)
{
return
acpi_battery_read
(
ACPI_BATTERY_STATE
,
seq
);
}
static
int
acpi_battery_read_alarm
(
struct
seq_file
*
seq
,
void
*
offset
)
{
return
acpi_battery_read
(
ACPI_BATTERY_ALARM
,
seq
);
}
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_state_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
acpi_battery_read_state
,
PDE
(
inode
)
->
data
);
}
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
battery_file
{
static
struct
battery_file
{
struct
file_operations
ops
;
struct
file_operations
ops
;
mode_t
mode
;
mode_t
mode
;
char
*
name
;
char
*
name
;
}
acpi_battery_file
[]
=
{
}
acpi_battery_file
[]
=
{
{
FILE_DESCRIPTION_RO
(
info
),
.
name
=
"info"
,
FILE_DESCRIPTION_RO
(
state
),
.
mode
=
S_IRUGO
,
FILE_DESCRIPTION_RW
(
alarm
),
.
ops
=
{
.
open
=
acpi_battery_info_open_fs
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
},
},
{
.
name
=
"state"
,
.
mode
=
S_IRUGO
,
.
ops
=
{
.
open
=
acpi_battery_state_open_fs
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
},
},
{
.
name
=
"alarm"
,
.
mode
=
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
.
ops
=
{
.
open
=
acpi_battery_alarm_open_fs
,
.
read
=
seq_read
,
.
write
=
acpi_battery_write_alarm
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
},
},
};
};
#undef FILE_DESCRIPTION_RO
#undef FILE_DESCRIPTION_RW
static
int
acpi_battery_add_fs
(
struct
acpi_device
*
device
)
static
int
acpi_battery_add_fs
(
struct
acpi_device
*
device
)
{
{
struct
proc_dir_entry
*
entry
=
NULL
;
struct
proc_dir_entry
*
entry
=
NULL
;
...
@@ -832,25 +670,51 @@ static int acpi_battery_add_fs(struct acpi_device *device)
...
@@ -832,25 +670,51 @@ static int acpi_battery_add_fs(struct acpi_device *device)
entry
->
owner
=
THIS_MODULE
;
entry
->
owner
=
THIS_MODULE
;
}
}
}
}
return
0
;
return
0
;
}
}
static
int
acpi_battery_remove_fs
(
struct
acpi_device
*
device
)
static
void
acpi_battery_remove_fs
(
struct
acpi_device
*
device
)
{
{
int
i
;
int
i
;
if
(
acpi_device_dir
(
device
))
{
if
(
!
acpi_device_dir
(
device
))
for
(
i
=
0
;
i
<
ACPI_BATTERY_NUMFILES
;
++
i
)
{
return
;
remove_proc_entry
(
acpi_battery_file
[
i
].
name
,
for
(
i
=
0
;
i
<
ACPI_BATTERY_NUMFILES
;
++
i
)
remove_proc_entry
(
acpi_battery_file
[
i
].
name
,
acpi_device_dir
(
device
));
acpi_device_dir
(
device
));
}
remove_proc_entry
(
acpi_device_bid
(
device
),
acpi_battery_dir
);
acpi_device_dir
(
device
)
=
NULL
;
}
return
0
;
remove_proc_entry
(
acpi_device_bid
(
device
),
acpi_battery_dir
);
acpi_device_dir
(
device
)
=
NULL
;
}
#endif
static
ssize_t
acpi_battery_alarm_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
acpi_battery
*
battery
=
to_acpi_battery
(
dev_get_drvdata
(
dev
));
return
sprintf
(
buf
,
"%d
\n
"
,
battery
->
alarm
*
1000
);
}
static
ssize_t
acpi_battery_alarm_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
unsigned
long
x
;
struct
acpi_battery
*
battery
=
to_acpi_battery
(
dev_get_drvdata
(
dev
));
if
(
sscanf
(
buf
,
"%ld
\n
"
,
&
x
)
==
1
)
battery
->
alarm
=
x
/
1000
;
if
(
acpi_battery_present
(
battery
))
acpi_battery_set_alarm
(
battery
);
return
count
;
}
}
static
struct
device_attribute
alarm_attr
=
{
.
attr
=
{.
name
=
"alarm"
,
.
mode
=
0644
,
.
owner
=
THIS_MODULE
},
.
show
=
acpi_battery_alarm_show
,
.
store
=
acpi_battery_alarm_store
,
};
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
Driver Interface
Driver Interface
-------------------------------------------------------------------------- */
-------------------------------------------------------------------------- */
...
@@ -858,33 +722,17 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
...
@@ -858,33 +722,17 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
static
void
acpi_battery_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
static
void
acpi_battery_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
{
{
struct
acpi_battery
*
battery
=
data
;
struct
acpi_battery
*
battery
=
data
;
struct
acpi_device
*
device
=
NULL
;
struct
acpi_device
*
device
;
if
(
!
battery
)
if
(
!
battery
)
return
;
return
;
device
=
battery
->
device
;
device
=
battery
->
device
;
acpi_battery_update
(
battery
);
switch
(
event
)
{
acpi_bus_generate_proc_event
(
device
,
event
,
case
ACPI_BATTERY_NOTIFY_STATUS
:
acpi_battery_present
(
battery
));
case
ACPI_BATTERY_NOTIFY_INFO
:
acpi_bus_generate_netlink_event
(
device
->
pnp
.
device_class
,
case
ACPI_NOTIFY_BUS_CHECK
:
device
->
dev
.
bus_id
,
event
,
case
ACPI_NOTIFY_DEVICE_CHECK
:
device
=
battery
->
device
;
acpi_battery_notify_update
(
battery
);
acpi_bus_generate_proc_event
(
device
,
event
,
acpi_battery_present
(
battery
));
acpi_battery_present
(
battery
));
acpi_bus_generate_netlink_event
(
device
->
pnp
.
device_class
,
kobject_uevent
(
&
battery
->
bat
.
dev
->
kobj
,
KOBJ_CHANGE
);
device
->
dev
.
bus_id
,
event
,
acpi_battery_present
(
battery
));
break
;
default:
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Unsupported event [0x%x]
\n
"
,
event
));
break
;
}
return
;
}
}
static
int
acpi_battery_add
(
struct
acpi_device
*
device
)
static
int
acpi_battery_add
(
struct
acpi_device
*
device
)
...
@@ -892,33 +740,27 @@ static int acpi_battery_add(struct acpi_device *device)
...
@@ -892,33 +740,27 @@ static int acpi_battery_add(struct acpi_device *device)
int
result
=
0
;
int
result
=
0
;
acpi_status
status
=
0
;
acpi_status
status
=
0
;
struct
acpi_battery
*
battery
=
NULL
;
struct
acpi_battery
*
battery
=
NULL
;
if
(
!
device
)
if
(
!
device
)
return
-
EINVAL
;
return
-
EINVAL
;
battery
=
kzalloc
(
sizeof
(
struct
acpi_battery
),
GFP_KERNEL
);
battery
=
kzalloc
(
sizeof
(
struct
acpi_battery
),
GFP_KERNEL
);
if
(
!
battery
)
if
(
!
battery
)
return
-
ENOMEM
;
return
-
ENOMEM
;
mutex_init
(
&
battery
->
mutex
);
mutex_lock
(
&
battery
->
mutex
);
battery
->
device
=
device
;
battery
->
device
=
device
;
strcpy
(
acpi_device_name
(
device
),
ACPI_BATTERY_DEVICE_NAME
);
strcpy
(
acpi_device_name
(
device
),
ACPI_BATTERY_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_BATTERY_CLASS
);
strcpy
(
acpi_device_class
(
device
),
ACPI_BATTERY_CLASS
);
acpi_driver_data
(
device
)
=
battery
;
acpi_driver_data
(
device
)
=
battery
;
mutex_init
(
&
battery
->
lock
);
result
=
acpi_battery_get_status
(
battery
);
acpi_battery_update
(
battery
);
if
(
result
)
#ifdef CONFIG_ACPI_PROCFS
goto
end
;
battery
->
flags
.
init_update
=
1
;
result
=
acpi_battery_add_fs
(
device
);
result
=
acpi_battery_add_fs
(
device
);
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
#endif
battery
->
bat
.
name
=
acpi_device_bid
(
device
);
battery
->
bat
.
type
=
POWER_SUPPLY_TYPE_BATTERY
;
battery
->
bat
.
get_property
=
acpi_battery_get_property
;
result
=
power_supply_register
(
&
battery
->
device
->
dev
,
&
battery
->
bat
);
result
=
device_create_file
(
battery
->
bat
.
dev
,
&
alarm_attr
);
status
=
acpi_install_notify_handler
(
device
->
handle
,
status
=
acpi_install_notify_handler
(
device
->
handle
,
ACPI_ALL_NOTIFY
,
ACPI_ALL_NOTIFY
,
acpi_battery_notify
,
battery
);
acpi_battery_notify
,
battery
);
...
@@ -927,20 +769,16 @@ static int acpi_battery_add(struct acpi_device *device)
...
@@ -927,20 +769,16 @@ static int acpi_battery_add(struct acpi_device *device)
result
=
-
ENODEV
;
result
=
-
ENODEV
;
goto
end
;
goto
end
;
}
}
printk
(
KERN_INFO
PREFIX
"%s Slot [%s] (battery %s)
\n
"
,
printk
(
KERN_INFO
PREFIX
"%s Slot [%s] (battery %s)
\n
"
,
ACPI_BATTERY_DEVICE_NAME
,
acpi_device_bid
(
device
),
ACPI_BATTERY_DEVICE_NAME
,
acpi_device_bid
(
device
),
device
->
status
.
battery_present
?
"present"
:
"absent"
);
device
->
status
.
battery_present
?
"present"
:
"absent"
);
end:
end:
if
(
result
)
{
if
(
result
)
{
#ifdef CONFIG_ACPI_PROCFS
acpi_battery_remove_fs
(
device
);
acpi_battery_remove_fs
(
device
);
#endif
kfree
(
battery
);
kfree
(
battery
);
}
}
mutex_unlock
(
&
battery
->
mutex
);
return
result
;
return
result
;
}
}
...
@@ -951,27 +789,19 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
...
@@ -951,27 +789,19 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
if
(
!
device
||
!
acpi_driver_data
(
device
))
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
-
EINVAL
;
return
-
EINVAL
;
battery
=
acpi_driver_data
(
device
);
battery
=
acpi_driver_data
(
device
);
mutex_lock
(
&
battery
->
mutex
);
status
=
acpi_remove_notify_handler
(
device
->
handle
,
status
=
acpi_remove_notify_handler
(
device
->
handle
,
ACPI_ALL_NOTIFY
,
ACPI_ALL_NOTIFY
,
acpi_battery_notify
);
acpi_battery_notify
);
#ifdef CONFIG_ACPI_PROCFS
acpi_battery_remove_fs
(
device
);
acpi_battery_remove_fs
(
device
);
#endif
kfree
(
battery
->
bif_data
.
pointer
);
if
(
battery
->
bat
.
dev
)
{
device_remove_file
(
battery
->
bat
.
dev
,
&
alarm_attr
);
kfree
(
battery
->
bst_data
.
pointer
);
power_supply_unregister
(
&
battery
->
bat
);
}
mutex_unlock
(
&
battery
->
mutex
);
mutex_destroy
(
&
battery
->
lock
);
mutex_destroy
(
&
battery
->
mutex
);
kfree
(
battery
);
kfree
(
battery
);
return
0
;
return
0
;
}
}
...
@@ -979,44 +809,48 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
...
@@ -979,44 +809,48 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
static
int
acpi_battery_resume
(
struct
acpi_device
*
device
)
static
int
acpi_battery_resume
(
struct
acpi_device
*
device
)
{
{
struct
acpi_battery
*
battery
;
struct
acpi_battery
*
battery
;
if
(
!
device
)
if
(
!
device
)
return
-
EINVAL
;
return
-
EINVAL
;
battery
=
acpi_driver_data
(
device
);
battery
=
device
->
driver_data
;
battery
->
update_time
=
0
;
battery
->
flags
.
init_update
=
1
;
return
0
;
return
0
;
}
}
static
struct
acpi_driver
acpi_battery_driver
=
{
.
name
=
"battery"
,
.
class
=
ACPI_BATTERY_CLASS
,
.
ids
=
battery_device_ids
,
.
ops
=
{
.
add
=
acpi_battery_add
,
.
resume
=
acpi_battery_resume
,
.
remove
=
acpi_battery_remove
,
},
};
static
int
__init
acpi_battery_init
(
void
)
static
int
__init
acpi_battery_init
(
void
)
{
{
int
result
;
if
(
acpi_disabled
)
if
(
acpi_disabled
)
return
-
ENODEV
;
return
-
ENODEV
;
#ifdef CONFIG_ACPI_PROCFS
acpi_battery_dir
=
acpi_lock_battery_dir
();
acpi_battery_dir
=
acpi_lock_battery_dir
();
if
(
!
acpi_battery_dir
)
if
(
!
acpi_battery_dir
)
return
-
ENODEV
;
return
-
ENODEV
;
#endif
result
=
acpi_bus_register_driver
(
&
acpi_battery_driver
);
if
(
acpi_bus_register_driver
(
&
acpi_battery_driver
)
<
0
)
{
if
(
result
<
0
)
{
#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_battery_dir
(
acpi_battery_dir
);
acpi_unlock_battery_dir
(
acpi_battery_dir
);
#endif
return
-
ENODEV
;
return
-
ENODEV
;
}
}
return
0
;
return
0
;
}
}
static
void
__exit
acpi_battery_exit
(
void
)
static
void
__exit
acpi_battery_exit
(
void
)
{
{
acpi_bus_unregister_driver
(
&
acpi_battery_driver
);
acpi_bus_unregister_driver
(
&
acpi_battery_driver
);
#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_battery_dir
(
acpi_battery_dir
);
acpi_unlock_battery_dir
(
acpi_battery_dir
);
#endif
return
;
}
}
module_init
(
acpi_battery_init
);
module_init
(
acpi_battery_init
);
...
...
drivers/acpi/bus.c
View file @
e270051d
...
@@ -284,15 +284,11 @@ DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
...
@@ -284,15 +284,11 @@ DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
extern
int
event_is_open
;
extern
int
event_is_open
;
int
acpi_bus_generate_proc_event
(
struct
acpi_device
*
device
,
u8
type
,
int
data
)
int
acpi_bus_generate_proc_event
4
(
const
char
*
device_class
,
const
char
*
bus_id
,
u8
type
,
int
data
)
{
{
struct
acpi_bus_event
*
event
=
NULL
;
struct
acpi_bus_event
*
event
;
unsigned
long
flags
=
0
;
unsigned
long
flags
=
0
;
if
(
!
device
)
return
-
EINVAL
;
/* drop event on the floor if no one's listening */
/* drop event on the floor if no one's listening */
if
(
!
event_is_open
)
if
(
!
event_is_open
)
return
0
;
return
0
;
...
@@ -301,8 +297,8 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
...
@@ -301,8 +297,8 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
if
(
!
event
)
if
(
!
event
)
return
-
ENOMEM
;
return
-
ENOMEM
;
strcpy
(
event
->
device_class
,
device
->
pnp
.
device
_class
);
strcpy
(
event
->
device_class
,
device_class
);
strcpy
(
event
->
bus_id
,
device
->
pnp
.
bus_id
);
strcpy
(
event
->
bus_id
,
bus_id
);
event
->
type
=
type
;
event
->
type
=
type
;
event
->
data
=
data
;
event
->
data
=
data
;
...
@@ -313,6 +309,17 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
...
@@ -313,6 +309,17 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
wake_up_interruptible
(
&
acpi_bus_event_queue
);
wake_up_interruptible
(
&
acpi_bus_event_queue
);
return
0
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
acpi_bus_generate_proc_event4
);
int
acpi_bus_generate_proc_event
(
struct
acpi_device
*
device
,
u8
type
,
int
data
)
{
if
(
!
device
)
return
-
EINVAL
;
return
acpi_bus_generate_proc_event4
(
device
->
pnp
.
device_class
,
device
->
pnp
.
bus_id
,
type
,
data
);
}
}
EXPORT_SYMBOL
(
acpi_bus_generate_proc_event
);
EXPORT_SYMBOL
(
acpi_bus_generate_proc_event
);
...
...
drivers/acpi/ec.c
View file @
e270051d
...
@@ -425,7 +425,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
...
@@ -425,7 +425,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
handler
->
func
=
func
;
handler
->
func
=
func
;
handler
->
data
=
data
;
handler
->
data
=
data
;
mutex_lock
(
&
ec
->
lock
);
mutex_lock
(
&
ec
->
lock
);
list_add
_tail
(
&
handler
->
node
,
&
ec
->
list
);
list_add
(
&
handler
->
node
,
&
ec
->
list
);
mutex_unlock
(
&
ec
->
lock
);
mutex_unlock
(
&
ec
->
lock
);
return
0
;
return
0
;
}
}
...
@@ -440,7 +440,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
...
@@ -440,7 +440,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
if
(
query_bit
==
handler
->
query_bit
)
{
if
(
query_bit
==
handler
->
query_bit
)
{
list_del
(
&
handler
->
node
);
list_del
(
&
handler
->
node
);
kfree
(
handler
);
kfree
(
handler
);
break
;
}
}
}
}
mutex_unlock
(
&
ec
->
lock
);
mutex_unlock
(
&
ec
->
lock
);
...
...
drivers/acpi/sbs.c
View file @
e270051d
/*
/*
*
acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16
$)
*
sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0
$)
*
*
* Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
* Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
* Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
* Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
*
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
@@ -26,15 +28,22 @@
...
@@ -26,15 +28,22 @@
#include <linux/module.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#endif
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/delay.h>
#define ACPI_SBS_COMPONENT 0x00080000
#include <linux/power_supply.h>
#include "sbshc.h"
#define ACPI_SBS_CLASS "sbs"
#define ACPI_SBS_CLASS "sbs"
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_CLASS "battery"
...
@@ -44,836 +53,436 @@
...
@@ -44,836 +53,436 @@
#define ACPI_SBS_FILE_ALARM "alarm"
#define ACPI_SBS_FILE_ALARM "alarm"
#define ACPI_BATTERY_DIR_NAME "BAT%i"
#define ACPI_BATTERY_DIR_NAME "BAT%i"
#define ACPI_AC_DIR_NAME "AC0"
#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
enum
acpi_sbs_device_addr
{
ACPI_SBS_CHARGER
=
0x9
,
ACPI_SBS_MANAGER
=
0xa
,
ACPI_SBS_BATTERY
=
0xb
,
};
ACPI_MODULE_NAME
(
"sbs"
);
#define ACPI_SBS_NOTIFY_STATUS 0x80
#define ACPI_SBS_NOTIFY_INFO 0x81
MODULE_AUTHOR
(
"
Rich Townsend
"
);
MODULE_AUTHOR
(
"
Alexey Starikovskiy <astarikovskiy@suse.de>
"
);
MODULE_DESCRIPTION
(
"Smart Battery System ACPI interface driver"
);
MODULE_DESCRIPTION
(
"Smart Battery System ACPI interface driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
#define xmsleep(t) msleep(t)
static
unsigned
int
cache_time
=
1000
;
module_param
(
cache_time
,
uint
,
0644
);
#define ACPI_EC_SMB_PRTCL 0x00
/* protocol, PEC */
MODULE_PARM_DESC
(
cache_time
,
"cache time in milliseconds"
);
#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_STS_DONE 0x80
#define ACPI_EC_SMB_STS_STATUS 0x1f
#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
#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_ac_dir
(
void
);
extern
struct
proc_dir_entry
*
acpi_lock_battery_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_ac_dir
(
struct
proc_dir_entry
*
acpi_ac_dir
);
extern
void
acpi_unlock_battery_dir
(
struct
proc_dir_entry
*
acpi_battery_dir
);
extern
void
acpi_unlock_battery_dir
(
struct
proc_dir_entry
*
acpi_battery_dir
);
#define
MAX_SBS_BAT 4
#define
MAX_SBS_BAT 4
#define ACPI_SBS_BLOCK_MAX 32
#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
int
acpi_sbs_resume
(
struct
acpi_device
*
device
);
static
const
struct
acpi_device_id
sbs_device_ids
[]
=
{
static
const
struct
acpi_device_id
sbs_device_ids
[]
=
{
{
"ACPI0001"
,
0
},
{
"ACPI0002"
,
0
},
{
"ACPI0005"
,
0
},
{
""
,
0
},
{
""
,
0
},
};
};
MODULE_DEVICE_TABLE
(
acpi
,
sbs_device_ids
);
MODULE_DEVICE_TABLE
(
acpi
,
sbs_device_ids
);
static
struct
acpi_driver
acpi_sbs_driver
=
{
.
name
=
"sbs"
,
.
class
=
ACPI_SBS_CLASS
,
.
ids
=
sbs_device_ids
,
.
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
;
s16
design_capacity
;
s16
design_voltage
;
int
vscale
;
int
ipscale
;
s16
serial_number
;
char
manufacturer_name
[
ACPI_SBS_BLOCK_MAX
+
3
];
char
device_name
[
ACPI_SBS_BLOCK_MAX
+
3
];
char
device_chemistry
[
ACPI_SBS_BLOCK_MAX
+
3
];
};
struct
acpi_battery_state
{
s16
voltage
;
s16
amperage
;
s16
remaining_capacity
;
s16
battery_state
;
};
struct
acpi_battery_alarm
{
s16
remaining_capacity
;
};
struct
acpi_battery
{
struct
acpi_battery
{
int
alive
;
struct
power_supply
bat
;
int
id
;
int
init_state
;
int
battery_present
;
struct
acpi_sbs
*
sbs
;
struct
acpi_sbs
*
sbs
;
struct
acpi_battery_info
info
;
#ifdef CONFIG_ACPI_PROCFS
struct
acpi_battery_state
state
;
struct
proc_dir_entry
*
proc_entry
;
struct
acpi_battery_alarm
alarm
;
#endif
struct
proc_dir_entry
*
battery_entry
;
unsigned
long
update_time
;
char
name
[
8
];
char
manufacturer_name
[
ACPI_SBS_BLOCK_MAX
];
char
device_name
[
ACPI_SBS_BLOCK_MAX
];
char
device_chemistry
[
ACPI_SBS_BLOCK_MAX
];
u16
alarm_capacity
;
u16
full_charge_capacity
;
u16
design_capacity
;
u16
design_voltage
;
u16
serial_number
;
u16
cycle_count
;
u16
temp_now
;
u16
voltage_now
;
s16
current_now
;
s16
current_avg
;
u16
capacity_now
;
u16
state_of_charge
;
u16
state
;
u16
mode
;
u16
spec
;
u8
id
;
u8
present
:
1
;
};
};
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
struct
acpi_sbs
{
struct
acpi_sbs
{
int
base
;
struct
power_supply
charger
;
struct
acpi_device
*
device
;
struct
acpi_device
*
device
;
struct
mutex
mutex
;
struct
acpi_smb_hc
*
hc
;
int
sbsm_present
;
struct
mutex
lock
;
int
sbsm_batteries_supported
;
#ifdef CONFIG_ACPI_PROCFS
struct
proc_dir_entry
*
ac
_entry
;
struct
proc_dir_entry
*
charger
_entry
;
struct
acpi_ac
ac
;
#endif
struct
acpi_battery
battery
[
MAX_SBS_BAT
];
struct
acpi_battery
battery
[
MAX_SBS_BAT
];
int
zombie
;
u8
batteries_supported
:
4
;
struct
timer_list
update_timer
;
u8
manager_present
:
1
;
int
run_cnt
;
u8
charger_present
:
1
;
int
update_proc_flg
;
};
};
static
int
acpi_sbs_update_run
(
struct
acpi_sbs
*
sbs
,
int
id
,
int
data_type
);
#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
static
void
acpi_sbs_update_time
(
void
*
data
);
union
sbs_rw_data
{
static
inline
int
battery_scale
(
int
log
)
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
int
acpi_ec_sbs_read
(
struct
acpi_sbs
*
sbs
,
u8
address
,
u8
*
data
)
{
u8
val
;
int
err
;
err
=
ec_read
(
sbs
->
base
+
address
,
&
val
);
if
(
!
err
)
{
*
data
=
val
;
}
xmsleep
(
ACPI_EC_SMB_TRANSACTION_SLEEP
);
return
(
err
);
}
static
int
acpi_ec_sbs_write
(
struct
acpi_sbs
*
sbs
,
u8
address
,
u8
data
)
{
{
int
err
;
int
scale
=
1
;
while
(
log
--
)
err
=
ec_write
(
sbs
->
base
+
address
,
data
);
scale
*=
10
;
return
(
err
);
return
scale
;
}
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
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
;
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
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:
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"unsupported transaction %d"
,
size
));
return
(
-
1
);
}
return
(
0
);
}
}
static
int
static
inline
int
acpi_battery_vscale
(
struct
acpi_battery
*
battery
)
acpi_sbs_read_word
(
struct
acpi_sbs
*
sbs
,
int
addr
,
int
func
,
u16
*
word
)
{
{
union
sbs_rw_data
data
;
return
battery_scale
((
battery
->
spec
&
0x0f00
)
>>
8
);
int
result
=
0
;
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
static
inline
int
acpi_battery_ipscale
(
struct
acpi_battery
*
battery
)
acpi_sbs_read_str
(
struct
acpi_sbs
*
sbs
,
int
addr
,
int
func
,
char
*
str
)
{
{
union
sbs_rw_data
data
;
return
battery_scale
((
battery
->
spec
&
0xf000
)
>>
12
);
int
result
=
0
;
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
static
inline
int
acpi_battery_mode
(
struct
acpi_battery
*
battery
)
acpi_sbs_write_word
(
struct
acpi_sbs
*
sbs
,
int
addr
,
int
func
,
int
word
)
{
{
union
sbs_rw_data
data
;
return
(
battery
->
mode
&
0x8000
);
int
result
=
0
;
data
.
word
=
word
;
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
in
t
sbs_zombie
(
struct
acpi_sbs
*
sbs
)
static
in
line
int
acpi_battery_scale
(
struct
acpi_battery
*
battery
)
{
{
return
(
sbs
->
zombie
);
return
(
acpi_battery_mode
(
battery
)
?
10
:
1
)
*
acpi_battery_ipscale
(
battery
);
}
}
static
int
sbs_mutex_lock
(
struct
acpi_sbs
*
sbs
)
static
int
sbs_get_ac_property
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
{
if
(
sbs_zombie
(
sbs
))
{
struct
acpi_sbs
*
sbs
=
to_acpi_sbs
(
psy
);
return
-
ENODEV
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_ONLINE
:
val
->
intval
=
sbs
->
charger_present
;
break
;
default:
return
-
EINVAL
;
}
}
mutex_lock
(
&
sbs
->
mutex
);
return
0
;
return
0
;
}
}
static
void
sbs_mutex_unlock
(
struct
acpi_sbs
*
sbs
)
static
int
acpi_battery_technology
(
struct
acpi_battery
*
battery
)
{
{
mutex_unlock
(
&
sbs
->
mutex
);
if
(
!
strcasecmp
(
"NiCd"
,
battery
->
device_chemistry
))
return
POWER_SUPPLY_TECHNOLOGY_NiCd
;
if
(
!
strcasecmp
(
"NiMH"
,
battery
->
device_chemistry
))
return
POWER_SUPPLY_TECHNOLOGY_NiMH
;
if
(
!
strcasecmp
(
"LION"
,
battery
->
device_chemistry
))
return
POWER_SUPPLY_TECHNOLOGY_LION
;
if
(
!
strcasecmp
(
"LiP"
,
battery
->
device_chemistry
))
return
POWER_SUPPLY_TECHNOLOGY_LIPO
;
return
POWER_SUPPLY_TECHNOLOGY_UNKNOWN
;
}
}
/* --------------------------------------------------------------------------
static
int
acpi_sbs_battery_get_property
(
struct
power_supply
*
psy
,
Smart Battery System Management
enum
power_supply_property
psp
,
-------------------------------------------------------------------------- */
union
power_supply_propval
*
val
)
static
int
acpi_check_update_proc
(
struct
acpi_sbs
*
sbs
)
{
{
acpi_status
status
=
AE_OK
;
struct
acpi_battery
*
battery
=
to_acpi_battery
(
psy
)
;
if
(
update_time
==
0
)
{
if
((
!
battery
->
present
)
&&
psp
!=
POWER_SUPPLY_PROP_PRESENT
)
sbs
->
update_proc_flg
=
0
;
return
-
ENODEV
;
return
0
;
switch
(
psp
)
{
}
case
POWER_SUPPLY_PROP_STATUS
:
if
(
sbs
->
update_proc_flg
==
0
)
{
if
(
battery
->
current_now
<
0
)
status
=
acpi_os_execute
(
OSL_GPE_HANDLER
,
val
->
intval
=
POWER_SUPPLY_STATUS_DISCHARGING
;
acpi_sbs_update_time
,
sbs
);
else
if
(
battery
->
current_now
>
0
)
if
(
status
!=
AE_OK
)
{
val
->
intval
=
POWER_SUPPLY_STATUS_CHARGING
;
ACPI_EXCEPTION
((
AE_INFO
,
status
,
else
"acpi_os_execute() failed"
));
val
->
intval
=
POWER_SUPPLY_STATUS_FULL
;
return
1
;
break
;
}
case
POWER_SUPPLY_PROP_PRESENT
:
sbs
->
update_proc_flg
=
1
;
val
->
intval
=
battery
->
present
;
break
;
case
POWER_SUPPLY_PROP_TECHNOLOGY
:
val
->
intval
=
acpi_battery_technology
(
battery
);
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
val
->
intval
=
battery
->
design_voltage
*
acpi_battery_vscale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_NOW
:
val
->
intval
=
battery
->
voltage_now
*
acpi_battery_vscale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CURRENT_NOW
:
val
->
intval
=
abs
(
battery
->
current_now
)
*
acpi_battery_ipscale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CURRENT_AVG
:
val
->
intval
=
abs
(
battery
->
current_avg
)
*
acpi_battery_ipscale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CAPACITY
:
val
->
intval
=
battery
->
state_of_charge
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
:
case
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN
:
val
->
intval
=
battery
->
design_capacity
*
acpi_battery_scale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_FULL
:
case
POWER_SUPPLY_PROP_ENERGY_FULL
:
val
->
intval
=
battery
->
full_charge_capacity
*
acpi_battery_scale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_NOW
:
case
POWER_SUPPLY_PROP_ENERGY_NOW
:
val
->
intval
=
battery
->
capacity_now
*
acpi_battery_scale
(
battery
)
*
1000
;
break
;
case
POWER_SUPPLY_PROP_TEMP
:
val
->
intval
=
battery
->
temp_now
-
2730
;
// dK -> dC
break
;
case
POWER_SUPPLY_PROP_MODEL_NAME
:
val
->
strval
=
battery
->
device_name
;
break
;
case
POWER_SUPPLY_PROP_MANUFACTURER
:
val
->
strval
=
battery
->
manufacturer_name
;
break
;
default:
return
-
EINVAL
;
}
}
return
0
;
return
0
;
}
}
static
int
acpi_sbs_generate_event
(
struct
acpi_device
*
device
,
static
enum
power_supply_property
sbs_ac_props
[]
=
{
int
event
,
int
state
,
char
*
bid
,
char
*
class
)
POWER_SUPPLY_PROP_ONLINE
,
{
};
char
bid_saved
[
5
];
char
class_saved
[
20
];
int
result
=
0
;
strcpy
(
bid_saved
,
acpi_device_bid
(
device
));
strcpy
(
class_saved
,
acpi_device_class
(
device
));
strcpy
(
acpi_device_bid
(
device
),
bid
);
strcpy
(
acpi_device_class
(
device
),
class
);
result
=
acpi_bus_generate_proc_event
(
device
,
event
,
state
);
strcpy
(
acpi_device_bid
(
device
),
bid_saved
);
strcpy
(
acpi_device_class
(
device
),
class_saved
);
acpi_bus_generate_netlink_event
(
class
,
bid
,
event
,
state
);
return
result
;
}
static
int
acpi_battery_get_present
(
struct
acpi_battery
*
battery
)
{
s16
state
;
int
result
=
0
;
int
is_present
=
0
;
result
=
acpi_sbs_read_word
(
battery
->
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
&
state
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
}
if
(
!
result
)
{
is_present
=
(
state
&
0x000f
)
&
(
1
<<
battery
->
id
);
}
battery
->
battery_present
=
is_present
;
return
result
;
}
static
int
acpi_battery_select
(
struct
acpi_battery
*
battery
)
static
enum
power_supply_property
sbs_charge_battery_props
[]
=
{
{
POWER_SUPPLY_PROP_STATUS
,
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
POWER_SUPPLY_PROP_PRESENT
,
int
result
=
0
;
POWER_SUPPLY_PROP_TECHNOLOGY
,
s16
state
;
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
int
foo
;
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_CURRENT_NOW
,
POWER_SUPPLY_PROP_CURRENT_AVG
,
POWER_SUPPLY_PROP_CAPACITY
,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
,
POWER_SUPPLY_PROP_CHARGE_FULL
,
POWER_SUPPLY_PROP_CHARGE_NOW
,
POWER_SUPPLY_PROP_TEMP
,
POWER_SUPPLY_PROP_MODEL_NAME
,
POWER_SUPPLY_PROP_MANUFACTURER
,
};
if
(
sbs
->
sbsm_present
)
{
static
enum
power_supply_property
sbs_energy_battery_props
[]
=
{
POWER_SUPPLY_PROP_STATUS
,
POWER_SUPPLY_PROP_PRESENT
,
POWER_SUPPLY_PROP_TECHNOLOGY
,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_CURRENT_NOW
,
POWER_SUPPLY_PROP_CURRENT_AVG
,
POWER_SUPPLY_PROP_CAPACITY
,
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN
,
POWER_SUPPLY_PROP_ENERGY_FULL
,
POWER_SUPPLY_PROP_ENERGY_NOW
,
POWER_SUPPLY_PROP_TEMP
,
POWER_SUPPLY_PROP_MODEL_NAME
,
POWER_SUPPLY_PROP_MANUFACTURER
,
};
/* Take special care not to knobble other nibbles of
/* --------------------------------------------------------------------------
* state (aka selector_state), since
Smart Battery System Management
* it causes charging to halt on SBSELs
*/
--------------------------------------------------------------------------
*/
result
=
struct
acpi_battery_reader
{
acpi_sbs_read_word
(
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
&
state
);
u8
command
;
/* command for battery */
if
(
result
)
{
u8
mode
;
/* word or block? */
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
size_t
offset
;
/* offset inside struct acpi_sbs_battery */
"acpi_sbs_read_word() failed"
));
};
goto
end
;
}
foo
=
(
state
&
0x0fff
)
|
(
1
<<
(
battery
->
id
+
12
));
static
struct
acpi_battery_reader
info_readers
[]
=
{
result
=
{
0x01
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
alarm_capacity
)},
acpi_sbs_write_word
(
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x01
,
foo
);
{
0x03
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
mode
)},
if
(
result
)
{
{
0x10
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
full_charge_capacity
)},
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
{
0x17
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
cycle_count
)},
"acpi_sbs_write_word() failed"
));
{
0x18
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
design_capacity
)},
goto
end
;
{
0x19
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
design_voltage
)},
}
{
0x1a
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
spec
)},
}
{
0x1c
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
serial_number
)},
{
0x20
,
SMBUS_READ_BLOCK
,
offsetof
(
struct
acpi_battery
,
manufacturer_name
)},
{
0x21
,
SMBUS_READ_BLOCK
,
offsetof
(
struct
acpi_battery
,
device_name
)},
{
0x22
,
SMBUS_READ_BLOCK
,
offsetof
(
struct
acpi_battery
,
device_chemistry
)},
};
end:
static
struct
acpi_battery_reader
state_readers
[]
=
{
return
result
;
{
0x08
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
temp_now
)},
}
{
0x09
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
voltage_now
)},
{
0x0a
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
current_now
)},
{
0x0b
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
current_avg
)},
{
0x0f
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
capacity_now
)},
{
0x0e
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
state_of_charge
)},
{
0x16
,
SMBUS_READ_WORD
,
offsetof
(
struct
acpi_battery
,
state
)},
};
static
int
acpi_
sbsm
_get_info
(
struct
acpi_sbs
*
sbs
)
static
int
acpi_
manager
_get_info
(
struct
acpi_sbs
*
sbs
)
{
{
int
result
=
0
;
int
result
=
0
;
s16
battery_system_info
;
u16
battery_system_info
;
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SBSM_SMBUS_ADDR
,
0x04
,
&
battery_system_info
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
sbs
->
sbsm_present
=
1
;
sbs
->
sbsm_batteries_supported
=
battery_system_info
&
0x000f
;
end:
result
=
acpi_smbus_read
(
sbs
->
hc
,
SMBUS_READ_WORD
,
ACPI_SBS_MANAGER
,
0x04
,
(
u8
*
)
&
battery_system_info
);
if
(
!
result
)
sbs
->
batteries_supported
=
battery_system_info
&
0x000f
;
return
result
;
return
result
;
}
}
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_get_info
(
struct
acpi_battery
*
battery
)
{
{
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
i
,
result
=
0
;
int
result
=
0
;
s16
battery_mode
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
info_readers
);
++
i
)
{
s16
specification_info
;
result
=
acpi_smbus_read
(
battery
->
sbs
->
hc
,
info_readers
[
i
].
mode
,
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
ACPI_SBS_BATTERY
,
&
battery_mode
);
info_readers
[
i
].
command
,
if
(
result
)
{
(
u8
*
)
battery
+
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
info_readers
[
i
].
offset
);
"acpi_sbs_read_word() failed"
));
if
(
result
)
goto
end
;
break
;
}
battery
->
info
.
capacity_mode
=
(
battery_mode
&
0x8000
)
>>
15
;
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x10
,
&
battery
->
info
.
full_charge_capacity
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
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_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x19
,
&
battery
->
info
.
design_voltage
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x1a
,
&
specification_info
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
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
;
}
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_read_str
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x20
,
battery
->
info
.
manufacturer_name
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_str() failed"
));
goto
end
;
}
result
=
acpi_sbs_read_str
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x21
,
battery
->
info
.
device_name
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_str() failed"
));
goto
end
;
}
}
result
=
acpi_sbs_read_str
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x22
,
battery
->
info
.
device_chemistry
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_str() failed"
));
goto
end
;
}
end:
return
result
;
return
result
;
}
}
static
int
acpi_battery_get_state
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_get_state
(
struct
acpi_battery
*
battery
)
{
{
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
i
,
result
=
0
;
int
result
=
0
;
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x09
,
&
battery
->
state
.
voltage
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x0a
,
&
battery
->
state
.
amperage
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x0f
,
&
battery
->
state
.
remaining_capacity
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x16
,
if
(
battery
->
update_time
&&
&
battery
->
state
.
battery_state
);
time_before
(
jiffies
,
battery
->
update_time
+
if
(
result
)
{
msecs_to_jiffies
(
cache_time
)))
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
return
0
;
"acpi_sbs_read_word() failed"
));
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
state_readers
);
++
i
)
{
goto
end
;
result
=
acpi_smbus_read
(
battery
->
sbs
->
hc
,
state_readers
[
i
].
mode
,
ACPI_SBS_BATTERY
,
state_readers
[
i
].
command
,
(
u8
*
)
battery
+
state_readers
[
i
].
offset
);
if
(
result
)
goto
end
;
}
}
end:
end:
battery
->
update_time
=
jiffies
;
return
result
;
return
result
;
}
}
static
int
acpi_battery_get_alarm
(
struct
acpi_battery
*
battery
)
static
int
acpi_battery_get_alarm
(
struct
acpi_battery
*
battery
)
{
{
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
return
acpi_smbus_read
(
battery
->
sbs
->
hc
,
SMBUS_READ_WORD
,
int
result
=
0
;
ACPI_SBS_BATTERY
,
0x01
,
(
u8
*
)
&
battery
->
alarm_capacity
);
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
&
battery
->
alarm
.
remaining_capacity
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
end:
return
result
;
}
}
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
,
static
int
acpi_battery_set_alarm
(
struct
acpi_battery
*
battery
)
unsigned
long
alarm
)
{
{
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
=
0
;
u16
value
,
sel
=
1
<<
(
battery
->
id
+
12
);
s16
battery_mode
;
int
foo
;
result
=
acpi_battery_select
(
battery
);
int
ret
;
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_select() failed"
));
goto
end
;
}
/* If necessary, enable the alarm */
if
(
alarm
>
0
)
{
if
(
sbs
->
manager_present
)
{
result
=
ret
=
acpi_smbus_read
(
sbs
->
hc
,
SMBUS_READ_WORD
,
ACPI_SBS_MANAGER
,
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
0x01
,
(
u8
*
)
&
value
);
&
battery_mode
);
if
(
ret
)
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
goto
end
;
}
if
((
value
&
0xf000
)
!=
sel
)
{
value
&=
0x0fff
;
result
=
value
|=
sel
;
acpi_sbs_write_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
ret
=
acpi_smbus_write
(
sbs
->
hc
,
SMBUS_WRITE_WORD
,
battery_mode
&
0xbfff
);
ACPI_SBS_MANAGER
,
if
(
result
)
{
0x01
,
(
u8
*
)
&
value
,
2
);
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
if
(
ret
)
"acpi_sbs_write_word() failed"
));
goto
end
;
goto
end
;
}
}
}
}
ret
=
acpi_smbus_write
(
sbs
->
hc
,
SMBUS_WRITE_WORD
,
ACPI_SBS_BATTERY
,
foo
=
alarm
/
(
battery
->
info
.
capacity_mode
?
10
:
1
);
0x01
,
(
u8
*
)
&
battery
->
alarm_capacity
,
2
);
result
=
acpi_sbs_write_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x01
,
foo
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_write_word() failed"
));
goto
end
;
}
end:
end:
return
ret
;
return
result
;
}
}
static
int
acpi_
battery_set_mode
(
struct
acpi_battery
*
battery
)
static
int
acpi_
ac_get_present
(
struct
acpi_sbs
*
sbs
)
{
{
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
;
int
result
=
0
;
u16
status
;
s16
battery_mode
;
if
(
capacity_mode
==
DEF_CAPACITY_UNIT
)
{
goto
end
;
}
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
if
(
capacity_mode
==
MAH_CAPACITY_UNIT
)
{
battery_mode
&=
0x7fff
;
}
else
{
battery_mode
|=
0x8000
;
}
result
=
acpi_sbs_write_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
battery_mode
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_write_word() failed"
));
goto
end
;
}
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SB_SMBUS_ADDR
,
0x03
,
&
battery_mode
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_read_word() failed"
));
goto
end
;
}
end:
result
=
acpi_smbus_read
(
sbs
->
hc
,
SMBUS_READ_WORD
,
ACPI_SBS_CHARGER
,
0x13
,
(
u8
*
)
&
status
);
if
(
!
result
)
sbs
->
charger_present
=
(
status
>>
15
)
&
0x1
;
return
result
;
return
result
;
}
}
static
int
acpi_battery_init
(
struct
acpi_battery
*
battery
)
static
ssize_t
acpi_battery_alarm_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
{
int
result
=
0
;
struct
acpi_battery
*
battery
=
to_acpi_battery
(
dev_get_drvdata
(
dev
));
acpi_battery_get_alarm
(
battery
);
result
=
acpi_battery_select
(
battery
);
return
sprintf
(
buf
,
"%d
\n
"
,
battery
->
alarm_capacity
*
if
(
result
)
{
acpi_battery_scale
(
battery
)
*
1000
);
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_select() failed"
));
goto
end
;
}
result
=
acpi_battery_set_mode
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_set_mode() failed"
));
goto
end
;
}
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_info() failed"
));
goto
end
;
}
result
=
acpi_battery_get_state
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_state() failed"
));
goto
end
;
}
result
=
acpi_battery_get_alarm
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_alarm() failed"
));
goto
end
;
}
end:
return
result
;
}
}
static
int
acpi_ac_get_present
(
struct
acpi_sbs
*
sbs
)
static
ssize_t
acpi_battery_alarm_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
{
int
result
=
0
;
unsigned
long
x
;
s16
charger_status
;
struct
acpi_battery
*
battery
=
to_acpi_battery
(
dev_get_drvdata
(
dev
));
if
(
sscanf
(
buf
,
"%ld
\n
"
,
&
x
)
==
1
)
result
=
acpi_sbs_read_word
(
sbs
,
ACPI_SBC_SMBUS_ADDR
,
0x13
,
battery
->
alarm_capacity
=
x
/
&
charger_status
);
(
1000
*
acpi_battery_scale
(
battery
));
if
(
battery
->
present
)
if
(
result
)
{
acpi_battery_set_alarm
(
battery
);
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
return
count
;
"acpi_sbs_read_word() failed"
));
goto
end
;
}
sbs
->
ac
.
ac_present
=
(
charger_status
&
0x8000
)
>>
15
;
end:
return
result
;
}
}
static
struct
device_attribute
alarm_attr
=
{
.
attr
=
{.
name
=
"alarm"
,
.
mode
=
0644
,
.
owner
=
THIS_MODULE
},
.
show
=
acpi_battery_alarm_show
,
.
store
=
acpi_battery_alarm_store
,
};
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
FS Interface (/proc/acpi)
FS Interface (/proc/acpi)
-------------------------------------------------------------------------- */
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS
/* Generic Routines */
/* Generic Routines */
static
int
static
int
acpi_sbs_
generic_
add_fs
(
struct
proc_dir_entry
**
dir
,
acpi_sbs_add_fs
(
struct
proc_dir_entry
**
dir
,
struct
proc_dir_entry
*
parent_dir
,
struct
proc_dir_entry
*
parent_dir
,
char
*
dir_name
,
char
*
dir_name
,
struct
file_operations
*
info_fops
,
struct
file_operations
*
info_fops
,
struct
file_operations
*
state_fops
,
struct
file_operations
*
state_fops
,
struct
file_operations
*
alarm_fops
,
void
*
data
)
struct
file_operations
*
alarm_fops
,
void
*
data
)
{
{
struct
proc_dir_entry
*
entry
=
NULL
;
struct
proc_dir_entry
*
entry
=
NULL
;
if
(
!*
dir
)
{
if
(
!*
dir
)
{
*
dir
=
proc_mkdir
(
dir_name
,
parent_dir
);
*
dir
=
proc_mkdir
(
dir_name
,
parent_dir
);
if
(
!*
dir
)
{
if
(
!*
dir
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"proc_mkdir() failed"
));
return
-
ENODEV
;
return
-
ENODEV
;
}
}
(
*
dir
)
->
owner
=
THIS_MODULE
;
(
*
dir
)
->
owner
=
THIS_MODULE
;
...
@@ -882,10 +491,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
...
@@ -882,10 +491,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
/* 'info' [R] */
/* 'info' [R] */
if
(
info_fops
)
{
if
(
info_fops
)
{
entry
=
create_proc_entry
(
ACPI_SBS_FILE_INFO
,
S_IRUGO
,
*
dir
);
entry
=
create_proc_entry
(
ACPI_SBS_FILE_INFO
,
S_IRUGO
,
*
dir
);
if
(
!
entry
)
{
if
(
entry
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"create_proc_entry() failed"
));
}
else
{
entry
->
proc_fops
=
info_fops
;
entry
->
proc_fops
=
info_fops
;
entry
->
data
=
data
;
entry
->
data
=
data
;
entry
->
owner
=
THIS_MODULE
;
entry
->
owner
=
THIS_MODULE
;
...
@@ -895,10 +501,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
...
@@ -895,10 +501,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
/* 'state' [R] */
/* 'state' [R] */
if
(
state_fops
)
{
if
(
state_fops
)
{
entry
=
create_proc_entry
(
ACPI_SBS_FILE_STATE
,
S_IRUGO
,
*
dir
);
entry
=
create_proc_entry
(
ACPI_SBS_FILE_STATE
,
S_IRUGO
,
*
dir
);
if
(
!
entry
)
{
if
(
entry
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"create_proc_entry() failed"
));
}
else
{
entry
->
proc_fops
=
state_fops
;
entry
->
proc_fops
=
state_fops
;
entry
->
data
=
data
;
entry
->
data
=
data
;
entry
->
owner
=
THIS_MODULE
;
entry
->
owner
=
THIS_MODULE
;
...
@@ -908,24 +511,19 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
...
@@ -908,24 +511,19 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
/* 'alarm' [R/W] */
/* 'alarm' [R/W] */
if
(
alarm_fops
)
{
if
(
alarm_fops
)
{
entry
=
create_proc_entry
(
ACPI_SBS_FILE_ALARM
,
S_IRUGO
,
*
dir
);
entry
=
create_proc_entry
(
ACPI_SBS_FILE_ALARM
,
S_IRUGO
,
*
dir
);
if
(
!
entry
)
{
if
(
entry
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"create_proc_entry() failed"
));
}
else
{
entry
->
proc_fops
=
alarm_fops
;
entry
->
proc_fops
=
alarm_fops
;
entry
->
data
=
data
;
entry
->
data
=
data
;
entry
->
owner
=
THIS_MODULE
;
entry
->
owner
=
THIS_MODULE
;
}
}
}
}
return
0
;
return
0
;
}
}
static
void
static
void
acpi_sbs_
generic_
remove_fs
(
struct
proc_dir_entry
**
dir
,
acpi_sbs_remove_fs
(
struct
proc_dir_entry
**
dir
,
struct
proc_dir_entry
*
parent_dir
)
struct
proc_dir_entry
*
parent_dir
)
{
{
if
(
*
dir
)
{
if
(
*
dir
)
{
remove_proc_entry
(
ACPI_SBS_FILE_INFO
,
*
dir
);
remove_proc_entry
(
ACPI_SBS_FILE_INFO
,
*
dir
);
remove_proc_entry
(
ACPI_SBS_FILE_STATE
,
*
dir
);
remove_proc_entry
(
ACPI_SBS_FILE_STATE
,
*
dir
);
...
@@ -933,82 +531,52 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
...
@@ -933,82 +531,52 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
remove_proc_entry
((
*
dir
)
->
name
,
parent_dir
);
remove_proc_entry
((
*
dir
)
->
name
,
parent_dir
);
*
dir
=
NULL
;
*
dir
=
NULL
;
}
}
}
}
/* Smart Battery Interface */
/* Smart Battery Interface */
static
struct
proc_dir_entry
*
acpi_battery_dir
=
NULL
;
static
struct
proc_dir_entry
*
acpi_battery_dir
=
NULL
;
static
inline
char
*
acpi_battery_units
(
struct
acpi_battery
*
battery
)
{
return
acpi_battery_mode
(
battery
)
?
" mWh"
:
" mAh"
;
}
static
int
acpi_battery_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
static
int
acpi_battery_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
{
{
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
cscale
;
int
result
=
0
;
int
result
=
0
;
if
(
sbs_mutex_lock
(
sbs
))
{
mutex_lock
(
&
sbs
->
lock
);
return
-
ENODEV
;
}
result
=
acpi_check_update_proc
(
sbs
);
seq_printf
(
seq
,
"present: %s
\n
"
,
if
(
result
)
(
battery
->
present
)
?
"yes"
:
"no"
);
if
(
!
battery
->
present
)
goto
end
;
goto
end
;
if
(
update_time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
battery
->
id
,
DATA_TYPE_INFO
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_update_run() failed"
));
}
}
if
(
battery
->
battery_present
)
{
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
;
}
seq_printf
(
seq
,
"design capacity: %i%s
\n
"
,
seq_printf
(
seq
,
"design capacity: %i%s
\n
"
,
battery
->
info
.
design_capacity
*
cscale
,
battery
->
design_capacity
*
acpi_battery_scale
(
battery
),
battery
->
info
.
capacity_mode
?
"0 mWh"
:
" mAh"
);
acpi_battery_units
(
battery
));
seq_printf
(
seq
,
"last full capacity: %i%s
\n
"
,
seq_printf
(
seq
,
"last full capacity: %i%s
\n
"
,
battery
->
info
.
full_charge_capacity
*
cscale
,
battery
->
full_charge_capacity
*
acpi_battery_scale
(
battery
),
battery
->
info
.
capacity_mode
?
"0 mWh"
:
" mAh"
);
acpi_battery_units
(
battery
));
seq_printf
(
seq
,
"battery technology: rechargeable
\n
"
);
seq_printf
(
seq
,
"battery technology: rechargeable
\n
"
);
seq_printf
(
seq
,
"design voltage: %i mV
\n
"
,
seq_printf
(
seq
,
"design voltage: %i mV
\n
"
,
battery
->
info
.
design_voltage
*
battery
->
info
.
vscale
);
battery
->
design_voltage
*
acpi_battery_vscale
(
battery
));
seq_printf
(
seq
,
"design capacity warning: unknown
\n
"
);
seq_printf
(
seq
,
"design capacity warning: unknown
\n
"
);
seq_printf
(
seq
,
"design capacity low: unknown
\n
"
);
seq_printf
(
seq
,
"design capacity low: unknown
\n
"
);
seq_printf
(
seq
,
"capacity granularity 1: unknown
\n
"
);
seq_printf
(
seq
,
"capacity granularity 1: unknown
\n
"
);
seq_printf
(
seq
,
"capacity granularity 2: unknown
\n
"
);
seq_printf
(
seq
,
"capacity granularity 2: unknown
\n
"
);
seq_printf
(
seq
,
"model number: %s
\n
"
,
battery
->
device_name
);
seq_printf
(
seq
,
"model number: %s
\n
"
,
battery
->
info
.
device_name
);
seq_printf
(
seq
,
"serial number: %i
\n
"
,
seq_printf
(
seq
,
"serial number: %i
\n
"
,
battery
->
info
.
serial_number
);
battery
->
serial_number
);
seq_printf
(
seq
,
"battery type: %s
\n
"
,
seq_printf
(
seq
,
"battery type: %s
\n
"
,
battery
->
info
.
device_chemistry
);
battery
->
device_chemistry
);
seq_printf
(
seq
,
"OEM info: %s
\n
"
,
seq_printf
(
seq
,
"OEM info: %s
\n
"
,
battery
->
info
.
manufacturer_name
);
battery
->
manufacturer_name
);
end:
end:
mutex_unlock
(
&
sbs
->
lock
);
sbs_mutex_unlock
(
sbs
);
return
result
;
return
result
;
}
}
...
@@ -1022,73 +590,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
...
@@ -1022,73 +590,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
=
0
;
int
result
=
0
;
int
cscale
;
int
foo
;
if
(
sbs_mutex_lock
(
sbs
))
{
return
-
ENODEV
;
}
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
if
(
update_time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
battery
->
id
,
DATA_TYPE_STATE
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_update_run() failed"
));
}
}
if
(
battery
->
battery_present
)
{
mutex_lock
(
&
sbs
->
lock
);
seq_printf
(
seq
,
"present: yes
\n
"
);
seq_printf
(
seq
,
"present: %s
\n
"
,
}
else
{
(
battery
->
present
)
?
"yes"
:
"no"
);
seq_printf
(
seq
,
"present: no
\n
"
);
if
(
!
battery
->
present
)
goto
end
;
goto
end
;
}
if
(
battery
->
info
.
capacity_mode
)
{
cscale
=
battery
->
info
.
vscale
*
battery
->
info
.
ipscale
;
}
else
{
cscale
=
battery
->
info
.
ipscale
;
}
if
(
battery
->
state
.
battery_state
&
0x0010
)
{
seq_printf
(
seq
,
"capacity state: critical
\n
"
);
}
else
{
seq_printf
(
seq
,
"capacity state: ok
\n
"
);
}
foo
=
(
s16
)
battery
->
state
.
amperage
*
battery
->
info
.
ipscale
;
if
(
battery
->
info
.
capacity_mode
)
{
foo
=
foo
*
battery
->
info
.
design_voltage
/
1000
;
}
if
(
battery
->
state
.
amperage
<
0
)
{
seq_printf
(
seq
,
"charging state: discharging
\n
"
);
seq_printf
(
seq
,
"present rate: %d %s
\n
"
,
-
foo
,
battery
->
info
.
capacity_mode
?
"mW"
:
"mA"
);
}
else
if
(
battery
->
state
.
amperage
>
0
)
{
seq_printf
(
seq
,
"charging state: charging
\n
"
);
seq_printf
(
seq
,
"present rate: %d %s
\n
"
,
foo
,
battery
->
info
.
capacity_mode
?
"mW"
:
"mA"
);
}
else
{
seq_printf
(
seq
,
"charging state: charged
\n
"
);
seq_printf
(
seq
,
"present rate: 0 %s
\n
"
,
battery
->
info
.
capacity_mode
?
"mW"
:
"mA"
);
}
acpi_battery_get_state
(
battery
);
seq_printf
(
seq
,
"capacity state: %s
\n
"
,
(
battery
->
state
&
0x0010
)
?
"critical"
:
"ok"
);
seq_printf
(
seq
,
"charging state: %s
\n
"
,
(
battery
->
current_now
<
0
)
?
"discharging"
:
((
battery
->
current_now
>
0
)
?
"charging"
:
"charged"
));
seq_printf
(
seq
,
"present rate: %d mA
\n
"
,
abs
(
battery
->
current_now
)
*
acpi_battery_ipscale
(
battery
));
seq_printf
(
seq
,
"remaining capacity: %i%s
\n
"
,
seq_printf
(
seq
,
"remaining capacity: %i%s
\n
"
,
battery
->
state
.
remaining_capacity
*
cscale
,
battery
->
capacity_now
*
acpi_battery_scale
(
battery
),
battery
->
info
.
capacity_mode
?
"0 mWh"
:
" mAh"
);
acpi_battery_units
(
battery
));
seq_printf
(
seq
,
"present voltage: %i mV
\n
"
,
seq_printf
(
seq
,
"present voltage: %i mV
\n
"
,
battery
->
state
.
voltage
*
battery
->
info
.
vscale
);
battery
->
voltage_now
*
acpi_battery_vscale
(
battery
)
);
end:
end:
mutex_unlock
(
&
sbs
->
lock
);
sbs_mutex_unlock
(
sbs
);
return
result
;
return
result
;
}
}
...
@@ -1102,48 +626,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
...
@@ -1102,48 +626,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
int
result
=
0
;
int
result
=
0
;
int
cscale
;
if
(
sbs_mutex_lock
(
sbs
))
{
return
-
ENODEV
;
}
result
=
acpi_check_update_proc
(
sbs
);
mutex_lock
(
&
sbs
->
lock
);
if
(
result
)
goto
end
;
if
(
update_time
==
0
)
{
result
=
acpi_sbs_update_run
(
sbs
,
battery
->
id
,
DATA_TYPE_ALARM
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_update_run() failed"
));
}
}
if
(
!
battery
->
battery_
present
)
{
if
(
!
battery
->
present
)
{
seq_printf
(
seq
,
"present: no
\n
"
);
seq_printf
(
seq
,
"present: no
\n
"
);
goto
end
;
goto
end
;
}
}
if
(
battery
->
info
.
capacity_mode
)
{
acpi_battery_get_alarm
(
battery
);
cscale
=
battery
->
info
.
vscale
*
battery
->
info
.
ipscale
;
}
else
{
cscale
=
battery
->
info
.
ipscale
;
}
seq_printf
(
seq
,
"alarm: "
);
seq_printf
(
seq
,
"alarm: "
);
if
(
battery
->
alarm
.
remaining_capacity
)
{
if
(
battery
->
alarm
_capacity
)
seq_printf
(
seq
,
"%i%s
\n
"
,
seq_printf
(
seq
,
"%i%s
\n
"
,
battery
->
alarm
.
remaining_capacity
*
cscale
,
battery
->
alarm_capacity
*
battery
->
info
.
capacity_mode
?
"0 mWh"
:
" mAh"
);
acpi_battery_scale
(
battery
),
}
else
{
acpi_battery_units
(
battery
));
else
seq_printf
(
seq
,
"disabled
\n
"
);
seq_printf
(
seq
,
"disabled
\n
"
);
}
end:
end:
mutex_unlock
(
&
sbs
->
lock
);
sbs_mutex_unlock
(
sbs
);
return
result
;
return
result
;
}
}
...
@@ -1155,59 +656,29 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
...
@@ -1155,59 +656,29 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_battery
*
battery
=
seq
->
private
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
struct
acpi_sbs
*
sbs
=
battery
->
sbs
;
char
alarm_string
[
12
]
=
{
'\0'
};
char
alarm_string
[
12
]
=
{
'\0'
};
int
result
,
old_alarm
,
new_alarm
;
int
result
=
0
;
mutex_lock
(
&
sbs
->
lock
);
if
(
sbs_mutex_lock
(
sbs
))
{
if
(
!
battery
->
present
)
{
return
-
ENODEV
;
}
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
goto
end
;
if
(
!
battery
->
battery_present
)
{
result
=
-
ENODEV
;
result
=
-
ENODEV
;
goto
end
;
goto
end
;
}
}
if
(
count
>
sizeof
(
alarm_string
)
-
1
)
{
if
(
count
>
sizeof
(
alarm_string
)
-
1
)
{
result
=
-
EINVAL
;
result
=
-
EINVAL
;
goto
end
;
goto
end
;
}
}
if
(
copy_from_user
(
alarm_string
,
buffer
,
count
))
{
if
(
copy_from_user
(
alarm_string
,
buffer
,
count
))
{
result
=
-
EFAULT
;
result
=
-
EFAULT
;
goto
end
;
goto
end
;
}
}
alarm_string
[
count
]
=
0
;
alarm_string
[
count
]
=
0
;
battery
->
alarm_capacity
=
simple_strtoul
(
alarm_string
,
NULL
,
0
)
/
old_alarm
=
battery
->
alarm
.
remaining_capacity
;
acpi_battery_scale
(
battery
);
new_alarm
=
simple_strtoul
(
alarm_string
,
NULL
,
0
);
acpi_battery_set_alarm
(
battery
);
result
=
acpi_battery_set_alarm
(
battery
,
new_alarm
);
if
(
result
)
{
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_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_alarm() failed"
));
acpi_battery_set_alarm
(
battery
,
old_alarm
);
goto
end
;
}
end:
end:
sbs_mutex_unlock
(
sbs
);
mutex_unlock
(
&
sbs
->
lock
);
if
(
result
)
if
(
result
)
{
return
result
;
return
result
;
}
else
{
return
count
;
return
count
;
}
}
}
static
int
acpi_battery_alarm_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
acpi_battery_alarm_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
)
...
@@ -1246,26 +717,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
...
@@ -1246,26 +717,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
static
int
acpi_ac_read_state
(
struct
seq_file
*
seq
,
void
*
offset
)
static
int
acpi_ac_read_state
(
struct
seq_file
*
seq
,
void
*
offset
)
{
{
struct
acpi_sbs
*
sbs
=
seq
->
private
;
int
result
;
if
(
sbs_mutex_lock
(
sbs
))
{
struct
acpi_sbs
*
sbs
=
seq
->
private
;
return
-
ENODEV
;
}
if
(
update_time
==
0
)
{
mutex_lock
(
&
sbs
->
lock
);
result
=
acpi_sbs_update_run
(
sbs
,
-
1
,
DATA_TYPE_AC_STATE
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_update_run() failed"
));
}
}
seq_printf
(
seq
,
"state: %s
\n
"
,
seq_printf
(
seq
,
"state: %s
\n
"
,
sbs
->
ac
.
ac_present
?
"on-line"
:
"off-line"
);
sbs
->
charger_present
?
"on-line"
:
"off-line"
);
sbs_mutex_unlock
(
sbs
);
mutex_unlock
(
&
sbs
->
lock
);
return
0
;
return
0
;
}
}
...
@@ -1282,429 +742,203 @@ static struct file_operations acpi_ac_state_fops = {
...
@@ -1282,429 +742,203 @@ static struct file_operations acpi_ac_state_fops = {
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
};
};
#endif
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
Driver Interface
Driver Interface
-------------------------------------------------------------------------- */
-------------------------------------------------------------------------- */
static
int
acpi_battery_read
(
struct
acpi_battery
*
battery
)
{
int
result
=
0
,
saved_present
=
battery
->
present
;
u16
state
;
if
(
battery
->
sbs
->
manager_present
)
{
result
=
acpi_smbus_read
(
battery
->
sbs
->
hc
,
SMBUS_READ_WORD
,
ACPI_SBS_MANAGER
,
0x01
,
(
u8
*
)
&
state
);
if
(
!
result
)
battery
->
present
=
state
&
(
1
<<
battery
->
id
);
state
&=
0x0fff
;
state
|=
1
<<
(
battery
->
id
+
12
);
acpi_smbus_write
(
battery
->
sbs
->
hc
,
SMBUS_WRITE_WORD
,
ACPI_SBS_MANAGER
,
0x01
,
(
u8
*
)
&
state
,
2
);
}
else
if
(
battery
->
id
==
0
)
battery
->
present
=
1
;
if
(
result
||
!
battery
->
present
)
return
result
;
/* Smart Battery */
if
(
saved_present
!=
battery
->
present
)
{
battery
->
update_time
=
0
;
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
return
result
;
}
result
=
acpi_battery_get_state
(
battery
);
return
result
;
}
/* Smart Battery */
static
int
acpi_battery_add
(
struct
acpi_sbs
*
sbs
,
int
id
)
static
int
acpi_battery_add
(
struct
acpi_sbs
*
sbs
,
int
id
)
{
{
int
is_present
;
struct
acpi_battery
*
battery
=
&
sbs
->
battery
[
id
]
;
int
result
;
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
->
id
=
id
;
battery
->
sbs
=
sbs
;
battery
->
sbs
=
sbs
;
result
=
acpi_battery_read
(
battery
);
if
(
result
)
return
result
;
result
=
acpi_battery_select
(
battery
);
sprintf
(
battery
->
name
,
ACPI_BATTERY_DIR_NAME
,
id
);
if
(
result
)
{
#ifdef CONFIG_ACPI_PROCFS
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
acpi_sbs_add_fs
(
&
battery
->
proc_entry
,
acpi_battery_dir
,
"acpi_battery_select() failed"
));
battery
->
name
,
&
acpi_battery_info_fops
,
goto
end
;
&
acpi_battery_state_fops
,
&
acpi_battery_alarm_fops
,
}
battery
);
#endif
result
=
acpi_battery_get_present
(
battery
);
battery
->
bat
.
name
=
battery
->
name
;
if
(
result
)
{
battery
->
bat
.
type
=
POWER_SUPPLY_TYPE_BATTERY
;
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
if
(
!
acpi_battery_mode
(
battery
))
{
"acpi_battery_get_present() failed"
));
battery
->
bat
.
properties
=
sbs_charge_battery_props
;
goto
end
;
battery
->
bat
.
num_properties
=
}
ARRAY_SIZE
(
sbs_charge_battery_props
);
}
else
{
is_present
=
battery
->
battery_present
;
battery
->
bat
.
properties
=
sbs_energy_battery_props
;
battery
->
bat
.
num_properties
=
if
(
is_present
)
{
ARRAY_SIZE
(
sbs_energy_battery_props
);
result
=
acpi_battery_init
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_init() failed"
));
goto
end
;
}
battery
->
init_state
=
1
;
}
sprintf
(
dir_name
,
ACPI_BATTERY_DIR_NAME
,
id
);
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
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_generic_add_fs() failed"
));
goto
end
;
}
}
battery
->
alive
=
1
;
battery
->
bat
.
get_property
=
acpi_sbs_battery_get_property
;
result
=
power_supply_register
(
&
sbs
->
device
->
dev
,
&
battery
->
bat
);
device_create_file
(
battery
->
bat
.
dev
,
&
alarm_attr
);
printk
(
KERN_INFO
PREFIX
"%s [%s]: Battery Slot [%s] (battery %s)
\n
"
,
printk
(
KERN_INFO
PREFIX
"%s [%s]: Battery Slot [%s] (battery %s)
\n
"
,
ACPI_SBS_DEVICE_NAME
,
acpi_device_bid
(
sbs
->
device
),
dir_name
,
ACPI_SBS_DEVICE_NAME
,
acpi_device_bid
(
sbs
->
device
),
sbs
->
battery
->
battery_present
?
"present"
:
"absent"
);
battery
->
name
,
sbs
->
battery
->
present
?
"present"
:
"absent"
);
end:
return
result
;
return
result
;
}
}
static
void
acpi_battery_remove
(
struct
acpi_sbs
*
sbs
,
int
id
)
static
void
acpi_battery_remove
(
struct
acpi_sbs
*
sbs
,
int
id
)
{
{
if
(
sbs
->
battery
[
id
].
bat
.
dev
)
if
(
sbs
->
battery
[
id
].
battery_entry
)
{
device_remove_file
(
sbs
->
battery
[
id
].
bat
.
dev
,
&
alarm_attr
);
acpi_sbs_generic_remove_fs
(
&
(
sbs
->
battery
[
id
].
battery_entry
),
power_supply_unregister
(
&
sbs
->
battery
[
id
].
bat
);
acpi_battery_dir
);
#ifdef CONFIG_ACPI_PROCFS
}
if
(
sbs
->
battery
[
id
].
proc_entry
)
{
acpi_sbs_remove_fs
(
&
(
sbs
->
battery
[
id
].
proc_entry
),
acpi_battery_dir
);
}
#endif
}
}
static
int
acpi_
ac
_add
(
struct
acpi_sbs
*
sbs
)
static
int
acpi_
charger
_add
(
struct
acpi_sbs
*
sbs
)
{
{
int
result
;
int
result
;
result
=
acpi_ac_get_present
(
sbs
);
result
=
acpi_ac_get_present
(
sbs
);
if
(
result
)
{
if
(
result
)
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ac_get_present() failed"
));
goto
end
;
goto
end
;
}
#ifdef CONFIG_ACPI_PROCFS
result
=
acpi_sbs_add_fs
(
&
sbs
->
charger_entry
,
acpi_ac_dir
,
result
=
acpi_sbs_generic_add_fs
(
&
sbs
->
ac_entry
,
ACPI_AC_DIR_NAME
,
NULL
,
acpi_ac_dir
,
&
acpi_ac_state_fops
,
NULL
,
sbs
);
ACPI_AC_DIR_NAME
,
if
(
result
)
NULL
,
&
acpi_ac_state_fops
,
NULL
,
sbs
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_generic_add_fs() failed"
));
goto
end
;
goto
end
;
}
#endif
sbs
->
charger
.
name
=
"sbs-charger"
;
sbs
->
charger
.
type
=
POWER_SUPPLY_TYPE_MAINS
;
sbs
->
charger
.
properties
=
sbs_ac_props
;
sbs
->
charger
.
num_properties
=
ARRAY_SIZE
(
sbs_ac_props
);
sbs
->
charger
.
get_property
=
sbs_get_ac_property
;
power_supply_register
(
&
sbs
->
device
->
dev
,
&
sbs
->
charger
);
printk
(
KERN_INFO
PREFIX
"%s [%s]: AC Adapter [%s] (%s)
\n
"
,
printk
(
KERN_INFO
PREFIX
"%s [%s]: AC Adapter [%s] (%s)
\n
"
,
ACPI_SBS_DEVICE_NAME
,
acpi_device_bid
(
sbs
->
device
),
ACPI_SBS_DEVICE_NAME
,
acpi_device_bid
(
sbs
->
device
),
ACPI_AC_DIR_NAME
,
sbs
->
ac
.
ac_present
?
"on-line"
:
"off-line"
);
ACPI_AC_DIR_NAME
,
sbs
->
charger_present
?
"on-line"
:
"off-line"
);
end:
end:
return
result
;
return
result
;
}
}
static
void
acpi_ac_remove
(
struct
acpi_sbs
*
sbs
)
static
void
acpi_charger_remove
(
struct
acpi_sbs
*
sbs
)
{
if
(
sbs
->
ac_entry
)
{
acpi_sbs_generic_remove_fs
(
&
sbs
->
ac_entry
,
acpi_ac_dir
);
}
}
static
void
acpi_sbs_update_time_run
(
unsigned
long
data
)
{
{
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_sbs_update_time
,
(
void
*
)
data
);
if
(
sbs
->
charger
.
dev
)
power_supply_unregister
(
&
sbs
->
charger
);
#ifdef CONFIG_ACPI_PROCFS
if
(
sbs
->
charger_entry
)
acpi_sbs_remove_fs
(
&
sbs
->
charger_entry
,
acpi_ac_dir
);
#endif
}
}
static
int
acpi_sbs_update_run
(
struct
acpi_sbs
*
sbs
,
int
id
,
int
data_type
)
void
acpi_sbs_callback
(
void
*
context
)
{
{
struct
acpi_battery
*
battery
;
int
id
;
int
result
=
0
,
cnt
;
struct
acpi_sbs
*
sbs
=
context
;
int
old_ac_present
=
-
1
;
struct
acpi_battery
*
bat
;
int
old_battery_present
=
-
1
;
u8
saved_charger_state
=
sbs
->
charger_present
;
int
new_ac_present
=
-
1
;
u8
saved_battery_state
;
int
new_battery_present
=
-
1
;
acpi_ac_get_present
(
sbs
);
int
id_min
=
0
,
id_max
=
MAX_SBS_BAT
-
1
;
if
(
sbs
->
charger_present
!=
saved_charger_state
)
{
char
dir_name
[
32
];
#ifdef CONFIG_ACPI_PROC_EVENT
int
do_battery_init
=
0
,
do_ac_init
=
0
;
acpi_bus_generate_proc_event4
(
ACPI_AC_CLASS
,
ACPI_AC_DIR_NAME
,
int
old_remaining_capacity
=
0
;
ACPI_SBS_NOTIFY_STATUS
,
int
update_battery
=
1
;
sbs
->
charger_present
);
int
up_tm
=
update_time
;
#endif
kobject_uevent
(
&
sbs
->
charger
.
dev
->
kobj
,
KOBJ_CHANGE
);
if
(
sbs_zombie
(
sbs
))
{
}
goto
end
;
if
(
sbs
->
manager_present
)
{
}
for
(
id
=
0
;
id
<
MAX_SBS_BAT
;
++
id
)
{
if
(
!
(
sbs
->
batteries_supported
&
(
1
<<
id
)))
if
(
id
>=
0
)
{
continue
;
id_min
=
id_max
=
id
;
bat
=
&
sbs
->
battery
[
id
];
}
saved_battery_state
=
bat
->
present
;
acpi_battery_read
(
bat
);
if
(
data_type
==
DATA_TYPE_COMMON
&&
up_tm
>
0
)
{
if
(
saved_battery_state
==
bat
->
present
)
cnt
=
up_tm
/
(
up_tm
>
UPDATE_DELAY
?
UPDATE_DELAY
:
up_tm
);
continue
;
if
(
sbs
->
run_cnt
%
cnt
!=
0
)
{
#ifdef CONFIG_ACPI_PROC_EVENT
update_battery
=
0
;
acpi_bus_generate_proc_event4
(
ACPI_BATTERY_CLASS
,
}
bat
->
name
,
}
ACPI_SBS_NOTIFY_STATUS
,
bat
->
present
);
sbs
->
run_cnt
++
;
#endif
kobject_uevent
(
&
bat
->
bat
.
dev
->
kobj
,
KOBJ_CHANGE
);
old_ac_present
=
sbs
->
ac
.
ac_present
;
result
=
acpi_ac_get_present
(
sbs
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ac_get_present() failed"
));
}
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
(
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
=
id_min
;
id
<=
id_max
;
id
++
)
{
battery
=
&
sbs
->
battery
[
id
];
if
(
battery
->
alive
==
0
)
{
continue
;
}
old_remaining_capacity
=
battery
->
state
.
remaining_capacity
;
old_battery_present
=
battery
->
battery_present
;
result
=
acpi_battery_select
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_select() failed"
));
}
result
=
acpi_battery_get_present
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_present() failed"
));
}
new_battery_present
=
battery
->
battery_present
;
do_battery_init
=
((
old_battery_present
!=
new_battery_present
)
&&
new_battery_present
);
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
((
data_type
==
DATA_TYPE_COMMON
||
data_type
==
DATA_TYPE_INFO
)
&&
new_battery_present
)
{
result
=
acpi_battery_get_info
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_info() failed"
));
}
}
if
(
data_type
==
DATA_TYPE_INFO
)
{
continue
;
}
if
(
sbs_zombie
(
sbs
))
{
goto
end
;
}
if
((
data_type
==
DATA_TYPE_COMMON
||
data_type
==
DATA_TYPE_STATE
)
&&
new_battery_present
)
{
result
=
acpi_battery_get_state
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_state() failed"
));
}
}
if
(
data_type
==
DATA_TYPE_STATE
)
{
goto
event
;
}
if
(
sbs_zombie
(
sbs
))
{
goto
end
;
}
if
((
data_type
==
DATA_TYPE_COMMON
||
data_type
==
DATA_TYPE_ALARM
)
&&
new_battery_present
)
{
result
=
acpi_battery_get_alarm
(
battery
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_get_alarm() "
"failed"
));
}
}
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
,
new_battery_present
,
dir_name
,
ACPI_BATTERY_CLASS
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_generate_event() "
"failed"
));
}
}
}
}
}
end:
return
result
;
}
}
static
void
acpi_sbs_update_time
(
void
*
data
)
static
int
acpi_sbs_remove
(
struct
acpi_device
*
device
,
int
type
);
{
struct
acpi_sbs
*
sbs
=
data
;
unsigned
long
delay
=
-
1
;
int
result
;
unsigned
int
up_tm
=
update_time
;
if
(
sbs_mutex_lock
(
sbs
))
return
;
result
=
acpi_sbs_update_run
(
sbs
,
-
1
,
DATA_TYPE_COMMON
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_update_run() failed"
));
}
if
(
sbs_zombie
(
sbs
))
{
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
);
}
}
end:
sbs_mutex_unlock
(
sbs
);
}
static
int
acpi_sbs_add
(
struct
acpi_device
*
device
)
static
int
acpi_sbs_add
(
struct
acpi_device
*
device
)
{
{
struct
acpi_sbs
*
sbs
=
NULL
;
struct
acpi_sbs
*
sbs
;
int
result
=
0
,
remove_result
=
0
;
int
result
=
0
;
int
id
;
int
id
;
acpi_status
status
=
AE_OK
;
unsigned
long
val
;
status
=
acpi_evaluate_integer
(
device
->
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
);
sbs
=
kzalloc
(
sizeof
(
struct
acpi_sbs
),
GFP_KERNEL
);
if
(
!
sbs
)
{
if
(
!
sbs
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"kzalloc() failed"
));
result
=
-
ENOMEM
;
result
=
-
ENOMEM
;
goto
end
;
goto
end
;
}
}
mutex_init
(
&
sbs
->
mutex
);
mutex_init
(
&
sbs
->
lock
);
sbs_mutex_lock
(
sbs
);
sbs
->
hc
=
acpi_driver_data
(
device
->
parent
);
sbs
->
base
=
0xff
&
(
val
>>
8
);
sbs
->
device
=
device
;
sbs
->
device
=
device
;
strcpy
(
acpi_device_name
(
device
),
ACPI_SBS_DEVICE_NAME
);
strcpy
(
acpi_device_name
(
device
),
ACPI_SBS_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_SBS_CLASS
);
strcpy
(
acpi_device_class
(
device
),
ACPI_SBS_CLASS
);
acpi_driver_data
(
device
)
=
sbs
;
acpi_driver_data
(
device
)
=
sbs
;
result
=
acpi_ac_add
(
sbs
);
result
=
acpi_charger_add
(
sbs
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_ac_add() failed"
));
goto
end
;
}
acpi_sbsm_get_info
(
sbs
);
if
(
!
sbs
->
sbsm_present
)
{
result
=
acpi_battery_add
(
sbs
,
0
);
if
(
result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_add() failed"
));
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
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_battery_add() failed"
));
goto
end
;
}
}
}
}
init_timer
(
&
sbs
->
update_timer
);
result
=
acpi_check_update_proc
(
sbs
);
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
result
=
acpi_manager_get_info
(
sbs
);
if
(
!
result
)
{
sbs
->
manager_present
=
1
;
for
(
id
=
0
;
id
<
MAX_SBS_BAT
;
++
id
)
if
((
sbs
->
batteries_supported
&
(
1
<<
id
)))
acpi_battery_add
(
sbs
,
id
);
}
else
acpi_battery_add
(
sbs
,
0
);
acpi_smbus_register_callback
(
sbs
->
hc
,
acpi_sbs_callback
,
sbs
);
end:
end:
if
(
result
)
sbs_mutex_unlock
(
sbs
);
acpi_sbs_remove
(
device
,
0
);
if
(
result
)
{
remove_result
=
acpi_sbs_remove
(
device
,
0
);
if
(
remove_result
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_sbs_remove() failed"
));
}
}
return
result
;
return
result
;
}
}
...
@@ -1713,39 +947,25 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
...
@@ -1713,39 +947,25 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
struct
acpi_sbs
*
sbs
;
struct
acpi_sbs
*
sbs
;
int
id
;
int
id
;
if
(
!
device
)
{
if
(
!
device
)
return
-
EINVAL
;
return
-
EINVAL
;
}
sbs
=
acpi_driver_data
(
device
);
sbs
=
acpi_driver_data
(
device
);
if
(
!
sbs
)
{
if
(
!
sbs
)
return
-
EINVAL
;
return
-
EINVAL
;
}
mutex_lock
(
&
sbs
->
lock
);
acpi_smbus_unregister_callback
(
sbs
->
hc
);
sbs_mutex_lock
(
sbs
);
for
(
id
=
0
;
id
<
MAX_SBS_BAT
;
++
id
)
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_battery_remove
(
sbs
,
id
);
}
acpi_charger_remove
(
sbs
);
mutex_unlock
(
&
sbs
->
lock
);
acpi_ac_remove
(
sbs
);
mutex_destroy
(
&
sbs
->
lock
);
sbs_mutex_unlock
(
sbs
);
mutex_destroy
(
&
sbs
->
mutex
);
kfree
(
sbs
);
kfree
(
sbs
);
return
0
;
return
0
;
}
}
static
void
acpi_sbs_rmdirs
(
void
)
static
void
acpi_sbs_rmdirs
(
void
)
{
{
#ifdef CONFIG_ACPI_PROCFS
if
(
acpi_ac_dir
)
{
if
(
acpi_ac_dir
)
{
acpi_unlock_ac_dir
(
acpi_ac_dir
);
acpi_unlock_ac_dir
(
acpi_ac_dir
);
acpi_ac_dir
=
NULL
;
acpi_ac_dir
=
NULL
;
...
@@ -1754,69 +974,58 @@ static void acpi_sbs_rmdirs(void)
...
@@ -1754,69 +974,58 @@ static void acpi_sbs_rmdirs(void)
acpi_unlock_battery_dir
(
acpi_battery_dir
);
acpi_unlock_battery_dir
(
acpi_battery_dir
);
acpi_battery_dir
=
NULL
;
acpi_battery_dir
=
NULL
;
}
}
#endif
}
}
static
int
acpi_sbs_resume
(
struct
acpi_device
*
device
)
static
int
acpi_sbs_resume
(
struct
acpi_device
*
device
)
{
{
struct
acpi_sbs
*
sbs
;
struct
acpi_sbs
*
sbs
;
if
(
!
device
)
if
(
!
device
)
return
-
EINVAL
;
return
-
EINVAL
;
sbs
=
device
->
driver_data
;
sbs
=
device
->
driver_data
;
acpi_sbs_callback
(
sbs
);
sbs
->
run_cnt
=
0
;
return
0
;
return
0
;
}
}
static
struct
acpi_driver
acpi_sbs_driver
=
{
.
name
=
"sbs"
,
.
class
=
ACPI_SBS_CLASS
,
.
ids
=
sbs_device_ids
,
.
ops
=
{
.
add
=
acpi_sbs_add
,
.
remove
=
acpi_sbs_remove
,
.
resume
=
acpi_sbs_resume
,
},
};
static
int
__init
acpi_sbs_init
(
void
)
static
int
__init
acpi_sbs_init
(
void
)
{
{
int
result
=
0
;
int
result
=
0
;
if
(
acpi_disabled
)
if
(
acpi_disabled
)
return
-
ENODEV
;
return
-
ENODEV
;
#ifdef CONFIG_ACPI_PROCFS
if
(
capacity_mode
!=
DEF_CAPACITY_UNIT
&&
capacity_mode
!=
MAH_CAPACITY_UNIT
&&
capacity_mode
!=
MWH_CAPACITY_UNIT
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"invalid capacity_mode = %d"
,
capacity_mode
));
return
-
EINVAL
;
}
acpi_ac_dir
=
acpi_lock_ac_dir
();
acpi_ac_dir
=
acpi_lock_ac_dir
();
if
(
!
acpi_ac_dir
)
{
if
(
!
acpi_ac_dir
)
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_lock_ac_dir() failed"
));
return
-
ENODEV
;
return
-
ENODEV
;
}
acpi_battery_dir
=
acpi_lock_battery_dir
();
acpi_battery_dir
=
acpi_lock_battery_dir
();
if
(
!
acpi_battery_dir
)
{
if
(
!
acpi_battery_dir
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_lock_battery_dir() failed"
));
acpi_sbs_rmdirs
();
acpi_sbs_rmdirs
();
return
-
ENODEV
;
return
-
ENODEV
;
}
}
#endif
result
=
acpi_bus_register_driver
(
&
acpi_sbs_driver
);
result
=
acpi_bus_register_driver
(
&
acpi_sbs_driver
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
ACPI_EXCEPTION
((
AE_INFO
,
AE_ERROR
,
"acpi_bus_register_driver() failed"
));
acpi_sbs_rmdirs
();
acpi_sbs_rmdirs
();
return
-
ENODEV
;
return
-
ENODEV
;
}
}
return
0
;
return
0
;
}
}
static
void
__exit
acpi_sbs_exit
(
void
)
static
void
__exit
acpi_sbs_exit
(
void
)
{
{
acpi_bus_unregister_driver
(
&
acpi_sbs_driver
);
acpi_bus_unregister_driver
(
&
acpi_sbs_driver
);
acpi_sbs_rmdirs
();
acpi_sbs_rmdirs
();
return
;
return
;
}
}
...
...
drivers/acpi/sbshc.c
0 → 100644
View file @
e270051d
/*
* SMBus driver for ACPI Embedded Controller (v0.1)
*
* Copyright (c) 2007 Alexey Starikovskiy
*
* 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 <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/actypes.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include "sbshc.h"
#define ACPI_SMB_HC_CLASS "smbus_host_controller"
#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"
struct
acpi_smb_hc
{
struct
acpi_ec
*
ec
;
struct
mutex
lock
;
wait_queue_head_t
wait
;
u8
offset
;
u8
query_bit
;
smbus_alarm_callback
callback
;
void
*
context
;
};
static
int
acpi_smbus_hc_add
(
struct
acpi_device
*
device
);
static
int
acpi_smbus_hc_remove
(
struct
acpi_device
*
device
,
int
type
);
static
const
struct
acpi_device_id
sbs_device_ids
[]
=
{
{
"ACPI0001"
,
0
},
{
"ACPI0005"
,
0
},
{
""
,
0
},
};
MODULE_DEVICE_TABLE
(
acpi
,
sbs_device_ids
);
static
struct
acpi_driver
acpi_smb_hc_driver
=
{
.
name
=
"smbus_hc"
,
.
class
=
ACPI_SMB_HC_CLASS
,
.
ids
=
sbs_device_ids
,
.
ops
=
{
.
add
=
acpi_smbus_hc_add
,
.
remove
=
acpi_smbus_hc_remove
,
},
};
union
acpi_smb_status
{
u8
raw
;
struct
{
u8
status
:
5
;
u8
reserved
:
1
;
u8
alarm
:
1
;
u8
done
:
1
;
}
fields
;
};
enum
acpi_smb_status_codes
{
SMBUS_OK
=
0
,
SMBUS_UNKNOWN_FAILURE
=
0x07
,
SMBUS_DEVICE_ADDRESS_NACK
=
0x10
,
SMBUS_DEVICE_ERROR
=
0x11
,
SMBUS_DEVICE_COMMAND_ACCESS_DENIED
=
0x12
,
SMBUS_UNKNOWN_ERROR
=
0x13
,
SMBUS_DEVICE_ACCESS_DENIED
=
0x17
,
SMBUS_TIMEOUT
=
0x18
,
SMBUS_HOST_UNSUPPORTED_PROTOCOL
=
0x19
,
SMBUS_BUSY
=
0x1a
,
SMBUS_PEC_ERROR
=
0x1f
,
};
enum
acpi_smb_offset
{
ACPI_SMB_PROTOCOL
=
0
,
/* protocol, PEC */
ACPI_SMB_STATUS
=
1
,
/* status */
ACPI_SMB_ADDRESS
=
2
,
/* address */
ACPI_SMB_COMMAND
=
3
,
/* command */
ACPI_SMB_DATA
=
4
,
/* 32 data registers */
ACPI_SMB_BLOCK_COUNT
=
0x24
,
/* number of data bytes */
ACPI_SMB_ALARM_ADDRESS
=
0x25
,
/* alarm address */
ACPI_SMB_ALARM_DATA
=
0x26
,
/* 2 bytes alarm data */
};
static
inline
int
smb_hc_read
(
struct
acpi_smb_hc
*
hc
,
u8
address
,
u8
*
data
)
{
return
ec_read
(
hc
->
offset
+
address
,
data
);
}
static
inline
int
smb_hc_write
(
struct
acpi_smb_hc
*
hc
,
u8
address
,
u8
data
)
{
return
ec_write
(
hc
->
offset
+
address
,
data
);
}
static
inline
int
smb_check_done
(
struct
acpi_smb_hc
*
hc
)
{
union
acpi_smb_status
status
=
{.
raw
=
0
};
smb_hc_read
(
hc
,
ACPI_SMB_STATUS
,
&
status
.
raw
);
return
status
.
fields
.
done
&&
(
status
.
fields
.
status
==
SMBUS_OK
);
}
static
int
wait_transaction_complete
(
struct
acpi_smb_hc
*
hc
,
int
timeout
)
{
if
(
wait_event_timeout
(
hc
->
wait
,
smb_check_done
(
hc
),
msecs_to_jiffies
(
timeout
)))
return
0
;
else
return
-
ETIME
;
}
int
acpi_smbus_transaction
(
struct
acpi_smb_hc
*
hc
,
u8
protocol
,
u8
address
,
u8
command
,
u8
*
data
,
u8
length
)
{
int
ret
=
-
EFAULT
,
i
;
u8
temp
,
sz
=
0
;
mutex_lock
(
&
hc
->
lock
);
if
(
smb_hc_read
(
hc
,
ACPI_SMB_PROTOCOL
,
&
temp
))
goto
end
;
if
(
temp
)
{
ret
=
-
EBUSY
;
goto
end
;
}
smb_hc_write
(
hc
,
ACPI_SMB_COMMAND
,
command
);
smb_hc_write
(
hc
,
ACPI_SMB_COMMAND
,
command
);
if
(
!
(
protocol
&
0x01
))
{
smb_hc_write
(
hc
,
ACPI_SMB_BLOCK_COUNT
,
length
);
for
(
i
=
0
;
i
<
length
;
++
i
)
smb_hc_write
(
hc
,
ACPI_SMB_DATA
+
i
,
data
[
i
]);
}
smb_hc_write
(
hc
,
ACPI_SMB_ADDRESS
,
address
<<
1
);
smb_hc_write
(
hc
,
ACPI_SMB_PROTOCOL
,
protocol
);
/*
* Wait for completion. Save the status code, data size,
* and data into the return package (if required by the protocol).
*/
ret
=
wait_transaction_complete
(
hc
,
1000
);
if
(
ret
||
!
(
protocol
&
0x01
))
goto
end
;
switch
(
protocol
)
{
case
SMBUS_RECEIVE_BYTE
:
case
SMBUS_READ_BYTE
:
sz
=
1
;
break
;
case
SMBUS_READ_WORD
:
sz
=
2
;
break
;
case
SMBUS_READ_BLOCK
:
if
(
smb_hc_read
(
hc
,
ACPI_SMB_BLOCK_COUNT
,
&
sz
))
{
ret
=
-
EFAULT
;
goto
end
;
}
sz
&=
0x1f
;
break
;
}
for
(
i
=
0
;
i
<
sz
;
++
i
)
smb_hc_read
(
hc
,
ACPI_SMB_DATA
+
i
,
&
data
[
i
]);
end:
mutex_unlock
(
&
hc
->
lock
);
return
ret
;
}
int
acpi_smbus_read
(
struct
acpi_smb_hc
*
hc
,
u8
protocol
,
u8
address
,
u8
command
,
u8
*
data
)
{
return
acpi_smbus_transaction
(
hc
,
protocol
,
address
,
command
,
data
,
0
);
}
EXPORT_SYMBOL_GPL
(
acpi_smbus_read
);
int
acpi_smbus_write
(
struct
acpi_smb_hc
*
hc
,
u8
protocol
,
u8
address
,
u8
command
,
u8
*
data
,
u8
length
)
{
return
acpi_smbus_transaction
(
hc
,
protocol
,
address
,
command
,
data
,
length
);
}
EXPORT_SYMBOL_GPL
(
acpi_smbus_write
);
int
acpi_smbus_register_callback
(
struct
acpi_smb_hc
*
hc
,
smbus_alarm_callback
callback
,
void
*
context
)
{
mutex_lock
(
&
hc
->
lock
);
hc
->
callback
=
callback
;
hc
->
context
=
context
;
mutex_unlock
(
&
hc
->
lock
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
acpi_smbus_register_callback
);
int
acpi_smbus_unregister_callback
(
struct
acpi_smb_hc
*
hc
)
{
mutex_lock
(
&
hc
->
lock
);
hc
->
callback
=
NULL
;
hc
->
context
=
NULL
;
mutex_unlock
(
&
hc
->
lock
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
acpi_smbus_unregister_callback
);
static
void
acpi_smbus_callback
(
void
*
context
)
{
struct
acpi_smb_hc
*
hc
=
context
;
if
(
hc
->
callback
)
hc
->
callback
(
hc
->
context
);
}
static
int
smbus_alarm
(
void
*
context
)
{
struct
acpi_smb_hc
*
hc
=
context
;
union
acpi_smb_status
status
;
if
(
smb_hc_read
(
hc
,
ACPI_SMB_STATUS
,
&
status
.
raw
))
return
0
;
/* Check if it is only a completion notify */
if
(
status
.
fields
.
done
)
wake_up
(
&
hc
->
wait
);
if
(
!
status
.
fields
.
alarm
)
return
0
;
mutex_lock
(
&
hc
->
lock
);
smb_hc_write
(
hc
,
ACPI_SMB_STATUS
,
status
.
raw
);
if
(
hc
->
callback
)
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_smbus_callback
,
hc
);
mutex_unlock
(
&
hc
->
lock
);
return
0
;
}
typedef
int
(
*
acpi_ec_query_func
)
(
void
*
data
);
extern
int
acpi_ec_add_query_handler
(
struct
acpi_ec
*
ec
,
u8
query_bit
,
acpi_handle
handle
,
acpi_ec_query_func
func
,
void
*
data
);
static
int
acpi_smbus_hc_add
(
struct
acpi_device
*
device
)
{
int
status
;
unsigned
long
val
;
struct
acpi_smb_hc
*
hc
;
if
(
!
device
)
return
-
EINVAL
;
status
=
acpi_evaluate_integer
(
device
->
handle
,
"_EC"
,
NULL
,
&
val
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_ERR
PREFIX
"error obtaining _EC.
\n
"
);
return
-
EIO
;
}
strcpy
(
acpi_device_name
(
device
),
ACPI_SMB_HC_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_SMB_HC_CLASS
);
hc
=
kzalloc
(
sizeof
(
struct
acpi_smb_hc
),
GFP_KERNEL
);
if
(
!
hc
)
return
-
ENOMEM
;
mutex_init
(
&
hc
->
lock
);
init_waitqueue_head
(
&
hc
->
wait
);
hc
->
ec
=
acpi_driver_data
(
device
->
parent
);
hc
->
offset
=
(
val
>>
8
)
&
0xff
;
hc
->
query_bit
=
val
&
0xff
;
acpi_driver_data
(
device
)
=
hc
;
acpi_ec_add_query_handler
(
hc
->
ec
,
hc
->
query_bit
,
NULL
,
smbus_alarm
,
hc
);
printk
(
KERN_INFO
PREFIX
"SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x
\n
"
,
hc
->
ec
,
hc
->
offset
,
hc
->
query_bit
);
return
0
;
}
extern
void
acpi_ec_remove_query_handler
(
struct
acpi_ec
*
ec
,
u8
query_bit
);
static
int
acpi_smbus_hc_remove
(
struct
acpi_device
*
device
,
int
type
)
{
struct
acpi_smb_hc
*
hc
;
if
(
!
device
)
return
-
EINVAL
;
hc
=
acpi_driver_data
(
device
);
acpi_ec_remove_query_handler
(
hc
->
ec
,
hc
->
query_bit
);
kfree
(
hc
);
return
0
;
}
static
int
__init
acpi_smb_hc_init
(
void
)
{
int
result
;
result
=
acpi_bus_register_driver
(
&
acpi_smb_hc_driver
);
if
(
result
<
0
)
return
-
ENODEV
;
return
0
;
}
static
void
__exit
acpi_smb_hc_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
acpi_smb_hc_driver
);
}
module_init
(
acpi_smb_hc_init
);
module_exit
(
acpi_smb_hc_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Alexey Starikovskiy"
);
MODULE_DESCRIPTION
(
"ACPI SMBus HC driver"
);
drivers/acpi/sbshc.h
0 → 100644
View file @
e270051d
struct
acpi_smb_hc
;
enum
acpi_smb_protocol
{
SMBUS_WRITE_QUICK
=
2
,
SMBUS_READ_QUICK
=
3
,
SMBUS_SEND_BYTE
=
4
,
SMBUS_RECEIVE_BYTE
=
5
,
SMBUS_WRITE_BYTE
=
6
,
SMBUS_READ_BYTE
=
7
,
SMBUS_WRITE_WORD
=
8
,
SMBUS_READ_WORD
=
9
,
SMBUS_WRITE_BLOCK
=
0xa
,
SMBUS_READ_BLOCK
=
0xb
,
SMBUS_PROCESS_CALL
=
0xc
,
SMBUS_BLOCK_PROCESS_CALL
=
0xd
,
};
static
const
u8
SMBUS_PEC
=
0x80
;
typedef
void
(
*
smbus_alarm_callback
)(
void
*
context
);
extern
int
acpi_smbus_read
(
struct
acpi_smb_hc
*
hc
,
u8
protocol
,
u8
address
,
u8
command
,
u8
*
data
);
extern
int
acpi_smbus_write
(
struct
acpi_smb_hc
*
hc
,
u8
protocol
,
u8
slave_address
,
u8
command
,
u8
*
data
,
u8
length
);
extern
int
acpi_smbus_register_callback
(
struct
acpi_smb_hc
*
hc
,
smbus_alarm_callback
callback
,
void
*
context
);
extern
int
acpi_smbus_unregister_callback
(
struct
acpi_smb_hc
*
hc
);
include/acpi/acpi_bus.h
View file @
e270051d
...
@@ -333,6 +333,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state);
...
@@ -333,6 +333,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state);
int
acpi_bus_set_power
(
acpi_handle
handle
,
int
state
);
int
acpi_bus_set_power
(
acpi_handle
handle
,
int
state
);
#ifdef CONFIG_ACPI_PROC_EVENT
#ifdef CONFIG_ACPI_PROC_EVENT
int
acpi_bus_generate_proc_event
(
struct
acpi_device
*
device
,
u8
type
,
int
data
);
int
acpi_bus_generate_proc_event
(
struct
acpi_device
*
device
,
u8
type
,
int
data
);
int
acpi_bus_generate_proc_event4
(
const
char
*
class
,
const
char
*
bid
,
u8
type
,
int
data
);
int
acpi_bus_receive_event
(
struct
acpi_bus_event
*
event
);
int
acpi_bus_receive_event
(
struct
acpi_bus_event
*
event
);
#else
#else
static
inline
int
acpi_bus_generate_proc_event
(
struct
acpi_device
*
device
,
u8
type
,
int
data
)
static
inline
int
acpi_bus_generate_proc_event
(
struct
acpi_device
*
device
,
u8
type
,
int
data
)
...
...
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