acpi_ec.c revision 124091
1/*-
2 * Copyright (c) 2003 Nate Lawson
3 * Copyright (c) 2000 Michael Smith
4 * Copyright (c) 2000 BSDi
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 *	$FreeBSD: head/sys/dev/acpica/acpi_ec.c 124091 2004-01-03 02:01:39Z njl $
29 */
30/******************************************************************************
31 *
32 * 1. Copyright Notice
33 *
34 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
35 * reserved.
36 *
37 * 2. License
38 *
39 * 2.1. This is your license from Intel Corp. under its intellectual property
40 * rights.  You may have additional license terms from the party that provided
41 * you this software, covering your right to use that party's intellectual
42 * property rights.
43 *
44 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
45 * copy of the source code appearing in this file ("Covered Code") an
46 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
47 * base code distributed originally by Intel ("Original Intel Code") to copy,
48 * make derivatives, distribute, use and display any portion of the Covered
49 * Code in any form, with the right to sublicense such rights; and
50 *
51 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
52 * license (with the right to sublicense), under only those claims of Intel
53 * patents that are infringed by the Original Intel Code, to make, use, sell,
54 * offer to sell, and import the Covered Code and derivative works thereof
55 * solely to the minimum extent necessary to exercise the above copyright
56 * license, and in no event shall the patent license extend to any additions
57 * to or modifications of the Original Intel Code.  No other license or right
58 * is granted directly or by implication, estoppel or otherwise;
59 *
60 * The above copyright and patent license is granted only if the following
61 * conditions are met:
62 *
63 * 3. Conditions
64 *
65 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
66 * Redistribution of source code of any substantial portion of the Covered
67 * Code or modification with rights to further distribute source must include
68 * the above Copyright Notice, the above License, this list of Conditions,
69 * and the following Disclaimer and Export Compliance provision.  In addition,
70 * Licensee must cause all Covered Code to which Licensee contributes to
71 * contain a file documenting the changes Licensee made to create that Covered
72 * Code and the date of any change.  Licensee must include in that file the
73 * documentation of any changes made by any predecessor Licensee.  Licensee
74 * must include a prominent statement that the modification is derived,
75 * directly or indirectly, from Original Intel Code.
76 *
77 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
78 * Redistribution of source code of any substantial portion of the Covered
79 * Code or modification without rights to further distribute source must
80 * include the following Disclaimer and Export Compliance provision in the
81 * documentation and/or other materials provided with distribution.  In
82 * addition, Licensee may not authorize further sublicense of source of any
83 * portion of the Covered Code, and must include terms to the effect that the
84 * license from Licensee to its licensee is limited to the intellectual
85 * property embodied in the software Licensee provides to its licensee, and
86 * not to intellectual property embodied in modifications its licensee may
87 * make.
88 *
89 * 3.3. Redistribution of Executable. Redistribution in executable form of any
90 * substantial portion of the Covered Code or modification must reproduce the
91 * above Copyright Notice, and the following Disclaimer and Export Compliance
92 * provision in the documentation and/or other materials provided with the
93 * distribution.
94 *
95 * 3.4. Intel retains all right, title, and interest in and to the Original
96 * Intel Code.
97 *
98 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
99 * Intel shall be used in advertising or otherwise to promote the sale, use or
100 * other dealings in products derived from or relating to the Covered Code
101 * without prior written authorization from Intel.
102 *
103 * 4. Disclaimer and Export Compliance
104 *
105 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
106 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
107 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
108 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
109 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
110 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
111 * PARTICULAR PURPOSE.
112 *
113 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
114 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
115 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
116 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
117 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
118 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
119 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
120 * LIMITED REMEDY.
121 *
122 * 4.3. Licensee shall not export, either directly or indirectly, any of this
123 * software or system incorporating such software without first obtaining any
124 * required license or other approval from the U. S. Department of Commerce or
125 * any other agency or department of the United States Government.  In the
126 * event Licensee exports any such software from the United States or
127 * re-exports any such software from a foreign destination, Licensee shall
128 * ensure that the distribution and export/re-export of the software is in
129 * compliance with all laws, regulations, orders, or other restrictions of the
130 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
131 * any of its subsidiaries will export/re-export any technical data, process,
132 * software, or service, directly or indirectly, to any country for which the
133 * United States government or any agency thereof requires an export license,
134 * other governmental approval, or letter of assurance, without first obtaining
135 * such license, approval or letter.
136 *
137 *****************************************************************************/
138
139#include <sys/cdefs.h>
140__FBSDID("$FreeBSD: head/sys/dev/acpica/acpi_ec.c 124091 2004-01-03 02:01:39Z njl $");
141
142#include "opt_acpi.h"
143#include <sys/param.h>
144#include <sys/kernel.h>
145#include <sys/bus.h>
146
147#include <machine/bus.h>
148#include <machine/resource.h>
149#include <sys/rman.h>
150
151#include "acpi.h"
152
153#include <dev/acpica/acpivar.h>
154
155/*
156 * Hooks for the ACPI CA debugging infrastructure
157 */
158#define _COMPONENT	ACPI_EC
159ACPI_MODULE_NAME("EC")
160
161/*
162 * EC_COMMAND:
163 * -----------
164 */
165typedef UINT8				EC_COMMAND;
166
167#define EC_COMMAND_UNKNOWN		((EC_COMMAND) 0x00)
168#define EC_COMMAND_READ			((EC_COMMAND) 0x80)
169#define EC_COMMAND_WRITE		((EC_COMMAND) 0x81)
170#define EC_COMMAND_BURST_ENABLE		((EC_COMMAND) 0x82)
171#define EC_COMMAND_BURST_DISABLE	((EC_COMMAND) 0x83)
172#define EC_COMMAND_QUERY		((EC_COMMAND) 0x84)
173
174/*
175 * EC_STATUS:
176 * ----------
177 * The encoding of the EC status register is illustrated below.
178 * Note that a set bit (1) indicates the property is TRUE
179 * (e.g. if bit 0 is set then the output buffer is full).
180 * +-+-+-+-+-+-+-+-+
181 * |7|6|5|4|3|2|1|0|
182 * +-+-+-+-+-+-+-+-+
183 *  | | | | | | | |
184 *  | | | | | | | +- Output Buffer Full?
185 *  | | | | | | +--- Input Buffer Full?
186 *  | | | | | +----- <reserved>
187 *  | | | | +------- Data Register is Command Byte?
188 *  | | | +--------- Burst Mode Enabled?
189 *  | | +----------- SCI Event?
190 *  | +------------- SMI Event?
191 *  +--------------- <Reserved>
192 *
193 */
194typedef UINT8				EC_STATUS;
195
196#define EC_FLAG_OUTPUT_BUFFER		((EC_STATUS) 0x01)
197#define EC_FLAG_INPUT_BUFFER		((EC_STATUS) 0x02)
198#define EC_FLAG_BURST_MODE		((EC_STATUS) 0x10)
199#define EC_FLAG_SCI			((EC_STATUS) 0x20)
200
201/*
202 * EC_EVENT:
203 * ---------
204 */
205typedef UINT8				EC_EVENT;
206
207#define EC_EVENT_UNKNOWN		((EC_EVENT) 0x00)
208#define EC_EVENT_OUTPUT_BUFFER_FULL	((EC_EVENT) 0x01)
209#define EC_EVENT_INPUT_BUFFER_EMPTY	((EC_EVENT) 0x02)
210#define EC_EVENT_SCI			((EC_EVENT) 0x20)
211
212/*
213 * Register access primitives
214 */
215#define EC_GET_DATA(sc)							\
216	bus_space_read_1((sc)->ec_data_tag, (sc)->ec_data_handle, 0)
217
218#define EC_SET_DATA(sc, v)						\
219	bus_space_write_1((sc)->ec_data_tag, (sc)->ec_data_handle, 0, (v))
220
221#define EC_GET_CSR(sc)							\
222	bus_space_read_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0)
223
224#define EC_SET_CSR(sc, v)						\
225	bus_space_write_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0, (v))
226
227/* Embedded Controller Boot Resources Table (ECDT) */
228typedef struct {
229    ACPI_TABLE_HEADER		header;
230    ACPI_GENERIC_ADDRESS	control;
231    ACPI_GENERIC_ADDRESS	data;
232    UINT32			uid;
233    UINT8			gpe_bit;
234    char			ec_id[0];
235} ACPI_TABLE_ECDT;
236
237/* Indicate that this device has already been probed via ECDT. */
238#define DEV_ECDT(x)		(acpi_get_private(x) == &acpi_ec_devclass)
239
240/* Indicate that this device should use the global lock. */
241#define DEV_GLK_FLAG		0x40000000
242
243/* Get/set GPE bit value in the magic ivar. */
244#define DEV_GET_GPEBIT(x)	((x) & 0xff)
245#define DEV_SET_GPEBIT(x, y)	((x) = ((x) & ~0xff) | ((y) & 0xff))
246
247/*
248 * Driver softc.
249 */
250struct acpi_ec_softc {
251    device_t		ec_dev;
252    ACPI_HANDLE		ec_handle;
253    UINT8		ec_gpebit;
254    UINT8		ec_csrvalue;
255
256    int			ec_data_rid;
257    struct resource	*ec_data_res;
258    bus_space_tag_t	ec_data_tag;
259    bus_space_handle_t	ec_data_handle;
260
261    int			ec_csr_rid;
262    struct resource	*ec_csr_res;
263    bus_space_tag_t	ec_csr_tag;
264    bus_space_handle_t	ec_csr_handle;
265
266    int			ec_glk;
267    int			ec_glkhandle;
268    struct mtx		ec_mtx;
269    int			ec_polldelay;
270};
271
272/*
273 * XXX
274 * I couldn't find it in the spec but other implementations also use a
275 * value of 1 ms for the time to acquire global lock.
276 */
277#define EC_LOCK_TIMEOUT	1000
278
279/*
280 * Start with an interval of 1 us for status poll loop.  This delay
281 * will be dynamically adjusted based on the actual time waited.
282 */
283#define EC_POLL_DELAY	1
284
285/* Total time in ms spent in the poll loop waiting for a response. */
286#define EC_POLL_TIMEOUT	100
287
288#define EVENT_READY(event, status)			\
289	(((event) == EC_EVENT_OUTPUT_BUFFER_FULL &&	\
290	 ((status) & EC_FLAG_OUTPUT_BUFFER) != 0) ||	\
291	 ((event) == EC_EVENT_INPUT_BUFFER_EMPTY && 	\
292	 ((status) & EC_FLAG_INPUT_BUFFER) == 0))
293
294static int	ec_poll_timeout = EC_POLL_TIMEOUT;
295TUNABLE_INT("hw.acpi.ec.poll_timeout", &ec_poll_timeout);
296
297static __inline ACPI_STATUS
298EcLock(struct acpi_ec_softc *sc)
299{
300    ACPI_STATUS	status = AE_OK;
301
302    /* Always acquire this EC's mutex. */
303    mtx_lock(&sc->ec_mtx);
304
305    /* If _GLK is non-zero, also acquire the global lock. */
306    if (sc->ec_glk) {
307	status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
308	if (ACPI_FAILURE(status))
309	    mtx_unlock(&sc->ec_mtx);
310    }
311
312    return (status);
313}
314
315static __inline void
316EcUnlock(struct acpi_ec_softc *sc)
317{
318    if (sc->ec_glk)
319	AcpiReleaseGlobalLock(sc->ec_glkhandle);
320    mtx_unlock(&sc->ec_mtx);
321}
322
323static void		EcGpeHandler(void *Context);
324static ACPI_STATUS	EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
325				void *Context, void **return_Context);
326static ACPI_STATUS	EcSpaceHandler(UINT32 Function,
327				ACPI_PHYSICAL_ADDRESS Address,
328				UINT32 width, ACPI_INTEGER *Value,
329				void *Context, void *RegionContext);
330static ACPI_STATUS	EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
331static ACPI_STATUS	EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd);
332static ACPI_STATUS	EcRead(struct acpi_ec_softc *sc, UINT8 Address,
333				UINT8 *Data);
334static ACPI_STATUS	EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
335				UINT8 *Data);
336static int		acpi_ec_probe(device_t dev);
337static int		acpi_ec_attach(device_t dev);
338
339static device_method_t acpi_ec_methods[] = {
340    /* Device interface */
341    DEVMETHOD(device_probe,	acpi_ec_probe),
342    DEVMETHOD(device_attach,	acpi_ec_attach),
343
344    {0, 0}
345};
346
347static driver_t acpi_ec_driver = {
348    "acpi_ec",
349    acpi_ec_methods,
350    sizeof(struct acpi_ec_softc),
351};
352
353static devclass_t acpi_ec_devclass;
354DRIVER_MODULE(acpi_ec, acpi, acpi_ec_driver, acpi_ec_devclass, 0, 0);
355
356/*
357 * Look for an ECDT and if we find one, set up default GPE and
358 * space handlers to catch attempts to access EC space before
359 * we have a real driver instance in place.
360 * TODO: if people report invalid ECDTs, add a tunable to disable them.
361 */
362void
363acpi_ec_ecdt_probe(device_t parent)
364{
365    ACPI_TABLE_ECDT *ecdt;
366    ACPI_STATUS	     status;
367    device_t	     child;
368    ACPI_HANDLE	     h;
369    int		     magic;
370
371    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
372
373    /* Find and validate the ECDT. */
374    status = AcpiGetFirmwareTable("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
375		(ACPI_TABLE_HEADER **)&ecdt);
376    if (ACPI_FAILURE(status) ||
377	ecdt->control.RegisterBitWidth != 8 ||
378	ecdt->data.RegisterBitWidth != 8) {
379	return;
380    }
381
382    /* Create the child device with the given unit number. */
383    child = BUS_ADD_CHILD(parent, 0, "acpi_ec", ecdt->uid);
384    if (child == NULL) {
385	printf("acpi_ec_ecdt_probe: can't add child\n");
386	return;
387    }
388
389    /* Find and save the ACPI handle for this device. */
390    status = AcpiGetHandle(NULL, ecdt->ec_id, &h);
391    if (ACPI_FAILURE(status)) {
392	device_delete_child(parent, child);
393	printf("acpi_ec_ecdt_probe: can't get handle\n");
394	return;
395    }
396    acpi_set_handle(child, h);
397
398    /* Set the data and CSR register addresses. */
399    bus_set_resource(child, SYS_RES_IOPORT, 0, ecdt->data.Address,
400	/*count*/1);
401    bus_set_resource(child, SYS_RES_IOPORT, 1, ecdt->control.Address,
402	/*count*/1);
403
404    /*
405     * Store values for the probe/attach routines to use.  Store the
406     * ECDT GPE bit and set the global lock flag (just to be safe).
407     * We'll determine whether we really want to use the global lock
408     * in a later call to attach.
409     */
410    acpi_set_private(child, &acpi_ec_devclass);
411    magic = DEV_GLK_FLAG;
412    DEV_SET_GPEBIT(magic, ecdt->gpe_bit);
413    acpi_set_magic(child, magic);
414
415    /* Finish the attach process. */
416    if (device_probe_and_attach(child) != 0)
417	device_delete_child(parent, child);
418}
419
420static int
421acpi_ec_probe(device_t dev)
422{
423    ACPI_HANDLE h;
424    ACPI_STATUS status;
425    device_t	peer;
426    char	desc[64];
427    int		magic, uid, glk, gpebit, ret = ENXIO;
428
429    /* Check that this is a device and that EC is not disabled. */
430    if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec"))
431	return (ENXIO);
432
433    /*
434     * If probed via ECDT, set description and continue.  Otherwise,
435     * we can access the namespace and make sure this is not a
436     * duplicate probe.
437     */
438    magic = acpi_get_magic(dev);
439    if (DEV_ECDT(dev)) {
440	snprintf(desc, sizeof(desc), "Embedded Controller: ECDT, GPE %#x, GLK",
441		 DEV_GET_GPEBIT(magic));
442	device_set_desc_copy(dev, desc);
443	ret = 0;
444    } else if (acpi_MatchHid(dev, "PNP0C09")) {
445	h = acpi_get_handle(dev);
446
447	/*
448	 * Read the unit ID to check for duplicate attach and the
449	 * global lock value to see if we should acquire it when
450	 * accessing the EC.
451	 */
452	status = acpi_EvaluateInteger(h, "_UID", &uid);
453	if (ACPI_FAILURE(status))
454	    uid = 0;
455	status = acpi_EvaluateInteger(h, "_GLK", &glk);
456	if (ACPI_FAILURE(status))
457	    glk = 0;
458
459	/*
460	 * Evaluate the _GPE method to find the GPE bit used by the EC to
461	 * signal status (SCI).  Note that we don't handle the case where
462	 * it can return a package instead of an int.
463	 */
464	status = acpi_EvaluateInteger(h, "_GPE", &gpebit);
465	if (ACPI_FAILURE(status)) {
466	    device_printf(dev, "can't evaluate _GPE - %s\n",
467			  AcpiFormatException(status));
468	    return (ENXIO);
469	}
470
471	/* Store the values we got from the namespace for attach. */
472	magic = glk != 0 ? DEV_GLK_FLAG : 0;
473	DEV_SET_GPEBIT(magic, gpebit);
474	acpi_set_magic(dev, magic);
475
476	/*
477	 * Check for a duplicate probe.  This can happen when a probe
478	 * via ECDT succeeded already.  If there is a duplicate, override
479	 * its value for GLK in the peer's softc since the ECDT case
480	 * always enables the global lock to be safe.  Otherwise, just
481	 * continue on to attach.
482	 */
483	peer = devclass_get_device(acpi_ec_devclass, uid);
484	if (peer == NULL || !device_is_alive(peer)) {
485	    snprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s",
486		     gpebit, glk != 0 ? ", GLK" : "");
487	    device_set_desc_copy(dev, desc);
488	    ret = 0;
489	} else {
490	    struct acpi_ec_softc *sc;
491
492	    /*
493	     * Set the peer's sc->ec_glk with locks held so we won't
494	     * override it between another thread's lock/unlock calls.
495	     */
496	    sc = device_get_softc(peer);
497	    if (sc->ec_glk != glk) {
498		ACPI_VPRINT(peer, acpi_device_get_parent_softc(peer),
499		    "Changing GLK from %d to %d\n", sc->ec_glk, glk);
500		mtx_lock(&sc->ec_mtx);
501		sc->ec_glk = glk != 0 ? 1 : 0;
502		mtx_unlock(&sc->ec_mtx);
503	    }
504	}
505    }
506
507    return (ret);
508}
509
510static int
511acpi_ec_attach(device_t dev)
512{
513    struct acpi_ec_softc	*sc;
514    ACPI_STATUS			Status;
515    int				magic, errval = 0;
516
517    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
518
519    /* Fetch/initialize softc (assumes softc is pre-zeroed). */
520    sc = device_get_softc(dev);
521    sc->ec_dev = dev;
522    sc->ec_handle = acpi_get_handle(dev);
523    sc->ec_polldelay = EC_POLL_DELAY;
524    mtx_init(&sc->ec_mtx, "ACPI embedded controller", NULL, MTX_DEF);
525
526    /* Retrieve previously probed values via device ivars. */
527    magic = acpi_get_magic(dev);
528    sc->ec_glk = (magic & DEV_GLK_FLAG) != 0 ? 1 : 0;
529    sc->ec_gpebit = DEV_GET_GPEBIT(magic);
530
531    /* Attach bus resources for data and command/status ports. */
532    sc->ec_data_rid = 0;
533    sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
534			&sc->ec_data_rid, 0, ~0, 1, RF_ACTIVE);
535    if (sc->ec_data_res == NULL) {
536	device_printf(dev, "can't allocate data port\n");
537	errval = ENXIO;
538	goto out;
539    }
540    sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
541    sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);
542
543    sc->ec_csr_rid = 1;
544    sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
545			&sc->ec_csr_rid, 0, ~0, 1, RF_ACTIVE);
546    if (sc->ec_csr_res == NULL) {
547	device_printf(dev, "can't allocate command/status port\n");
548	errval = ENXIO;
549	goto out;
550    }
551    sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
552    sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
553
554    /*
555     * Install a handler for this EC's GPE bit.  We want edge-triggered
556     * behavior.
557     */
558    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
559    Status = AcpiInstallGpeHandler(NULL, sc->ec_gpebit,
560		ACPI_EVENT_EDGE_TRIGGERED, &EcGpeHandler, sc);
561    if (ACPI_FAILURE(Status)) {
562	device_printf(dev, "can't install GPE handler for %s - %s\n",
563		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
564	errval = ENXIO;
565	goto out;
566    }
567
568    /*
569     * Install address space handler
570     */
571    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
572    Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
573		&EcSpaceHandler, &EcSpaceSetup, sc);
574    if (ACPI_FAILURE(Status)) {
575	device_printf(dev, "can't install address space handler for %s - %s\n",
576		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
577	Status = AcpiRemoveGpeHandler(NULL, sc->ec_gpebit, &EcGpeHandler);
578	if (ACPI_FAILURE(Status))
579	    panic("Added GPE handler but can't remove it");
580	errval = ENXIO;
581	goto out;
582    }
583
584    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
585    return (0);
586
587 out:
588    if (sc->ec_csr_res)
589	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
590			     sc->ec_csr_res);
591    if (sc->ec_data_res)
592	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
593			     sc->ec_data_res);
594    mtx_destroy(&sc->ec_mtx);
595    return (errval);
596}
597
598static void
599EcGpeQueryHandler(void *Context)
600{
601    struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
602    UINT8			Data;
603    ACPI_STATUS			Status;
604    EC_STATUS			EcStatus;
605    char			qxx[5];
606
607    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
608    KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL"));
609
610    Status = EcLock(sc);
611    if (ACPI_FAILURE(Status)) {
612	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
613		    "GpeQuery lock error: %s\n", AcpiFormatException(Status));
614	return;
615    }
616
617    /*
618     * If the EC_SCI bit of the status register is not set, then pass
619     * it along to any potential waiters as it may be an IBE/OBF event.
620     */
621    EcStatus = EC_GET_CSR(sc);
622    if ((EcStatus & EC_EVENT_SCI) == 0) {
623	sc->ec_csrvalue = EcStatus;
624	wakeup(&sc->ec_csrvalue);
625	EcUnlock(sc);
626	goto re_enable;
627    }
628
629    /*
630     * Send a query command to the EC to find out which _Qxx call it
631     * wants to make.  This command clears the SCI bit and also the
632     * interrupt source since we are edge-triggered.
633     */
634    Status = EcCommand(sc, EC_COMMAND_QUERY);
635    if (ACPI_FAILURE(Status)) {
636	EcUnlock(sc);
637	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
638		    "GPE query failed - %s\n", AcpiFormatException(Status));
639	goto re_enable;
640    }
641    Data = EC_GET_DATA(sc);
642    EcUnlock(sc);
643
644    /* Ignore the value for "no outstanding event". (13.3.5) */
645    if (Data == 0)
646	goto re_enable;
647
648    /* Evaluate _Qxx to respond to the controller. */
649    sprintf(qxx, "_Q%02x", Data);
650    strupr(qxx);
651    Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
652    if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) {
653	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
654		    "evaluation of GPE query method %s failed - %s\n",
655		    qxx, AcpiFormatException(Status));
656    }
657
658re_enable:
659    /* Re-enable the GPE event so we'll get future requests. */
660    Status = AcpiEnableGpe(NULL, sc->ec_gpebit, ACPI_NOT_ISR);
661    if (ACPI_FAILURE(Status))
662	printf("EcGpeQueryHandler: AcpiEnableEvent failed\n");
663}
664
665/*
666 * Handle a GPE.  Currently we only handle SCI events as others must
667 * be handled by polling in EcWaitEvent().  This is because some ECs
668 * treat events as level when they should be edge-triggered.
669 */
670static void
671EcGpeHandler(void *Context)
672{
673    struct acpi_ec_softc *sc = Context;
674    ACPI_STATUS		       Status;
675
676    KASSERT(Context != NULL, ("EcGpeHandler called with NULL"));
677
678    /* Disable further GPEs while we handle this one. */
679    AcpiDisableGpe(NULL, sc->ec_gpebit, ACPI_ISR);
680
681    /* Schedule the GPE query handler. */
682    Status = AcpiOsQueueForExecution(OSD_PRIORITY_GPE, EcGpeQueryHandler,
683		Context);
684    if (ACPI_FAILURE(Status)) {
685	printf("Queuing GPE query handler failed.\n");
686	Status = AcpiEnableGpe(NULL, sc->ec_gpebit, ACPI_ISR);
687	if (ACPI_FAILURE(Status))
688	    printf("EcGpeHandler: AcpiEnableEvent failed\n");
689    }
690}
691
692static ACPI_STATUS
693EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
694	     void **RegionContext)
695{
696
697    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
698
699    /*
700     * If deactivating a region, always set the output to NULL.  Otherwise,
701     * just pass the context through.
702     */
703    if (Function == ACPI_REGION_DEACTIVATE)
704	*RegionContext = NULL;
705    else
706	*RegionContext = Context;
707
708    return_ACPI_STATUS (AE_OK);
709}
710
711static ACPI_STATUS
712EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
713	       ACPI_INTEGER *Value, void *Context, void *RegionContext)
714{
715    struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
716    ACPI_STATUS			Status = AE_OK;
717    UINT8			EcAddr, EcData;
718    int				i;
719
720    ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
721
722    if (Address > 0xFF || width % 8 != 0 || Value == NULL || Context == NULL)
723	return_ACPI_STATUS (AE_BAD_PARAMETER);
724
725    /*
726     * Perform the transaction.
727     */
728    EcAddr = Address;
729    for (i = 0; i < width; i += 8) {
730	Status = EcLock(sc);
731	if (ACPI_FAILURE(Status))
732	    return (Status);
733
734	switch (Function) {
735	case ACPI_READ:
736	    EcData = 0;
737	    Status = EcRead(sc, EcAddr, &EcData);
738	    break;
739	case ACPI_WRITE:
740	    EcData = (UINT8)((*Value) >> i);
741	    Status = EcWrite(sc, EcAddr, &EcData);
742	    break;
743	default:
744	    device_printf(sc->ec_dev, "invalid EcSpaceHandler function %d\n",
745			  Function);
746	    Status = AE_BAD_PARAMETER;
747	    break;
748	}
749
750	EcUnlock(sc);
751	if (ACPI_FAILURE(Status))
752	    return (Status);
753
754	*Value |= (ACPI_INTEGER)EcData << i;
755	if (++EcAddr == 0)
756	    return_ACPI_STATUS (AE_BAD_PARAMETER);
757    }
758    return_ACPI_STATUS (Status);
759}
760
761static ACPI_STATUS
762EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
763{
764    EC_STATUS	EcStatus;
765    ACPI_STATUS	Status;
766    int		i, period, retval;
767    static int	EcDbgMaxDelay;
768
769    mtx_assert(&sc->ec_mtx, MA_OWNED);
770    Status = AE_NO_HARDWARE_RESPONSE;
771
772    /*
773     * Wait for 1 us before checking the CSR.  Testing shows about
774     * 50% of requests complete in 1 us and 90% of them complete
775     * in 5 us or less.
776     */
777    AcpiOsStall(1);
778
779    /*
780     * Poll the EC status register to detect completion of the last
781     * command.  First, wait up to 1 ms in chunks of sc->ec_polldelay
782     * microseconds.
783     */
784    for (i = 0; i < 1000 / sc->ec_polldelay; i++) {
785	EcStatus = EC_GET_CSR(sc);
786	if (EVENT_READY(Event, EcStatus)) {
787	    Status = AE_OK;
788	    break;
789	}
790	AcpiOsStall(sc->ec_polldelay);
791    }
792
793    /* Scale poll delay by the amount of time actually waited. */
794    period = i * sc->ec_polldelay;
795    if (period <= 5)
796	sc->ec_polldelay = 1;
797    else if (period <= 20)
798	sc->ec_polldelay = 5;
799    else if (period <= 100)
800	sc->ec_polldelay = 10;
801    else
802	sc->ec_polldelay = 100;
803
804    /*
805     * If we still don't have a response, wait up to ec_poll_timeout ms
806     * for completion, sleeping for chunks of 10 ms.
807     */
808    if (Status != AE_OK) {
809	retval = -1;
810	for (i = 0; i < ec_poll_timeout / 10; i++) {
811	    if (retval != 0)
812		EcStatus = EC_GET_CSR(sc);
813	    else
814		EcStatus = sc->ec_csrvalue;
815	    if (EVENT_READY(Event, EcStatus)) {
816		Status = AE_OK;
817		break;
818	    }
819	    retval = msleep(&sc->ec_csrvalue, &sc->ec_mtx, PZERO, "ecpoll",
820			    10/*ms*/);
821	}
822    }
823
824    /* Calculate new delay and print it if it exceeds the max. */
825    if (period == 1000)
826	period += i * 10000;
827    if (period > EcDbgMaxDelay) {
828	EcDbgMaxDelay = period;
829	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
830		    "info: new max delay is %d us\n", period);
831    }
832
833    return (Status);
834}
835
836static ACPI_STATUS
837EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd)
838{
839    ACPI_STATUS	Status;
840    EC_EVENT	Event;
841
842    mtx_assert(&sc->ec_mtx, MA_OWNED);
843
844    /* Decide what to wait for based on command type. */
845    switch (cmd) {
846    case EC_COMMAND_READ:
847    case EC_COMMAND_WRITE:
848    case EC_COMMAND_BURST_DISABLE:
849	Event = EC_EVENT_INPUT_BUFFER_EMPTY;
850	break;
851    case EC_COMMAND_QUERY:
852    case EC_COMMAND_BURST_ENABLE:
853	Event = EC_EVENT_OUTPUT_BUFFER_FULL;
854	break;
855    default:
856	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
857		    "EcCommand: Invalid command %#x\n", cmd);
858	return (AE_BAD_PARAMETER);
859    }
860
861    /* Run the command and wait for the chosen event. */
862    EC_SET_CSR(sc, cmd);
863    Status = EcWaitEvent(sc, Event);
864    if (ACPI_FAILURE(Status)) {
865	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
866		    "EcCommand: no response to %#x\n", cmd);
867    }
868
869    return (Status);
870}
871
872static ACPI_STATUS
873EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
874{
875    ACPI_STATUS	Status;
876
877    mtx_assert(&sc->ec_mtx, MA_OWNED);
878
879#ifdef notyet
880    /* If we can't start burst mode, continue anyway. */
881    EcCommand(sc, EC_COMMAND_BURST_ENABLE);
882#endif
883
884    Status = EcCommand(sc, EC_COMMAND_READ);
885    if (ACPI_FAILURE(Status))
886	return (Status);
887
888    EC_SET_DATA(sc, Address);
889    Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
890    if (ACPI_FAILURE(Status)) {
891	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
892		    "EcRead: Failed waiting for EC to send data.\n");
893	return (Status);
894    }
895
896    *Data = EC_GET_DATA(sc);
897
898#ifdef notyet
899    if (sc->ec_burstactive) {
900	Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
901	if (ACPI_FAILURE(Status))
902	    return (Status);
903    }
904#endif
905
906    return (AE_OK);
907}
908
909static ACPI_STATUS
910EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
911{
912    ACPI_STATUS	Status;
913
914    mtx_assert(&sc->ec_mtx, MA_OWNED);
915
916#ifdef notyet
917    /* If we can't start burst mode, continue anyway. */
918    EcCommand(sc, EC_COMMAND_BURST_ENABLE);
919#endif
920
921    Status = EcCommand(sc, EC_COMMAND_WRITE);
922    if (ACPI_FAILURE(Status))
923	return (Status);
924
925    EC_SET_DATA(sc, Address);
926    Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
927    if (ACPI_FAILURE(Status)) {
928	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
929		    "EcRead: Failed waiting for EC to process address\n");
930	return (Status);
931    }
932
933    EC_SET_DATA(sc, *Data);
934    Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
935    if (ACPI_FAILURE(Status)) {
936	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
937		    "EcWrite: Failed waiting for EC to process data\n");
938	return (Status);
939    }
940
941#ifdef notyet
942    if (sc->ec_burstactive) {
943	Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
944	if (ACPI_FAILURE(Status))
945	    return (Status);
946    }
947#endif
948
949    return (AE_OK);
950}
951