2 * ec.c - Embedded controller support
4 * Copyright (C) 2000 Andrew Henroid
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/slab.h>
25 #include <linux/acpi.h>
26 #include <linux/delay.h>
31 #define _COMPONENT OS_DEPENDENT
34 #define ACPI_EC_HID "PNP0C09"
50 ACPI_EC_BURST_ENABLE
= 0x82,
51 ACPI_EC_BURST_DISABLE
= 0x83,
58 ACPI_IO_ADDRESS status_port
;
59 ACPI_IO_ADDRESS data_port
;
64 static DECLARE_WAIT_QUEUE_HEAD(acpi_ec_wait
);
70 acpi_ec_gpe(void *context
)
72 printk(KERN_INFO
"ACPI: EC GPE\n");
73 /* TODO fix this to use per-device sem */
74 if (waitqueue_active(&acpi_ec_wait
))
75 wake_up_interruptible(&acpi_ec_wait
);
79 * wait for read/write status to clear
82 acpi_ec_wait_control(struct ec_context
*ec_cxt
)
85 while(inb(ec_cxt
->status_port
) & ACPI_EC_IBF
)
90 * read a byte from the EC
93 acpi_ec_read(struct ec_context
*ec_cxt
,
97 if (!ec_cxt
->data_port
|| !ec_cxt
->status_port
)
100 if (ec_cxt
->need_global_lock
)
101 acpi_acquire_global_lock();
103 outb(ACPI_EC_READ
, ec_cxt
->status_port
);
104 acpi_ec_wait_control(ec_cxt
);
105 outb(addr
, ec_cxt
->data_port
);
106 acpi_ec_wait_control(ec_cxt
);
107 /*interruptible_sleep_on(&acpi_ec_wait);*/
108 *value
= inb(ec_cxt
->data_port
);
110 if (ec_cxt
->need_global_lock
)
111 acpi_release_global_lock();
117 * write a byte to the EC
120 acpi_ec_write(struct ec_context
*ec_cxt
,
124 if (!ec_cxt
->data_port
|| !ec_cxt
->status_port
)
127 if (ec_cxt
->need_global_lock
)
128 acpi_acquire_global_lock();
130 outb(ACPI_EC_WRITE
, ec_cxt
->status_port
);
131 acpi_ec_wait_control(ec_cxt
);
132 outb(addr
, ec_cxt
->data_port
);
133 acpi_ec_wait_control(ec_cxt
);
134 outb(value
, ec_cxt
->data_port
);
135 acpi_ec_wait_control(ec_cxt
);
136 /*interruptible_sleep_on(&acpi_ec_wait);*/
138 if (ec_cxt
->need_global_lock
)
139 acpi_release_global_lock();
145 acpi_ec_region_setup (
148 void *handler_context
,
149 void **region_context
)
151 FUNCTION_TRACE("acpi_ec_region_setup");
153 printk("acpi_ec_region_setup\n");
155 if (function
== ACPI_REGION_DEACTIVATE
)
159 acpi_cm_free (*region_context
);
160 *region_context
= NULL
;
163 return_ACPI_STATUS (AE_OK
);
166 *region_context
= NULL
;
168 return_ACPI_STATUS (AE_OK
);
172 acpi_ec_region_handler (u32 function
,
173 ACPI_PHYSICAL_ADDRESS address
,
176 void *handler_context
,
177 void *region_context
)
179 struct ec_context
*ec_cxt
;
181 FUNCTION_TRACE("acpi_ec_region_handler");
183 ec_cxt
= handler_context
;
185 if (function
== ADDRESS_SPACE_READ
) {
187 acpi_ec_read(ec_cxt
, address
, value
);
188 /*printk("EC read %x from %x\n", *value, address);*/
191 acpi_ec_write(ec_cxt
, address
, *value
);
192 /*printk("EC write value %x to %x\n", *value, address);*/
195 return_ACPI_STATUS (AE_OK
);
199 * Get Embedded Controller information
202 acpi_found_ec(ACPI_HANDLE handle
, u32 level
, void *ctx
, void **value
)
208 struct ec_context
*ec_cxt
;
212 if (acpi_get_current_resources(handle
, &buf
) != AE_BUFFER_OVERFLOW
)
215 buf
.pointer
= kmalloc(buf
.length
, GFP_KERNEL
);
219 if (!ACPI_SUCCESS(acpi_get_current_resources(handle
, &buf
))) {
224 ec_cxt
= kmalloc(sizeof(struct ec_context
), GFP_KERNEL
);
230 res
= (RESOURCE
*) buf
.pointer
;
231 ec_cxt
->data_port
= res
->data
.io
.min_base_address
;
232 res
= NEXT_RESOURCE(res
);
233 ec_cxt
->status_port
= (int) res
->data
.io
.min_base_address
;
237 /* determine GPE bit */
238 /* BUG: in acpi 2.0 this could return a package */
239 buf
.length
= sizeof(obj
);
241 if (!ACPI_SUCCESS(acpi_evaluate_object(handle
, "_GPE", NULL
, &buf
))
242 || obj
.type
!= ACPI_TYPE_NUMBER
)
245 ec_cxt
->gpe_bit
= obj
.number
.value
;
247 /* determine if we need the Global Lock when accessing */
248 buf
.length
= sizeof(obj
);
251 status
= acpi_evaluate_object(handle
, "_GLK", NULL
, &buf
);
252 if (status
== AE_NOT_FOUND
)
253 ec_cxt
->need_global_lock
= 0;
254 else if (!ACPI_SUCCESS(status
) || obj
.type
!= ACPI_TYPE_NUMBER
) {
255 DEBUG_PRINT(ACPI_ERROR
, ("_GLK failed\n"));
259 ec_cxt
->need_global_lock
= obj
.number
.value
;
261 printk(KERN_INFO
"ACPI: found EC @ (0x%02x,0x%02x,gpe %d GL %d)\n",
262 ec_cxt
->data_port
, ec_cxt
->status_port
, ec_cxt
->gpe_bit
,
263 ec_cxt
->need_global_lock
);
265 if (!ACPI_SUCCESS(acpi_install_gpe_handler(
267 (ACPI_EVENT_LEVEL_TRIGGERED
268 | ACPI_EVENT_EDGE_TRIGGERED
),
272 REPORT_ERROR(("Could not install GPE handler for EC.\n"));
276 status
= acpi_install_address_space_handler (handle
, ADDRESS_SPACE_EC
,
277 acpi_ec_region_handler
, acpi_ec_region_setup
, ec_cxt
);
279 if (!ACPI_SUCCESS(status
)) {
280 REPORT_ERROR(("Could not install EC address "
281 "space handler, error %s\n", acpi_cm_format_exception (status
)));
290 acpi_get_devices(ACPI_EC_HID
,
299 acpi_ec_terminate(void)
302 /* walk list of EC's */
303 /* free their context and release resources */