- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / ec.c
blob8bf7c0c687fb4104d8db4780f450927a4ef39e60
1 /*
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>
24 #include <linux/pm.h>
25 #include <linux/acpi.h>
26 #include <linux/delay.h>
27 #include <asm/io.h>
28 #include "acpi.h"
29 #include "driver.h"
31 #define _COMPONENT OS_DEPENDENT
32 MODULE_NAME ("ec")
34 #define ACPI_EC_HID "PNP0C09"
36 enum
38 ACPI_EC_SMI = 0x40,
39 ACPI_EC_SCI = 0x20,
40 ACPI_EC_BURST = 0x10,
41 ACPI_EC_CMD = 0x08,
42 ACPI_EC_IBF = 0x02,
43 ACPI_EC_OBF = 0x01
46 enum
48 ACPI_EC_READ = 0x80,
49 ACPI_EC_WRITE = 0x81,
50 ACPI_EC_BURST_ENABLE = 0x82,
51 ACPI_EC_BURST_DISABLE = 0x83,
52 ACPI_EC_QUERY = 0x84,
55 struct ec_context
57 u32 gpe_bit;
58 ACPI_IO_ADDRESS status_port;
59 ACPI_IO_ADDRESS data_port;
60 u32 need_global_lock;
64 static DECLARE_WAIT_QUEUE_HEAD(acpi_ec_wait);
67 * handle GPE
69 static void
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
81 static void
82 acpi_ec_wait_control(struct ec_context *ec_cxt)
84 udelay(1);
85 while(inb(ec_cxt->status_port) & ACPI_EC_IBF)
86 udelay(10);
90 * read a byte from the EC
92 int
93 acpi_ec_read(struct ec_context *ec_cxt,
94 int addr,
95 int *value)
97 if (!ec_cxt->data_port || !ec_cxt->status_port)
98 return -1;
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();
113 return 0;
117 * write a byte to the EC
120 acpi_ec_write(struct ec_context *ec_cxt,
121 int addr,
122 int value)
124 if (!ec_cxt->data_port || !ec_cxt->status_port)
125 return -1;
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();
141 return 0;
144 static ACPI_STATUS
145 acpi_ec_region_setup (
146 ACPI_HANDLE handle,
147 u32 function,
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)
157 if (*region_context)
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);
171 static ACPI_STATUS
172 acpi_ec_region_handler (u32 function,
173 ACPI_PHYSICAL_ADDRESS address,
174 u32 bitwidth,
175 u32 *value,
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) {
186 *value = 0;
187 acpi_ec_read(ec_cxt, address, value);
188 /*printk("EC read %x from %x\n", *value, address);*/
190 else {
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
201 static ACPI_STATUS
202 acpi_found_ec(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
204 ACPI_STATUS status;
205 ACPI_OBJECT obj;
206 ACPI_BUFFER buf;
207 RESOURCE *res;
208 struct ec_context *ec_cxt;
210 buf.length = 0;
211 buf.pointer = NULL;
212 if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW)
213 return AE_OK;
215 buf.pointer = kmalloc(buf.length, GFP_KERNEL);
216 if (!buf.pointer)
217 return AE_NO_MEMORY;
219 if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) {
220 kfree(buf.pointer);
221 return AE_OK;
224 ec_cxt = kmalloc(sizeof(struct ec_context), GFP_KERNEL);
225 if (!ec_cxt) {
226 kfree(buf.pointer);
227 return AE_NO_MEMORY;
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;
235 kfree(buf.pointer);
237 /* determine GPE bit */
238 /* BUG: in acpi 2.0 this could return a package */
239 buf.length = sizeof(obj);
240 buf.pointer = &obj;
241 if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf))
242 || obj.type != ACPI_TYPE_NUMBER)
243 return AE_OK;
245 ec_cxt->gpe_bit = obj.number.value;
247 /* determine if we need the Global Lock when accessing */
248 buf.length = sizeof(obj);
249 buf.pointer = &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"));
256 return AE_OK;
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(
266 ec_cxt->gpe_bit,
267 (ACPI_EVENT_LEVEL_TRIGGERED
268 | ACPI_EVENT_EDGE_TRIGGERED),
269 acpi_ec_gpe,
270 NULL))) {
272 REPORT_ERROR(("Could not install GPE handler for EC.\n"));
273 return AE_OK;
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)));
284 return AE_OK;
288 acpi_ec_init(void)
290 acpi_get_devices(ACPI_EC_HID,
291 acpi_found_ec,
292 NULL,
293 NULL);
295 return 0;
299 acpi_ec_terminate(void)
301 /* TODO */
302 /* walk list of EC's */
303 /* free their context and release resources */
304 return 0;