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
42extern "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
61typedef 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
91typedef 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 */
102typedef 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 */
137struct 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
181static bool		ec_burst_mode = true;
182static bool		ec_polled_mode = false;
183
184static int		ec_timeout = EC_TIMEOUT;
185
186
187static status_t
188EcLock(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
201static void
202EcUnlock(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
210static uint32			EcGpeHandler(acpi_handle gpeDevice, uint32 gpeNumber,
211							void *context);
212
213static acpi_status		EcSpaceSetup(acpi_handle region, uint32 function,
214							void *context, void **return_Context);
215static acpi_status		EcSpaceHandler(uint32 function,
216							acpi_physical_address address,
217							uint32 width, int *value,
218							void *context, void *regionContext);
219static acpi_status		EcWaitEvent(struct acpi_ec_cookie *sc, EC_EVENT event,
220							int32 gen_count);
221static acpi_status		EcCommand(struct acpi_ec_cookie *sc, EC_COMMAND cmd);
222static acpi_status		EcRead(struct acpi_ec_cookie *sc, uint8 address,
223							uint8 *readData);
224static acpi_status		EcWrite(struct acpi_ec_cookie *sc, uint8 address,
225							uint8 writeData);
226
227
228#endif	// ACPI_EMBEDDED_CONTROLLER_H
229