acpi: Add a method to write tables for a device
[oweals/u-boot.git] / drivers / core / acpi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Core driver model support for ACPI table generation
4  *
5  * Copyright 2019 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  */
8
9 #define LOG_CATEOGRY    LOGC_ACPI
10
11 #include <common.h>
12 #include <dm.h>
13 #include <dm/acpi.h>
14 #include <dm/device-internal.h>
15 #include <dm/root.h>
16
17 /* Type of method to call */
18 enum method_t {
19         METHOD_WRITE_TABLES,
20 };
21
22 /* Prototype for all methods */
23 typedef int (*acpi_method)(const struct udevice *dev, struct acpi_ctx *ctx);
24
25 int acpi_copy_name(char *out_name, const char *name)
26 {
27         strncpy(out_name, name, ACPI_NAME_LEN);
28         out_name[ACPI_NAME_LEN] = '\0';
29
30         return 0;
31 }
32
33 int acpi_get_name(const struct udevice *dev, char *out_name)
34 {
35         struct acpi_ops *aops;
36
37         aops = device_get_acpi_ops(dev);
38         if (aops && aops->get_name)
39                 return aops->get_name(dev, out_name);
40
41         return -ENOSYS;
42 }
43
44 acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
45 {
46         struct acpi_ops *aops;
47
48         aops = device_get_acpi_ops(dev);
49         if (aops) {
50                 switch (method) {
51                 case METHOD_WRITE_TABLES:
52                         return aops->write_tables;
53                 }
54         }
55
56         return NULL;
57 }
58
59 int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
60                         enum method_t method)
61 {
62         struct udevice *dev;
63         acpi_method func;
64         int ret;
65
66         func = acpi_get_method(parent, method);
67         if (func) {
68                 log_debug("\n");
69                 log_debug("- %s %p\n", parent->name, func);
70                 ret = device_ofdata_to_platdata(parent);
71                 if (ret)
72                         return log_msg_ret("ofdata", ret);
73                 ret = func(parent, ctx);
74                 if (ret)
75                         return log_msg_ret("func", ret);
76         }
77         device_foreach_child(dev, parent) {
78                 ret = acpi_recurse_method(ctx, dev, method);
79                 if (ret)
80                         return log_msg_ret("recurse", ret);
81         }
82
83         return 0;
84 }
85
86 int acpi_write_dev_tables(struct acpi_ctx *ctx)
87 {
88         int ret;
89
90         log_debug("Writing device tables\n");
91         ret = acpi_recurse_method(ctx, dm_root(), METHOD_WRITE_TABLES);
92         log_debug("Writing finished, err=%d\n", ret);
93
94         return ret;
95 }