blob: 26d1b76db48fa898550abcf1df39d2ac7b1b0f94 [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 Glass61cc9332020-07-07 13:11:42 -060015#include <asm/unaligned.h>
16#include <dm/acpi.h>
17#include <dm/test.h>
18#include <test/ut.h>
19
20/* Maximum size of the ACPI context needed for most tests */
21#define ACPI_CONTEXT_SIZE 150
22
Simon Glass7fb8da42020-07-07 13:11:45 -060023#define TEST_STRING "frogmore"
24#define TEST_STREAM2 "\xfa\xde"
25
Simon Glass61cc9332020-07-07 13:11:42 -060026static int alloc_context(struct acpi_ctx **ctxp)
27{
28 struct acpi_ctx *ctx;
29
30 *ctxp = NULL;
31 ctx = malloc(sizeof(*ctx));
32 if (!ctx)
33 return -ENOMEM;
34 ctx->base = malloc(ACPI_CONTEXT_SIZE);
35 if (!ctx->base) {
36 free(ctx);
37 return -ENOMEM;
38 }
39 ctx->current = ctx->base;
40 *ctxp = ctx;
41
42 return 0;
43}
44
45static void free_context(struct acpi_ctx **ctxp)
46{
47 free((*ctxp)->base);
48 free(*ctxp);
49 *ctxp = NULL;
50}
51
52/* Test emitting simple types and acpigen_get_current() */
53static int dm_test_acpi_emit_simple(struct unit_test_state *uts)
54{
55 struct acpi_ctx *ctx;
56 u8 *ptr;
57
58 ut_assertok(alloc_context(&ctx));
59
60 ptr = acpigen_get_current(ctx);
61 acpigen_emit_byte(ctx, 0x23);
62 ut_asserteq(1, acpigen_get_current(ctx) - ptr);
63 ut_asserteq(0x23, *(u8 *)ptr);
64
65 acpigen_emit_word(ctx, 0x1234);
66 ut_asserteq(3, acpigen_get_current(ctx) - ptr);
67 ut_asserteq(0x1234, get_unaligned((u16 *)(ptr + 1)));
68
69 acpigen_emit_dword(ctx, 0x87654321);
70 ut_asserteq(7, acpigen_get_current(ctx) - ptr);
71 ut_asserteq(0x87654321, get_unaligned((u32 *)(ptr + 3)));
72
73 free_context(&ctx);
74
75 return 0;
76}
77DM_TEST(dm_test_acpi_emit_simple, 0);
Simon Glassff715c62020-07-07 13:11:43 -060078
Simon Glass7fb8da42020-07-07 13:11:45 -060079/* Test emitting a stream */
80static int dm_test_acpi_emit_stream(struct unit_test_state *uts)
81{
82 struct acpi_ctx *ctx;
83 u8 *ptr;
84
85 ut_assertok(alloc_context(&ctx));
86
87 ptr = acpigen_get_current(ctx);
88 acpigen_emit_stream(ctx, TEST_STREAM2, 2);
89 ut_asserteq(2, acpigen_get_current(ctx) - ptr);
90 ut_asserteq((u8)TEST_STREAM2[0], ptr[0]);
91 ut_asserteq((u8)TEST_STREAM2[1], ptr[1]);
92
93 free_context(&ctx);
94
95 return 0;
96}
97DM_TEST(dm_test_acpi_emit_stream, 0);
98
99/* Test emitting a string */
100static int dm_test_acpi_emit_string(struct unit_test_state *uts)
101{
102 struct acpi_ctx *ctx;
103 u8 *ptr;
104
105 ut_assertok(alloc_context(&ctx));
106
107 ptr = acpigen_get_current(ctx);
108 acpigen_emit_string(ctx, TEST_STRING);
109 ut_asserteq(sizeof(TEST_STRING), acpigen_get_current(ctx) - ptr);
110 ut_asserteq_str(TEST_STRING, (char *)ptr);
111
112 free_context(&ctx);
113
114 return 0;
115}
116DM_TEST(dm_test_acpi_emit_string, 0);
117
Simon Glassff715c62020-07-07 13:11:43 -0600118/* Test emitting an interrupt descriptor */
119static int dm_test_acpi_interrupt(struct unit_test_state *uts)
120{
121 struct acpi_ctx *ctx;
122 struct udevice *dev;
123 struct irq irq;
124 u8 *ptr;
125
126 ut_assertok(alloc_context(&ctx));
127
128 ptr = acpigen_get_current(ctx);
129
130 ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
131 ut_assertok(irq_get_by_index(dev, 0, &irq));
132
133 /* See a-test, property interrupts-extended in the device tree */
134 ut_asserteq(3, acpi_device_write_interrupt_irq(ctx, &irq));
135 ut_asserteq(9, acpigen_get_current(ctx) - ptr);
136 ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
137 ut_asserteq(6, get_unaligned((u16 *)(ptr + 1)));
138 ut_asserteq(0x19, ptr[3]);
139 ut_asserteq(1, ptr[4]);
140 ut_asserteq(3, get_unaligned((u32 *)(ptr + 5)));
141
142 free_context(&ctx);
143
144 return 0;
145}
146DM_TEST(dm_test_acpi_interrupt, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);