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)->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 int32 ec_sci_pending;
154 int32 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 50
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 bool ec_burst_mode = true;
182 static bool ec_polled_mode = false;
183
184 static int ec_timeout = EC_TIMEOUT;
185
186
187 static status_t
EcLock(struct acpi_ec_cookie * sc)188 EcLock(struct acpi_ec_cookie *sc)
189 {
190 /* If _GLK is non-zero, acquire the global lock. */
191 if (sc->ec_glk) {
192 status_t status = sc->ec_acpi_module->acquire_global_lock(EC_LOCK_TIMEOUT,
193 &sc->ec_glkhandle);
194 if (status != B_OK)
195 return status;
196 }
197 return mutex_lock(&sc->ec_lock);
198 }
199
200
201 static void
EcUnlock(struct acpi_ec_cookie * sc)202 EcUnlock(struct acpi_ec_cookie *sc)
203 {
204 mutex_unlock(&sc->ec_lock);
205 if (sc->ec_glk)
206 sc->ec_acpi_module->release_global_lock(sc->ec_glkhandle);
207 }
208
209
210 static uint32 EcGpeHandler(acpi_handle gpeDevice, uint32 gpeNumber,
211 void *context);
212
213 static acpi_status EcSpaceSetup(acpi_handle region, uint32 function,
214 void *context, void **return_Context);
215 static acpi_status EcSpaceHandler(uint32 function,
216 acpi_physical_address address,
217 uint32 width, int *value,
218 void *context, void *regionContext);
219 static acpi_status EcWaitEvent(struct acpi_ec_cookie *sc, EC_EVENT event,
220 int32 gen_count);
221 static acpi_status EcCommand(struct acpi_ec_cookie *sc, EC_COMMAND cmd);
222 static acpi_status EcRead(struct acpi_ec_cookie *sc, uint8 address,
223 uint8 *readData);
224 static acpi_status EcWrite(struct acpi_ec_cookie *sc, uint8 address,
225 uint8 writeData);
226
227
228 #endif // ACPI_EMBEDDED_CONTROLLER_H
229