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
03feb052
Commit
03feb052
authored
Apr 28, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull ec into release branch
parents
fb165969
9fd9f8e8
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
181 additions
and
321 deletions
+181
-321
drivers/acpi/Makefile
drivers/acpi/Makefile
+4
-3
drivers/acpi/ec.c
drivers/acpi/ec.c
+177
-318
No files found.
drivers/acpi/Makefile
View file @
03feb052
...
...
@@ -38,10 +38,11 @@ endif
obj-y
+=
sleep
/
obj-y
+=
bus.o glue.o
obj-y
+=
scan.o
# Keep EC driver first. Initialization of others depend on it.
obj-$(CONFIG_ACPI_EC)
+=
ec.o
obj-$(CONFIG_ACPI_AC)
+=
ac.o
obj-$(CONFIG_ACPI_BATTERY)
+=
battery.o
obj-$(CONFIG_ACPI_BUTTON)
+=
button.o
obj-$(CONFIG_ACPI_EC)
+=
ec.o
obj-$(CONFIG_ACPI_FAN)
+=
fan.o
obj-$(CONFIG_ACPI_DOCK)
+=
dock.o
obj-$(CONFIG_ACPI_BAY)
+=
bay.o
...
...
drivers/acpi/ec.c
View file @
03feb052
/*
*
acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $
)
*
ec.c - ACPI Embedded Controller Driver (v2.0
)
*
* Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
...
...
@@ -91,9 +93,9 @@ 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 */
static
struct
acpi_ec
{
acpi_handle
handle
;
unsigned
long
uid
;
unsigned
long
gpe
;
unsigned
long
command_addr
;
unsigned
long
data_addr
;
...
...
@@ -101,12 +103,8 @@ static struct acpi_ec {
struct
mutex
lock
;
atomic_t
query_pending
;
atomic_t
event_count
;
atomic_t
leaving_burst
;
/* 0 : No, 1 : Yes, 2: abort */
wait_queue_head_t
wait
;
}
*
ec_ecdt
;
/* External interfaces use first EC only, so remember */
static
struct
acpi_device
*
first_ec
;
}
*
boot_ec
,
*
first_ec
;
/* --------------------------------------------------------------------------
Transaction Management
...
...
@@ -173,56 +171,6 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
return
-
ETIME
;
}
#ifdef ACPI_FUTURE_USAGE
/*
* Note: samsung nv5000 doesn't work with ec burst mode.
* http://bugzilla.kernel.org/show_bug.cgi?id=4980
*/
int
acpi_ec_enter_burst_mode
(
struct
acpi_ec
*
ec
)
{
u8
tmp
=
0
;
u8
status
=
0
;
status
=
acpi_ec_read_status
(
ec
);
if
(
status
!=
-
EINVAL
&&
!
(
status
&
ACPI_EC_FLAG_BURST
))
{
status
=
acpi_ec_wait
(
ec
,
ACPI_EC_EVENT_IBF_0
);
if
(
status
)
goto
end
;
acpi_ec_write_cmd
(
ec
,
ACPI_EC_BURST_ENABLE
);
status
=
acpi_ec_wait
(
ec
,
ACPI_EC_EVENT_OBF_1
);
tmp
=
acpi_ec_read_data
(
ec
);
if
(
tmp
!=
0x90
)
{
/* Burst ACK byte */
return
-
EINVAL
;
}
}
atomic_set
(
&
ec
->
leaving_burst
,
0
);
return
0
;
end:
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"EC wait, burst mode"
));
return
-
1
;
}
int
acpi_ec_leave_burst_mode
(
struct
acpi_ec
*
ec
)
{
u8
status
=
0
;
status
=
acpi_ec_read_status
(
ec
);
if
(
status
!=
-
EINVAL
&&
(
status
&
ACPI_EC_FLAG_BURST
))
{
status
=
acpi_ec_wait
(
ec
,
ACPI_EC_EVENT_IBF_0
);
if
(
status
)
goto
end
;
acpi_ec_write_cmd
(
ec
,
ACPI_EC_BURST_DISABLE
);
acpi_ec_wait
(
ec
,
ACPI_EC_EVENT_IBF_0
);
}
atomic_set
(
&
ec
->
leaving_burst
,
1
);
return
0
;
end:
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"EC leave burst mode"
));
return
-
1
;
}
#endif
/* ACPI_FUTURE_USAGE */
static
int
acpi_ec_transaction_unlocked
(
struct
acpi_ec
*
ec
,
u8
command
,
const
u8
*
wdata
,
unsigned
wdata_len
,
u8
*
rdata
,
unsigned
rdata_len
)
...
...
@@ -312,6 +260,21 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
return
status
;
}
/*
* Note: samsung nv5000 doesn't work with ec burst mode.
* http://bugzilla.kernel.org/show_bug.cgi?id=4980
*/
int
acpi_ec_burst_enable
(
struct
acpi_ec
*
ec
)
{
u8
d
;
return
acpi_ec_transaction
(
ec
,
ACPI_EC_BURST_ENABLE
,
NULL
,
0
,
&
d
,
1
);
}
int
acpi_ec_burst_disable
(
struct
acpi_ec
*
ec
)
{
return
acpi_ec_transaction
(
ec
,
ACPI_EC_BURST_DISABLE
,
NULL
,
0
,
NULL
,
0
);
}
static
int
acpi_ec_read
(
struct
acpi_ec
*
ec
,
u8
address
,
u8
*
data
)
{
int
result
;
...
...
@@ -333,18 +296,33 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
/*
* Externally callable EC access functions. For now, assume 1 EC only
*/
int
ec_burst_enable
(
void
)
{
if
(
!
first_ec
)
return
-
ENODEV
;
return
acpi_ec_burst_enable
(
first_ec
);
}
EXPORT_SYMBOL
(
ec_burst_enable
);
int
ec_burst_disable
(
void
)
{
if
(
!
first_ec
)
return
-
ENODEV
;
return
acpi_ec_burst_disable
(
first_ec
);
}
EXPORT_SYMBOL
(
ec_burst_disable
);
int
ec_read
(
u8
addr
,
u8
*
val
)
{
struct
acpi_ec
*
ec
;
int
err
;
u8
temp_data
;
if
(
!
first_ec
)
return
-
ENODEV
;
ec
=
acpi_driver_data
(
first_ec
);
err
=
acpi_ec_read
(
ec
,
addr
,
&
temp_data
);
err
=
acpi_ec_read
(
first_ec
,
addr
,
&
temp_data
);
if
(
!
err
)
{
*
val
=
temp_data
;
...
...
@@ -357,15 +335,12 @@ EXPORT_SYMBOL(ec_read);
int
ec_write
(
u8
addr
,
u8
val
)
{
struct
acpi_ec
*
ec
;
int
err
;
if
(
!
first_ec
)
return
-
ENODEV
;
ec
=
acpi_driver_data
(
first_ec
);
err
=
acpi_ec_write
(
ec
,
addr
,
val
);
err
=
acpi_ec_write
(
first_ec
,
addr
,
val
);
return
err
;
}
...
...
@@ -376,14 +351,10 @@ int ec_transaction(u8 command,
const
u8
*
wdata
,
unsigned
wdata_len
,
u8
*
rdata
,
unsigned
rdata_len
)
{
struct
acpi_ec
*
ec
;
if
(
!
first_ec
)
return
-
ENODEV
;
ec
=
acpi_driver_data
(
first_ec
);
return
acpi_ec_transaction
(
ec
,
command
,
wdata
,
return
acpi_ec_transaction
(
first_ec
,
command
,
wdata
,
wdata_len
,
rdata
,
rdata_len
);
}
...
...
@@ -420,7 +391,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
static
void
acpi_ec_gpe_query
(
void
*
ec_cxt
)
{
struct
acpi_ec
*
ec
=
(
struct
acpi_ec
*
)
ec_cxt
;
struct
acpi_ec
*
ec
=
ec_cxt
;
u8
value
=
0
;
char
object_name
[
8
];
...
...
@@ -438,8 +409,9 @@ static u32 acpi_ec_gpe_handler(void *data)
{
acpi_status
status
=
AE_OK
;
u8
value
;
struct
acpi_ec
*
ec
=
(
struct
acpi_ec
*
)
data
;
struct
acpi_ec
*
ec
=
data
;
atomic_inc
(
&
ec
->
event_count
);
if
(
acpi_ec_mode
==
EC_INTR
)
{
wake_up
(
&
ec
->
wait
);
}
...
...
@@ -482,7 +454,7 @@ acpi_ec_space_handler(u32 function,
void
*
handler_context
,
void
*
region_context
)
{
int
result
=
0
;
struct
acpi_ec
*
ec
=
NULL
;
struct
acpi_ec
*
ec
=
handler_context
;
u64
temp
=
*
value
;
acpi_integer
f_v
=
0
;
int
i
=
0
;
...
...
@@ -494,8 +466,6 @@ acpi_ec_space_handler(u32 function,
return
AE_BAD_PARAMETER
;
}
ec
=
(
struct
acpi_ec
*
)
handler_context
;
next_byte:
switch
(
function
)
{
case
ACPI_READ
:
...
...
@@ -551,18 +521,16 @@ static struct proc_dir_entry *acpi_ec_dir;
static
int
acpi_ec_read_info
(
struct
seq_file
*
seq
,
void
*
offset
)
{
struct
acpi_ec
*
ec
=
(
struct
acpi_ec
*
)
seq
->
private
;
struct
acpi_ec
*
ec
=
seq
->
private
;
if
(
!
ec
)
goto
end
;
seq_printf
(
seq
,
"gpe:
0x%02x
\n
"
,
(
u32
)
ec
->
gpe
);
seq_printf
(
seq
,
"ports:
0x%02x, 0x%02x
\n
"
,
(
u
32
)
ec
->
command_addr
,
(
u32
)
ec
->
data_addr
);
seq_printf
(
seq
,
"use global lock:
%s
\n
"
,
seq_printf
(
seq
,
"gpe:
\t\t\t
0x%02x
\n
"
,
(
u32
)
ec
->
gpe
);
seq_printf
(
seq
,
"ports:
\t\t\t
0x%02x, 0x%02x
\n
"
,
(
u
nsigned
)
ec
->
command_addr
,
(
unsigned
)
ec
->
data_addr
);
seq_printf
(
seq
,
"use global lock:
\t
%s
\n
"
,
ec
->
global_lock
?
"yes"
:
"no"
);
acpi_enable_gpe
(
NULL
,
ec
->
gpe
,
ACPI_NOT_ISR
);
end:
return
0
;
}
...
...
@@ -619,154 +587,122 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
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
);
if
(
!
ec
)
return
NULL
;
atomic_set
(
&
ec
->
query_pending
,
1
);
atomic_set
(
&
ec
->
event_count
,
1
);
mutex_init
(
&
ec
->
lock
);
init_waitqueue_head
(
&
ec
->
wait
);
return
ec
;
}
static
int
acpi_ec_add
(
struct
acpi_device
*
device
)
{
int
result
=
0
;
acpi_status
status
=
AE_OK
;
struct
acpi_ec
*
ec
=
NULL
;
if
(
!
device
)
return
-
EINVAL
;
ec
=
kzalloc
(
sizeof
(
struct
acpi_ec
),
GFP_KERNEL
);
if
(
!
ec
)
return
-
ENOMEM
;
ec
->
handle
=
device
->
handle
;
ec
->
uid
=
-
1
;
mutex_init
(
&
ec
->
lock
);
atomic_set
(
&
ec
->
query_pending
,
0
);
atomic_set
(
&
ec
->
event_count
,
1
);
if
(
acpi_ec_mode
==
EC_INTR
)
{
atomic_set
(
&
ec
->
leaving_burst
,
1
);
init_waitqueue_head
(
&
ec
->
wait
);
}
strcpy
(
acpi_device_name
(
device
),
ACPI_EC_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_EC_CLASS
);
acpi_driver_data
(
device
)
=
ec
;
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer
(
ec
->
handle
,
"_GLK"
,
NULL
,
&
ec
->
global_lock
);
/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
if
(
ec_ecdt
)
{
acpi_remove_address_space_handler
(
ACPI_ROOT_OBJECT
,
ACPI_ADR_SPACE_EC
,
&
acpi_ec_space_handler
);
acpi_remove_gpe_handler
(
NULL
,
ec_ecdt
->
gpe
,
&
acpi_ec_gpe_handler
);
ec
=
make_acpi_ec
();
if
(
!
ec
)
return
-
ENOMEM
;
kfree
(
ec_ecdt
);
status
=
ec_parse_device
(
device
->
handle
,
0
,
ec
,
NULL
);
if
(
status
!=
AE_CTRL_TERMINATE
)
{
kfree
(
ec
);
return
-
EINVAL
;
}
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status
=
acpi_evaluate_integer
(
ec
->
handle
,
"_GPE"
,
NULL
,
&
ec
->
gpe
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Obtaining GPE bit assignment"
));
result
=
-
ENODEV
;
goto
end
;
/* Check if we found the boot EC */
if
(
boot_ec
)
{
if
(
boot_ec
->
gpe
==
ec
->
gpe
)
{
/* We might have incorrect info for GL at boot time */
mutex_lock
(
&
boot_ec
->
lock
);
boot_ec
->
global_lock
=
ec
->
global_lock
;
mutex_unlock
(
&
boot_ec
->
lock
);
kfree
(
ec
);
ec
=
boot_ec
;
}
}
else
first_ec
=
ec
;
ec
->
handle
=
device
->
handle
;
acpi_driver_data
(
device
)
=
ec
;
result
=
acpi_ec_add_fs
(
device
);
if
(
result
)
goto
end
;
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
));
if
(
!
first_ec
)
first_ec
=
device
;
end:
if
(
result
)
kfree
(
ec
);
return
result
;
return
0
;
}
static
int
acpi_ec_remove
(
struct
acpi_device
*
device
,
int
type
)
{
struct
acpi_ec
*
ec
=
NULL
;
struct
acpi_ec
*
ec
;
if
(
!
device
)
return
-
EINVAL
;
ec
=
acpi_driver_data
(
device
);
acpi_ec_remove_fs
(
device
);
acpi_driver_data
(
device
)
=
NULL
;
if
(
ec
==
first_ec
)
first_ec
=
NULL
;
/* Don't touch boot EC */
if
(
boot_ec
!=
ec
)
kfree
(
ec
);
return
0
;
}
static
acpi_status
acpi_ec
_io_ports
(
struct
acpi_resource
*
resource
,
void
*
context
)
ec_parse
_io_ports
(
struct
acpi_resource
*
resource
,
void
*
context
)
{
struct
acpi_ec
*
ec
=
(
struct
acpi_ec
*
)
context
;
struct
acpi_ec
*
ec
=
context
;
if
(
resource
->
type
!=
ACPI_RESOURCE_TYPE_IO
)
{
if
(
resource
->
type
!=
ACPI_RESOURCE_TYPE_IO
)
return
AE_OK
;
}
/*
* The first address region returned is the data port, and
* the second address region returned is the status/command
* port.
*/
if
(
ec
->
data_addr
==
0
)
{
if
(
ec
->
data_addr
==
0
)
ec
->
data_addr
=
resource
->
data
.
io
.
minimum
;
}
else
if
(
ec
->
command_addr
==
0
)
{
else
if
(
ec
->
command_addr
==
0
)
ec
->
command_addr
=
resource
->
data
.
io
.
minimum
;
}
else
{
else
return
AE_CTRL_TERMINATE
;
}
return
AE_OK
;
}
static
int
acpi_ec_start
(
struct
acpi_device
*
device
)
static
int
ec_install_handlers
(
struct
acpi_ec
*
ec
)
{
acpi_status
status
=
AE_OK
;
struct
acpi_ec
*
ec
=
NULL
;
if
(
!
device
)
return
-
EINVAL
;
ec
=
acpi_driver_data
(
device
);
if
(
!
ec
)
return
-
EINVAL
;
/*
* Get I/O port addresses. Convert to GAS format.
*/
status
=
acpi_walk_resources
(
ec
->
handle
,
METHOD_NAME__CRS
,
acpi_ec_io_ports
,
ec
);
if
(
ACPI_FAILURE
(
status
)
||
ec
->
command_addr
==
0
)
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Error getting I/O port addresses"
));
return
-
ENODEV
;
}
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"gpe=0x%02lx, ports=0x%2lx,0x%2lx"
,
ec
->
gpe
,
ec
->
command_addr
,
ec
->
data_addr
));
/*
* Install GPE handler
*/
acpi_status
status
;
status
=
acpi_install_gpe_handler
(
NULL
,
ec
->
gpe
,
ACPI_GPE_EDGE_TRIGGERED
,
&
acpi_ec_gpe_handler
,
ec
);
if
(
ACPI_FAILURE
(
status
))
{
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
}
acpi_set_gpe_type
(
NULL
,
ec
->
gpe
,
ACPI_GPE_TYPE_RUNTIME
);
acpi_enable_gpe
(
NULL
,
ec
->
gpe
,
ACPI_NOT_ISR
);
...
...
@@ -779,18 +715,49 @@ static int acpi_ec_start(struct acpi_device *device)
return
-
ENODEV
;
}
return
AE_OK
;
/* 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
;
if
(
!
device
)
return
-
EINVAL
;
ec
=
acpi_driver_data
(
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
;
return
ec_install_handlers
(
ec
);
}
static
int
acpi_ec_stop
(
struct
acpi_device
*
device
,
int
type
)
{
acpi_status
status
=
AE_OK
;
struct
acpi_ec
*
ec
=
NULL
;
acpi_status
status
;
struct
acpi_ec
*
ec
;
if
(
!
device
)
return
-
EINVAL
;
ec
=
acpi_driver_data
(
device
);
if
(
!
ec
)
return
-
EINVAL
;
/* Don't touch boot EC */
if
(
ec
==
boot_ec
)
return
0
;
status
=
acpi_remove_address_space_handler
(
ec
->
handle
,
ACPI_ADR_SPACE_EC
,
...
...
@@ -805,164 +772,67 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
return
0
;
}
static
acpi_status
__init
acpi_fake_ecdt_callback
(
acpi_handle
handle
,
u32
Level
,
void
*
context
,
void
**
retval
)
static
acpi_status
ec_parse_device
(
acpi_handle
handle
,
u32
Level
,
void
*
context
,
void
**
retval
)
{
acpi_status
status
;
mutex_init
(
&
ec_ecdt
->
lock
);
atomic_set
(
&
ec_ecdt
->
event_count
,
1
);
if
(
acpi_ec_mode
==
EC_INTR
)
{
init_waitqueue_head
(
&
ec_ecdt
->
wait
);
}
struct
acpi_ec
*
ec
=
context
;
status
=
acpi_walk_resources
(
handle
,
METHOD_NAME__CRS
,
acpi_ec_io_ports
,
ec_ecdt
);
ec_parse_io_ports
,
ec
);
if
(
ACPI_FAILURE
(
status
))
return
status
;
ec_ecdt
->
uid
=
-
1
;
acpi_evaluate_integer
(
handle
,
"_UID"
,
NULL
,
&
ec_ecdt
->
uid
);
status
=
acpi_evaluate_integer
(
handle
,
"_GPE"
,
NULL
,
&
ec_ecdt
->
gpe
);
/* 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
;
ec_ecdt
->
global_lock
=
TRUE
;
ec_ecdt
->
handle
=
handle
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"GPE=0x%02lx, ports=0x%2lx, 0x%2lx"
,
ec_ecdt
->
gpe
,
ec_ecdt
->
command_addr
,
ec_ecdt
->
data_addr
));
return
AE_CTRL_TERMINATE
;
}
/*
* Some BIOS (such as some from Gateway laptops) access EC region very early
* such as in BAT0._INI or EC._INI before an EC device is found and
* do not provide an ECDT. According to ACPI spec, ECDT isn't mandatorily
* required, but if EC regison is accessed early, it is required.
* The routine tries to workaround the BIOS bug by pre-scan EC device
* It assumes that _CRS, _HID, _GPE, _UID methods of EC don't touch any
* op region (since _REG isn't invoked yet). The assumption is true for
* all systems found.
*/
static
int
__init
acpi_ec_fake_ecdt
(
void
)
{
acpi_status
status
;
int
ret
=
0
;
/* Use the global lock for all EC transactions? */
acpi_evaluate_integer
(
handle
,
"_GLK"
,
NULL
,
&
ec
->
global_lock
);
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Try to make an fake ECDT"
))
;
ec
->
handle
=
handle
;
ec_ecdt
=
kzalloc
(
sizeof
(
struct
acpi_ec
),
GFP_KERNEL
);
if
(
!
ec_ecdt
)
{
ret
=
-
ENOMEM
;
goto
error
;
}
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"GPE=0x%02lx, ports=0x%2lx, 0x%2lx"
,
ec
->
gpe
,
ec
->
command_addr
,
ec
->
data_addr
));
status
=
acpi_get_devices
(
ACPI_EC_HID
,
acpi_fake_ecdt_callback
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
kfree
(
ec_ecdt
);
ec_ecdt
=
NULL
;
ret
=
-
ENODEV
;
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Can't make an fake ECDT"
));
goto
error
;
}
return
0
;
error:
return
ret
;
return
AE_CTRL_TERMINATE
;
}
static
int
__init
acpi_ec_get_real_ecdt
(
void
)
int
__init
acpi_ec_ecdt_probe
(
void
)
{
int
ret
;
acpi_status
status
;
struct
acpi_table_ecdt
*
ecdt_ptr
;
status
=
acpi_get_table
(
ACPI_SIG_ECDT
,
1
,
(
struct
acpi_table_header
**
)
&
ecdt_ptr
);
if
(
ACPI_FAILURE
(
status
))
return
-
ENODEV
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Found ECDT"
));
boot_ec
=
make_acpi_ec
();
if
(
!
boot_ec
)
return
-
ENOMEM
;
/*
* Generate a
temporary ec context to use until the namespace is scanned
* Generate a
boot ec context
*/
ec_ecdt
=
kzalloc
(
sizeof
(
struct
acpi_ec
),
GFP_KERNEL
);
if
(
!
ec_ecdt
)
return
-
ENOMEM
;
mutex_init
(
&
ec_ecdt
->
lock
);
atomic_set
(
&
ec_ecdt
->
event_count
,
1
);
if
(
acpi_ec_mode
==
EC_INTR
)
{
init_waitqueue_head
(
&
ec_ecdt
->
wait
);
}
ec_ecdt
->
command_addr
=
ecdt_ptr
->
control
.
address
;
ec_ecdt
->
data_addr
=
ecdt_ptr
->
data
.
address
;
ec_ecdt
->
gpe
=
ecdt_ptr
->
gpe
;
/* use the GL just to be safe */
ec_ecdt
->
global_lock
=
TRUE
;
ec_ecdt
->
uid
=
ecdt_ptr
->
uid
;
status
=
acpi_get_handle
(
NULL
,
ecdt_ptr
->
id
,
&
ec_ecdt
->
handle
);
if
(
ACPI_FAILURE
(
status
))
{
status
=
acpi_get_table
(
ACPI_SIG_ECDT
,
1
,
(
struct
acpi_table_header
**
)
&
ecdt_ptr
);
if
(
ACPI_FAILURE
(
status
))
goto
error
;
}
return
0
;
error:
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Could not use ECDT"
));
kfree
(
ec_ecdt
);
ec_ecdt
=
NULL
;
return
-
ENODEV
;
}
static
int
__initdata
acpi_fake_ecdt_enabled
;
int
__init
acpi_ec_ecdt_probe
(
void
)
{
acpi_status
status
;
int
ret
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Found ECDT"
));
ret
=
acpi_ec_get_real_ecdt
();
/* Try to make a fake ECDT */
if
(
ret
&&
acpi_fake_ecdt_enabled
)
{
ret
=
acpi_ec_fake_ecdt
();
}
boot_ec
->
command_addr
=
ecdt_ptr
->
control
.
address
;
boot_ec
->
data_addr
=
ecdt_ptr
->
data
.
address
;
boot_ec
->
gpe
=
ecdt_ptr
->
gpe
;
boot_ec
->
handle
=
ACPI_ROOT_OBJECT
;
if
(
ret
)
ret
=
ec_install_handlers
(
boot_ec
);
if
(
!
ret
)
{
first_ec
=
boot_ec
;
return
0
;
/*
* Install GPE handler
*/
status
=
acpi_install_gpe_handler
(
NULL
,
ec_ecdt
->
gpe
,
ACPI_GPE_EDGE_TRIGGERED
,
&
acpi_ec_gpe_handler
,
ec_ecdt
);
if
(
ACPI_FAILURE
(
status
))
{
goto
error
;
}
acpi_set_gpe_type
(
NULL
,
ec_ecdt
->
gpe
,
ACPI_GPE_TYPE_RUNTIME
);
acpi_enable_gpe
(
NULL
,
ec_ecdt
->
gpe
,
ACPI_NOT_ISR
);
status
=
acpi_install_address_space_handler
(
ACPI_ROOT_OBJECT
,
ACPI_ADR_SPACE_EC
,
&
acpi_ec_space_handler
,
&
acpi_ec_space_setup
,
ec_ecdt
);
if
(
ACPI_FAILURE
(
status
))
{
acpi_remove_gpe_handler
(
NULL
,
ec_ecdt
->
gpe
,
&
acpi_ec_gpe_handler
);
goto
error
;
}
return
0
;
error:
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"Could not use ECDT"
));
kfree
(
ec_ecdt
);
ec_ecdt
=
NULL
;
kfree
(
boot_ec
);
boot_ec
=
NULL
;
return
-
ENODEV
;
}
...
...
@@ -1003,13 +873,6 @@ static void __exit acpi_ec_exit(void)
}
#endif /* 0 */
static
int
__init
acpi_fake_ecdt_setup
(
char
*
str
)
{
acpi_fake_ecdt_enabled
=
1
;
return
1
;
}
__setup
(
"acpi_fake_ecdt"
,
acpi_fake_ecdt_setup
);
static
int
__init
acpi_ec_set_intr_mode
(
char
*
str
)
{
int
intr
;
...
...
@@ -1017,12 +880,8 @@ static int __init acpi_ec_set_intr_mode(char *str)
if
(
!
get_option
(
&
str
,
&
intr
))
return
0
;
if
(
intr
)
{
acpi_ec_mode
=
EC_INTR
;
}
else
{
acpi_ec_mode
=
EC_POLL
;
}
acpi_ec_driver
.
ops
.
add
=
acpi_ec_add
;
acpi_ec_mode
=
(
intr
)
?
EC_INTR
:
EC_POLL
;
printk
(
KERN_NOTICE
PREFIX
"%s mode.
\n
"
,
intr
?
"interrupt"
:
"polling"
);
return
1
;
...
...
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