blob: a66601a1383f50461436121ddeb2f7860edd425f [file] [log] [blame]
Simon Glass61cc9332020-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 Glass7e148f22020-07-07 13:11:50 -060013#include <log.h>
Simon Glass29df8452020-07-07 13:11:55 -060014#include <uuid.h>
Simon Glass61cc9332020-07-07 13:11:42 -060015#include <acpi/acpigen.h>
Simon Glassf8054dd2020-07-07 13:12:01 -060016#include <acpi/acpi_device.h>
Simon Glassd7d631d2020-07-07 21:32:11 -060017#include <acpi/acpi_table.h>
Simon Glass61cc9332020-07-07 13:11:42 -060018#include <dm/acpi.h>
19
20u8 *acpigen_get_current(struct acpi_ctx *ctx)
21{
22 return ctx->current;
23}
24
25void acpigen_emit_byte(struct acpi_ctx *ctx, uint data)
26{
27 *(u8 *)ctx->current++ = data;
28}
29
30void acpigen_emit_word(struct acpi_ctx *ctx, uint data)
31{
32 acpigen_emit_byte(ctx, data & 0xff);
33 acpigen_emit_byte(ctx, (data >> 8) & 0xff);
34}
35
36void acpigen_emit_dword(struct acpi_ctx *ctx, uint data)
37{
38 /* Output the value in little-endian format */
39 acpigen_emit_byte(ctx, data & 0xff);
40 acpigen_emit_byte(ctx, (data >> 8) & 0xff);
41 acpigen_emit_byte(ctx, (data >> 16) & 0xff);
42 acpigen_emit_byte(ctx, (data >> 24) & 0xff);
43}
Simon Glass7fb8da42020-07-07 13:11:45 -060044
Simon Glass7e148f22020-07-07 13:11:50 -060045/*
46 * Maximum length for an ACPI object generated by this code,
47 *
48 * If you need to change this, change acpigen_write_len_f(ctx) and
49 * acpigen_pop_len(ctx)
50 */
51#define ACPIGEN_MAXLEN 0xfffff
52
53void acpigen_write_len_f(struct acpi_ctx *ctx)
54{
55 assert(ctx->ltop < (ACPIGEN_LENSTACK_SIZE - 1));
56 ctx->len_stack[ctx->ltop++] = ctx->current;
57 acpigen_emit_byte(ctx, 0);
58 acpigen_emit_byte(ctx, 0);
59 acpigen_emit_byte(ctx, 0);
60}
61
62void acpigen_pop_len(struct acpi_ctx *ctx)
63{
64 int len;
65 char *p;
66
67 assert(ctx->ltop > 0);
68 p = ctx->len_stack[--ctx->ltop];
69 len = ctx->current - (void *)p;
70 assert(len <= ACPIGEN_MAXLEN);
71 /* generate store length for 0xfffff max */
72 p[0] = ACPI_PKG_LEN_3_BYTES | (len & 0xf);
73 p[1] = len >> 4 & 0xff;
74 p[2] = len >> 12 & 0xff;
75}
76
Simon Glass9c70e7e2020-07-07 13:11:59 -060077void acpigen_emit_ext_op(struct acpi_ctx *ctx, uint op)
78{
79 acpigen_emit_byte(ctx, EXT_OP_PREFIX);
80 acpigen_emit_byte(ctx, op);
81}
82
Simon Glass03967ce2020-07-07 13:11:51 -060083char *acpigen_write_package(struct acpi_ctx *ctx, int nr_el)
84{
85 char *p;
86
87 acpigen_emit_byte(ctx, PACKAGE_OP);
88 acpigen_write_len_f(ctx);
89 p = ctx->current;
90 acpigen_emit_byte(ctx, nr_el);
91
92 return p;
93}
94
Simon Glass83b2bd52020-07-07 13:11:52 -060095void acpigen_write_byte(struct acpi_ctx *ctx, unsigned int data)
96{
97 acpigen_emit_byte(ctx, BYTE_PREFIX);
98 acpigen_emit_byte(ctx, data & 0xff);
99}
100
101void acpigen_write_word(struct acpi_ctx *ctx, unsigned int data)
102{
103 acpigen_emit_byte(ctx, WORD_PREFIX);
104 acpigen_emit_word(ctx, data);
105}
106
107void acpigen_write_dword(struct acpi_ctx *ctx, unsigned int data)
108{
109 acpigen_emit_byte(ctx, DWORD_PREFIX);
110 acpigen_emit_dword(ctx, data);
111}
112
113void acpigen_write_qword(struct acpi_ctx *ctx, u64 data)
114{
115 acpigen_emit_byte(ctx, QWORD_PREFIX);
116 acpigen_emit_dword(ctx, data & 0xffffffff);
117 acpigen_emit_dword(ctx, (data >> 32) & 0xffffffff);
118}
119
120void acpigen_write_zero(struct acpi_ctx *ctx)
121{
122 acpigen_emit_byte(ctx, ZERO_OP);
123}
124
125void acpigen_write_one(struct acpi_ctx *ctx)
126{
127 acpigen_emit_byte(ctx, ONE_OP);
128}
129
130void acpigen_write_integer(struct acpi_ctx *ctx, u64 data)
131{
132 if (data == 0)
133 acpigen_write_zero(ctx);
134 else if (data == 1)
135 acpigen_write_one(ctx);
136 else if (data <= 0xff)
137 acpigen_write_byte(ctx, (unsigned char)data);
138 else if (data <= 0xffff)
139 acpigen_write_word(ctx, (unsigned int)data);
140 else if (data <= 0xffffffff)
141 acpigen_write_dword(ctx, (unsigned int)data);
142 else
143 acpigen_write_qword(ctx, data);
144}
145
Simon Glass7fb8da42020-07-07 13:11:45 -0600146void acpigen_emit_stream(struct acpi_ctx *ctx, const char *data, int size)
147{
148 int i;
149
150 for (i = 0; i < size; i++)
151 acpigen_emit_byte(ctx, data[i]);
152}
153
154void acpigen_emit_string(struct acpi_ctx *ctx, const char *str)
155{
156 acpigen_emit_stream(ctx, str, str ? strlen(str) : 0);
157 acpigen_emit_byte(ctx, '\0');
158}
Simon Glass3df33bd2020-07-07 13:11:53 -0600159
160void acpigen_write_string(struct acpi_ctx *ctx, const char *str)
161{
162 acpigen_emit_byte(ctx, STRING_PREFIX);
163 acpigen_emit_string(ctx, str);
164}
Simon Glass7aed90d2020-07-07 13:11:54 -0600165
166/*
167 * The naming conventions for ACPI namespace names are a bit tricky as
168 * each element has to be 4 chars wide ("All names are a fixed 32 bits.")
169 * and "By convention, when an ASL compiler pads a name shorter than 4
170 * characters, it is done so with trailing underscores ('_')".
171 *
172 * Check sections 5.3, 20.2.2 and 20.4 of ACPI spec 6.3 for details.
173 */
174static void acpigen_emit_simple_namestring(struct acpi_ctx *ctx,
175 const char *name)
176{
177 const char *ptr;
178 int i;
179
180 for (i = 0, ptr = name; i < 4; i++) {
181 if (!*ptr || *ptr == '.')
182 acpigen_emit_byte(ctx, '_');
183 else
184 acpigen_emit_byte(ctx, *ptr++);
185 }
186}
187
188static void acpigen_emit_double_namestring(struct acpi_ctx *ctx,
189 const char *name, int dotpos)
190{
191 acpigen_emit_byte(ctx, DUAL_NAME_PREFIX);
192 acpigen_emit_simple_namestring(ctx, name);
193 acpigen_emit_simple_namestring(ctx, &name[dotpos + 1]);
194}
195
196static void acpigen_emit_multi_namestring(struct acpi_ctx *ctx,
197 const char *name)
198{
199 unsigned char *pathlen;
200 int count = 0;
201
202 acpigen_emit_byte(ctx, MULTI_NAME_PREFIX);
203 pathlen = ctx->current;
204 acpigen_emit_byte(ctx, 0);
205
206 while (*name) {
207 acpigen_emit_simple_namestring(ctx, name);
208 /* find end or next entity */
209 while (*name != '.' && *name)
210 name++;
211 /* forward to next */
212 if (*name == '.')
213 name++;
214 count++;
215 }
216
217 *pathlen = count;
218}
219
220void acpigen_emit_namestring(struct acpi_ctx *ctx, const char *namepath)
221{
222 int dotcount;
223 int dotpos;
224 int i;
225
226 /* We can start with a '\' */
227 if (*namepath == '\\') {
228 acpigen_emit_byte(ctx, '\\');
229 namepath++;
230 }
231
232 /* And there can be any number of '^' */
233 while (*namepath == '^') {
234 acpigen_emit_byte(ctx, '^');
235 namepath++;
236 }
237
238 for (i = 0, dotcount = 0; namepath[i]; i++) {
239 if (namepath[i] == '.') {
240 dotcount++;
241 dotpos = i;
242 }
243 }
244
245 /* If we have only \\ or only ^* then we need to add a null name */
246 if (!*namepath)
247 acpigen_emit_byte(ctx, ZERO_OP);
248 else if (dotcount == 0)
249 acpigen_emit_simple_namestring(ctx, namepath);
250 else if (dotcount == 1)
251 acpigen_emit_double_namestring(ctx, namepath, dotpos);
252 else
253 acpigen_emit_multi_namestring(ctx, namepath);
254}
255
256void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath)
257{
258 acpigen_emit_byte(ctx, NAME_OP);
259 acpigen_emit_namestring(ctx, namepath);
260}
Simon Glass29df8452020-07-07 13:11:55 -0600261
Simon Glass82659cc2020-07-07 21:32:10 -0600262void acpigen_write_scope(struct acpi_ctx *ctx, const char *scope)
263{
264 acpigen_emit_byte(ctx, SCOPE_OP);
265 acpigen_write_len_f(ctx);
266 acpigen_emit_namestring(ctx, scope);
267}
268
Simon Glass9c70e7e2020-07-07 13:11:59 -0600269static void acpigen_write_method_internal(struct acpi_ctx *ctx,
270 const char *name, uint flags)
271{
272 acpigen_emit_byte(ctx, METHOD_OP);
273 acpigen_write_len_f(ctx);
274 acpigen_emit_namestring(ctx, name);
275 acpigen_emit_byte(ctx, flags);
276}
277
278/* Method (name, nargs, NotSerialized) */
279void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs)
280{
281 acpigen_write_method_internal(ctx, name,
282 nargs & ACPI_METHOD_NARGS_MASK);
283}
284
285/* Method (name, nargs, Serialized) */
286void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
287 int nargs)
288{
289 acpigen_write_method_internal(ctx, name,
290 (nargs & ACPI_METHOD_NARGS_MASK) |
291 ACPI_METHOD_SERIALIZED_MASK);
292}
293
Simon Glass91c2f9c2020-07-07 21:32:14 -0600294void acpigen_write_device(struct acpi_ctx *ctx, const char *name)
295{
296 acpigen_emit_ext_op(ctx, DEVICE_OP);
297 acpigen_write_len_f(ctx);
298 acpigen_emit_namestring(ctx, name);
299}
300
Simon Glass9c70e7e2020-07-07 13:11:59 -0600301void acpigen_write_sta(struct acpi_ctx *ctx, uint status)
302{
303 /* Method (_STA, 0, NotSerialized) { Return (status) } */
304 acpigen_write_method(ctx, "_STA", 0);
305 acpigen_emit_byte(ctx, RETURN_OP);
306 acpigen_write_byte(ctx, status);
307 acpigen_pop_len(ctx);
308}
309
Simon Glassd7d631d2020-07-07 21:32:11 -0600310static void acpigen_write_register(struct acpi_ctx *ctx,
311 const struct acpi_gen_regaddr *addr)
312{
313 /* See ACPI v6.3 section 6.4.3.7: Generic Register Descriptor */
314 acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_REGISTER);
315 acpigen_emit_byte(ctx, 0x0c); /* Register Length 7:0 */
316 acpigen_emit_byte(ctx, 0x00); /* Register Length 15:8 */
317 acpigen_emit_byte(ctx, addr->space_id);
318 acpigen_emit_byte(ctx, addr->bit_width);
319 acpigen_emit_byte(ctx, addr->bit_offset);
320 acpigen_emit_byte(ctx, addr->access_size);
321 acpigen_emit_dword(ctx, addr->addrl);
322 acpigen_emit_dword(ctx, addr->addrh);
323}
324
325void acpigen_write_resourcetemplate_header(struct acpi_ctx *ctx)
326{
327 /*
328 * A ResourceTemplate() is a Buffer() with a
329 * (Byte|Word|DWord) containing the length, followed by one or more
330 * resource items, terminated by the end tag.
331 * (small item 0xf, len 1)
332 */
333 acpigen_emit_byte(ctx, BUFFER_OP);
334 acpigen_write_len_f(ctx);
335 acpigen_emit_byte(ctx, WORD_PREFIX);
336 ctx->len_stack[ctx->ltop++] = ctx->current;
337
338 /*
339 * Add two dummy bytes for the ACPI word (keep aligned with the
340 * calculation in acpigen_write_resourcetemplate_footer() below)
341 */
342 acpigen_emit_byte(ctx, 0x00);
343 acpigen_emit_byte(ctx, 0x00);
344}
345
346void acpigen_write_resourcetemplate_footer(struct acpi_ctx *ctx)
347{
348 char *p = ctx->len_stack[--ctx->ltop];
349 int len;
350 /*
351 * See ACPI v6.3 section 6.4.2.9: End Tag
352 * 0x79 <checksum>
353 * 0x00 is treated as a good checksum according to the spec
354 * and is what iasl generates.
355 */
356 acpigen_emit_byte(ctx, ACPI_END_TAG);
357 acpigen_emit_byte(ctx, 0x00);
358
359 /*
360 * Start counting past the 2-bytes length added in
361 * acpigen_write_resourcetemplate_header() above
362 */
363 len = (char *)ctx->current - (p + 2);
364
365 /* patch len word */
366 p[0] = len & 0xff;
367 p[1] = (len >> 8) & 0xff;
368
369 acpigen_pop_len(ctx);
370}
371
372void acpigen_write_register_resource(struct acpi_ctx *ctx,
373 const struct acpi_gen_regaddr *addr)
374{
375 acpigen_write_resourcetemplate_header(ctx);
376 acpigen_write_register(ctx, addr);
377 acpigen_write_resourcetemplate_footer(ctx);
378}
379
Simon Glass29df8452020-07-07 13:11:55 -0600380/*
381 * ToUUID(uuid)
382 *
383 * ACPI 6.3 Section 19.6.142 table 19-438 defines a special output order for the
384 * bytes that make up a UUID Buffer object:
385 *
386 * UUID byte order for input to this function:
387 * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
388 *
389 * UUID byte order output by this function:
390 * ddccbbaa-ffee-hhgg-iijj-kkllmmnnoopp
391 */
392int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid)
393{
394 u8 buf[UUID_BIN_LEN];
395 int ret;
396
397 /* Parse UUID string into bytes */
398 ret = uuid_str_to_bin(uuid, buf, UUID_STR_FORMAT_GUID);
399 if (ret)
400 return log_msg_ret("bad hex", -EINVAL);
401
402 /* BufferOp */
403 acpigen_emit_byte(ctx, BUFFER_OP);
404 acpigen_write_len_f(ctx);
405
406 /* Buffer length in bytes */
407 acpigen_write_word(ctx, UUID_BIN_LEN);
408
409 /* Output UUID in expected order */
410 acpigen_emit_stream(ctx, (char *)buf, UUID_BIN_LEN);
411
412 acpigen_pop_len(ctx);
413
414 return 0;
415}
Simon Glass9c70e7e2020-07-07 13:11:59 -0600416
Simon Glassf9189d52020-07-07 13:12:00 -0600417void acpigen_write_power_res(struct acpi_ctx *ctx, const char *name, uint level,
418 uint order, const char *const dev_states[],
419 size_t dev_states_count)
420{
421 size_t i;
422
423 for (i = 0; i < dev_states_count; i++) {
424 acpigen_write_name(ctx, dev_states[i]);
425 acpigen_write_package(ctx, 1);
426 acpigen_emit_simple_namestring(ctx, name);
427 acpigen_pop_len(ctx); /* Package */
428 }
429
430 acpigen_emit_ext_op(ctx, POWER_RES_OP);
431
432 acpigen_write_len_f(ctx);
433
434 acpigen_emit_simple_namestring(ctx, name);
435 acpigen_emit_byte(ctx, level);
436 acpigen_emit_word(ctx, order);
437}
438
Simon Glass9c70e7e2020-07-07 13:11:59 -0600439/* Sleep (ms) */
440void acpigen_write_sleep(struct acpi_ctx *ctx, u64 sleep_ms)
441{
442 acpigen_emit_ext_op(ctx, SLEEP_OP);
443 acpigen_write_integer(ctx, sleep_ms);
444}
445
446void acpigen_write_store(struct acpi_ctx *ctx)
447{
448 acpigen_emit_byte(ctx, STORE_OP);
449}
450
451/* Or (arg1, arg2, res) */
452void acpigen_write_or(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res)
453{
454 acpigen_emit_byte(ctx, OR_OP);
455 acpigen_emit_byte(ctx, arg1);
456 acpigen_emit_byte(ctx, arg2);
457 acpigen_emit_byte(ctx, res);
458}
459
460/* And (arg1, arg2, res) */
461void acpigen_write_and(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res)
462{
463 acpigen_emit_byte(ctx, AND_OP);
464 acpigen_emit_byte(ctx, arg1);
465 acpigen_emit_byte(ctx, arg2);
466 acpigen_emit_byte(ctx, res);
467}
468
469/* Not (arg, res) */
470void acpigen_write_not(struct acpi_ctx *ctx, u8 arg, u8 res)
471{
472 acpigen_emit_byte(ctx, NOT_OP);
473 acpigen_emit_byte(ctx, arg);
474 acpigen_emit_byte(ctx, res);
475}
476
477/* Store (str, DEBUG) */
478void acpigen_write_debug_string(struct acpi_ctx *ctx, const char *str)
479{
480 acpigen_write_store(ctx);
481 acpigen_write_string(ctx, str);
482 acpigen_emit_ext_op(ctx, DEBUG_OP);
483}
Simon Glassf8054dd2020-07-07 13:12:01 -0600484
485/**
486 * acpigen_get_dw0_in_local5() - Generate code to put dw0 cfg0 in local5
487 *
488 * Store (\_SB.GPC0 (addr), Local5)
489 *
490 * \_SB.GPC0 is used to read cfg0 value from dw0. It is typically defined in
491 * the board's gpiolib.asl
492 *
493 * The value needs to be stored in a local variable so that it can be used in
494 * expressions in the ACPI code.
495 *
496 * @ctx: ACPI context pointer
497 * @dw0_read: Name to use to read dw0, e.g. "\\_SB.GPC0"
498 * @addr: GPIO pin configuration register address
499 *
500 */
501static void acpigen_get_dw0_in_local5(struct acpi_ctx *ctx,
502 const char *dw0_read, ulong addr)
503{
504 acpigen_write_store(ctx);
505 acpigen_emit_namestring(ctx, dw0_read);
506 acpigen_write_integer(ctx, addr);
507 acpigen_emit_byte(ctx, LOCAL5_OP);
508}
509
510/**
511 * acpigen_set_gpio_val() - Emit code to set value of TX GPIO to on/off
512 *
513 * @ctx: ACPI context pointer
514 * @dw0_read: Method name to use to read dw0, e.g. "\\_SB.GPC0"
515 * @dw0_write: Method name to use to read dw0, e.g. "\\_SB.SPC0"
516 * @gpio_num: GPIO number to adjust
517 * @vaL: true to set on, false to set off
518 */
519static int acpigen_set_gpio_val(struct acpi_ctx *ctx, u32 tx_state_val,
520 const char *dw0_read, const char *dw0_write,
521 struct acpi_gpio *gpio, bool val)
522{
523 acpigen_get_dw0_in_local5(ctx, dw0_read, gpio->pin0_addr);
524
525 /* Store (0x40, Local0) */
526 acpigen_write_store(ctx);
527 acpigen_write_integer(ctx, tx_state_val);
528 acpigen_emit_byte(ctx, LOCAL0_OP);
529
530 if (val) {
531 /* Or (Local5, PAD_CFG0_TX_STATE, Local5) */
532 acpigen_write_or(ctx, LOCAL5_OP, LOCAL0_OP, LOCAL5_OP);
533 } else {
534 /* Not (PAD_CFG0_TX_STATE, Local6) */
535 acpigen_write_not(ctx, LOCAL0_OP, LOCAL6_OP);
536
537 /* And (Local5, Local6, Local5) */
538 acpigen_write_and(ctx, LOCAL5_OP, LOCAL6_OP, LOCAL5_OP);
539 }
540
541 /*
542 * \_SB.SPC0 (addr, Local5)
543 * \_SB.SPC0 is used to write cfg0 value in dw0. It is defined in
544 * gpiolib.asl.
545 */
546 acpigen_emit_namestring(ctx, dw0_write);
547 acpigen_write_integer(ctx, gpio->pin0_addr);
548 acpigen_emit_byte(ctx, LOCAL5_OP);
549
550 return 0;
551}
552
553int acpigen_set_enable_tx_gpio(struct acpi_ctx *ctx, u32 tx_state_val,
554 const char *dw0_read, const char *dw0_write,
555 struct acpi_gpio *gpio, bool enable)
556{
557 bool set;
558 int ret;
559
560 set = gpio->polarity == ACPI_GPIO_ACTIVE_HIGH ? enable : !enable;
561 ret = acpigen_set_gpio_val(ctx, tx_state_val, dw0_read, dw0_write, gpio,
562 set);
563 if (ret)
564 return log_msg_ret("call", ret);
565
566 return 0;
567}