summaryrefslogtreecommitdiff
path: root/src/ec/acpi/ec.asl
blob: 47c74bdd44e60707dd6a5f80051f0b920a3ffba3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* SPDX-License-Identifier: GPL-2.0-only */

/*
 * ACPI style embedded controller commands
 *
 * Controlled by the following preprocessor defines:
 * EC_SC_IO	I/o address of the EC_SC register
 * EC_DATA_IO	I/o address of the EC_DATA register
 */

#define EC_MUTEX	ECMX
#define WAIT_EC_SC	WECC
#define SEND_EC_COMMAND	SECC
#define SEND_EC_DATA	SECD
#define RECV_EC_DATA	RECD
#define EC_READ		ECRD
#define EC_WRITE	ECWR
#define EC_SC		ECSC
#define EC_DATA		ECDT

#define EC_OBF		0x01 /* Output buffer full (EC_DATA) */
#define EC_IBF		0x02 /* Input buffer full (EC_DATA or EC_SC) */

#define EC_ERROR_MASK	0xff00
#define EC_TIMEOUT	0x8000

#define EC_READ_CMD	0x80
#define EC_WRITE_CMD	0x81

Mutex(EC_MUTEX, 1)

OperationRegion(ERSC, SystemIO, EC_SC_IO, 1)
Field(ERSC, ByteAcc, NoLock, Preserve) { EC_SC, 8 }
OperationRegion(ERDT, SystemIO, EC_DATA_IO, 1)
Field(ERDT, ByteAcc, NoLock, Preserve) { EC_DATA, 8 }

/*
 * Wait for a bit in the status and command (EC_SC) register
 *
 * The caller is responsible of acquiring the EC_MUTEX before
 * calling this method.
 *
 * Arg0: Mask, Arg1: State waiting for
 * Returns EC_TIMEOUT if timed out, 0 else
 */
Method (WAIT_EC_SC, 2)
{
	Store (0x7ff, Local0) /* Timeout */
	While (LAnd (LNotEqual (And (EC_SC, Arg0), Arg1), Decrement (Local0))) {
		Stall (10)
	}
	If (Local0) {
		Return (0)
	} Else {
		Return (EC_TIMEOUT)
	}
}

/*
 * Send command byte in Arg0 to status and command (EC_SC) register
 *
 * The caller is responsible of acquiring the EC_MUTEX before
 * calling this method.
 *
 * Returns EC_TIMEOUT if timed out, 0 else
 */
Method (SEND_EC_COMMAND, 1)
{
	Store (WAIT_EC_SC (EC_IBF, 0), Local0)
	If (LNot (Local0)) {
		Store (Arg0, EC_SC)
	}
	Return (Local0)
}

/*
 * Send data byte in Arg0 to data (EC_DATA) register
 *
 * The caller is responsible of acquiring the EC_MUTEX before
 * calling this method.
 *
 * Returns EC_TIMEOUT if timed out, 0 else
 */
Method (SEND_EC_DATA, 1)
{
	Store (WAIT_EC_SC (EC_IBF, 0), Local0)
	If (LNot (Local0)) {
		Store (Arg0, EC_DATA)
	}
	Return (Local0)
}

/*
 * Read one byte of data from data (EC_DATA) register
 *
 * The caller is responsible of acquiring the EC_MUTEX before
 * calling this method.
 *
 * Returns EC_TIMEOUT if timed out, the read data byte else
 */
Method (RECV_EC_DATA)
{
	Store (WAIT_EC_SC (EC_OBF, EC_OBF), Local0)
	If (LNot (Local0)) {
		Return (EC_DATA)
	} Else {
		Return (Local0)
	}
}

/*
 * Read one byte from ec memory (cmd 0x80)
 *
 * Arg0: Address (1 byte) to read from
 * Returns EC_TIMEOUT if timed out, the read data byte else
 */
Method (EC_READ, 1)
{
	Acquire (EC_MUTEX, 0xffff)
	Store (SEND_EC_COMMAND (EC_READ_CMD), Local0)
	If (LNot (Local0)) {
		Store (SEND_EC_DATA (Arg0), Local0)
	}
	If (LNot (Local0)) {
		Store (RECV_EC_DATA (), Local0)
	}
	Release (EC_MUTEX)

	Return (Local0)
}

/*
 * Write one byte to ec memory (cmd 0x81)
 *
 * Arg0: Address (1 byte) to write to
 * Arg1: Byte to write
 * Returns EC_TIMEOUT if timed out, 0 else
 */
Method (EC_WRITE, 2)
{
	Acquire (EC_MUTEX, 0xffff)
	Store (SEND_EC_COMMAND (EC_WRITE_CMD), Local0)
	If (LNot (Local0)) {
		Store (SEND_EC_DATA (Arg0), Local0)
	}
	If (LNot (Local0)) {
		Store (SEND_EC_DATA (Arg1), Local0)
	}
	Release (EC_MUTEX)

	Return (Local0)
}