blob: d15273d6bff5adfae4263e63fca682d00468483c [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>
19#include <test/ut.h>
20
21/* Maximum size of the ACPI context needed for most tests */
22#define ACPI_CONTEXT_SIZE 150
23
Simon Glass7fb8da42020-07-07 13:11:45 -060024#define TEST_STRING "frogmore"
25#define TEST_STREAM2 "\xfa\xde"
26
Simon Glass61cc9332020-07-07 13:11:42 -060027static int alloc_context(struct acpi_ctx **ctxp)
28{
29 struct acpi_ctx *ctx;
30
31 *ctxp = NULL;
32 ctx = malloc(sizeof(*ctx));
33 if (!ctx)
34 return -ENOMEM;
35 ctx->base = malloc(ACPI_CONTEXT_SIZE);
36 if (!ctx->base) {
37 free(ctx);
38 return -ENOMEM;
39 }
40 ctx->current = ctx->base;
41 *ctxp = ctx;
42
43 return 0;
44}
45
46static void free_context(struct acpi_ctx **ctxp)
47{
48 free((*ctxp)->base);
49 free(*ctxp);
50 *ctxp = NULL;
51}
52
53/* Test emitting simple types and acpigen_get_current() */
54static int dm_test_acpi_emit_simple(struct unit_test_state *uts)
55{
56 struct acpi_ctx *ctx;
57 u8 *ptr;
58
59 ut_assertok(alloc_context(&ctx));
60
61 ptr = acpigen_get_current(ctx);
62 acpigen_emit_byte(ctx, 0x23);
63 ut_asserteq(1, acpigen_get_current(ctx) - ptr);
64 ut_asserteq(0x23, *(u8 *)ptr);
65
66 acpigen_emit_word(ctx, 0x1234);
67 ut_asserteq(3, acpigen_get_current(ctx) - ptr);
68 ut_asserteq(0x1234, get_unaligned((u16 *)(ptr + 1)));
69
70 acpigen_emit_dword(ctx, 0x87654321);
71 ut_asserteq(7, acpigen_get_current(ctx) - ptr);
72 ut_asserteq(0x87654321, get_unaligned((u32 *)(ptr + 3)));
73
74 free_context(&ctx);
75
76 return 0;
77}
78DM_TEST(dm_test_acpi_emit_simple, 0);
Simon Glassff715c62020-07-07 13:11:43 -060079
Simon Glass7fb8da42020-07-07 13:11:45 -060080/* Test emitting a stream */
81static int dm_test_acpi_emit_stream(struct unit_test_state *uts)
82{
83 struct acpi_ctx *ctx;
84 u8 *ptr;
85
86 ut_assertok(alloc_context(&ctx));
87
88 ptr = acpigen_get_current(ctx);
89 acpigen_emit_stream(ctx, TEST_STREAM2, 2);
90 ut_asserteq(2, acpigen_get_current(ctx) - ptr);
91 ut_asserteq((u8)TEST_STREAM2[0], ptr[0]);
92 ut_asserteq((u8)TEST_STREAM2[1], ptr[1]);
93
94 free_context(&ctx);
95
96 return 0;
97}
98DM_TEST(dm_test_acpi_emit_stream, 0);
99
100/* Test emitting a string */
101static int dm_test_acpi_emit_string(struct unit_test_state *uts)
102{
103 struct acpi_ctx *ctx;
104 u8 *ptr;
105
106 ut_assertok(alloc_context(&ctx));
107
108 ptr = acpigen_get_current(ctx);
109 acpigen_emit_string(ctx, TEST_STRING);
110 ut_asserteq(sizeof(TEST_STRING), acpigen_get_current(ctx) - ptr);
111 ut_asserteq_str(TEST_STRING, (char *)ptr);
112
113 free_context(&ctx);
114
115 return 0;
116}
117DM_TEST(dm_test_acpi_emit_string, 0);
118
Simon Glassff715c62020-07-07 13:11:43 -0600119/* Test emitting an interrupt descriptor */
120static int dm_test_acpi_interrupt(struct unit_test_state *uts)
121{
122 struct acpi_ctx *ctx;
123 struct udevice *dev;
124 struct irq irq;
125 u8 *ptr;
126
127 ut_assertok(alloc_context(&ctx));
128
129 ptr = acpigen_get_current(ctx);
130
131 ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
132 ut_assertok(irq_get_by_index(dev, 0, &irq));
133
134 /* See a-test, property interrupts-extended in the device tree */
135 ut_asserteq(3, acpi_device_write_interrupt_irq(ctx, &irq));
136 ut_asserteq(9, acpigen_get_current(ctx) - ptr);
137 ut_asserteq(ACPI_DESCRIPTOR_INTERRUPT, ptr[0]);
138 ut_asserteq(6, get_unaligned((u16 *)(ptr + 1)));
139 ut_asserteq(0x19, ptr[3]);
140 ut_asserteq(1, ptr[4]);
141 ut_asserteq(3, get_unaligned((u32 *)(ptr + 5)));
142
143 free_context(&ctx);
144
145 return 0;
146}
147DM_TEST(dm_test_acpi_interrupt, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glassa9e0a072020-07-07 13:11:46 -0600148
149/* Test emitting a GPIO descriptor */
150static int dm_test_acpi_gpio(struct unit_test_state *uts)
151{
152 struct gpio_desc desc;
153 struct acpi_ctx *ctx;
154 struct udevice *dev;
155 u8 *ptr;
156
157 ut_assertok(alloc_context(&ctx));
158
159 ptr = acpigen_get_current(ctx);
160
161 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
162 ut_asserteq_str("a-test", dev->name);
163 ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0));
164
165 /* This should write GPIO pin 4 (see device tree test.dts ) */
166 ut_asserteq(4, acpi_device_write_gpio_desc(ctx, &desc));
167 ut_asserteq(35, acpigen_get_current(ctx) - ptr);
168 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
169 ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
170 ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
171 ut_asserteq(ACPI_GPIO_TYPE_IO, ptr[4]);
172 ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
173 ut_asserteq(9, get_unaligned((u16 *)(ptr + 7)));
174 ut_asserteq(ACPI_GPIO_PULL_UP, ptr[9]);
175 ut_asserteq(1234, get_unaligned((u16 *)(ptr + 10)));
176 ut_asserteq(0, get_unaligned((u16 *)(ptr + 12)));
177 ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
178 ut_asserteq(0, ptr[16]);
179 ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
180 ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
181 ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
182
183 /* pin0 */
184 ut_asserteq(4, get_unaligned((u16 *)(ptr + 23)));
185
186 ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
187
188 free_context(&ctx);
189
190 return 0;
191}
192DM_TEST(dm_test_acpi_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
193
194/* Test emitting a GPIO descriptor with an interrupt */
195static int dm_test_acpi_gpio_irq(struct unit_test_state *uts)
196{
197 struct gpio_desc desc;
198 struct acpi_ctx *ctx;
199 struct udevice *dev;
200 u8 *ptr;
201
202 ut_assertok(alloc_context(&ctx));
203
204 ptr = acpigen_get_current(ctx);
205
206 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
207 ut_asserteq_str("a-test", dev->name);
208 ut_assertok(gpio_request_by_name(dev, "test2-gpios", 2, &desc, 0));
209
210 /* This should write GPIO pin 6 (see device tree test.dts ) */
211 ut_asserteq(6, acpi_device_write_gpio_desc(ctx, &desc));
212 ut_asserteq(35, acpigen_get_current(ctx) - ptr);
213 ut_asserteq(ACPI_DESCRIPTOR_GPIO, ptr[0]);
214 ut_asserteq(32, get_unaligned((u16 *)(ptr + 1)));
215 ut_asserteq(ACPI_GPIO_REVISION_ID, ptr[3]);
216 ut_asserteq(ACPI_GPIO_TYPE_INTERRUPT, ptr[4]);
217 ut_asserteq(1, get_unaligned((u16 *)(ptr + 5)));
218 ut_asserteq(29, get_unaligned((u16 *)(ptr + 7)));
219 ut_asserteq(ACPI_GPIO_PULL_DOWN, ptr[9]);
220 ut_asserteq(0, get_unaligned((u16 *)(ptr + 10)));
221 ut_asserteq(4321, get_unaligned((u16 *)(ptr + 12)));
222 ut_asserteq(23, get_unaligned((u16 *)(ptr + 14)));
223 ut_asserteq(0, ptr[16]);
224 ut_asserteq(25, get_unaligned((u16 *)(ptr + 17)));
225 ut_asserteq(35, get_unaligned((u16 *)(ptr + 19)));
226 ut_asserteq(0, get_unaligned((u16 *)(ptr + 21)));
227
228 /* pin0 */
229 ut_asserteq(6, get_unaligned((u16 *)(ptr + 23)));
230
231 ut_asserteq_str("\\_SB.PINC", (char *)ptr + 25);
232
233 free_context(&ctx);
234
235 return 0;
236}
237DM_TEST(dm_test_acpi_gpio_irq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);