blob: 7779bf38aab1653db5354a78712ec4da2cfc1ef4 [file] [log] [blame]
Simon Glass6afa63a2021-12-01 09:02:47 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Handles writing the declared ACPI tables
4 *
5 * Copyright 2021 Google LLC
6 */
7
8#define LOG_CATEGORY LOGC_ACPI
9
10#include <common.h>
11#include <log.h>
12#include <malloc.h>
13#include <mapmem.h>
14#include <acpi/acpi_table.h>
15#include <asm/global_data.h>
16#include <dm/acpi.h>
17
18DECLARE_GLOBAL_DATA_PTR;
19
20int acpi_write_one(struct acpi_ctx *ctx, const struct acpi_writer *entry)
21{
22 int ret;
23
24 log_debug("%s: writing table '%s'\n", entry->name,
25 entry->table);
26 ctx->tab_start = ctx->current;
27 ret = entry->h_write(ctx, entry);
28 if (ret == -ENOENT) {
29 log_debug("%s: Omitted due to being empty\n",
30 entry->name);
31 ret = 0;
32 ctx->current = ctx->tab_start; /* drop the table */
33 return ret;
34 }
35 if (ret)
36 return log_msg_ret("write", ret);
37
38 acpi_align(ctx);
39
40 return 0;
41}
42
43static int acpi_write_all(struct acpi_ctx *ctx)
44{
45 const struct acpi_writer *writer =
46 ll_entry_start(struct acpi_writer, acpi_writer);
47 const int n_ents = ll_entry_count(struct acpi_writer, acpi_writer);
48 const struct acpi_writer *entry;
49 int ret;
50
51 for (entry = writer; entry != writer + n_ents; entry++) {
52 ret = acpi_write_one(ctx, entry);
53 if (ret && ret != -ENOENT)
54 return log_msg_ret("one", ret);
55 }
56
57 return 0;
58}
59
60/*
61 * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
62 */
Simon Glasscc1f8c32021-12-01 09:02:48 -070063ulong new_write_acpi_tables(ulong start_addr)
Simon Glass6afa63a2021-12-01 09:02:47 -070064{
65 struct acpi_ctx *ctx;
66 ulong addr;
Simon Glass6afa63a2021-12-01 09:02:47 -070067 int ret;
68
Simon Glasscc1f8c32021-12-01 09:02:48 -070069 ctx = malloc(sizeof(*ctx));
Simon Glass6afa63a2021-12-01 09:02:47 -070070 if (!ctx)
71 return log_msg_ret("mem", -ENOMEM);
Simon Glass6afa63a2021-12-01 09:02:47 -070072
73 log_debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
74
75 acpi_reset_items();
Simon Glasscc1f8c32021-12-01 09:02:48 -070076 acpi_setup_ctx(ctx, start_addr);
Simon Glass6afa63a2021-12-01 09:02:47 -070077
78 ret = acpi_write_all(ctx);
79 if (ret) {
80 log_err("Failed to write ACPI tables (err=%d)\n", ret);
81 return log_msg_ret("write", -ENOMEM);
82 }
83
84 addr = map_to_sysmem(ctx->current);
85 log_debug("ACPI current = %lx\n", addr);
86
87 return addr;
88}
Simon Glasscc1f8c32021-12-01 09:02:48 -070089
90void acpi_setup_ctx(struct acpi_ctx *ctx, ulong start)
91{
92 gd->acpi_ctx = ctx;
93 memset(ctx, '\0', sizeof(*ctx));
94
95 /* Align ACPI tables to 16-byte boundary */
96 start = ALIGN(start, 16);
97 ctx->base = map_sysmem(start, 0);
98 ctx->current = ctx->base;
99
100 gd_set_acpi_start(start);
101}