From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C702EC433F5 for ; Fri, 5 Nov 2021 19:06:19 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4727361215 for ; Fri, 5 Nov 2021 19:06:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4727361215 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1AC7C83744; Fri, 5 Nov 2021 20:05:51 +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="jS4elqMq"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BE1FF83723; Fri, 5 Nov 2021 20:05:38 +0100 (CET) Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) (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 C65D783723 for ; Fri, 5 Nov 2021 20:05:26 +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-wm1-x32b.google.com with SMTP id z11-20020a1c7e0b000000b0030db7b70b6bso10231290wmc.1 for ; Fri, 05 Nov 2021 12:05:26 -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=itduj/vm8pAuXM1cgITUNK8dELlNKjAMwFg5N7qomTQ=; b=jS4elqMqRBupaztVUvinnsgkx820zQ7EWxiQN4nWTsJo9o6UkRg/z6sDqmOJv52xiZ L9C/i/PmZeox9eo2eGyOwDtSJw9RYgDus1Oun8iMbFpsELK863rnkn3+4UiggbprZUHi xZC0jLJwZgM3KsozbNLGREX4+svEkHakylc6FKUPulqojtpNLBWUwLxNJMZnFAruSguJ Ww5d5xANdM7/bAEDV9iEkJSxM76Kx+xQhKw/+9cRS/IMb7BtX5gkDXkVV077BRPxj38p m/MsnE8Xy3eRgi/MVamZbVpmv3kct2Idx55Z0AbtEfEmD8fQSVhsRTNg5E/c1sBB5Wy1 yTrw== 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=itduj/vm8pAuXM1cgITUNK8dELlNKjAMwFg5N7qomTQ=; b=JYpN6sW2Jpyz4AoAHSpv0d4MH9gR17PajQnnwF5J6/wHrU2QsImpEZ20ToGwnaS2TK Zs2XA7Uh2VQ1YRxxUMTqVqSHBjH7PxACIL+ziAjEH/UjaehIvYbY7K7xvhTRHEgiwPBo lKr3EEcbJc+b0BPaowtlkzeg6uayD9eQoN4Ov0jvzpHuA4AUeHnzaMv0Pw9VMhBQSowd mCz0XpjpIzfRdE+CLljHb3dP2zegwSwBnQn0seU9qKk2Atz3hEGVZjKQMVFZ7WifKbnZ ck3XxkYK/SE+7pLVOSI42/mrLAHJhnqW9AeMk6lUZwpTFptw9yBvVkUUF3tPxjFVi5XE SDYQ== X-Gm-Message-State: AOAM533Bi2OBEetVOWtXt9ObaLyik+hKSMyr0HPeCrfP6Fgrdg3PnMEY zKbCqP2IM5Romyn15Rfq4LPq2Y8zWlxlKA== X-Google-Smtp-Source: ABdhPJy8D12SLpX0/4A6JSl0brI5zMIwuhIKo5/+L2xgstJnDpgH/sWgYu8ausNVQAMhl5VByRWgRA== X-Received: by 2002:a05:600c:253:: with SMTP id 19mr32135765wmj.179.1636139126210; Fri, 05 Nov 2021 12:05:26 -0700 (PDT) Received: from apalos.home ([2a02:587:4682:26e0:2e56:dcff:fe9a:8f06]) by smtp.gmail.com with ESMTPSA id m125sm11832350wmm.39.2021.11.05.12.05.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Nov 2021 12:05:25 -0700 (PDT) From: Ilias Apalodimas To: u-boot@lists.denx.de Cc: trini@konsulko.com, Ilias Apalodimas , Simon Glass , Rick Chen , Sean Anderson , Heinrich Schuchardt , Masahisa Kojima Subject: [PATCH 3/6 v5] tpm: Use the new API on tpm2 spi driver Date: Fri, 5 Nov 2021 21:05:13 +0200 Message-Id: <20211105190517.233079-4-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211105190517.233079-1-ilias.apalodimas@linaro.org> References: <20211105190517.233079-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Simon Glass Signed-off-by: Ilias Apalodimas --- drivers/tpm/Makefile | 2 +- drivers/tpm/tpm2_tis_spi.c | 447 +++---------------------------------- 2 files changed, 32 insertions(+), 417 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..58b6f3351057 100644 --- a/drivers/tpm/tpm2_tis_spi.c +++ b/drivers/tpm/tpm2_tis_spi.c @@ -30,13 +30,6 @@ #include "tpm_tis.h" #include "tpm_internal.h" -#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) -#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) -#define TPM_STS(l) (0x0018 | ((l) << 12)) -#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) -#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) -#define TPM_RID(l) (0x0F04 | ((l) << 12)) - #define MAX_SPI_FRAMESIZE 64 /* Number of wait states to wait for */ @@ -165,7 +158,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 +168,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) +static int tpm_tis_spi_write(struct udevice *dev, u32 addr, u16 len, const u8 *out) { - 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) -{ - 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 +200,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 +211,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 +253,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 = { -- 2.33.1