xref: /freebsd/sys/dev/acpica/acpi_ec.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
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$
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$");
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
159 ACPI_MODULE_NAME("EC")
160 
161 /*
162  * EC_COMMAND:
163  * -----------
164  */
165 typedef 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  */
194 typedef 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  */
205 typedef 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) */
228 typedef 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  */
250 struct 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 
294 static int	ec_poll_timeout = EC_POLL_TIMEOUT;
295 TUNABLE_INT("hw.acpi.ec.poll_timeout", &ec_poll_timeout);
296 
297 static __inline ACPI_STATUS
298 EcLock(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 
315 static __inline void
316 EcUnlock(struct acpi_ec_softc *sc)
317 {
318     if (sc->ec_glk)
319 	AcpiReleaseGlobalLock(sc->ec_glkhandle);
320     mtx_unlock(&sc->ec_mtx);
321 }
322 
323 static void		EcGpeHandler(void *Context);
324 static ACPI_STATUS	EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
325 				void *Context, void **return_Context);
326 static ACPI_STATUS	EcSpaceHandler(UINT32 Function,
327 				ACPI_PHYSICAL_ADDRESS Address,
328 				UINT32 width, ACPI_INTEGER *Value,
329 				void *Context, void *RegionContext);
330 static ACPI_STATUS	EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
331 static ACPI_STATUS	EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd);
332 static ACPI_STATUS	EcRead(struct acpi_ec_softc *sc, UINT8 Address,
333 				UINT8 *Data);
334 static ACPI_STATUS	EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
335 				UINT8 *Data);
336 static int		acpi_ec_probe(device_t dev);
337 static int		acpi_ec_attach(device_t dev);
338 
339 static 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 
347 static driver_t acpi_ec_driver = {
348     "acpi_ec",
349     acpi_ec_methods,
350     sizeof(struct acpi_ec_softc),
351 };
352 
353 static devclass_t acpi_ec_devclass;
354 DRIVER_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  */
362 void
363 acpi_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 
420 static int
421 acpi_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 
510 static int
511 acpi_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 
598 static void
599 EcGpeQueryHandler(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 
658 re_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  */
670 static void
671 EcGpeHandler(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 
692 static ACPI_STATUS
693 EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
694 	     void **RegionContext)
695 {
696 
697     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
698 
699     /*
700      * Just pass the context through, there's nothing to do here.
701      */
702     *RegionContext = Context;
703 
704     return_ACPI_STATUS (AE_OK);
705 }
706 
707 static ACPI_STATUS
708 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
709 	       ACPI_INTEGER *Value, void *Context, void *RegionContext)
710 {
711     struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
712     ACPI_STATUS			Status = AE_OK;
713     UINT8			EcAddr, EcData;
714     int				i;
715 
716     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
717 
718     if (Address > 0xFF || width % 8 != 0 || Value == NULL || Context == NULL)
719 	return_ACPI_STATUS (AE_BAD_PARAMETER);
720 
721     /*
722      * Perform the transaction.
723      */
724     EcAddr = Address;
725     for (i = 0; i < width; i += 8) {
726 	Status = EcLock(sc);
727 	if (ACPI_FAILURE(Status))
728 	    return (Status);
729 
730 	switch (Function) {
731 	case ACPI_READ:
732 	    EcData = 0;
733 	    Status = EcRead(sc, EcAddr, &EcData);
734 	    break;
735 	case ACPI_WRITE:
736 	    EcData = (UINT8)((*Value) >> i);
737 	    Status = EcWrite(sc, EcAddr, &EcData);
738 	    break;
739 	default:
740 	    device_printf(sc->ec_dev, "invalid EcSpaceHandler function %d\n",
741 			  Function);
742 	    Status = AE_BAD_PARAMETER;
743 	    break;
744 	}
745 
746 	EcUnlock(sc);
747 	if (ACPI_FAILURE(Status))
748 	    return (Status);
749 
750 	*Value |= (ACPI_INTEGER)EcData << i;
751 	if (++EcAddr == 0)
752 	    return_ACPI_STATUS (AE_BAD_PARAMETER);
753     }
754     return_ACPI_STATUS (Status);
755 }
756 
757 static ACPI_STATUS
758 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
759 {
760     EC_STATUS	EcStatus;
761     ACPI_STATUS	Status;
762     int		i, period, retval;
763     static int	EcDbgMaxDelay;
764 
765     mtx_assert(&sc->ec_mtx, MA_OWNED);
766     Status = AE_NO_HARDWARE_RESPONSE;
767 
768     /*
769      * Wait for 1 us before checking the CSR.  Testing shows about
770      * 50% of requests complete in 1 us and 90% of them complete
771      * in 5 us or less.
772      */
773     AcpiOsStall(1);
774 
775     /*
776      * Poll the EC status register to detect completion of the last
777      * command.  First, wait up to 1 ms in chunks of sc->ec_polldelay
778      * microseconds.
779      */
780     for (i = 0; i < 1000 / sc->ec_polldelay; i++) {
781 	EcStatus = EC_GET_CSR(sc);
782 	if (EVENT_READY(Event, EcStatus)) {
783 	    Status = AE_OK;
784 	    break;
785 	}
786 	AcpiOsStall(sc->ec_polldelay);
787     }
788 
789     /* Scale poll delay by the amount of time actually waited. */
790     period = i * sc->ec_polldelay;
791     if (period <= 5)
792 	sc->ec_polldelay = 1;
793     else if (period <= 20)
794 	sc->ec_polldelay = 5;
795     else if (period <= 100)
796 	sc->ec_polldelay = 10;
797     else
798 	sc->ec_polldelay = 100;
799 
800     /*
801      * If we still don't have a response, wait up to ec_poll_timeout ms
802      * for completion, sleeping for chunks of 10 ms.
803      */
804     if (Status != AE_OK) {
805 	retval = -1;
806 	for (i = 0; i < ec_poll_timeout / 10; i++) {
807 	    if (retval != 0)
808 		EcStatus = EC_GET_CSR(sc);
809 	    else
810 		EcStatus = sc->ec_csrvalue;
811 	    if (EVENT_READY(Event, EcStatus)) {
812 		Status = AE_OK;
813 		break;
814 	    }
815 	    retval = msleep(&sc->ec_csrvalue, &sc->ec_mtx, PZERO, "ecpoll",
816 			    10/*ms*/);
817 	}
818     }
819 
820     /* Calculate new delay and print it if it exceeds the max. */
821     if (period == 1000)
822 	period += i * 10000;
823     if (period > EcDbgMaxDelay) {
824 	EcDbgMaxDelay = period;
825 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
826 		    "info: new max delay is %d us\n", period);
827     }
828 
829     return (Status);
830 }
831 
832 static ACPI_STATUS
833 EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd)
834 {
835     ACPI_STATUS	Status;
836     EC_EVENT	Event;
837 
838     mtx_assert(&sc->ec_mtx, MA_OWNED);
839 
840     /* Decide what to wait for based on command type. */
841     switch (cmd) {
842     case EC_COMMAND_READ:
843     case EC_COMMAND_WRITE:
844     case EC_COMMAND_BURST_DISABLE:
845 	Event = EC_EVENT_INPUT_BUFFER_EMPTY;
846 	break;
847     case EC_COMMAND_QUERY:
848     case EC_COMMAND_BURST_ENABLE:
849 	Event = EC_EVENT_OUTPUT_BUFFER_FULL;
850 	break;
851     default:
852 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
853 		    "EcCommand: Invalid command %#x\n", cmd);
854 	return (AE_BAD_PARAMETER);
855     }
856 
857     /* Run the command and wait for the chosen event. */
858     EC_SET_CSR(sc, cmd);
859     Status = EcWaitEvent(sc, Event);
860     if (ACPI_FAILURE(Status)) {
861 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
862 		    "EcCommand: no response to %#x\n", cmd);
863     }
864 
865     return (Status);
866 }
867 
868 static ACPI_STATUS
869 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
870 {
871     ACPI_STATUS	Status;
872 
873     mtx_assert(&sc->ec_mtx, MA_OWNED);
874 
875 #ifdef notyet
876     /* If we can't start burst mode, continue anyway. */
877     EcCommand(sc, EC_COMMAND_BURST_ENABLE);
878 #endif
879 
880     Status = EcCommand(sc, EC_COMMAND_READ);
881     if (ACPI_FAILURE(Status))
882 	return (Status);
883 
884     EC_SET_DATA(sc, Address);
885     Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
886     if (ACPI_FAILURE(Status)) {
887 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
888 		    "EcRead: Failed waiting for EC to send data.\n");
889 	return (Status);
890     }
891 
892     *Data = EC_GET_DATA(sc);
893 
894 #ifdef notyet
895     if (sc->ec_burstactive) {
896 	Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
897 	if (ACPI_FAILURE(Status))
898 	    return (Status);
899     }
900 #endif
901 
902     return (AE_OK);
903 }
904 
905 static ACPI_STATUS
906 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
907 {
908     ACPI_STATUS	Status;
909 
910     mtx_assert(&sc->ec_mtx, MA_OWNED);
911 
912 #ifdef notyet
913     /* If we can't start burst mode, continue anyway. */
914     EcCommand(sc, EC_COMMAND_BURST_ENABLE);
915 #endif
916 
917     Status = EcCommand(sc, EC_COMMAND_WRITE);
918     if (ACPI_FAILURE(Status))
919 	return (Status);
920 
921     EC_SET_DATA(sc, Address);
922     Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
923     if (ACPI_FAILURE(Status)) {
924 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
925 		    "EcRead: Failed waiting for EC to process address\n");
926 	return (Status);
927     }
928 
929     EC_SET_DATA(sc, *Data);
930     Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
931     if (ACPI_FAILURE(Status)) {
932 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
933 		    "EcWrite: Failed waiting for EC to process data\n");
934 	return (Status);
935     }
936 
937 #ifdef notyet
938     if (sc->ec_burstactive) {
939 	Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
940 	if (ACPI_FAILURE(Status))
941 	    return (Status);
942     }
943 #endif
944 
945     return (AE_OK);
946 }
947