~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/acpi/ec.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  ec.c - Embedded controller support
  3  *
  4  *  Copyright (C) 2000 Andrew Henroid
  5  *
  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.
 10  *
 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.
 15  *
 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
 19  */
 20 
 21 #include <linux/kernel.h>
 22 #include <linux/acpi.h>
 23 #include <linux/slab.h>
 24 #include "acpi.h"
 25 #include "driver.h"
 26 #include "ec.h"
 27 
 28 #define _COMPONENT      OS_DEPENDENT
 29         MODULE_NAME     ("ec")
 30 
 31 #define ACPI_EC_HID     "PNP0C09"
 32 
 33 enum
 34 {
 35         ACPI_EC_SMI = 0x40,
 36         ACPI_EC_SCI = 0x20,
 37         ACPI_EC_BURST = 0x10,
 38         ACPI_EC_CMD = 0x08,
 39         ACPI_EC_IBF = 0x02,
 40         ACPI_EC_OBF = 0x01
 41 };
 42 
 43 enum
 44 {
 45         ACPI_EC_READ = 0x80,
 46         ACPI_EC_WRITE = 0x81,
 47         ACPI_EC_BURST_ENABLE = 0x82,
 48         ACPI_EC_BURST_DISABLE = 0x83,
 49         ACPI_EC_QUERY = 0x84,
 50 };
 51 
 52 typedef struct
 53 {
 54         ACPI_HANDLE             acpi_handle;
 55         u32                     gpe_bit;
 56         ACPI_IO_ADDRESS         status_port;
 57         ACPI_IO_ADDRESS         data_port;
 58         u32                     need_global_lock;
 59 } ec_context_t;
 60 
 61 
 62 typedef struct 
 63 {
 64     ec_context_t        *ec;
 65     u8                  data;
 66 
 67 } EC_QUERY_DATA;
 68 
 69 static char object_name[] = {'_', 'Q', '', '', '\0'};
 70 
 71 static char hex[] = {'','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
 72 
 73 
 74 static ACPI_STATUS
 75 ec_io_wait (
 76     ec_context_t              *ec,
 77     EC_EVENT                wait_event)
 78 {
 79     EC_STATUS               ec_status = 0;
 80     UINT32                  i = 100;
 81 
 82     if (!ec || ((wait_event != EC_EVENT_OUTPUT_BUFFER_FULL) 
 83         && (wait_event != EC_EVENT_INPUT_BUFFER_EMPTY)))
 84         return(AE_BAD_PARAMETER);
 85 
 86     /* 
 87      * Wait for Event:
 88      * ---------------
 89      * Poll the EC status register waiting for the event to occur.
 90      * Note that we'll wait a maximum of 1ms in 10us chunks.
 91      */
 92     switch (wait_event) {
 93     case EC_EVENT_OUTPUT_BUFFER_FULL:
 94         do {
 95             ec_status = acpi_os_in8(ec->status_port);
 96             if (ec_status & EC_FLAG_OUTPUT_BUFFER)
 97                 return(AE_OK);
 98             acpi_os_sleep_usec(10);
 99         } while (--i>0);
100         break;
101     case EC_EVENT_INPUT_BUFFER_EMPTY:
102         do {
103             ec_status = acpi_os_in8(ec->status_port);
104             if (!(ec_status & EC_FLAG_INPUT_BUFFER))
105                 return(AE_OK);
106             acpi_os_sleep_usec(10);
107         } while (--i>0);
108         break;
109     }
110 
111     return(AE_TIME);
112 }
113 
114 static ACPI_STATUS
115 ec_io_read (
116     ec_context_t              *ec,
117     ACPI_IO_ADDRESS         io_port,
118     UINT8                   *data,
119     EC_EVENT                wait_event)
120 {
121     ACPI_STATUS             status = AE_OK;
122 
123     if (!ec || !data)
124         return(AE_BAD_PARAMETER);
125 
126     *data = acpi_os_in8(io_port);
127 
128     if (wait_event)
129         status = ec_io_wait(ec, wait_event);
130 
131     return(status);
132 }
133 
134 static ACPI_STATUS
135 ec_io_write (
136     ec_context_t              *ec,
137     ACPI_IO_ADDRESS         io_port,
138     UINT8                   data,
139     EC_EVENT                wait_event)
140 {
141     ACPI_STATUS             status = AE_OK;
142 
143     if (!ec)
144         return(AE_BAD_PARAMETER);
145 
146     acpi_os_out8(io_port, data);
147 
148     if (wait_event)
149         status = ec_io_wait(ec, wait_event);
150 
151     return(status);
152 }
153 
154 static ACPI_STATUS
155 ec_read (
156     ec_context_t              *ec,
157     UINT8                   address,
158     UINT8                   *data)
159 {
160     ACPI_STATUS             status = AE_OK;
161 
162     FUNCTION_TRACE("ec_read");
163 
164     if (!ec || !data)
165         return_ACPI_STATUS(AE_BAD_PARAMETER);
166 
167     status = ec_io_write(ec, ec->status_port, EC_COMMAND_READ, EC_EVENT_INPUT_BUFFER_EMPTY);
168     if (ACPI_FAILURE(status)) {
169         DEBUG_PRINT(ACPI_WARN, ("Unable to send 'read command' to EC.\n"));
170         return_ACPI_STATUS(status);
171     }
172 
173     status = ec_io_write(ec, ec->data_port, address, EC_EVENT_OUTPUT_BUFFER_FULL);
174     if (ACPI_FAILURE(status)) {
175         DEBUG_PRINT(ACPI_WARN, ("Unable to send 'read address' to EC.\n"));
176         return_ACPI_STATUS(status);
177     }
178 
179     status = ec_io_read(ec, ec->data_port, data, EC_EVENT_NONE);
180 
181     DEBUG_PRINT(ACPI_INFO, ("Read data[0x%02x] from address[0x%02x] on ec.\n", (*data), address));
182 
183     return_ACPI_STATUS(status);
184 }
185 
186 static ACPI_STATUS
187 ec_write (
188     ec_context_t              *ec,
189     UINT8                   address,
190     UINT8                   data)
191 {
192     ACPI_STATUS             status = AE_OK;
193 
194     FUNCTION_TRACE("ec_write");
195 
196     if (!ec)
197         return_ACPI_STATUS(AE_BAD_PARAMETER);
198 
199     status = ec_io_write(ec, ec->status_port, EC_COMMAND_WRITE, EC_EVENT_INPUT_BUFFER_EMPTY);
200     if (ACPI_FAILURE(status)) {
201         DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write command' to EC.\n"));
202         return_ACPI_STATUS(status);
203     }
204 
205     status = ec_io_write(ec, ec->data_port, address, EC_EVENT_INPUT_BUFFER_EMPTY);
206     if (ACPI_FAILURE(status)) {
207         DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write address' to EC.\n"));
208         return_ACPI_STATUS(status);
209     }
210 
211     status = ec_io_write(ec, ec->data_port, data, EC_EVENT_INPUT_BUFFER_EMPTY);
212     if (ACPI_FAILURE(status)) {
213         DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write data' to EC.\n"));
214         return_ACPI_STATUS(status);
215     }
216 
217     DEBUG_PRINT(ACPI_INFO, ("Wrote data[0x%02x] to address[0x%02x] on ec.\n", data, address));
218 
219     return_ACPI_STATUS(status);
220 }
221 
222 static ACPI_STATUS
223 ec_transaction (
224     ec_context_t              *ec,
225     EC_REQUEST              *request)
226 {
227     ACPI_STATUS             status = AE_OK;
228 
229     FUNCTION_TRACE("ec_transaction");
230 
231     if (!ec || !request)
232         return_ACPI_STATUS(AE_BAD_PARAMETER);
233 
234     /*
235      * Obtaining semaphore (mutex) to serialize all EC transactions.
236      */
237     /*
238     DEBUG_PRINT(ACPI_INFO, ("Calling acpi_os_wait_semaphore(%p, 1, %d)\n", ec->mutex, EC_DEFAULT_TIMEOUT));
239     status = acpi_os_wait_semaphore(ec->mutex, 1, EC_DEFAULT_TIMEOUT);
240     if (ACPI_FAILURE(status))
241         return_ACPI_STATUS(status);
242     */
243 
244     /*
245      * Perform the transaction.
246      */
247     switch (request->command) {
248 
249     case EC_COMMAND_READ:
250         status = ec_read(ec, request->address, &(request->data));
251         break;
252 
253     case EC_COMMAND_WRITE:
254         status = ec_write(ec, request->address, request->data);
255         break;
256 
257     default:
258         status = AE_SUPPORT;
259         break;
260     }
261 
262     /*
263      * Signal the semaphore (mutex) to indicate transaction completion.
264      */
265     /*
266     DEBUG_PRINT(ACPI_INFO, ("Calling acpi_os_signal_semaphore(%p, 1)\n", ec->mutex));
267     acpi_os_signal_semaphore(ec->mutex, 1);
268     */
269 
270     return_ACPI_STATUS(status);
271 }
272 
273 
274 static void
275 ec_query_handler (
276     void                    *context)
277 {
278     ACPI_STATUS             status = AE_OK;
279     EC_QUERY_DATA           *ec_q = (EC_QUERY_DATA*)context;
280 
281     FUNCTION_TRACE("ec_query_handler");
282 
283     if (!ec_q || !ec_q->ec) {
284         DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) context.\n"));
285         return_VOID;
286     }
287 
288     /*
289      * Evaluate _Qxx:
290      * --------------
291      * Evaluate corresponding _Qxx method.  Note that a zero query
292      * value indicates a spurious EC_SCI (no such thing as _Q00).
293      */
294     object_name[2] = hex[((ec_q->data >> 4) & 0x0F)];
295     object_name[3] = hex[(ec_q->data & 0x0F)];
296 
297     DEBUG_PRINT(ACPI_INFO, ("Read query data[0x%02x] from ec - evaluating [%s].\n", ec_q->data, object_name));
298 
299     status = acpi_evaluate_object(ec_q->ec->acpi_handle, object_name, NULL, NULL);
300 
301     kfree(ec_q);
302 
303     return_VOID;
304 }
305 
306 /*
307  * handle GPE
308  */
309 static void
310 ec_gpe_handler(void *context)
311 {
312     ACPI_STATUS             status = AE_OK;
313     ec_context_t            *ec = (ec_context_t *) context;
314     EC_QUERY_DATA           *ec_q = NULL;
315     EC_STATUS               ec_status = 0;
316 
317     FUNCTION_TRACE("ec_gpe_handler");
318 
319     if (!ec) {
320         DEBUG_PRINT(ACPI_INFO, ("Invalid (NULL) context.\n"));
321         return_VOID;
322     }
323 
324     // GET SPINLOCK!
325 
326     /*
327      * EC_SCI?
328      * -------
329      * Check the EC_SCI bit to see if this is an EC_SCI event.  If not (e.g.
330      * OBF/IBE) just return, as we already poll to detect these events.
331      */
332     ec_status = acpi_os_in8(ec->status_port);
333     DEBUG_PRINT(ACPI_INFO, ("EC Status Register: [0x%02x]\n", ec_status));
334     if (!(ec_status & EC_FLAG_SCI))
335         return_VOID;
336 
337     DEBUG_PRINT(ACPI_INFO, ("EC_SCI detected - running QUERY.\n"));
338 
339     // TODO: Need GFP_ATOMIC 'switch' for OSL interface...
340     ec_q = kmalloc(sizeof(EC_QUERY_DATA), GFP_ATOMIC);
341     if (!ec_q) {
342         DEBUG_PRINT(ACPI_INFO, ("Memory allocation failure.\n"));
343         return_VOID;
344     }
345 
346     ec_q->ec = ec;
347     ec_q->data = 0;
348 
349     /*
350      * Run Query:
351      * ----------
352      * Query the EC to find out which _Qxx method we need to evaluate.
353      * Note that successful completion of the query causes the EC_SCI
354      * bit to be cleared (and thus clearing the interrupt source).
355      */
356     status = ec_io_write(ec, ec->status_port, EC_COMMAND_QUERY, EC_EVENT_OUTPUT_BUFFER_FULL);
357     if (ACPI_FAILURE(status)) {
358         DEBUG_PRINT(ACPI_WARN, ("Unable to send 'query command' to EC.\n"));
359         goto End;
360     }
361 
362     status = ec_io_read(ec, ec->data_port, &(ec_q->data), EC_EVENT_NONE);
363     if (ACPI_FAILURE(status)) {
364         DEBUG_PRINT(ACPI_WARN, ("Error reading query data.\n"));
365         goto End;
366     }
367 
368     // RELEASE SPINLOCK!
369 
370     if (!ec_q->data) {
371         DEBUG_PRINT(ACPI_WARN, ("Spurious EC SCI detected.\n"));
372         status = AE_ERROR;
373         goto End;
374     }
375 
376     /*
377      * Defer _Qxx Execution:
378      * ---------------------
379      * Can't evaluate this method now 'cause we're at interrupt-level.
380      */
381     status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, ec_query_handler, ec_q);
382     if (ACPI_FAILURE(status)) {
383         DEBUG_PRINT(ACPI_ERROR, ("Unable to defer _Qxx method evaluation.\n"));
384         goto End;
385     }
386 
387 End:
388     if (ACPI_FAILURE(status))
389         kfree(ec_q);
390     
391     return_VOID;
392 }
393 
394 static ACPI_STATUS
395 ec_region_setup (
396     ACPI_HANDLE handle,
397     u32 function,
398     void *handler_context,
399     void **region_context)
400 {
401         FUNCTION_TRACE("acpi_ec_region_setup");
402 
403         if (function == ACPI_REGION_DEACTIVATE)
404         {
405                 if (*region_context)
406                 {
407                         acpi_cm_free (*region_context);
408                         *region_context = NULL;
409                 }
410 
411                 return_ACPI_STATUS (AE_OK);
412         }
413 
414         *region_context = NULL;
415 
416         return_ACPI_STATUS (AE_OK);
417 }
418 
419 /*****************************************************************************
420  * 
421  * FUNCTION:    ec_region_handler
422  *
423  * PARAMETERS:  function            - Read or Write operation
424  *              address             - Where in the space to read or write
425  *              bit_width            - Field width in bits (8, 16, or 32)
426  *              value               - Pointer to in or out value
427  *              context             - context pointer
428  *
429  * RETURN:      <TBD>
430  *
431  * DESCRIPTION: Handler for the Embedded Controller (EC) address space 
432  *              (Op Region)
433  *
434  ****************************************************************************/
435 
436 static ACPI_STATUS
437 ec_region_handler (
438     UINT32                  function,
439     ACPI_PHYSICAL_ADDRESS   address,
440     UINT32                  bit_width,
441     UINT32                  *value,
442     void                    *handler_context,
443     void                    *region_context)
444 {
445     ACPI_STATUS             status = AE_OK;
446     ec_context_t              *ec = NULL;
447     EC_REQUEST              ec_request;
448 
449     FUNCTION_TRACE("ec_space_handler");
450 
451     if (address > 0xFF || bit_width != 8 || !value || !handler_context)
452         return_ACPI_STATUS(AE_BAD_PARAMETER);
453 
454     ec = (ec_context_t*)handler_context;
455 
456     switch (function) {
457 
458     case ADDRESS_SPACE_READ:
459         ec_request.command = EC_COMMAND_READ;
460         ec_request.address = address;
461         ec_request.data = 0;
462         break;
463 
464     case ADDRESS_SPACE_WRITE:
465         ec_request.command = EC_COMMAND_WRITE;
466         ec_request.address = address;
467         ec_request.data = (UINT8)(*value);
468         break;
469 
470     default:
471         DEBUG_PRINT(ACPI_WARN, ("Received request with invalid function [0x%08X].\n", function));
472         return_ACPI_STATUS(AE_BAD_PARAMETER);
473         break;
474     }
475 
476     DEBUG_PRINT(ACPI_INFO, ("device[ec] command[0x%02X] address[0x%02X] data[0x%02X]\n", ec_request.command, ec_request.address, ec_request.data));
477 
478     /*
479      * Perform the Transaction.
480      */
481     status = ec_transaction(ec, &ec_request);
482     if (ACPI_SUCCESS(status))
483         (*value) = (UINT32)ec_request.data;
484 
485     return_ACPI_STATUS(status);
486 }
487 
488 /*
489  * Get Embedded Controller information
490  */
491 static ACPI_STATUS
492 found_ec(
493         ACPI_HANDLE handle,
494         u32 level, 
495         void *ctx, 
496         void **value)
497 {
498         ACPI_STATUS status;
499         ACPI_OBJECT obj;
500         ACPI_BUFFER buf;
501         RESOURCE *res;
502         ec_context_t *ec_cxt;
503 
504         buf.length = 0;
505         buf.pointer = NULL;
506         if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW)
507                 return AE_OK;
508 
509         buf.pointer = kmalloc(buf.length, GFP_KERNEL);
510         if (!buf.pointer)
511                 return AE_NO_MEMORY;
512 
513         if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) {
514                 kfree(buf.pointer);
515                 return AE_OK;
516         }
517 
518         ec_cxt = kmalloc(sizeof(ec_context_t), GFP_KERNEL);
519         if (!ec_cxt) {
520                 kfree(buf.pointer);
521                 return AE_NO_MEMORY;
522         }
523 
524         ec_cxt->acpi_handle = handle;
525 
526         res = (RESOURCE*) buf.pointer;
527         ec_cxt->data_port = res->data.io.min_base_address;
528         res = NEXT_RESOURCE(res);
529         ec_cxt->status_port = (int) res->data.io.min_base_address;
530 
531         kfree(buf.pointer);
532 
533         /* determine GPE bit */
534         /* BUG: in acpi 2.0 this could return a package */
535         buf.length = sizeof(obj);
536         buf.pointer = &obj;
537         if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf))
538                 || obj.type != ACPI_TYPE_INTEGER)
539                 return AE_OK;
540 
541         ec_cxt->gpe_bit = obj.integer.value;
542 
543         /* determine if we need the Global Lock when accessing */
544         buf.length = sizeof(obj);
545         buf.pointer = &obj;
546 
547         status = acpi_evaluate_object(handle, "_GLK", NULL, &buf);
548         if (status == AE_NOT_FOUND)
549                 ec_cxt->need_global_lock = 0;
550         else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_INTEGER) {
551                 DEBUG_PRINT(ACPI_ERROR, ("_GLK failed\n"));
552                 return AE_OK;
553         }
554 
555         ec_cxt->need_global_lock = obj.integer.value;
556 
557         printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,gpe %d GL %d)\n",
558                 ec_cxt->data_port, ec_cxt->status_port, ec_cxt->gpe_bit,
559                 ec_cxt->need_global_lock);
560 
561         if (!ACPI_SUCCESS(acpi_install_gpe_handler(
562                 ec_cxt->gpe_bit,
563                 ACPI_EVENT_EDGE_TRIGGERED,
564                 ec_gpe_handler,
565                 ec_cxt))) {
566                 
567                 REPORT_ERROR(("Could not install GPE handler for EC.\n"));
568                 return AE_OK;
569         }
570 
571         status = acpi_install_address_space_handler (handle, ADDRESS_SPACE_EC, 
572                     ec_region_handler, ec_region_setup, ec_cxt);
573 
574         if (!ACPI_SUCCESS(status)) {
575                 REPORT_ERROR(("Could not install EC address "
576                         "space handler, error %s\n", acpi_cm_format_exception (status)));
577         }
578         
579         return AE_OK;
580 }
581 
582 int
583 acpi_ec_init(void)
584 {
585         acpi_get_devices(ACPI_EC_HID, 
586                         found_ec,
587                         NULL,
588                         NULL);
589 
590         return 0;
591 }
592 
593 int
594 acpi_ec_terminate(void)
595 {
596         /* TODO */      
597         /* walk list of EC's */
598         /* free their context and release resources */
599         return 0;
600 }
601 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.