xref: /haiku/src/add-ons/kernel/bus_managers/acpi/EmbeddedController.h (revision 70449c90d95aeea01b25f686d51da4217fe41317)
1 /*-
2  * Copyright (c) 2009 Clemens Zeidler
3  * Copyright (c) 2003-2007 Nate Lawson
4  * Copyright (c) 2000 Michael Smith
5  * Copyright (c) 2000 BSDi
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 #ifndef ACPI_EMBEDDED_CONTROLLER_H
30 #define ACPI_EMBEDDED_CONTROLLER_H
31 
32 
33 #include <ctype.h>
34 
35 #include <ACPI.h>
36 #include <condition_variable.h>
37 
38 #include <Drivers.h>
39 #include <KernelExport.h>
40 #include <lock.h>
41 
42 extern "C" {
43 #	include "acpi.h"
44 #	include "accommon.h"
45 #	include "acnamesp.h"
46 #	include "actypes.h"
47 #	include "ACPIPrivate.h"
48 }
49 
50 
51 // #define TRACE_EMBEDDED_CONTROLLER
52 #ifdef TRACE_EMBEDDED_CONTROLLER
53 #	define TRACE(x...) dprintf("EC: " x)
54 #else
55 #	define TRACE(x...)
56 #endif
57 
58 #define ERROR(x...) dprintf("EC: " x)
59 
60 
61 typedef uint8							EC_COMMAND;
62 
63 #define EC_COMMAND_UNKNOWN				((EC_COMMAND) 0x00)
64 #define EC_COMMAND_READ					((EC_COMMAND) 0x80)
65 #define EC_COMMAND_WRITE				((EC_COMMAND) 0x81)
66 #define EC_COMMAND_BURST_ENABLE			((EC_COMMAND) 0x82)
67 #define EC_COMMAND_BURST_DISABLE		((EC_COMMAND) 0x83)
68 #define EC_COMMAND_QUERY				((EC_COMMAND) 0x84)
69 
70 /*
71  * EC_STATUS:
72  * ----------
73  * The encoding of the EC status register is illustrated below.
74  * Note that a set bit (1) indicates the property is TRUE
75  * (e.g. if bit 0 is set then the output buffer is full).
76  * +-+-+-+-+-+-+-+-+
77  * |7|6|5|4|3|2|1|0|
78  * +-+-+-+-+-+-+-+-+
79  *  | | | | | | | |
80  *  | | | | | | | +- Output Buffer Full?
81  *  | | | | | | +--- Input Buffer Full?
82  *  | | | | | +----- <reserved>
83  *  | | | | +------- Data Register is Command Byte?
84  *  | | | +--------- Burst Mode Enabled?
85  *  | | +----------- SCI Event?
86  *  | +------------- SMI Event?
87  *  +--------------- <reserved>
88  *
89  */
90 
91 typedef uint8							EC_STATUS;
92 
93 #define EC_FLAG_OUTPUT_BUFFER			((EC_STATUS) 0x01)
94 #define EC_FLAG_INPUT_BUFFER			((EC_STATUS) 0x02)
95 #define EC_FLAG_DATA_IS_CMD				((EC_STATUS) 0x08)
96 #define EC_FLAG_BURST_MODE				((EC_STATUS) 0x10)
97 
98 /*
99  * EC_EVENT:
100  * ---------
101  */
102 typedef uint8							EC_EVENT;
103 
104 #define EC_EVENT_UNKNOWN				((EC_EVENT) 0x00)
105 #define EC_EVENT_OUTPUT_BUFFER_FULL		((EC_EVENT) 0x01)
106 #define EC_EVENT_INPUT_BUFFER_EMPTY		((EC_EVENT) 0x02)
107 #define EC_EVENT_SCI					((EC_EVENT) 0x20)
108 #define EC_EVENT_SMI					((EC_EVENT) 0x40)
109 
110 /* Data byte returned after burst enable indicating it was successful. */
111 #define EC_BURST_ACK					0x90
112 
113 
114 /*
115  * Register access primitives
116  */
117 #define EC_GET_DATA(sc) \
118 		bus_space_read_1((sc)->ec_data_pci_address)
119 
120 #define EC_SET_DATA(sc, v) \
121 		bus_space_write_1((sc)->ec_data_pci_address, (v))
122 
123 #define EC_GET_CSR(sc) \
124 		bus_space_read_1((sc)->ec_csr_pci_address)
125 
126 #define EC_SET_CSR(sc, v) \
127 		bus_space_write_1((sc)->ec_csr_pci_address, (v))
128 
129 #define ACPI_PKG_VALID(pkg, size) \
130 		((pkg) != NULL && (pkg)->object_type == ACPI_TYPE_PACKAGE && \
131 		(pkg)->data.package.count >= (size))
132 
133 
134 /*
135  * Driver cookie.
136  */
137 struct acpi_ec_cookie {
138 	device_node*				ec_dev;
139 	acpi_module_info*			ec_acpi_module;
140 	acpi_device_module_info* 	ec_acpi;
141 	acpi_device					ec_handle;
142 	int							ec_uid;
143 	acpi_handle					ec_gpehandle;
144 	uint8						ec_gpebit;
145 
146 	int							ec_data_pci_address;
147 	int							ec_csr_pci_address;
148 
149 	int							ec_glk;
150 	uint32						ec_glkhandle;
151 	mutex						ec_lock;
152 	int							ec_burstactive;
153 	int							ec_sci_pending;
154 	vint32						ec_gencount;
155 	ConditionVariable			ec_condition_var;
156 	int							ec_suspending;
157 };
158 
159 
160 /*
161  * XXX njl
162  * I couldn't find it in the spec but other implementations also use a
163  * value of 1 ms for the time to acquire global lock.
164  */
165 #define EC_LOCK_TIMEOUT 1000
166 
167 /* Default delay in microseconds between each run of the status polling loop. */
168 #define EC_POLL_DELAY	5
169 
170 /* Total time in ms spent waiting for a response from EC. */
171 #define EC_TIMEOUT		750
172 
173 #define EVENT_READY(event, status) \
174 		(((event) == EC_EVENT_OUTPUT_BUFFER_FULL && \
175 		((status) & EC_FLAG_OUTPUT_BUFFER) != 0) || \
176 		((event) == EC_EVENT_INPUT_BUFFER_EMPTY && \
177 		((status) & EC_FLAG_INPUT_BUFFER) == 0))
178 
179 
180 
181 static int		ec_burst_mode = 1;
182 static int		ec_polled_mode = 0;
183 
184 static int		ec_timeout = EC_TIMEOUT;
185 
186 
187 static status_t
188 EcLock(struct acpi_ec_cookie *sc)
189 {
190 	/* If _GLK is non-zero, acquire the global lock. */
191 	status_t status = B_OK;
192 	if (sc->ec_glk) {
193 		status = sc->ec_acpi_module->acquire_global_lock(EC_LOCK_TIMEOUT,
194 			&sc->ec_glkhandle);
195 		if (status != B_OK)
196 			return status;
197 	}
198 	mutex_lock(&sc->ec_lock);
199 	return status;
200 }
201 
202 
203 static void
204 EcUnlock(struct acpi_ec_cookie *sc)
205 {
206 	mutex_unlock(&sc->ec_lock);
207 	if (sc->ec_glk)
208 		sc->ec_acpi_module->release_global_lock(sc->ec_glkhandle);
209 }
210 
211 
212 static uint32			EcGpeHandler(acpi_handle gpeDevice, uint32 gpeNumber,
213 							void *context);
214 
215 static acpi_status		EcSpaceSetup(acpi_handle region, uint32 function,
216 							void *context, void **return_Context);
217 static acpi_status		EcSpaceHandler(uint32 function,
218 							acpi_physical_address address,
219 							uint32 width, int *value,
220 							void *context, void *regionContext);
221 static acpi_status		EcWaitEvent(struct acpi_ec_cookie *sc, EC_EVENT event,
222 							int32 gen_count);
223 static acpi_status		EcCommand(struct acpi_ec_cookie *sc, EC_COMMAND cmd);
224 static acpi_status		EcRead(struct acpi_ec_cookie *sc, uint8 address,
225 							uint8 *readData);
226 static acpi_status		EcWrite(struct acpi_ec_cookie *sc, uint8 address,
227 							uint8 writeData);
228 
229 
230 #endif	// ACPI_EMBEDDED_CONTROLLER_H
231