1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2019 Google LLC
6 #define LOG_CATEGORY UCLASS_SYSINFO
16 #include <acpi/acpigen.h>
17 #include <asm-generic/gpio.h>
18 #include <asm/acpi_nhlt.h>
19 #include <asm/cb_sysinfo.h>
20 #include <asm/intel_gnvs.h>
21 #include <asm/intel_pinctrl.h>
23 #include <linux/delay.h>
24 #include "variant_gpio.h"
26 DECLARE_GLOBAL_DATA_PTR;
28 struct cros_gpio_info {
29 const char *linux_name;
30 enum cros_gpio_t type;
37 if (!ll_boot_init()) {
38 printf("Running as secondary loader");
39 if (gd->arch.coreboot_table) {
42 printf(" (found coreboot table at %lx)",
43 gd->arch.coreboot_table);
45 ret = get_coreboot_info(&lib_sysinfo);
47 printf("\nFailed to parse coreboot tables (err=%d)\n",
59 int arch_misc_init(void)
64 static int get_memconfig(struct udevice *dev)
66 struct gpio_desc gpios[4];
70 ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios,
72 GPIOD_IS_IN | GPIOD_PULL_UP);
74 log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
78 /* Give the lines time to settle */
81 ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios));
83 return log_msg_ret("get", ret);
86 ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
88 return log_msg_ret("free", ret);
94 * get_skuconfig() - Get the SKU number either from pins or the EC
96 * Two options are supported:
97 * skuconfig-gpios - two pins in the device tree (tried first)
98 * EC - reading from the EC (backup)
100 * @dev: sysinfo device to use
101 * Return: SKU ID, or -ve error if not found
103 static int get_skuconfig(struct udevice *dev)
105 struct gpio_desc gpios[2];
109 ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios,
112 if (ret != ARRAY_SIZE(gpios)) {
113 struct udevice *cros_ec;
115 log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
118 ret = uclass_first_device_err(UCLASS_CROS_EC, &cros_ec);
120 log_err("Cannot find EC for SKU details\n");
121 return log_msg_ret("sku", ret);
123 ret = cros_ec_get_sku_id(cros_ec);
125 log_err("Cannot read SKU details\n");
126 return log_msg_ret("sku", ret);
132 ret = dm_gpio_get_values_as_int_base3(gpios, ARRAY_SIZE(gpios));
134 return log_msg_ret("get", ret);
137 ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
139 return log_msg_ret("free", ret);
144 static int coral_get_str(struct udevice *dev, int id, size_t size, char *val)
148 if (IS_ENABLED(CONFIG_SPL_BUILD))
152 case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
153 case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: {
154 ret = get_skuconfig(dev);
160 sprintf(val, "rev%d", ret);
163 case SYSINFO_ID_BOARD_MODEL: {
164 int mem_config, sku_config;
167 ret = get_memconfig(dev);
169 log_warning("Unable to read memconfig (err=%d)\n", ret);
171 ret = get_skuconfig(dev);
173 log_warning("Unable to read skuconfig (err=%d)\n", ret);
175 model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
176 snprintf(val, size, "%s (memconfig %d, SKU %d)", model,
177 mem_config, sku_config);
187 int chromeos_get_gpio(const struct udevice *dev, const char *prop,
188 enum cros_gpio_t type, struct cros_gpio_info *info)
190 struct udevice *pinctrl;
191 struct gpio_desc desc;
194 ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0);
195 if (ret == -ENOTBLK) {
196 info->gpio_num = CROS_GPIO_VIRTUAL;
197 log_debug("GPIO '%s' is virtual\n", prop);
199 return log_msg_ret("gpio", ret);
201 info->gpio_num = desc.offset;
202 dm_gpio_free((struct udevice *)dev, &desc);
204 info->linux_name = dev_read_string(desc.dev, "linux-name");
205 if (!info->linux_name)
206 return log_msg_ret("linux-name", -ENOENT);
208 /* Get ACPI pin from GPIO library if available */
209 if (info->gpio_num != CROS_GPIO_VIRTUAL) {
210 pinctrl = dev_get_parent(desc.dev);
211 info->gpio_num = intel_pinctrl_get_acpi_pin(pinctrl,
214 info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW :
215 CROS_GPIO_ACTIVE_HIGH;
217 dm_gpio_free(desc.dev, &desc);
222 static int chromeos_acpi_gpio_generate(const struct udevice *dev,
223 struct acpi_ctx *ctx)
225 struct cros_gpio_info info[3];
230 ret = chromeos_get_gpio(dev, "recovery-gpios", CROS_GPIO_REC, &info[0]);
232 return log_msg_ret("rec", ret);
233 ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP,
236 return log_msg_ret("wp", ret);
237 ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE,
240 return log_msg_ret("phase", ret);
241 acpigen_write_scope(ctx, "\\");
242 acpigen_write_name(ctx, "OIPG");
243 acpigen_write_package(ctx, count);
244 for (i = 0; i < count; i++) {
245 acpigen_write_package(ctx, 4);
246 acpigen_write_integer(ctx, info[i].type);
247 acpigen_write_integer(ctx, info[i].flags);
248 acpigen_write_integer(ctx, info[i].gpio_num);
249 acpigen_write_string(ctx, info[i].linux_name);
250 acpigen_pop_len(ctx);
253 acpigen_pop_len(ctx);
254 acpigen_pop_len(ctx);
259 static int coral_write_acpi_tables(const struct udevice *dev,
260 struct acpi_ctx *ctx)
262 struct acpi_global_nvs *gnvs;
264 const char *oem_id = "coral";
265 const char *oem_table_id = "coral";
266 u32 oem_revision = 3;
269 gnvs = bloblist_find(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs));
271 return log_msg_ret("bloblist", -ENOENT);
277 log_debug("Setting up NHLT\n");
278 ret = acpi_setup_nhlt(ctx, nhlt);
280 return log_msg_ret("setup", ret);
282 /* Update NHLT GNVS Data */
283 gnvs->nhla = (uintptr_t)ctx->current;
284 gnvs->nhll = nhlt_current_size(nhlt);
286 ret = nhlt_serialise_oem_overrides(ctx, nhlt, oem_id, oem_table_id,
289 return log_msg_ret("serialise", ret);
294 struct acpi_ops coral_acpi_ops = {
295 .write_tables = coral_write_acpi_tables,
296 .inject_dsdt = chromeos_acpi_gpio_generate,
299 struct sysinfo_ops coral_sysinfo_ops = {
300 .get_str = coral_get_str,
303 #if CONFIG_IS_ENABLED(OF_REAL)
304 static const struct udevice_id coral_ids[] = {
305 { .compatible = "google,coral" },
310 U_BOOT_DRIVER(coral_drv) = {
312 .id = UCLASS_SYSINFO,
313 .of_match = of_match_ptr(coral_ids),
314 .ops = &coral_sysinfo_ops,
315 ACPI_OPS_PTR(&coral_acpi_ops)