blob: 187001d2fcbcd0e1f0eb0b37317e610aa7a6e69a [file] [log] [blame]
Simon Glass61cc9332020-07-07 13:11:42 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Tests for ACPI code generation
4 *
5 * Copyright 2019 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#include <common.h>
10#include <dm.h>
Simon Glassff715c62020-07-07 13:11:43 -060011#include <irq.h>
Simon Glass61cc9332020-07-07 13:11:42 -060012#include <malloc.h>
13#include <acpi/acpigen.h>
Simon Glassff715c62020-07-07 13:11:43 -060014#include <acpi/acpi_device.h>
Simon Glassa9e0a072020-07-07 13:11:46 -060015#include <asm/gpio.h>
Simon Glass61cc9332020-07-07 13:11:42 -060016#include <asm/unaligned.h>
17#include <dm/acpi.h>
18#include <dm/test.h>
Simon Glass4ebc9402020-07-07 13:11:47 -060019#include <dm/uclass-internal.h>
Simon Glass61cc9332020-07-07 13:11:42 -060020#include <test/ut.h>
21
22/* Maximum size of the ACPI context needed for most tests */
23#define ACPI_CONTEXT_SIZE 150
24
Simon Glass7fb8da42020-07-07 13:11:45 -060025#define TEST_STRING "frogmore"
26#define TEST_STREAM2 "\xfa\xde"
27
Simon Glass83b2bd52020-07-07 13:11:52 -060028#define TEST_INT8 0x7d
29#define TEST_INT16 0x2345
30#define TEST_INT32 0x12345678
31#define TEST_INT64 0x4567890123456
32
Simon Glass7e148f22020-07-07 13:11:50 -060033static int alloc_context_size(struct acpi_ctx **ctxp, int size)
Simon Glass61cc9332020-07-07 13:11:42 -060034{
35 struct acpi_ctx *ctx;
36
37 *ctxp = NULL;
38 ctx = malloc(sizeof(*ctx));
39 if (!ctx)
40 return -ENOMEM;
Simon Glass7e148f22020-07-07 13:11:50 -060041 ctx->base = malloc(size);
Simon Glass61cc9332020-07-07 13:11:42 -060042 if (!ctx->base) {
43 free(ctx);
44 return -ENOMEM;
45 }
Simon Glass7e148f22020-07-07 13:11:50 -060046 ctx->ltop = 0;
Simon Glass61cc9332020-07-07 13:11:42 -060047 ctx->current = ctx->base;
48 *ctxp = ctx;
49
50 return 0;
51}
52
Simon Glass7e148f22020-07-07 13:11:50 -060053static int alloc_context(struct acpi_ctx **ctxp)
54{
55 return alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
56}
57
Simon Glass61cc9332020-07-07 13:11:42 -060058static void free_context(struct acpi_ctx **ctxp)
59{
60 free((*ctxp)->base);
61 free(*ctxp);
62 *ctxp = NULL;
63}
64
65/* Test emitting simple types and acpigen_get_current() */
66static int dm_test_acpi_emit_simple(struct unit_test_state *uts)
67{
68 struct acpi_ctx *ctx;
69 u8 *ptr;
70
71 ut_assertok(alloc_context(&ctx));
72
73 ptr = acpigen_get_current(ctx);
74 acpigen_emit_byte(ctx, 0x23);
75 ut_asserteq(1, acpigen_get_current(ctx) - ptr);
76 ut_asserteq(0x23, *(u8 *)ptr);
77
78 acpigen_emit_word(ctx, 0x1234);
79 ut_asserteq(3, acpigen_get_current(ctx) - ptr);
80 ut_asserteq(0x1234, get_unaligned((u16 *)(ptr + 1)));
81
82 acpigen_emit_dword(ctx, 0x87654321);
83 ut_asserteq(7, acpigen_get_current(ctx) - ptr);
84 ut_asserteq(0x87654321, get_unaligned((u32 *)(ptr + 3)));
85
86 free_context(&ctx);
87
88 return 0;
89}
90DM_TEST(dm_test_acpi_emit_simple, 0);
Simon Glassff715c62020-07-07 13:11:43 -060091
Simon Glass7fb8da42020-07-07 13:11:45 -060092/* Test emitting a stream */
93static int dm_test_acpi_emit_stream(struct unit_test_state *uts)
94{
95 struct acpi_ctx *ctx;
96 u8 *ptr;
97
98 ut_assertok(alloc_context(&ctx));
99
100 ptr = acpigen_get_current(ctx);
101 acpigen_emit_stream(ctx, TEST_STREAM2, 2);
102 ut_asserteq(2, acpigen_get_current(ctx) - ptr);
103 ut_asserteq((u8)TEST_STREAM2[0], ptr[0]);
104 ut_asserteq((u8)TEST_STREAM2[1], ptr[1]);
105
106 free_context(&ctx);
107
108 return 0;
109}
110DM_TEST(dm_test_acpi_emit_stream, 0);
111
112/* Test emitting a string */
113static int dm_test_acpi_emit_string(struct unit_test_state *uts)
114{
115 struct acpi_ctx *ctx;
116 u8 *ptr;
117
118 ut_assertok(alloc_context(&ctx));
119
120 ptr = acpigen_get_current(ctx);
121 acpigen_emit_string(ctx, TEST_STRING);
122 ut_asserteq(sizeof(TEST_STRING), acpigen_get_current(ctx) - ptr);
123 ut_asserteq_str(TEST_STRING, (char *)ptr);
124
125 free_context(&ctx);
126
127 return 0;
128}
129DM_TEST(dm_test_acpi_emit_string, 0);
130
Simon Glassff715c62020-07-07 13:11:43 -0600131/* Test emitting an interrupt descriptor */
132static int dm_test_acpi_interrupt(struct unit_test_state *uts)
133{
134 struct acpi_ctx *ctx;
135 struct udevice *dev;
136 struct irq irq;
137 u8 *ptr;
138
139 ut_assertok(alloc_context(&ctx));
140
141 ptr = acpigen_get_current(ctx);
142
143 ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
144 ut_assertok(irq_get_by_index(dev, 0, &irq));
145
146 /* See a-test, property interrupts-extended in the device tree */
147 ut_asserteq(3, acpi_device_write_interrupt_irq(ctx, &irq));
148 ut_asserteq(9, acpigen_get_current(ctx) - ptr);
149 ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
150 ut_asserteq(6, get_unaligned((u16 *)(ptr + 1)));
151 ut_asserteq(0x19, ptr[3]);
152 ut_asserteq(1, ptr[4]);
153 ut_asserteq(3, get_unaligned((u32 *)(ptr + 5)));
154
155 free_context(&ctx);
156
157 return 0;
158}
159DM_TEST(dm_test_acpi_interrupt, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glassa9e0a072020-07-07 13:11:46 -0600160
161/* Test emitting a GPIO descriptor */
162static int dm_test_acpi_gpio(struct unit_test_state *uts)
163{
164 struct gpio_desc desc;
165 struct acpi_ctx *ctx;
166 struct udevice *dev;
167 u8 *ptr;
168
169 ut_assertok(alloc_context(&ctx));
170
171 ptr = acpigen_get_current(ctx);
172
173 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
174 ut_asserteq_str("a-test", dev->name);
175 ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
176
177 /* This should write GPIO pin 4 (see device tree test.dts ) */
178 ut_asserteq(4, acpi_device_write_gpio_desc(ctx, &desc));
179 ut_asserteq(35, acpigen_get_current(ctx) - ptr);
180 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
181 ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
182 ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
183 ut_asserteq(ACPI_GPIO_TYPE_IO, ptr[4]);
184 ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
185 ut_asserteq(9, get_unaligned((u16 *)(ptr + 7)));
186 ut_asserteq(ACPI_GPIO_PULL_UP, ptr[9]);
187 ut_asserteq(1234, get_unaligned((u16 *)(ptr + 10)));
188 ut_asserteq(0, get_unaligned((u16 *)(ptr + 12)));
189 ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
190 ut_asserteq(0, ptr[16]);
191 ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
192 ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
193 ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
194
195 /* pin0 */
196 ut_asserteq(4, get_unaligned((u16 *)(ptr + 23)));
197
198 ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
199
200 free_context(&ctx);
201
202 return 0;
203}
204DM_TEST(dm_test_acpi_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
205
206/* Test emitting a GPIO descriptor with an interrupt */
207static int dm_test_acpi_gpio_irq(struct unit_test_state *uts)
208{
209 struct gpio_desc desc;
210 struct acpi_ctx *ctx;
211 struct udevice *dev;
212 u8 *ptr;
213
214 ut_assertok(alloc_context(&ctx));
215
216 ptr = acpigen_get_current(ctx);
217
218 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
219 ut_asserteq_str("a-test", dev->name);
220 ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0));
221
222 /* This should write GPIO pin 6 (see device tree test.dts ) */
223 ut_asserteq(6, acpi_device_write_gpio_desc(ctx, &desc));
224 ut_asserteq(35, acpigen_get_current(ctx) - ptr);
225 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
226 ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
227 ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
228 ut_asserteq(ACPI_GPIO_TYPE_INTERRUPT, ptr[4]);
229 ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
230 ut_asserteq(29, get_unaligned((u16 *)(ptr + 7)));
231 ut_asserteq(ACPI_GPIO_PULL_DOWN, ptr[9]);
232 ut_asserteq(0, get_unaligned((u16 *)(ptr + 10)));
233 ut_asserteq(4321, get_unaligned((u16 *)(ptr + 12)));
234 ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
235 ut_asserteq(0, ptr[16]);
236 ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
237 ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
238 ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
239
240 /* pin0 */
241 ut_asserteq(6, get_unaligned((u16 *)(ptr + 23)));
242
243 ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
244
245 free_context(&ctx);
246
247 return 0;
248}
249DM_TEST(dm_test_acpi_gpio_irq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass4ebc9402020-07-07 13:11:47 -0600250
251/* Test emitting either a GPIO or interrupt descriptor */
252static int dm_test_acpi_interrupt_or_gpio(struct unit_test_state *uts)
253{
254 struct acpi_ctx *ctx;
255 struct udevice *dev;
256 u8 *ptr;
257
258 ut_assertok(alloc_context(&ctx));
259
260 ptr = acpigen_get_current(ctx);
261
262 /* This should produce an interrupt, even though it also has a GPIO */
263 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
264 ut_asserteq_str("a-test", dev->name);
265 ut_asserteq(3, acpi_device_write_interrupt_or_gpio(ctx, dev,
266 "test2-gpios"));
267 ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
268
269 /* This has no interrupt so should produce a GPIO */
270 ptr = ctx->current;
271 ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &dev));
272 ut_asserteq(1, acpi_device_write_interrupt_or_gpio(ctx, dev,
273 "enable-gpios"));
274 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
275
276 /* This one has neither */
277 ptr = acpigen_get_current(ctx);
278 ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev));
279 ut_asserteq_str("b-test", dev->name);
280 ut_asserteq(-ENOENT,
281 acpi_device_write_interrupt_or_gpio(ctx, dev,
282 "enable-gpios"));
283
284 free_context(&ctx);
285
286 return 0;
287}
288DM_TEST(dm_test_acpi_interrupt_or_gpio,
289 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass31e17872020-07-07 13:11:48 -0600290
291/* Test emitting an I2C descriptor */
292static int dm_test_acpi_i2c(struct unit_test_state *uts)
293{
294 struct acpi_ctx *ctx;
295 struct udevice *dev;
296 u8 *ptr;
297
298 ut_assertok(alloc_context(&ctx));
299
300 ptr = acpigen_get_current(ctx);
301
302 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
303 ut_asserteq(0x43, acpi_device_write_i2c_dev(ctx, dev));
304 ut_asserteq(28, acpigen_get_current(ctx) - ptr);
305 ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]);
306 ut_asserteq(25, get_unaligned((u16 *)(ptr + 1)));
307 ut_asserteq(ACPI_I2C_SERIAL_BUS_REVISION_ID, ptr[3]);
308 ut_asserteq(0, ptr[4]);
309 ut_asserteq(ACPI_SERIAL_BUS_TYPE_I2C, ptr[5]);
310 ut_asserteq(0, get_unaligned((u16 *)(ptr + 7)));
311 ut_asserteq(ACPI_I2C_TYPE_SPECIFIC_REVISION_ID, ptr[9]);
312 ut_asserteq(6, get_unaligned((u16 *)(ptr + 10)));
313 ut_asserteq(100000, get_unaligned((u32 *)(ptr + 12)));
314 ut_asserteq(0x43, get_unaligned((u16 *)(ptr + 16)));
315 ut_asserteq_str("\\_SB.I2C0", (char *)ptr + 18);
316
317 free_context(&ctx);
318
319 return 0;
320}
321DM_TEST(dm_test_acpi_i2c, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass70e5e672020-07-07 13:11:49 -0600322
323/* Test emitting a SPI descriptor */
324static int dm_test_acpi_spi(struct unit_test_state *uts)
325{
326 struct acpi_ctx *ctx;
327 struct udevice *dev;
328 u8 *ptr;
329
330 ut_assertok(alloc_context(&ctx));
331
332 ptr = acpigen_get_current(ctx);
333
334 ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev));
335 ut_assertok(acpi_device_write_spi_dev(ctx, dev));
336 ut_asserteq(31, acpigen_get_current(ctx) - ptr);
337 ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]);
338 ut_asserteq(28, get_unaligned((u16 *)(ptr + 1)));
339 ut_asserteq(ACPI_SPI_SERIAL_BUS_REVISION_ID, ptr[3]);
340 ut_asserteq(0, ptr[4]);
341 ut_asserteq(ACPI_SERIAL_BUS_TYPE_SPI, ptr[5]);
342 ut_asserteq(2, ptr[6]);
343 ut_asserteq(0, get_unaligned((u16 *)(ptr + 7)));
344 ut_asserteq(ACPI_SPI_TYPE_SPECIFIC_REVISION_ID, ptr[9]);
345 ut_asserteq(9, get_unaligned((u16 *)(ptr + 10)));
346 ut_asserteq(40000000, get_unaligned((u32 *)(ptr + 12)));
347 ut_asserteq(8, ptr[16]);
348 ut_asserteq(0, ptr[17]);
349 ut_asserteq(0, ptr[18]);
350 ut_asserteq(0, get_unaligned((u16 *)(ptr + 19)));
351 ut_asserteq_str("\\_SB.SPI0", (char *)ptr + 21);
352
353 free_context(&ctx);
354
355 return 0;
356}
357DM_TEST(dm_test_acpi_spi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass7e148f22020-07-07 13:11:50 -0600358
359/**
360 * get_length() - decode a three-byte length field
361 *
362 * @ptr: Length encoded as per ACPI
363 * @return decoded length, or -EINVAL on error
364 */
365static int get_length(u8 *ptr)
366{
367 if (!(*ptr & 0x80))
368 return -EINVAL;
369
370 return (*ptr & 0xf) | ptr[1] << 4 | ptr[2] << 12;
371}
372
373/* Test emitting a length */
374static int dm_test_acpi_len(struct unit_test_state *uts)
375{
376 const int size = 0xc0000;
377 struct acpi_ctx *ctx;
378 u8 *ptr;
379 int i;
380
381 ut_assertok(alloc_context_size(&ctx, size));
382
383 ptr = acpigen_get_current(ctx);
384
385 /* Write a byte and a 3-byte length */
386 acpigen_write_len_f(ctx);
387 acpigen_emit_byte(ctx, 0x23);
388 acpigen_pop_len(ctx);
389 ut_asserteq(1 + 3, get_length(ptr));
390
391 /* Write 200 bytes so we need two length bytes */
392 ptr = ctx->current;
393 acpigen_write_len_f(ctx);
394 for (i = 0; i < 200; i++)
395 acpigen_emit_byte(ctx, 0x23);
396 acpigen_pop_len(ctx);
397 ut_asserteq(200 + 3, get_length(ptr));
398
399 /* Write 40KB so we need three length bytes */
400 ptr = ctx->current;
401 acpigen_write_len_f(ctx);
402 for (i = 0; i < 40000; i++)
403 acpigen_emit_byte(ctx, 0x23);
404 acpigen_pop_len(ctx);
405 ut_asserteq(40000 + 3, get_length(ptr));
406
407 free_context(&ctx);
408
409 return 0;
410}
411DM_TEST(dm_test_acpi_len, 0);
Simon Glass03967ce2020-07-07 13:11:51 -0600412
413/* Test writing a package */
414static int dm_test_acpi_package(struct unit_test_state *uts)
415{
416 struct acpi_ctx *ctx;
417 char *num_elements;
418 u8 *ptr;
419
420 ut_assertok(alloc_context(&ctx));
421
422 ptr = acpigen_get_current(ctx);
423
424 num_elements = acpigen_write_package(ctx, 3);
425 ut_asserteq_ptr(num_elements, ptr + 4);
426
427 /* For ease of testing, just emit a byte, not valid package contents */
428 acpigen_emit_byte(ctx, 0x23);
429 acpigen_pop_len(ctx);
430 ut_asserteq(PACKAGE_OP, ptr[0]);
431 ut_asserteq(5, get_length(ptr + 1));
432 ut_asserteq(3, ptr[4]);
433
434 free_context(&ctx);
435
436 return 0;
437}
438DM_TEST(dm_test_acpi_package, 0);
Simon Glass83b2bd52020-07-07 13:11:52 -0600439
440/* Test writing an integer */
441static int dm_test_acpi_integer(struct unit_test_state *uts)
442{
443 struct acpi_ctx *ctx;
444 u8 *ptr;
445
446 ut_assertok(alloc_context(&ctx));
447
448 ptr = acpigen_get_current(ctx);
449
450 acpigen_write_integer(ctx, 0);
451 acpigen_write_integer(ctx, 1);
452 acpigen_write_integer(ctx, TEST_INT8);
453 acpigen_write_integer(ctx, TEST_INT16);
454 acpigen_write_integer(ctx, TEST_INT32);
455 acpigen_write_integer(ctx, TEST_INT64);
456
457 ut_asserteq(6 + 1 + 2 + 4 + 8, acpigen_get_current(ctx) - ptr);
458
459 ut_asserteq(ZERO_OP, ptr[0]);
460
461 ut_asserteq(ONE_OP, ptr[1]);
462
463 ut_asserteq(BYTE_PREFIX, ptr[2]);
464 ut_asserteq(TEST_INT8, ptr[3]);
465
466 ut_asserteq(WORD_PREFIX, ptr[4]);
467 ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 5)));
468
469 ut_asserteq(DWORD_PREFIX, ptr[7]);
470 ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 8)));
471
472 ut_asserteq(QWORD_PREFIX, ptr[12]);
473 ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 13)));
474
475 free_context(&ctx);
476
477 return 0;
478}
479DM_TEST(dm_test_acpi_integer, 0);