x86: coral: Free the ACPI GPIOs after using them
[platform/kernel/u-boot.git] / board / google / chromebook_coral / coral.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2019 Google LLC
4  */
5
6 #include <common.h>
7 #include <bloblist.h>
8 #include <command.h>
9 #include <dm.h>
10 #include <log.h>
11 #include <sysinfo.h>
12 #include <acpi/acpigen.h>
13 #include <asm-generic/gpio.h>
14 #include <asm/acpi_nhlt.h>
15 #include <asm/intel_gnvs.h>
16 #include <asm/intel_pinctrl.h>
17 #include <dm/acpi.h>
18 #include "variant_gpio.h"
19
20 struct cros_gpio_info {
21         const char *linux_name;
22         enum cros_gpio_t type;
23         int gpio_num;
24         int flags;
25 };
26
27 int arch_misc_init(void)
28 {
29         return 0;
30 }
31
32 /* This function is needed if CONFIG_CMDLINE is not enabled */
33 int board_run_command(const char *cmdline)
34 {
35         printf("No command line\n");
36
37         return 0;
38 }
39
40 int chromeos_get_gpio(const struct udevice *dev, const char *prop,
41                       enum cros_gpio_t type, struct cros_gpio_info *info)
42 {
43         struct udevice *pinctrl;
44         struct gpio_desc desc;
45         int ret;
46
47         ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0);
48         if (ret == -ENOTBLK)
49                 info->gpio_num = CROS_GPIO_VIRTUAL;
50         else if (ret)
51                 return log_msg_ret("gpio", ret);
52         else
53                 info->gpio_num = desc.offset;
54         info->linux_name = dev_read_string(desc.dev, "linux-name");
55         if (!info->linux_name)
56                 return log_msg_ret("linux-name", -ENOENT);
57         info->type = type;
58         /* Get ACPI pin from GPIO library if available */
59         if (info->gpio_num != CROS_GPIO_VIRTUAL) {
60                 pinctrl = dev_get_parent(desc.dev);
61                 info->gpio_num = intel_pinctrl_get_acpi_pin(pinctrl,
62                                                             info->gpio_num);
63         }
64         info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW :
65                 CROS_GPIO_ACTIVE_HIGH;
66         if (!ret)
67                 dm_gpio_free(desc.dev, &desc);
68
69         return 0;
70 }
71
72 static int chromeos_acpi_gpio_generate(const struct udevice *dev,
73                                        struct acpi_ctx *ctx)
74 {
75         struct cros_gpio_info info[3];
76         int count, i;
77         int ret;
78
79         count = 3;
80         ret = chromeos_get_gpio(dev, "recovery-gpios", CROS_GPIO_REC, &info[0]);
81         if (ret)
82                 return log_msg_ret("rec", ret);
83         ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP,
84                                 &info[1]);
85         if (ret)
86                 return log_msg_ret("rec", ret);
87         ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE,
88                                 &info[2]);
89         if (ret)
90                 return log_msg_ret("rec", ret);
91         acpigen_write_scope(ctx, "\\");
92         acpigen_write_name(ctx, "OIPG");
93         acpigen_write_package(ctx, count);
94         for (i = 0; i < count; i++) {
95                 acpigen_write_package(ctx, 4);
96                 acpigen_write_integer(ctx, info[i].type);
97                 acpigen_write_integer(ctx, info[i].flags);
98                 acpigen_write_integer(ctx, info[i].gpio_num);
99                 acpigen_write_string(ctx, info[i].linux_name);
100                 acpigen_pop_len(ctx);
101         }
102
103         acpigen_pop_len(ctx);
104         acpigen_pop_len(ctx);
105
106         return 0;
107 }
108
109 static int coral_write_acpi_tables(const struct udevice *dev,
110                                    struct acpi_ctx *ctx)
111 {
112         struct acpi_global_nvs *gnvs;
113         struct nhlt *nhlt;
114         const char *oem_id = "coral";
115         const char *oem_table_id = "coral";
116         u32 oem_revision = 3;
117         int ret;
118
119         gnvs = bloblist_find(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs));
120         if (!gnvs)
121                 return log_msg_ret("bloblist", -ENOENT);
122
123         nhlt = nhlt_init();
124         if (!nhlt)
125                 return -ENOMEM;
126
127         log_debug("Setting up NHLT\n");
128         ret = acpi_setup_nhlt(ctx, nhlt);
129         if (ret)
130                 return log_msg_ret("setup", ret);
131
132         /* Update NHLT GNVS Data */
133         gnvs->nhla = (uintptr_t)ctx->current;
134         gnvs->nhll = nhlt_current_size(nhlt);
135
136         ret = nhlt_serialise_oem_overrides(ctx, nhlt, oem_id, oem_table_id,
137                                            oem_revision);
138         if (ret)
139                 return log_msg_ret("serialise", ret);
140
141         return 0;
142 }
143
144 struct acpi_ops coral_acpi_ops = {
145         .write_tables   = coral_write_acpi_tables,
146         .inject_dsdt    = chromeos_acpi_gpio_generate,
147 };
148
149 struct sysinfo_ops coral_sysinfo_ops = {
150 };
151
152 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
153 static const struct udevice_id coral_ids[] = {
154         { .compatible = "google,coral" },
155         { }
156 };
157 #endif
158
159 U_BOOT_DRIVER(coral_drv) = {
160         .name           = "coral",
161         .id             = UCLASS_SYSINFO,
162         .of_match       = of_match_ptr(coral_ids),
163         .ops            = &coral_sysinfo_ops,
164         ACPI_OPS_PTR(&coral_acpi_ops)
165 };