1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2019 Google LLC
6 #define LOG_CATEGORY UCLASS_SYSINFO
15 #include <acpi/acpigen.h>
16 #include <asm-generic/gpio.h>
17 #include <asm/acpi_nhlt.h>
18 #include <asm/intel_gnvs.h>
19 #include <asm/intel_pinctrl.h>
21 #include <linux/delay.h>
22 #include "variant_gpio.h"
24 struct cros_gpio_info {
25 const char *linux_name;
26 enum cros_gpio_t type;
31 int arch_misc_init(void)
36 static int get_memconfig(struct udevice *dev)
38 struct gpio_desc gpios[4];
42 ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios,
44 GPIOD_IS_IN | GPIOD_PULL_UP);
46 log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
50 /* Give the lines time to settle */
53 ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios));
55 return log_msg_ret("get", ret);
58 ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
60 return log_msg_ret("free", ret);
66 * get_skuconfig() - Get the SKU number either from pins or the EC
68 * Two options are supported:
69 * skuconfig-gpios - two pins in the device tree (tried first)
70 * EC - reading from the EC (backup)
72 * @dev: sysinfo device to use
73 * @return SKU ID, or -ve error if not found
75 static int get_skuconfig(struct udevice *dev)
77 struct gpio_desc gpios[2];
81 ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios,
84 if (ret != ARRAY_SIZE(gpios)) {
85 struct udevice *cros_ec;
87 log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret);
90 ret = uclass_first_device_err(UCLASS_CROS_EC, &cros_ec);
92 log_err("Cannot find EC for SKU details\n");
93 return log_msg_ret("sku", ret);
95 ret = cros_ec_get_sku_id(cros_ec);
97 log_err("Cannot read SKU details\n");
98 return log_msg_ret("sku", ret);
104 ret = dm_gpio_get_values_as_int_base3(gpios, ARRAY_SIZE(gpios));
106 return log_msg_ret("get", ret);
109 ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios));
111 return log_msg_ret("free", ret);
116 static int coral_get_str(struct udevice *dev, int id, size_t size, char *val)
120 if (IS_ENABLED(CONFIG_SPL_BUILD))
124 case SYSINFO_ID_SMBIOS_SYSTEM_VERSION:
125 case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: {
126 ret = get_skuconfig(dev);
132 sprintf(val, "rev%d", ret);
135 case SYSINFO_ID_BOARD_MODEL: {
136 int mem_config, sku_config;
139 ret = get_memconfig(dev);
141 log_warning("Unable to read memconfig (err=%d)\n", ret);
143 ret = get_skuconfig(dev);
145 log_warning("Unable to read skuconfig (err=%d)\n", ret);
147 model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
148 snprintf(val, size, "%s (memconfig %d, SKU %d)", model,
149 mem_config, sku_config);
159 int chromeos_get_gpio(const struct udevice *dev, const char *prop,
160 enum cros_gpio_t type, struct cros_gpio_info *info)
162 struct udevice *pinctrl;
163 struct gpio_desc desc;
166 ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0);
167 if (ret == -ENOTBLK) {
168 info->gpio_num = CROS_GPIO_VIRTUAL;
169 log_debug("GPIO '%s' is virtual\n", prop);
171 return log_msg_ret("gpio", ret);
173 info->gpio_num = desc.offset;
174 dm_gpio_free((struct udevice *)dev, &desc);
176 info->linux_name = dev_read_string(desc.dev, "linux-name");
177 if (!info->linux_name)
178 return log_msg_ret("linux-name", -ENOENT);
180 /* Get ACPI pin from GPIO library if available */
181 if (info->gpio_num != CROS_GPIO_VIRTUAL) {
182 pinctrl = dev_get_parent(desc.dev);
183 info->gpio_num = intel_pinctrl_get_acpi_pin(pinctrl,
186 info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW :
187 CROS_GPIO_ACTIVE_HIGH;
189 dm_gpio_free(desc.dev, &desc);
194 static int chromeos_acpi_gpio_generate(const struct udevice *dev,
195 struct acpi_ctx *ctx)
197 struct cros_gpio_info info[3];
202 ret = chromeos_get_gpio(dev, "recovery-gpios", CROS_GPIO_REC, &info[0]);
204 return log_msg_ret("rec", ret);
205 ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP,
208 return log_msg_ret("wp", ret);
209 ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE,
212 return log_msg_ret("phase", ret);
213 acpigen_write_scope(ctx, "\\");
214 acpigen_write_name(ctx, "OIPG");
215 acpigen_write_package(ctx, count);
216 for (i = 0; i < count; i++) {
217 acpigen_write_package(ctx, 4);
218 acpigen_write_integer(ctx, info[i].type);
219 acpigen_write_integer(ctx, info[i].flags);
220 acpigen_write_integer(ctx, info[i].gpio_num);
221 acpigen_write_string(ctx, info[i].linux_name);
222 acpigen_pop_len(ctx);
225 acpigen_pop_len(ctx);
226 acpigen_pop_len(ctx);
231 static int coral_write_acpi_tables(const struct udevice *dev,
232 struct acpi_ctx *ctx)
234 struct acpi_global_nvs *gnvs;
236 const char *oem_id = "coral";
237 const char *oem_table_id = "coral";
238 u32 oem_revision = 3;
241 gnvs = bloblist_find(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs));
243 return log_msg_ret("bloblist", -ENOENT);
249 log_debug("Setting up NHLT\n");
250 ret = acpi_setup_nhlt(ctx, nhlt);
252 return log_msg_ret("setup", ret);
254 /* Update NHLT GNVS Data */
255 gnvs->nhla = (uintptr_t)ctx->current;
256 gnvs->nhll = nhlt_current_size(nhlt);
258 ret = nhlt_serialise_oem_overrides(ctx, nhlt, oem_id, oem_table_id,
261 return log_msg_ret("serialise", ret);
266 struct acpi_ops coral_acpi_ops = {
267 .write_tables = coral_write_acpi_tables,
268 .inject_dsdt = chromeos_acpi_gpio_generate,
271 struct sysinfo_ops coral_sysinfo_ops = {
272 .get_str = coral_get_str,
275 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
276 static const struct udevice_id coral_ids[] = {
277 { .compatible = "google,coral" },
282 U_BOOT_DRIVER(coral_drv) = {
284 .id = UCLASS_SYSINFO,
285 .of_match = of_match_ptr(coral_ids),
286 .ops = &coral_sysinfo_ops,
287 ACPI_OPS_PTR(&coral_acpi_ops)