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
2e856220
Commit
2e856220
authored
Jul 22, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull ec into release branch
parents
b43035a5
837012ed
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
149 additions
and
104 deletions
+149
-104
MAINTAINERS
MAINTAINERS
+3
-3
drivers/acpi/ec.c
drivers/acpi/ec.c
+146
-101
No files found.
MAINTAINERS
View file @
2e856220
...
...
@@ -225,15 +225,15 @@ T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
S: Supported
ACPI BATTERY DRIVERS
P:
Vladimir P. Lebedev
M:
vladimir.p.lebedev@intel.com
P:
Alexey Starikovskiy
M:
astarikovskiy@suse.de
L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
ACPI EC DRIVER
P: Alexey Starikovskiy
M: a
lexey.y.starikovskiy@linux.intel.com
M: a
starikovskiy@suse.de
L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
...
...
drivers/acpi/ec.c
View file @
2e856220
...
...
@@ -34,25 +34,26 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/actypes.h>
#define _COMPONENT ACPI_EC_COMPONENT
ACPI_MODULE_NAME
(
"ec"
);
#define ACPI_EC_COMPONENT 0x00100000
#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_HID "PNP0C09"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
#undef PREFIX
#define PREFIX "ACPI: EC: "
/* EC status register */
#define ACPI_EC_FLAG_OBF 0x01
/* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02
/* Input buffer full */
#define ACPI_EC_FLAG_BURST 0x10
/* burst mode */
#define ACPI_EC_FLAG_SCI 0x20
/* EC-SCI occurred */
/* EC commands */
enum
ec_command
{
ACPI_EC_COMMAND_READ
=
0x80
,
...
...
@@ -61,6 +62,7 @@ enum ec_command {
ACPI_EC_BURST_DISABLE
=
0x83
,
ACPI_EC_COMMAND_QUERY
=
0x84
,
};
/* EC events */
enum
ec_event
{
ACPI_EC_EVENT_OBF_1
=
1
,
/* Output buffer full */
...
...
@@ -94,6 +96,16 @@ static struct acpi_driver acpi_ec_driver = {
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
/* External interfaces use first EC only, so remember */
typedef
int
(
*
acpi_ec_query_func
)
(
void
*
data
);
struct
acpi_ec_query_handler
{
struct
list_head
node
;
acpi_ec_query_func
func
;
acpi_handle
handle
;
void
*
data
;
u8
query_bit
;
};
static
struct
acpi_ec
{
acpi_handle
handle
;
unsigned
long
gpe
;
...
...
@@ -104,6 +116,7 @@ static struct acpi_ec {
atomic_t
query_pending
;
atomic_t
event_count
;
wait_queue_head_t
wait
;
struct
list_head
list
;
}
*
boot_ec
,
*
first_ec
;
/* --------------------------------------------------------------------------
...
...
@@ -245,7 +258,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
status
=
acpi_ec_wait
(
ec
,
ACPI_EC_EVENT_IBF_0
,
0
,
0
);
if
(
status
)
{
printk
(
KERN_
DEBUG
PREFIX
printk
(
KERN_
ERR
PREFIX
"input buffer is not empty, aborting transaction
\n
"
);
goto
end
;
}
...
...
@@ -394,21 +407,67 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
/* --------------------------------------------------------------------------
Event Management
-------------------------------------------------------------------------- */
int
acpi_ec_add_query_handler
(
struct
acpi_ec
*
ec
,
u8
query_bit
,
acpi_handle
handle
,
acpi_ec_query_func
func
,
void
*
data
)
{
struct
acpi_ec_query_handler
*
handler
=
kzalloc
(
sizeof
(
struct
acpi_ec_query_handler
),
GFP_KERNEL
);
if
(
!
handler
)
return
-
ENOMEM
;
handler
->
query_bit
=
query_bit
;
handler
->
handle
=
handle
;
handler
->
func
=
func
;
handler
->
data
=
data
;
mutex_lock
(
&
ec
->
lock
);
list_add_tail
(
&
handler
->
node
,
&
ec
->
list
);
mutex_unlock
(
&
ec
->
lock
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
acpi_ec_add_query_handler
);
void
acpi_ec_remove_query_handler
(
struct
acpi_ec
*
ec
,
u8
query_bit
)
{
struct
acpi_ec_query_handler
*
handler
;
mutex_lock
(
&
ec
->
lock
);
list_for_each_entry
(
handler
,
&
ec
->
list
,
node
)
{
if
(
query_bit
==
handler
->
query_bit
)
{
list_del
(
&
handler
->
node
);
kfree
(
handler
);
break
;
}
}
mutex_unlock
(
&
ec
->
lock
);
}
EXPORT_SYMBOL_GPL
(
acpi_ec_remove_query_handler
);
static
void
acpi_ec_gpe_query
(
void
*
ec_cxt
)
{
struct
acpi_ec
*
ec
=
ec_cxt
;
u8
value
=
0
;
char
object_name
[
8
]
;
struct
acpi_ec_query_handler
*
handler
,
copy
;
if
(
!
ec
||
acpi_ec_query
(
ec
,
&
value
))
return
;
snprintf
(
object_name
,
8
,
"_Q%2.2X"
,
value
);
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Evaluating %s"
,
object_name
));
acpi_evaluate_object
(
ec
->
handle
,
object_name
,
NULL
,
NULL
);
mutex_lock
(
&
ec
->
lock
);
list_for_each_entry
(
handler
,
&
ec
->
list
,
node
)
{
if
(
value
==
handler
->
query_bit
)
{
/* have custom handler for this bit */
memcpy
(
&
copy
,
handler
,
sizeof
(
copy
));
mutex_unlock
(
&
ec
->
lock
);
if
(
copy
.
func
)
{
copy
.
func
(
copy
.
data
);
}
else
if
(
copy
.
handle
)
{
acpi_evaluate_object
(
copy
.
handle
,
NULL
,
NULL
,
NULL
);
}
return
;
}
}
mutex_unlock
(
&
ec
->
lock
);
printk
(
KERN_ERR
PREFIX
"Handler for query 0x%x is not found!
\n
"
,
value
);
}
static
u32
acpi_ec_gpe_handler
(
void
*
data
)
...
...
@@ -427,8 +486,7 @@ static u32 acpi_ec_gpe_handler(void *data)
if
((
value
&
ACPI_EC_FLAG_SCI
)
&&
!
atomic_read
(
&
ec
->
query_pending
))
{
atomic_set
(
&
ec
->
query_pending
,
1
);
status
=
acpi_os_execute
(
OSL_EC_BURST_HANDLER
,
acpi_ec_gpe_query
,
ec
);
acpi_os_execute
(
OSL_EC_BURST_HANDLER
,
acpi_ec_gpe_query
,
ec
);
}
return
status
==
AE_OK
?
...
...
@@ -454,57 +512,35 @@ acpi_ec_space_setup(acpi_handle region_handle,
}
static
acpi_status
acpi_ec_space_handler
(
u32
function
,
acpi_physical_address
address
,
u32
bit_width
,
acpi_integer
*
value
,
acpi_ec_space_handler
(
u32
function
,
acpi_physical_address
address
,
u32
bits
,
acpi_integer
*
value
,
void
*
handler_context
,
void
*
region_context
)
{
int
result
=
0
;
struct
acpi_ec
*
ec
=
handler_context
;
u64
temp
=
*
value
;
acpi_integer
f_v
=
0
;
int
i
=
0
;
int
result
=
0
,
i
=
0
;
u8
temp
=
0
;
if
((
address
>
0xFF
)
||
!
value
||
!
handler_context
)
return
AE_BAD_PARAMETER
;
if
(
bit_width
!=
8
&&
acpi_strict
)
{
if
(
function
!=
ACPI_READ
&&
function
!=
ACPI_WRITE
)
return
AE_BAD_PARAMETER
;
}
next_byte:
switch
(
function
)
{
case
ACPI_READ
:
temp
=
0
;
result
=
acpi_ec_read
(
ec
,
(
u8
)
address
,
(
u8
*
)
&
temp
);
break
;
case
ACPI_WRITE
:
result
=
acpi_ec_write
(
ec
,
(
u8
)
address
,
(
u8
)
temp
);
break
;
default:
result
=
-
EINVAL
;
goto
out
;
break
;
}
bit_width
-=
8
;
if
(
bit_width
)
{
if
(
function
==
ACPI_READ
)
f_v
|=
temp
<<
8
*
i
;
if
(
function
==
ACPI_WRITE
)
temp
>>=
8
;
i
++
;
address
++
;
goto
next_byte
;
}
if
(
bits
!=
8
&&
acpi_strict
)
return
AE_BAD_PARAMETER
;
if
(
function
==
ACPI_READ
)
{
f_v
|=
temp
<<
8
*
i
;
*
value
=
f_v
;
while
(
bits
-
i
>
0
)
{
if
(
function
==
ACPI_READ
)
{
result
=
acpi_ec_read
(
ec
,
address
,
&
temp
);
(
*
value
)
|=
((
acpi_integer
)
temp
)
<<
i
;
}
else
{
temp
=
0xff
&
((
*
value
)
>>
i
);
result
=
acpi_ec_write
(
ec
,
address
,
temp
);
}
i
+=
8
;
++
address
;
}
out:
switch
(
result
)
{
case
-
EINVAL
:
return
AE_BAD_PARAMETER
;
...
...
@@ -597,9 +633,6 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
static
acpi_status
ec_parse_io_ports
(
struct
acpi_resource
*
resource
,
void
*
context
);
static
acpi_status
ec_parse_device
(
acpi_handle
handle
,
u32
Level
,
void
*
context
,
void
**
retval
);
static
struct
acpi_ec
*
make_acpi_ec
(
void
)
{
struct
acpi_ec
*
ec
=
kzalloc
(
sizeof
(
struct
acpi_ec
),
GFP_KERNEL
);
...
...
@@ -610,13 +643,52 @@ static struct acpi_ec *make_acpi_ec(void)
atomic_set
(
&
ec
->
event_count
,
1
);
mutex_init
(
&
ec
->
lock
);
init_waitqueue_head
(
&
ec
->
wait
);
INIT_LIST_HEAD
(
&
ec
->
list
);
return
ec
;
}
static
acpi_status
acpi_ec_register_query_methods
(
acpi_handle
handle
,
u32
level
,
void
*
context
,
void
**
return_value
)
{
struct
acpi_namespace_node
*
node
=
handle
;
struct
acpi_ec
*
ec
=
context
;
int
value
=
0
;
if
(
sscanf
(
node
->
name
.
ascii
,
"_Q%x"
,
&
value
)
==
1
)
{
acpi_ec_add_query_handler
(
ec
,
value
,
handle
,
NULL
,
NULL
);
}
return
AE_OK
;
}
static
int
ec_parse_device
(
struct
acpi_ec
*
ec
,
acpi_handle
handle
)
{
if
(
ACPI_FAILURE
(
acpi_walk_resources
(
handle
,
METHOD_NAME__CRS
,
ec_parse_io_ports
,
ec
)))
return
-
EINVAL
;
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
if
(
ACPI_FAILURE
(
acpi_evaluate_integer
(
handle
,
"_GPE"
,
NULL
,
&
ec
->
gpe
)))
return
-
EINVAL
;
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer
(
handle
,
"_GLK"
,
NULL
,
&
ec
->
global_lock
);
/* Find and register all query methods */
acpi_walk_namespace
(
ACPI_TYPE_METHOD
,
handle
,
1
,
acpi_ec_register_query_methods
,
ec
,
NULL
);
ec
->
handle
=
handle
;
printk
(
KERN_INFO
PREFIX
"GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx"
,
ec
->
gpe
,
ec
->
command_addr
,
ec
->
data_addr
);
return
0
;
}
static
int
acpi_ec_add
(
struct
acpi_device
*
device
)
{
acpi_status
status
=
AE_OK
;
struct
acpi_ec
*
ec
=
NULL
;
if
(
!
device
)
...
...
@@ -629,8 +701,7 @@ static int acpi_ec_add(struct acpi_device *device)
if
(
!
ec
)
return
-
ENOMEM
;
status
=
ec_parse_device
(
device
->
handle
,
0
,
ec
,
NULL
);
if
(
status
!=
AE_CTRL_TERMINATE
)
{
if
(
ec_parse_device
(
ec
,
device
->
handle
))
{
kfree
(
ec
);
return
-
EINVAL
;
}
...
...
@@ -641,6 +712,8 @@ static int acpi_ec_add(struct acpi_device *device)
/* We might have incorrect info for GL at boot time */
mutex_lock
(
&
boot_ec
->
lock
);
boot_ec
->
global_lock
=
ec
->
global_lock
;
/* Copy handlers from new ec into boot ec */
list_splice
(
&
ec
->
list
,
&
boot_ec
->
list
);
mutex_unlock
(
&
boot_ec
->
lock
);
kfree
(
ec
);
ec
=
boot_ec
;
...
...
@@ -651,22 +724,24 @@ static int acpi_ec_add(struct acpi_device *device)
acpi_driver_data
(
device
)
=
ec
;
acpi_ec_add_fs
(
device
);
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"%s [%s] (gpe %d) interrupt mode."
,
acpi_device_name
(
device
),
acpi_device_bid
(
device
),
(
u32
)
ec
->
gpe
));
return
0
;
}
static
int
acpi_ec_remove
(
struct
acpi_device
*
device
,
int
type
)
{
struct
acpi_ec
*
ec
;
struct
acpi_ec_query_handler
*
handler
;
if
(
!
device
)
return
-
EINVAL
;
ec
=
acpi_driver_data
(
device
);
mutex_lock
(
&
ec
->
lock
);
list_for_each_entry
(
handler
,
&
ec
->
list
,
node
)
{
list_del
(
&
handler
->
node
);
kfree
(
handler
);
}
mutex_unlock
(
&
ec
->
lock
);
acpi_ec_remove_fs
(
device
);
acpi_driver_data
(
device
)
=
NULL
;
if
(
ec
==
first_ec
)
...
...
@@ -722,15 +797,13 @@ static int ec_install_handlers(struct acpi_ec *ec)
return
-
ENODEV
;
}
/* EC is fully operational, allow queries */
atomic_set
(
&
ec
->
query_pending
,
0
);
return
0
;
}
static
int
acpi_ec_start
(
struct
acpi_device
*
device
)
{
struct
acpi_ec
*
ec
;
int
ret
=
0
;
if
(
!
device
)
return
-
EINVAL
;
...
...
@@ -740,14 +813,14 @@ static int acpi_ec_start(struct acpi_device *device)
if
(
!
ec
)
return
-
EINVAL
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"gpe=0x%02lx, ports=0x%2lx,0x%2lx"
,
ec
->
gpe
,
ec
->
command_addr
,
ec
->
data_addr
));
/* Boot EC is already working */
if
(
ec
==
boot_ec
)
return
0
;
if
(
ec
!=
boot_ec
)
ret
=
ec_install_handlers
(
ec
);
/* EC is fully operational, allow queries */
atomic_set
(
&
ec
->
query_pending
,
0
);
return
ec_install_handlers
(
ec
)
;
return
ret
;
}
static
int
acpi_ec_stop
(
struct
acpi_device
*
device
,
int
type
)
...
...
@@ -779,34 +852,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
return
0
;
}
static
acpi_status
ec_parse_device
(
acpi_handle
handle
,
u32
Level
,
void
*
context
,
void
**
retval
)
{
acpi_status
status
;
struct
acpi_ec
*
ec
=
context
;
status
=
acpi_walk_resources
(
handle
,
METHOD_NAME__CRS
,
ec_parse_io_ports
,
ec
);
if
(
ACPI_FAILURE
(
status
))
return
status
;
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status
=
acpi_evaluate_integer
(
handle
,
"_GPE"
,
NULL
,
&
ec
->
gpe
);
if
(
ACPI_FAILURE
(
status
))
return
status
;
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer
(
handle
,
"_GLK"
,
NULL
,
&
ec
->
global_lock
);
ec
->
handle
=
handle
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"GPE=0x%02lx, ports=0x%2lx, 0x%2lx"
,
ec
->
gpe
,
ec
->
command_addr
,
ec
->
data_addr
));
return
AE_CTRL_TERMINATE
;
}
int
__init
acpi_ec_ecdt_probe
(
void
)
{
int
ret
;
...
...
@@ -825,7 +870,7 @@ int __init acpi_ec_ecdt_probe(void)
if
(
ACPI_FAILURE
(
status
))
goto
error
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Found ECDT"
)
);
printk
(
KERN_INFO
PREFIX
"EC description table is found, configuring boot EC
\n
"
);
boot_ec
->
command_addr
=
ecdt_ptr
->
control
.
address
;
boot_ec
->
data_addr
=
ecdt_ptr
->
data
.
address
;
...
...
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