blob: babe1a65406c903d6f2ba16b903a4ca1300dbe88 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
/*
* A vboot flag controlled by coreboot sysinfo tables (x86 only)
*
* Copyright 2018 Google LLC
*/
#define LOG_CATEGORY UCLASS_CROS_VBOOT_FLAG
#include <common.h>
#include <asm/cb_sysinfo.h>
#include <dm.h>
#include <init.h>
#include <log.h>
#include <cros/vboot_flag.h>
/* Coreboot names for all the flag we know about */
static const char *const cb_flag_name[] = {
[VBOOT_FLAG_WRITE_PROTECT] = "write protect",
[VBOOT_FLAG_LID_OPEN] = "lid",
[VBOOT_FLAG_POWER_BUTTON] = "power",
[VBOOT_FLAG_EC_IN_RW] = "EC in RW",
[VBOOT_FLAG_OPROM_LOADED] = "oprom",
[VBOOT_FLAG_RECOVERY] = "recovery",
[VBOOT_FLAG_WIPEOUT] = "wipeout",
};
/**
* Private data for this driver
*
* @port: GPIO port number (coreboot value)
* @active_high: true if active high, false if active low (inverted)
* @value: raw GPIO value as read by coreboot
*/
struct flag_sysinfo_priv {
int port;
bool active_high;
int value;
};
static int flag_sysinfo_read(struct udevice *dev)
{
struct flag_sysinfo_priv *priv = dev_get_priv(dev);
return priv->value;
}
static int flag_sysinfo_probe(struct udevice *dev)
{
struct vboot_flag_uc_priv *uc_priv = dev_get_uclass_priv(dev);
struct flag_sysinfo_priv *priv = dev_get_priv(dev);
const struct sysinfo_t *sysinfo;
const char *cb_name;
int i;
sysinfo = cb_get_sysinfo();
cb_name = cb_flag_name[uc_priv->flag];
if (!cb_name) {
log_warning("No coreboot name for flag '%s'\n", dev->name);
return -ENOENT;
}
for (i = 0; i < sysinfo->num_gpios; i++) {
if (strncmp((char *)sysinfo->gpios[i].name, cb_name,
CB_GPIO_MAX_NAME_LENGTH))
continue;
/* Entry found */
priv->port = sysinfo->gpios[i].port;
priv->active_high = sysinfo->gpios[i].polarity;
priv->value = sysinfo->gpios[i].value;
if (!priv->active_high)
priv->value = !priv->value;
return 0;
}
log_warning("No coreboot flag '%s' in sysinfo\n", cb_name);
return -ENOTSUPP;
}
static const struct vboot_flag_ops flag_sysinfo_ops = {
.read = flag_sysinfo_read,
};
static const struct udevice_id flag_sysinfo_ids[] = {
{ .compatible = "google,sysinfo-flag" },
{ }
};
U_BOOT_DRIVER(google_sysinfo_flag) = {
.name = "google_sysinfo_flag",
.id = UCLASS_CROS_VBOOT_FLAG,
.of_match = flag_sysinfo_ids,
.probe = flag_sysinfo_probe,
.ops = &flag_sysinfo_ops,
.priv_auto = sizeof(struct flag_sysinfo_priv),
};