From patchwork Wed Nov 3 15:09:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 1550351 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=mFl5APBD; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HkqvY4Hx7z9s5P for ; Thu, 4 Nov 2021 02:10:15 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 022ED83651; Wed, 3 Nov 2021 16:09:50 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="mFl5APBD"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 42FB083642; Wed, 3 Nov 2021 16:09:45 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3B41C83630 for ; Wed, 3 Nov 2021 16:09:38 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wr1-x42f.google.com with SMTP id d5so4101561wrc.1 for ; Wed, 03 Nov 2021 08:09:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ng8V3YqUxVvU1yxHf4yDuLuvsjuzyO+P8CqwJ6Vzuws=; b=mFl5APBD8uzJqhWPrGbKvB2/18cx4o/p+pZx/B4NPUAeQdO73CNCdZoySsk/Ib7lap es6nK8KIxo0o5VJKKu+rHLmF17ISRvPTr72CphTOefhopmfxwGXhql2jeiGXPjX8WYEk 3uM7/o7XPBN4t1oAVuW0x2Hk+RHmK59x46VNtt6dNB0S3jledPw4z8uVmRJFQ/yOq/GS fttyWFg2noKmAO7aJ0Tpe7qgz5psY4Oy/FMeosdGg86AlKJg4JPuaDn90UfUNdOwFC7M LBrNIWv31YDql0ru+rpjR4RhcEd5AFckKnHYtyiTr39dpnXisjU53GvVWvQC/t8/l/ZF tb9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ng8V3YqUxVvU1yxHf4yDuLuvsjuzyO+P8CqwJ6Vzuws=; b=Q42SKw7HDKp1+3Ha1e+UTJmGK01XqxANPeJUz98+g887g3+MNint+YDn4tH5Jd9ZgI Ar7XkdA8PMO0aglR9NFEuk4Ul1Eb0DJM4d+o7TXYkkxDG5Vvxyfp1Af7K6AzTzEB0PHc sO2qNvZLLqMOOcjYMzc67vSZGeRctOD9SVhrUisCOl37zg2yDafWOjgkSTJMduff7qRt btqCrsNJuuW5f0xatyT6a98BFL/cC6wcLvf6KO+0AQE406U54sf3hdA7wH+a0YlsrRRU Py9xt/Sh2gxub0l2a6VD8v6K8W/tjKWz30uLMjkdK4tcNb7GBBW1t7cFU3QfRBdXEVTQ 6Z5A== X-Gm-Message-State: AOAM531p99DTyUBBJy0itCH0FoV3bb95RiK4PMmeIijd9ia0f9/zR8r+ 3j6FkA2nUtzW9nKit4lyfK0iYBDfN+Asqw== X-Google-Smtp-Source: ABdhPJyRnF0Vbe1CoDAGO2cd8kRZkgHd7n7+1mH3kE6/j4KMZnxKiUyWqD6mOmLgkXsvJCXOp2ccGw== X-Received: by 2002:adf:fc88:: with SMTP id g8mr27119157wrr.334.1635952177623; Wed, 03 Nov 2021 08:09:37 -0700 (PDT) Received: from apalos.home ([2a02:587:4682:26e0:2e56:dcff:fe9a:8f06]) by smtp.gmail.com with ESMTPSA id f19sm2094947wmq.34.2021.11.03.08.09.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Nov 2021 08:09:37 -0700 (PDT) From: Ilias Apalodimas To: u-boot@lists.denx.de Cc: trini@konsulko.com, Ilias Apalodimas , Rick Chen , Sean Anderson , Simon Glass , Heinrich Schuchardt , Masahisa Kojima Subject: [PATCH 3/6 v4] tpm: Use the new API on tpm2 spi driver Date: Wed, 3 Nov 2021 17:09:06 +0200 Message-Id: <20211103150910.69732-4-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211103150910.69732-1-ilias.apalodimas@linaro.org> References: <20211103150910.69732-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Convert our SPI TPM driver and use the newly added API Signed-off-by: Ilias Apalodimas Reviewed-by: Simon Glass --- drivers/tpm/Makefile | 2 +- drivers/tpm/tpm2_tis_spi.c | 440 +++---------------------------------- 2 files changed, 32 insertions(+), 410 deletions(-) diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 494aa5a46d30..51725230c780 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -12,6 +12,6 @@ obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o sandbox_common.o -obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_spi.o +obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_core.o tpm2_tis_spi.o obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o obj-$(CONFIG_TPM2_MMIO) += tpm2_tis_core.o tpm2_tis_mmio.o diff --git a/drivers/tpm/tpm2_tis_spi.c b/drivers/tpm/tpm2_tis_spi.c index 1d24d32d867e..547d163200ea 100644 --- a/drivers/tpm/tpm2_tis_spi.c +++ b/drivers/tpm/tpm2_tis_spi.c @@ -165,7 +165,7 @@ release_bus: return ret; } -static int tpm_tis_spi_read(struct udevice *dev, u16 addr, u8 *in, u16 len) +static int tpm_tis_spi_read(struct udevice *dev, u32 addr, u16 len, u8 *in) { return tpm_tis_spi_xfer(dev, addr, NULL, in, len); } @@ -175,382 +175,24 @@ static int tpm_tis_spi_read32(struct udevice *dev, u32 addr, u32 *result) __le32 result_le; int ret; - ret = tpm_tis_spi_read(dev, addr, (u8 *)&result_le, sizeof(u32)); + ret = tpm_tis_spi_read(dev, addr, sizeof(u32), (u8 *)&result_le); if (!ret) *result = le32_to_cpu(result_le); return ret; } -static int tpm_tis_spi_write(struct udevice *dev, u16 addr, const u8 *out, - u16 len) -{ - return tpm_tis_spi_xfer(dev, addr, out, NULL, len); -} - -static int tpm_tis_spi_check_locality(struct udevice *dev, int loc) -{ - const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; - struct tpm_chip *chip = dev_get_priv(dev); - u8 buf; - int ret; - - ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), &buf, 1); - if (ret) - return ret; - - if ((buf & mask) == mask) { - chip->locality = loc; - return 0; - } - - return -ENOENT; -} - -static void tpm_tis_spi_release_locality(struct udevice *dev, int loc, - bool force) -{ - const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; - u8 buf; - - if (tpm_tis_spi_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) - return; - - if (force || (buf & mask) == mask) { - buf = TPM_ACCESS_ACTIVE_LOCALITY; - tpm_tis_spi_write(dev, TPM_ACCESS(loc), &buf, 1); - } -} - -static int tpm_tis_spi_request_locality(struct udevice *dev, int loc) -{ - struct tpm_chip *chip = dev_get_priv(dev); - unsigned long start, stop; - u8 buf = TPM_ACCESS_REQUEST_USE; - int ret; - - ret = tpm_tis_spi_check_locality(dev, loc); - if (!ret) - return 0; - - if (ret != -ENOENT) { - log(LOGC_NONE, LOGL_ERR, "%s: Failed to get locality: %d\n", - __func__, ret); - return ret; - } - - ret = tpm_tis_spi_write(dev, TPM_ACCESS(loc), &buf, 1); - if (ret) { - log(LOGC_NONE, LOGL_ERR, "%s: Failed to write to TPM: %d\n", - __func__, ret); - return ret; - } - - start = get_timer(0); - stop = chip->timeout_a; - do { - ret = tpm_tis_spi_check_locality(dev, loc); - if (!ret) - return 0; - - if (ret != -ENOENT) { - log(LOGC_NONE, LOGL_ERR, - "%s: Failed to get locality: %d\n", __func__, ret); - return ret; - } - - mdelay(TPM_TIMEOUT_MS); - } while (get_timer(start) < stop); - - log(LOGC_NONE, LOGL_ERR, "%s: Timeout getting locality: %d\n", __func__, - ret); - - return ret; -} - -static u8 tpm_tis_spi_status(struct udevice *dev, u8 *status) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - return tpm_tis_spi_read(dev, TPM_STS(chip->locality), status, 1); -} - -static int tpm_tis_spi_wait_for_stat(struct udevice *dev, u8 mask, - unsigned long timeout, u8 *status) -{ - unsigned long start = get_timer(0); - unsigned long stop = timeout; - int ret; - - do { - mdelay(TPM_TIMEOUT_MS); - ret = tpm_tis_spi_status(dev, status); - if (ret) - return ret; - - if ((*status & mask) == mask) - return 0; - } while (get_timer(start) < stop); - - return -ETIMEDOUT; -} - -static u8 tpm_tis_spi_valid_status(struct udevice *dev, u8 *status) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - return tpm_tis_spi_wait_for_stat(dev, TPM_STS_VALID, - chip->timeout_c, status); -} - -static int tpm_tis_spi_get_burstcount(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - unsigned long start, stop; - u32 burstcount, ret; - - /* wait for burstcount */ - start = get_timer(0); - stop = chip->timeout_d; - do { - ret = tpm_tis_spi_read32(dev, TPM_STS(chip->locality), - &burstcount); - if (ret) - return -EBUSY; - - burstcount = (burstcount >> 8) & 0xFFFF; - if (burstcount) - return burstcount; - - mdelay(TPM_TIMEOUT_MS); - } while (get_timer(start) < stop); - - return -EBUSY; -} - -static int tpm_tis_spi_cancel(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - u8 data = TPM_STS_COMMAND_READY; - - return tpm_tis_spi_write(dev, TPM_STS(chip->locality), &data, 1); -} - -static int tpm_tis_spi_recv_data(struct udevice *dev, u8 *buf, size_t count) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int size = 0, burstcnt, len, ret; - u8 status; - - while (size < count && - tpm_tis_spi_wait_for_stat(dev, - TPM_STS_DATA_AVAIL | TPM_STS_VALID, - chip->timeout_c, &status) == 0) { - burstcnt = tpm_tis_spi_get_burstcount(dev); - if (burstcnt < 0) - return burstcnt; - - len = min_t(int, burstcnt, count - size); - ret = tpm_tis_spi_read(dev, TPM_DATA_FIFO(chip->locality), - buf + size, len); - if (ret < 0) - return ret; - - size += len; - } - - return size; -} - -static int tpm_tis_spi_recv(struct udevice *dev, u8 *buf, size_t count) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int size, expected; - if (!chip) - return -ENODEV; - - if (count < TPM_HEADER_SIZE) { - size = -EIO; - goto out; - } - - size = tpm_tis_spi_recv_data(dev, buf, TPM_HEADER_SIZE); - if (size < TPM_HEADER_SIZE) { - log(LOGC_NONE, LOGL_ERR, "TPM error, unable to read header\n"); - goto out; - } - - expected = get_unaligned_be32(buf + 2); - if (expected > count) { - size = -EIO; - goto out; - } - - size += tpm_tis_spi_recv_data(dev, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); - if (size < expected) { - log(LOGC_NONE, LOGL_ERR, - "TPM error, unable to read remaining bytes of result\n"); - size = -EIO; - goto out; - } - -out: - tpm_tis_spi_cancel(dev); - tpm_tis_spi_release_locality(dev, chip->locality, false); - - return size; -} - -static int tpm_tis_spi_send(struct udevice *dev, const u8 *buf, size_t len) -{ - struct tpm_chip *chip = dev_get_priv(dev); - u32 i, size; - u8 status; - int burstcnt, ret; - u8 data; - - if (!chip) - return -ENODEV; - - if (len > TPM_DEV_BUFSIZE) - return -E2BIG; /* Command is too long for our tpm, sorry */ - - ret = tpm_tis_spi_request_locality(dev, 0); - if (ret < 0) - return -EBUSY; - - /* - * Check if the TPM is ready. If not, if not, cancel the pending command - * and poll on the status to be finally ready. - */ - ret = tpm_tis_spi_status(dev, &status); - if (ret) - return ret; - - if (!(status & TPM_STS_COMMAND_READY)) { - /* Force the transition, usually this will be done at startup */ - ret = tpm_tis_spi_cancel(dev); - if (ret) { - log(LOGC_NONE, LOGL_ERR, - "%s: Could not cancel previous operation\n", - __func__); - goto out_err; - } - - ret = tpm_tis_spi_wait_for_stat(dev, TPM_STS_COMMAND_READY, - chip->timeout_b, &status); - if (ret < 0 || !(status & TPM_STS_COMMAND_READY)) { - log(LOGC_NONE, LOGL_ERR, - "status %d after wait for stat returned %d\n", - status, ret); - goto out_err; - } - } - - for (i = 0; i < len - 1;) { - burstcnt = tpm_tis_spi_get_burstcount(dev); - if (burstcnt < 0) - return burstcnt; - - size = min_t(int, len - i - 1, burstcnt); - ret = tpm_tis_spi_write(dev, TPM_DATA_FIFO(chip->locality), - buf + i, size); - if (ret < 0) - goto out_err; - - i += size; - } - - ret = tpm_tis_spi_valid_status(dev, &status); - if (ret) - goto out_err; - - if ((status & TPM_STS_DATA_EXPECT) == 0) { - ret = -EIO; - goto out_err; - } - - ret = tpm_tis_spi_write(dev, TPM_DATA_FIFO(chip->locality), - buf + len - 1, 1); - if (ret) - goto out_err; - - ret = tpm_tis_spi_valid_status(dev, &status); - if (ret) - goto out_err; - - if ((status & TPM_STS_DATA_EXPECT) != 0) { - ret = -EIO; - goto out_err; - } - - data = TPM_STS_GO; - ret = tpm_tis_spi_write(dev, TPM_STS(chip->locality), &data, 1); - if (ret) - goto out_err; - - return len; - -out_err: - tpm_tis_spi_cancel(dev); - tpm_tis_spi_release_locality(dev, chip->locality, false); - - return ret; -} - -static int tpm_tis_spi_cleanup(struct udevice *dev) +static int tpm_tis_spi_write(struct udevice *dev, u32 addr, u16 len, const u8 *out) { - struct tpm_chip *chip = dev_get_priv(dev); - - tpm_tis_spi_cancel(dev); - /* - * The TPM needs some time to clean up here, - * so we sleep rather than keeping the bus busy - */ - mdelay(2); - tpm_tis_spi_release_locality(dev, chip->locality, false); - - return 0; -} - -static int tpm_tis_spi_open(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - if (chip->is_open) - return -EBUSY; - - chip->is_open = 1; - - return 0; -} - -static int tpm_tis_spi_close(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - if (chip->is_open) { - tpm_tis_spi_release_locality(dev, chip->locality, true); - chip->is_open = 0; - } - - return 0; + return tpm_tis_spi_xfer(dev, addr, out, NULL, len); } -static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) +static int tpm_tis_spi_write32(struct udevice *dev, u32 addr, u32 value) { - struct tpm_chip *chip = dev_get_priv(dev); - - if (size < 80) - return -ENOSPC; + __le32 value_le = cpu_to_le32(value); - return snprintf(buf, size, - "%s v2.0: VendorID 0x%04x, DeviceID 0x%04x, RevisionID 0x%02x [%s]", - dev->name, chip->vend_dev & 0xFFFF, - chip->vend_dev >> 16, chip->rid, - (chip->is_open ? "open" : "closed")); + return tpm_tis_spi_write(dev, addr, sizeof(value), (u8 *)&value_le); } static int tpm_tis_wait_init(struct udevice *dev, int loc) @@ -565,7 +207,7 @@ static int tpm_tis_wait_init(struct udevice *dev, int loc) do { mdelay(TPM_TIMEOUT_MS); - ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), &status, 1); + ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), 1, &status); if (ret) break; @@ -576,6 +218,13 @@ static int tpm_tis_wait_init(struct udevice *dev, int loc) return -EIO; } +static struct tpm_tis_phy_ops phy_ops = { + .read_bytes = tpm_tis_spi_read, + .write_bytes = tpm_tis_spi_write, + .read32 = tpm_tis_spi_read32, + .write32 = tpm_tis_spi_write32, +}; + static int tpm_tis_spi_probe(struct udevice *dev) { struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev); @@ -611,65 +260,38 @@ init: /* Ensure a minimum amount of time elapsed since reset of the TPM */ mdelay(drv_data->time_before_first_cmd_ms); - chip->locality = 0; - chip->timeout_a = TIS_SHORT_TIMEOUT_MS; - chip->timeout_b = TIS_LONG_TIMEOUT_MS; - chip->timeout_c = TIS_SHORT_TIMEOUT_MS; - chip->timeout_d = TIS_SHORT_TIMEOUT_MS; - priv->pcr_count = drv_data->pcr_count; - priv->pcr_select_min = drv_data->pcr_select_min; - ret = tpm_tis_wait_init(dev, chip->locality); if (ret) { log(LOGC_DM, LOGL_ERR, "%s: no device found\n", __func__); return ret; } - ret = tpm_tis_spi_request_locality(dev, chip->locality); - if (ret) { - log(LOGC_NONE, LOGL_ERR, "%s: could not request locality %d\n", - __func__, chip->locality); - return ret; - } - - ret = tpm_tis_spi_read32(dev, TPM_DID_VID(chip->locality), - &chip->vend_dev); - if (ret) { - log(LOGC_NONE, LOGL_ERR, - "%s: could not retrieve VendorID/DeviceID\n", __func__); - return ret; - } - - ret = tpm_tis_spi_read(dev, TPM_RID(chip->locality), &chip->rid, 1); - if (ret) { - log(LOGC_NONE, LOGL_ERR, "%s: could not retrieve RevisionID\n", - __func__); - return ret; - } + tpm_tis_ops_register(dev, &phy_ops); + ret = tpm_tis_init(dev); + if (ret) + goto err; - log(LOGC_NONE, LOGL_ERR, - "SPI TPMv2.0 found (vid:%04x, did:%04x, rid:%02x)\n", - chip->vend_dev & 0xFFFF, chip->vend_dev >> 16, chip->rid); + priv->pcr_count = drv_data->pcr_count; + priv->pcr_select_min = drv_data->pcr_select_min; + priv->version = TPM_V2; return 0; +err: + return -EINVAL; } -static int tpm_tis_spi_remove(struct udevice *dev) +static int tpm_tis_spi_remove(struct udevice *udev) { - struct tpm_chip *chip = dev_get_priv(dev); - - tpm_tis_spi_release_locality(dev, chip->locality, true); - - return 0; + return tpm_tis_cleanup(udev); } static const struct tpm_ops tpm_tis_spi_ops = { - .open = tpm_tis_spi_open, - .close = tpm_tis_spi_close, + .open = tpm_tis_open, + .close = tpm_tis_close, .get_desc = tpm_tis_get_desc, - .send = tpm_tis_spi_send, - .recv = tpm_tis_spi_recv, - .cleanup = tpm_tis_spi_cleanup, + .send = tpm_tis_send, + .recv = tpm_tis_recv, + .cleanup = tpm_tis_cleanup, }; static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {