blob: 1e0a489d7b93ed9960bcaba2efb37283babbcb51 [file] [log] [blame]
Simon Glass98528d42020-07-07 13:11:42 -06001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Generation of ACPI (Advanced Configuration and Power Interface) tables
4 *
5 * Copyright 2019 Google LLC
6 * Mostly taken from coreboot
7 */
8
9#define LOG_CATEGORY LOGC_ACPI
10
11#include <common.h>
12#include <dm.h>
Simon Glass0f277632020-07-07 13:11:50 -060013#include <log.h>
Simon Glass48342b02020-07-07 13:11:55 -060014#include <uuid.h>
Simon Glass98528d42020-07-07 13:11:42 -060015#include <acpi/acpigen.h>
Simon Glass8a200762020-07-07 13:12:01 -060016#include <acpi/acpi_device.h>
Simon Glass98528d42020-07-07 13:11:42 -060017#include <dm/acpi.h>
18
19u8 *acpigen_get_current(struct acpi_ctx *ctx)
20{
21 return ctx->current;
22}
23
24void acpigen_emit_byte(struct acpi_ctx *ctx, uint data)
25{
26 *(u8 *)ctx->current++ = data;
27}
28
29void acpigen_emit_word(struct acpi_ctx *ctx, uint data)
30{
31 acpigen_emit_byte(ctx, data & 0xff);
32 acpigen_emit_byte(ctx, (data >> 8) & 0xff);
33}
34
35void acpigen_emit_dword(struct acpi_ctx *ctx, uint data)
36{
37 /* Output the value in little-endian format */
38 acpigen_emit_byte(ctx, data & 0xff);
39 acpigen_emit_byte(ctx, (data >> 8) & 0xff);
40 acpigen_emit_byte(ctx, (data >> 16) & 0xff);
41 acpigen_emit_byte(ctx, (data >> 24) & 0xff);
42}
Simon Glass071c4a52020-07-07 13:11:45 -060043
Simon Glass0f277632020-07-07 13:11:50 -060044/*
45 * Maximum length for an ACPI object generated by this code,
46 *
47 * If you need to change this, change acpigen_write_len_f(ctx) and
48 * acpigen_pop_len(ctx)
49 */
50#define ACPIGEN_MAXLEN 0xfffff
51
52void acpigen_write_len_f(struct acpi_ctx *ctx)
53{
54 assert(ctx->ltop < (ACPIGEN_LENSTACK_SIZE - 1));
55 ctx->len_stack[ctx->ltop++] = ctx->current;
56 acpigen_emit_byte(ctx, 0);
57 acpigen_emit_byte(ctx, 0);
58 acpigen_emit_byte(ctx, 0);
59}
60
61void acpigen_pop_len(struct acpi_ctx *ctx)
62{
63 int len;
64 char *p;
65
66 assert(ctx->ltop > 0);
67 p = ctx->len_stack[--ctx->ltop];
68 len = ctx->current - (void *)p;
69 assert(len <= ACPIGEN_MAXLEN);
70 /* generate store length for 0xfffff max */
71 p[0] = ACPI_PKG_LEN_3_BYTES | (len & 0xf);
72 p[1] = len >> 4 & 0xff;
73 p[2] = len >> 12 & 0xff;
74}
75
Simon Glass9238fac2020-07-07 13:11:59 -060076void acpigen_emit_ext_op(struct acpi_ctx *ctx, uint op)
77{
78 acpigen_emit_byte(ctx, EXT_OP_PREFIX);
79 acpigen_emit_byte(ctx, op);
80}
81
Simon Glassedc26802020-07-07 13:11:51 -060082char *acpigen_write_package(struct acpi_ctx *ctx, int nr_el)
83{
84 char *p;
85
86 acpigen_emit_byte(ctx, PACKAGE_OP);
87 acpigen_write_len_f(ctx);
88 p = ctx->current;
89 acpigen_emit_byte(ctx, nr_el);
90
91 return p;
92}
93
Simon Glass8715ce02020-07-07 13:11:52 -060094void acpigen_write_byte(struct acpi_ctx *ctx, unsigned int data)
95{
96 acpigen_emit_byte(ctx, BYTE_PREFIX);
97 acpigen_emit_byte(ctx, data & 0xff);
98}
99
100void acpigen_write_word(struct acpi_ctx *ctx, unsigned int data)
101{
102 acpigen_emit_byte(ctx, WORD_PREFIX);
103 acpigen_emit_word(ctx, data);
104}
105
106void acpigen_write_dword(struct acpi_ctx *ctx, unsigned int data)
107{
108 acpigen_emit_byte(ctx, DWORD_PREFIX);
109 acpigen_emit_dword(ctx, data);
110}
111
112void acpigen_write_qword(struct acpi_ctx *ctx, u64 data)
113{
114 acpigen_emit_byte(ctx, QWORD_PREFIX);
115 acpigen_emit_dword(ctx, data & 0xffffffff);
116 acpigen_emit_dword(ctx, (data >> 32) & 0xffffffff);
117}
118
119void acpigen_write_zero(struct acpi_ctx *ctx)
120{
121 acpigen_emit_byte(ctx, ZERO_OP);
122}
123
124void acpigen_write_one(struct acpi_ctx *ctx)
125{
126 acpigen_emit_byte(ctx, ONE_OP);
127}
128
129void acpigen_write_integer(struct acpi_ctx *ctx, u64 data)
130{
131 if (data == 0)
132 acpigen_write_zero(ctx);
133 else if (data == 1)
134 acpigen_write_one(ctx);
135 else if (data <= 0xff)
136 acpigen_write_byte(ctx, (unsigned char)data);
137 else if (data <= 0xffff)
138 acpigen_write_word(ctx, (unsigned int)data);
139 else if (data <= 0xffffffff)
140 acpigen_write_dword(ctx, (unsigned int)data);
141 else
142 acpigen_write_qword(ctx, data);
143}
144
Simon Glass071c4a52020-07-07 13:11:45 -0600145void acpigen_emit_stream(struct acpi_ctx *ctx, const char *data, int size)
146{
147 int i;
148
149 for (i = 0; i < size; i++)
150 acpigen_emit_byte(ctx, data[i]);
151}
152
153void acpigen_emit_string(struct acpi_ctx *ctx, const char *str)
154{
155 acpigen_emit_stream(ctx, str, str ? strlen(str) : 0);
156 acpigen_emit_byte(ctx, '\0');
157}
Simon Glass45d6d952020-07-07 13:11:53 -0600158
159void acpigen_write_string(struct acpi_ctx *ctx, const char *str)
160{
161 acpigen_emit_byte(ctx, STRING_PREFIX);
162 acpigen_emit_string(ctx, str);
163}
Simon Glass0dc3d512020-07-07 13:11:54 -0600164
165/*
166 * The naming conventions for ACPI namespace names are a bit tricky as
167 * each element has to be 4 chars wide ("All names are a fixed 32 bits.")
168 * and "By convention, when an ASL compiler pads a name shorter than 4
169 * characters, it is done so with trailing underscores ('_')".
170 *
171 * Check sections 5.3, 20.2.2 and 20.4 of ACPI spec 6.3 for details.
172 */
173static void acpigen_emit_simple_namestring(struct acpi_ctx *ctx,
174 const char *name)
175{
176 const char *ptr;
177 int i;
178
179 for (i = 0, ptr = name; i < 4; i++) {
180 if (!*ptr || *ptr == '.')
181 acpigen_emit_byte(ctx, '_');
182 else
183 acpigen_emit_byte(ctx, *ptr++);
184 }
185}
186
187static void acpigen_emit_double_namestring(struct acpi_ctx *ctx,
188 const char *name, int dotpos)
189{
190 acpigen_emit_byte(ctx, DUAL_NAME_PREFIX);
191 acpigen_emit_simple_namestring(ctx, name);
192 acpigen_emit_simple_namestring(ctx, &name[dotpos + 1]);
193}
194
195static void acpigen_emit_multi_namestring(struct acpi_ctx *ctx,
196 const char *name)
197{
198 unsigned char *pathlen;
199 int count = 0;
200
201 acpigen_emit_byte(ctx, MULTI_NAME_PREFIX);
202 pathlen = ctx->current;
203 acpigen_emit_byte(ctx, 0);
204
205 while (*name) {
206 acpigen_emit_simple_namestring(ctx, name);
207 /* find end or next entity */
208 while (*name != '.' && *name)
209 name++;
210 /* forward to next */
211 if (*name == '.')
212 name++;
213 count++;
214 }
215
216 *pathlen = count;
217}
218
219void acpigen_emit_namestring(struct acpi_ctx *ctx, const char *namepath)
220{
221 int dotcount;
222 int dotpos;
223 int i;
224
225 /* We can start with a '\' */
226 if (*namepath == '\\') {
227 acpigen_emit_byte(ctx, '\\');
228 namepath++;
229 }
230
231 /* And there can be any number of '^' */
232 while (*namepath == '^') {
233 acpigen_emit_byte(ctx, '^');
234 namepath++;
235 }
236
237 for (i = 0, dotcount = 0; namepath[i]; i++) {
238 if (namepath[i] == '.') {
239 dotcount++;
240 dotpos = i;
241 }
242 }
243
244 /* If we have only \\ or only ^* then we need to add a null name */
245 if (!*namepath)
246 acpigen_emit_byte(ctx, ZERO_OP);
247 else if (dotcount == 0)
248 acpigen_emit_simple_namestring(ctx, namepath);
249 else if (dotcount == 1)
250 acpigen_emit_double_namestring(ctx, namepath, dotpos);
251 else
252 acpigen_emit_multi_namestring(ctx, namepath);
253}
254
255void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath)
256{
257 acpigen_emit_byte(ctx, NAME_OP);
258 acpigen_emit_namestring(ctx, namepath);
259}
Simon Glass48342b02020-07-07 13:11:55 -0600260
Simon Glass6fcdaf12020-07-07 21:32:10 -0600261void acpigen_write_scope(struct acpi_ctx *ctx, const char *scope)
262{
263 acpigen_emit_byte(ctx, SCOPE_OP);
264 acpigen_write_len_f(ctx);
265 acpigen_emit_namestring(ctx, scope);
266}
267
Simon Glass9238fac2020-07-07 13:11:59 -0600268static void acpigen_write_method_internal(struct acpi_ctx *ctx,
269 const char *name, uint flags)
270{
271 acpigen_emit_byte(ctx, METHOD_OP);
272 acpigen_write_len_f(ctx);
273 acpigen_emit_namestring(ctx, name);
274 acpigen_emit_byte(ctx, flags);
275}
276
277/* Method (name, nargs, NotSerialized) */
278void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs)
279{
280 acpigen_write_method_internal(ctx, name,
281 nargs & ACPI_METHOD_NARGS_MASK);
282}
283
284/* Method (name, nargs, Serialized) */
285void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
286 int nargs)
287{
288 acpigen_write_method_internal(ctx, name,
289 (nargs & ACPI_METHOD_NARGS_MASK) |
290 ACPI_METHOD_SERIALIZED_MASK);
291}
292
293void acpigen_write_sta(struct acpi_ctx *ctx, uint status)
294{
295 /* Method (_STA, 0, NotSerialized) { Return (status) } */
296 acpigen_write_method(ctx, "_STA", 0);
297 acpigen_emit_byte(ctx, RETURN_OP);
298 acpigen_write_byte(ctx, status);
299 acpigen_pop_len(ctx);
300}
301
Simon Glass48342b02020-07-07 13:11:55 -0600302/*
303 * ToUUID(uuid)
304 *
305 * ACPI 6.3 Section 19.6.142 table 19-438 defines a special output order for the
306 * bytes that make up a UUID Buffer object:
307 *
308 * UUID byte order for input to this function:
309 * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
310 *
311 * UUID byte order output by this function:
312 * ddccbbaa-ffee-hhgg-iijj-kkllmmnnoopp
313 */
314int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid)
315{
316 u8 buf[UUID_BIN_LEN];
317 int ret;
318
319 /* Parse UUID string into bytes */
320 ret = uuid_str_to_bin(uuid, buf, UUID_STR_FORMAT_GUID);
321 if (ret)
322 return log_msg_ret("bad hex", -EINVAL);
323
324 /* BufferOp */
325 acpigen_emit_byte(ctx, BUFFER_OP);
326 acpigen_write_len_f(ctx);
327
328 /* Buffer length in bytes */
329 acpigen_write_word(ctx, UUID_BIN_LEN);
330
331 /* Output UUID in expected order */
332 acpigen_emit_stream(ctx, (char *)buf, UUID_BIN_LEN);
333
334 acpigen_pop_len(ctx);
335
336 return 0;
337}
Simon Glass9238fac2020-07-07 13:11:59 -0600338
Simon Glassd0f7d9b2020-07-07 13:12:00 -0600339void acpigen_write_power_res(struct acpi_ctx *ctx, const char *name, uint level,
340 uint order, const char *const dev_states[],
341 size_t dev_states_count)
342{
343 size_t i;
344
345 for (i = 0; i < dev_states_count; i++) {
346 acpigen_write_name(ctx, dev_states[i]);
347 acpigen_write_package(ctx, 1);
348 acpigen_emit_simple_namestring(ctx, name);
349 acpigen_pop_len(ctx); /* Package */
350 }
351
352 acpigen_emit_ext_op(ctx, POWER_RES_OP);
353
354 acpigen_write_len_f(ctx);
355
356 acpigen_emit_simple_namestring(ctx, name);
357 acpigen_emit_byte(ctx, level);
358 acpigen_emit_word(ctx, order);
359}
360
Simon Glass9238fac2020-07-07 13:11:59 -0600361/* Sleep (ms) */
362void acpigen_write_sleep(struct acpi_ctx *ctx, u64 sleep_ms)
363{
364 acpigen_emit_ext_op(ctx, SLEEP_OP);
365 acpigen_write_integer(ctx, sleep_ms);
366}
367
368void acpigen_write_store(struct acpi_ctx *ctx)
369{
370 acpigen_emit_byte(ctx, STORE_OP);
371}
372
373/* Or (arg1, arg2, res) */
374void acpigen_write_or(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res)
375{
376 acpigen_emit_byte(ctx, OR_OP);
377 acpigen_emit_byte(ctx, arg1);
378 acpigen_emit_byte(ctx, arg2);
379 acpigen_emit_byte(ctx, res);
380}
381
382/* And (arg1, arg2, res) */
383void acpigen_write_and(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res)
384{
385 acpigen_emit_byte(ctx, AND_OP);
386 acpigen_emit_byte(ctx, arg1);
387 acpigen_emit_byte(ctx, arg2);
388 acpigen_emit_byte(ctx, res);
389}
390
391/* Not (arg, res) */
392void acpigen_write_not(struct acpi_ctx *ctx, u8 arg, u8 res)
393{
394 acpigen_emit_byte(ctx, NOT_OP);
395 acpigen_emit_byte(ctx, arg);
396 acpigen_emit_byte(ctx, res);
397}
398
399/* Store (str, DEBUG) */
400void acpigen_write_debug_string(struct acpi_ctx *ctx, const char *str)
401{
402 acpigen_write_store(ctx);
403 acpigen_write_string(ctx, str);
404 acpigen_emit_ext_op(ctx, DEBUG_OP);
405}
Simon Glass8a200762020-07-07 13:12:01 -0600406
407/**
408 * acpigen_get_dw0_in_local5() - Generate code to put dw0 cfg0 in local5
409 *
410 * Store (\_SB.GPC0 (addr), Local5)
411 *
412 * \_SB.GPC0 is used to read cfg0 value from dw0. It is typically defined in
413 * the board's gpiolib.asl
414 *
415 * The value needs to be stored in a local variable so that it can be used in
416 * expressions in the ACPI code.
417 *
418 * @ctx: ACPI context pointer
419 * @dw0_read: Name to use to read dw0, e.g. "\\_SB.GPC0"
420 * @addr: GPIO pin configuration register address
421 *
422 */
423static void acpigen_get_dw0_in_local5(struct acpi_ctx *ctx,
424 const char *dw0_read, ulong addr)
425{
426 acpigen_write_store(ctx);
427 acpigen_emit_namestring(ctx, dw0_read);
428 acpigen_write_integer(ctx, addr);
429 acpigen_emit_byte(ctx, LOCAL5_OP);
430}
431
432/**
433 * acpigen_set_gpio_val() - Emit code to set value of TX GPIO to on/off
434 *
435 * @ctx: ACPI context pointer
436 * @dw0_read: Method name to use to read dw0, e.g. "\\_SB.GPC0"
437 * @dw0_write: Method name to use to read dw0, e.g. "\\_SB.SPC0"
438 * @gpio_num: GPIO number to adjust
439 * @vaL: true to set on, false to set off
440 */
441static int acpigen_set_gpio_val(struct acpi_ctx *ctx, u32 tx_state_val,
442 const char *dw0_read, const char *dw0_write,
443 struct acpi_gpio *gpio, bool val)
444{
445 acpigen_get_dw0_in_local5(ctx, dw0_read, gpio->pin0_addr);
446
447 /* Store (0x40, Local0) */
448 acpigen_write_store(ctx);
449 acpigen_write_integer(ctx, tx_state_val);
450 acpigen_emit_byte(ctx, LOCAL0_OP);
451
452 if (val) {
453 /* Or (Local5, PAD_CFG0_TX_STATE, Local5) */
454 acpigen_write_or(ctx, LOCAL5_OP, LOCAL0_OP, LOCAL5_OP);
455 } else {
456 /* Not (PAD_CFG0_TX_STATE, Local6) */
457 acpigen_write_not(ctx, LOCAL0_OP, LOCAL6_OP);
458
459 /* And (Local5, Local6, Local5) */
460 acpigen_write_and(ctx, LOCAL5_OP, LOCAL6_OP, LOCAL5_OP);
461 }
462
463 /*
464 * \_SB.SPC0 (addr, Local5)
465 * \_SB.SPC0 is used to write cfg0 value in dw0. It is defined in
466 * gpiolib.asl.
467 */
468 acpigen_emit_namestring(ctx, dw0_write);
469 acpigen_write_integer(ctx, gpio->pin0_addr);
470 acpigen_emit_byte(ctx, LOCAL5_OP);
471
472 return 0;
473}
474
475int acpigen_set_enable_tx_gpio(struct acpi_ctx *ctx, u32 tx_state_val,
476 const char *dw0_read, const char *dw0_write,
477 struct acpi_gpio *gpio, bool enable)
478{
479 bool set;
480 int ret;
481
482 set = gpio->polarity == ACPI_GPIO_ACTIVE_HIGH ? enable : !enable;
483 ret = acpigen_set_gpio_val(ctx, tx_state_val, dw0_read, dw0_write, gpio,
484 set);
485 if (ret)
486 return log_msg_ret("call", ret);
487
488 return 0;
489}