blob: aaffc6a4cf5696b1d307ec9d747f0255588c4b90 [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 Glass7e148f22020-07-07 13:11:50 -060028static int alloc_context_size(struct acpi_ctx **ctxp, int size)
Simon Glass61cc9332020-07-07 13:11:42 -060029{
30 struct acpi_ctx *ctx;
31
32 *ctxp = NULL;
33 ctx = malloc(sizeof(*ctx));
34 if (!ctx)
35 return -ENOMEM;
Simon Glass7e148f22020-07-07 13:11:50 -060036 ctx->base = malloc(size);
Simon Glass61cc9332020-07-07 13:11:42 -060037 if (!ctx->base) {
38 free(ctx);
39 return -ENOMEM;
40 }
Simon Glass7e148f22020-07-07 13:11:50 -060041 ctx->ltop = 0;
Simon Glass61cc9332020-07-07 13:11:42 -060042 ctx->current = ctx->base;
43 *ctxp = ctx;
44
45 return 0;
46}
47
Simon Glass7e148f22020-07-07 13:11:50 -060048static int alloc_context(struct acpi_ctx **ctxp)
49{
50 return alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
51}
52
Simon Glass61cc9332020-07-07 13:11:42 -060053static void free_context(struct acpi_ctx **ctxp)
54{
55 free((*ctxp)->base);
56 free(*ctxp);
57 *ctxp = NULL;
58}
59
60/* Test emitting simple types and acpigen_get_current() */
61static int dm_test_acpi_emit_simple(struct unit_test_state *uts)
62{
63 struct acpi_ctx *ctx;
64 u8 *ptr;
65
66 ut_assertok(alloc_context(&ctx));
67
68 ptr = acpigen_get_current(ctx);
69 acpigen_emit_byte(ctx, 0x23);
70 ut_asserteq(1, acpigen_get_current(ctx) - ptr);
71 ut_asserteq(0x23, *(u8 *)ptr);
72
73 acpigen_emit_word(ctx, 0x1234);
74 ut_asserteq(3, acpigen_get_current(ctx) - ptr);
75 ut_asserteq(0x1234, get_unaligned((u16 *)(ptr + 1)));
76
77 acpigen_emit_dword(ctx, 0x87654321);
78 ut_asserteq(7, acpigen_get_current(ctx) - ptr);
79 ut_asserteq(0x87654321, get_unaligned((u32 *)(ptr + 3)));
80
81 free_context(&ctx);
82
83 return 0;
84}
85DM_TEST(dm_test_acpi_emit_simple, 0);
Simon Glassff715c62020-07-07 13:11:43 -060086
Simon Glass7fb8da42020-07-07 13:11:45 -060087/* Test emitting a stream */
88static int dm_test_acpi_emit_stream(struct unit_test_state *uts)
89{
90 struct acpi_ctx *ctx;
91 u8 *ptr;
92
93 ut_assertok(alloc_context(&ctx));
94
95 ptr = acpigen_get_current(ctx);
96 acpigen_emit_stream(ctx, TEST_STREAM2, 2);
97 ut_asserteq(2, acpigen_get_current(ctx) - ptr);
98 ut_asserteq((u8)TEST_STREAM2[0], ptr[0]);
99 ut_asserteq((u8)TEST_STREAM2[1], ptr[1]);
100
101 free_context(&ctx);
102
103 return 0;
104}
105DM_TEST(dm_test_acpi_emit_stream, 0);
106
107/* Test emitting a string */
108static int dm_test_acpi_emit_string(struct unit_test_state *uts)
109{
110 struct acpi_ctx *ctx;
111 u8 *ptr;
112
113 ut_assertok(alloc_context(&ctx));
114
115 ptr = acpigen_get_current(ctx);
116 acpigen_emit_string(ctx, TEST_STRING);
117 ut_asserteq(sizeof(TEST_STRING), acpigen_get_current(ctx) - ptr);
118 ut_asserteq_str(TEST_STRING, (char *)ptr);
119
120 free_context(&ctx);
121
122 return 0;
123}
124DM_TEST(dm_test_acpi_emit_string, 0);
125
Simon Glassff715c62020-07-07 13:11:43 -0600126/* Test emitting an interrupt descriptor */
127static int dm_test_acpi_interrupt(struct unit_test_state *uts)
128{
129 struct acpi_ctx *ctx;
130 struct udevice *dev;
131 struct irq irq;
132 u8 *ptr;
133
134 ut_assertok(alloc_context(&ctx));
135
136 ptr = acpigen_get_current(ctx);
137
138 ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
139 ut_assertok(irq_get_by_index(dev, 0, &irq));
140
141 /* See a-test, property interrupts-extended in the device tree */
142 ut_asserteq(3, acpi_device_write_interrupt_irq(ctx, &irq));
143 ut_asserteq(9, acpigen_get_current(ctx) - ptr);
144 ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
145 ut_asserteq(6, get_unaligned((u16 *)(ptr + 1)));
146 ut_asserteq(0x19, ptr[3]);
147 ut_asserteq(1, ptr[4]);
148 ut_asserteq(3, get_unaligned((u32 *)(ptr + 5)));
149
150 free_context(&ctx);
151
152 return 0;
153}
154DM_TEST(dm_test_acpi_interrupt, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glassa9e0a072020-07-07 13:11:46 -0600155
156/* Test emitting a GPIO descriptor */
157static int dm_test_acpi_gpio(struct unit_test_state *uts)
158{
159 struct gpio_desc desc;
160 struct acpi_ctx *ctx;
161 struct udevice *dev;
162 u8 *ptr;
163
164 ut_assertok(alloc_context(&ctx));
165
166 ptr = acpigen_get_current(ctx);
167
168 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
169 ut_asserteq_str("a-test", dev->name);
170 ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
171
172 /* This should write GPIO pin 4 (see device tree test.dts ) */
173 ut_asserteq(4, acpi_device_write_gpio_desc(ctx, &desc));
174 ut_asserteq(35, acpigen_get_current(ctx) - ptr);
175 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
176 ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
177 ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
178 ut_asserteq(ACPI_GPIO_TYPE_IO, ptr[4]);
179 ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
180 ut_asserteq(9, get_unaligned((u16 *)(ptr + 7)));
181 ut_asserteq(ACPI_GPIO_PULL_UP, ptr[9]);
182 ut_asserteq(1234, get_unaligned((u16 *)(ptr + 10)));
183 ut_asserteq(0, get_unaligned((u16 *)(ptr + 12)));
184 ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
185 ut_asserteq(0, ptr[16]);
186 ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
187 ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
188 ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
189
190 /* pin0 */
191 ut_asserteq(4, get_unaligned((u16 *)(ptr + 23)));
192
193 ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
194
195 free_context(&ctx);
196
197 return 0;
198}
199DM_TEST(dm_test_acpi_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
200
201/* Test emitting a GPIO descriptor with an interrupt */
202static int dm_test_acpi_gpio_irq(struct unit_test_state *uts)
203{
204 struct gpio_desc desc;
205 struct acpi_ctx *ctx;
206 struct udevice *dev;
207 u8 *ptr;
208
209 ut_assertok(alloc_context(&ctx));
210
211 ptr = acpigen_get_current(ctx);
212
213 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
214 ut_asserteq_str("a-test", dev->name);
215 ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0));
216
217 /* This should write GPIO pin 6 (see device tree test.dts ) */
218 ut_asserteq(6, acpi_device_write_gpio_desc(ctx, &desc));
219 ut_asserteq(35, acpigen_get_current(ctx) - ptr);
220 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
221 ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
222 ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
223 ut_asserteq(ACPI_GPIO_TYPE_INTERRUPT, ptr[4]);
224 ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
225 ut_asserteq(29, get_unaligned((u16 *)(ptr + 7)));
226 ut_asserteq(ACPI_GPIO_PULL_DOWN, ptr[9]);
227 ut_asserteq(0, get_unaligned((u16 *)(ptr + 10)));
228 ut_asserteq(4321, get_unaligned((u16 *)(ptr + 12)));
229 ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
230 ut_asserteq(0, ptr[16]);
231 ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
232 ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
233 ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
234
235 /* pin0 */
236 ut_asserteq(6, get_unaligned((u16 *)(ptr + 23)));
237
238 ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
239
240 free_context(&ctx);
241
242 return 0;
243}
244DM_TEST(dm_test_acpi_gpio_irq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass4ebc9402020-07-07 13:11:47 -0600245
246/* Test emitting either a GPIO or interrupt descriptor */
247static int dm_test_acpi_interrupt_or_gpio(struct unit_test_state *uts)
248{
249 struct acpi_ctx *ctx;
250 struct udevice *dev;
251 u8 *ptr;
252
253 ut_assertok(alloc_context(&ctx));
254
255 ptr = acpigen_get_current(ctx);
256
257 /* This should produce an interrupt, even though it also has a GPIO */
258 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
259 ut_asserteq_str("a-test", dev->name);
260 ut_asserteq(3, acpi_device_write_interrupt_or_gpio(ctx, dev,
261 "test2-gpios"));
262 ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
263
264 /* This has no interrupt so should produce a GPIO */
265 ptr = ctx->current;
266 ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &dev));
267 ut_asserteq(1, acpi_device_write_interrupt_or_gpio(ctx, dev,
268 "enable-gpios"));
269 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
270
271 /* This one has neither */
272 ptr = acpigen_get_current(ctx);
273 ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev));
274 ut_asserteq_str("b-test", dev->name);
275 ut_asserteq(-ENOENT,
276 acpi_device_write_interrupt_or_gpio(ctx, dev,
277 "enable-gpios"));
278
279 free_context(&ctx);
280
281 return 0;
282}
283DM_TEST(dm_test_acpi_interrupt_or_gpio,
284 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass31e17872020-07-07 13:11:48 -0600285
286/* Test emitting an I2C descriptor */
287static int dm_test_acpi_i2c(struct unit_test_state *uts)
288{
289 struct acpi_ctx *ctx;
290 struct udevice *dev;
291 u8 *ptr;
292
293 ut_assertok(alloc_context(&ctx));
294
295 ptr = acpigen_get_current(ctx);
296
297 ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
298 ut_asserteq(0x43, acpi_device_write_i2c_dev(ctx, dev));
299 ut_asserteq(28, acpigen_get_current(ctx) - ptr);
300 ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]);
301 ut_asserteq(25, get_unaligned((u16 *)(ptr + 1)));
302 ut_asserteq(ACPI_I2C_SERIAL_BUS_REVISION_ID, ptr[3]);
303 ut_asserteq(0, ptr[4]);
304 ut_asserteq(ACPI_SERIAL_BUS_TYPE_I2C, ptr[5]);
305 ut_asserteq(0, get_unaligned((u16 *)(ptr + 7)));
306 ut_asserteq(ACPI_I2C_TYPE_SPECIFIC_REVISION_ID, ptr[9]);
307 ut_asserteq(6, get_unaligned((u16 *)(ptr + 10)));
308 ut_asserteq(100000, get_unaligned((u32 *)(ptr + 12)));
309 ut_asserteq(0x43, get_unaligned((u16 *)(ptr + 16)));
310 ut_asserteq_str("\\_SB.I2C0", (char *)ptr + 18);
311
312 free_context(&ctx);
313
314 return 0;
315}
316DM_TEST(dm_test_acpi_i2c, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass70e5e672020-07-07 13:11:49 -0600317
318/* Test emitting a SPI descriptor */
319static int dm_test_acpi_spi(struct unit_test_state *uts)
320{
321 struct acpi_ctx *ctx;
322 struct udevice *dev;
323 u8 *ptr;
324
325 ut_assertok(alloc_context(&ctx));
326
327 ptr = acpigen_get_current(ctx);
328
329 ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev));
330 ut_assertok(acpi_device_write_spi_dev(ctx, dev));
331 ut_asserteq(31, acpigen_get_current(ctx) - ptr);
332 ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]);
333 ut_asserteq(28, get_unaligned((u16 *)(ptr + 1)));
334 ut_asserteq(ACPI_SPI_SERIAL_BUS_REVISION_ID, ptr[3]);
335 ut_asserteq(0, ptr[4]);
336 ut_asserteq(ACPI_SERIAL_BUS_TYPE_SPI, ptr[5]);
337 ut_asserteq(2, ptr[6]);
338 ut_asserteq(0, get_unaligned((u16 *)(ptr + 7)));
339 ut_asserteq(ACPI_SPI_TYPE_SPECIFIC_REVISION_ID, ptr[9]);
340 ut_asserteq(9, get_unaligned((u16 *)(ptr + 10)));
341 ut_asserteq(40000000, get_unaligned((u32 *)(ptr + 12)));
342 ut_asserteq(8, ptr[16]);
343 ut_asserteq(0, ptr[17]);
344 ut_asserteq(0, ptr[18]);
345 ut_asserteq(0, get_unaligned((u16 *)(ptr + 19)));
346 ut_asserteq_str("\\_SB.SPI0", (char *)ptr + 21);
347
348 free_context(&ctx);
349
350 return 0;
351}
352DM_TEST(dm_test_acpi_spi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass7e148f22020-07-07 13:11:50 -0600353
354/**
355 * get_length() - decode a three-byte length field
356 *
357 * @ptr: Length encoded as per ACPI
358 * @return decoded length, or -EINVAL on error
359 */
360static int get_length(u8 *ptr)
361{
362 if (!(*ptr & 0x80))
363 return -EINVAL;
364
365 return (*ptr & 0xf) | ptr[1] << 4 | ptr[2] << 12;
366}
367
368/* Test emitting a length */
369static int dm_test_acpi_len(struct unit_test_state *uts)
370{
371 const int size = 0xc0000;
372 struct acpi_ctx *ctx;
373 u8 *ptr;
374 int i;
375
376 ut_assertok(alloc_context_size(&ctx, size));
377
378 ptr = acpigen_get_current(ctx);
379
380 /* Write a byte and a 3-byte length */
381 acpigen_write_len_f(ctx);
382 acpigen_emit_byte(ctx, 0x23);
383 acpigen_pop_len(ctx);
384 ut_asserteq(1 + 3, get_length(ptr));
385
386 /* Write 200 bytes so we need two length bytes */
387 ptr = ctx->current;
388 acpigen_write_len_f(ctx);
389 for (i = 0; i < 200; i++)
390 acpigen_emit_byte(ctx, 0x23);
391 acpigen_pop_len(ctx);
392 ut_asserteq(200 + 3, get_length(ptr));
393
394 /* Write 40KB so we need three length bytes */
395 ptr = ctx->current;
396 acpigen_write_len_f(ctx);
397 for (i = 0; i < 40000; i++)
398 acpigen_emit_byte(ctx, 0x23);
399 acpigen_pop_len(ctx);
400 ut_asserteq(40000 + 3, get_length(ptr));
401
402 free_context(&ctx);
403
404 return 0;
405}
406DM_TEST(dm_test_acpi_len, 0);
Simon Glass03967ce2020-07-07 13:11:51 -0600407
408/* Test writing a package */
409static int dm_test_acpi_package(struct unit_test_state *uts)
410{
411 struct acpi_ctx *ctx;
412 char *num_elements;
413 u8 *ptr;
414
415 ut_assertok(alloc_context(&ctx));
416
417 ptr = acpigen_get_current(ctx);
418
419 num_elements = acpigen_write_package(ctx, 3);
420 ut_asserteq_ptr(num_elements, ptr + 4);
421
422 /* For ease of testing, just emit a byte, not valid package contents */
423 acpigen_emit_byte(ctx, 0x23);
424 acpigen_pop_len(ctx);
425 ut_asserteq(PACKAGE_OP, ptr[0]);
426 ut_asserteq(5, get_length(ptr + 1));
427 ut_asserteq(3, ptr[4]);
428
429 free_context(&ctx);
430
431 return 0;
432}
433DM_TEST(dm_test_acpi_package, 0);