diff options
author | Simon Glass <sjg@chromium.org> | 2020-09-22 12:45:24 -0600 |
---|---|---|
committer | Bin Meng <bmeng.cn@gmail.com> | 2020-09-25 11:27:21 +0800 |
commit | eaac9717369c6ed9e6c5d9c7ed5effb420cb4840 (patch) | |
tree | c91487466256621b33c520cb9800197422baf18c /drivers/tpm | |
parent | ca60199fee9a5259250b6e4bd407bac239e52dca (diff) | |
download | u-boot-eaac9717369c6ed9e6c5d9c7ed5effb420cb4840.tar.gz |
tpm: cr50: Add ACPI support
Generate ACPI information for this device so that Linux can use it
correctly.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/tpm')
-rw-r--r-- | drivers/tpm/cr50_i2c.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c index 1942c07c60..64831a4223 100644 --- a/drivers/tpm/cr50_i2c.c +++ b/drivers/tpm/cr50_i2c.c @@ -14,11 +14,14 @@ #include <log.h> #include <spl.h> #include <tpm-v2.h> +#include <acpi/acpigen.h> +#include <acpi/acpi_device.h> #include <asm/gpio.h> #include <asm/io.h> #include <asm/arch/iomap.h> #include <asm/arch/pm.h> #include <linux/delay.h> +#include <dm/acpi.h> enum { TIMEOUT_INIT_MS = 30000, /* Very long timeout for TPM init */ @@ -581,6 +584,53 @@ static int cr50_i2c_cleanup(struct udevice *dev) return 0; } +static int cr50_acpi_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) +{ + char scope[ACPI_PATH_MAX]; + char name[ACPI_NAME_MAX]; + const char *hid; + int ret; + + ret = acpi_device_scope(dev, scope, sizeof(scope)); + if (ret) + return log_msg_ret("scope", ret); + ret = acpi_get_name(dev, name); + if (ret) + return log_msg_ret("name", ret); + + hid = dev_read_string(dev, "acpi,hid"); + if (!hid) + return log_msg_ret("hid", ret); + + /* Device */ + acpigen_write_scope(ctx, scope); + acpigen_write_device(ctx, name); + acpigen_write_name_string(ctx, "_HID", hid); + acpigen_write_name_integer(ctx, "_UID", + dev_read_u32_default(dev, "acpi,uid", 0)); + acpigen_write_name_string(ctx, "_DDN", + dev_read_string(dev, "acpi,ddn")); + acpigen_write_sta(ctx, acpi_device_status(dev)); + + /* Resources */ + acpigen_write_name(ctx, "_CRS"); + acpigen_write_resourcetemplate_header(ctx); + ret = acpi_device_write_i2c_dev(ctx, dev); + if (ret < 0) + return log_msg_ret("i2c", ret); + ret = acpi_device_write_interrupt_or_gpio(ctx, (struct udevice *)dev, + "ready-gpios"); + if (ret < 0) + return log_msg_ret("irq_gpio", ret); + + acpigen_write_resourcetemplate_footer(ctx); + + acpigen_pop_len(ctx); /* Device */ + acpigen_pop_len(ctx); /* Scope */ + + return 0; +} + enum { TPM_TIMEOUT_MS = 5, SHORT_TIMEOUT_MS = 750, @@ -653,6 +703,10 @@ static int cr50_i2c_probe(struct udevice *dev) return 0; } +struct acpi_ops cr50_acpi_ops = { + .fill_ssdt = cr50_acpi_fill_ssdt, +}; + static const struct tpm_ops cr50_i2c_ops = { .open = cr50_i2c_open, .get_desc = cr50_i2c_get_desc, @@ -675,5 +729,6 @@ U_BOOT_DRIVER(cr50_i2c) = { .probe = cr50_i2c_probe, .remove = cr50_i2c_cleanup, .priv_auto_alloc_size = sizeof(struct cr50_priv), + ACPI_OPS_PTR(&cr50_acpi_ops) .flags = DM_FLAG_OS_PREPARE, }; |