From patchwork Thu Apr 7 11:18:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lino Sanfilippo X-Patchwork-Id: 12805084 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28AC3C433F5 for ; Thu, 7 Apr 2022 11:19:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244241AbiDGLVe (ORCPT ); Thu, 7 Apr 2022 07:21:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35108 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233973AbiDGLVb (ORCPT ); Thu, 7 Apr 2022 07:21:31 -0400 Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 97A381959F0; Thu, 7 Apr 2022 04:19:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1649330357; bh=1zrH+Ig9KZGn6a8jMH9j/YTpYklf3j0vedc54T6FD0M=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=Cy5icd4tSFxtPW3R2ttANLK793/56WcdmmVC/yQAJ5+i3l8/lzx1WsbmzJ7J0eIgf K6JDeAIi9Cxgq8NUmGNd1CaeX0Tc9BKRqSMPFNFzYTI1emvvt0qhnwLcuwuiNtr/7g BGvebzDwZy5ofeUAznJRAV2DQYs57N7wkQkUvQNo= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from Venus.fritz.box ([46.223.2.23]) by mail.gmx.net (mrgmx005 [212.227.17.190]) with ESMTPSA (Nemesis) id 1M8QWA-1ngq0q3K3U-004WEt; Thu, 07 Apr 2022 13:19:16 +0200 From: Lino Sanfilippo To: peterhuewe@gmx.de, jarkko@kernel.org, jgg@ziepe.ca, =robh+dt@kernel.org Cc: devicetree@vger.kernel.org, linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org, stefanb@linux.ibm.com, p.rosenberger@kunbus.com, lukas@wunner.de, Lino Sanfilippo Subject: [PATCH 5/5] tpm: tpm_tis_spi_slb_9670: implement set_reset and unset_reset functions Date: Thu, 7 Apr 2022 13:18:49 +0200 Message-Id: <20220407111849.5676-6-LinoSanfilippo@gmx.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220407111849.5676-1-LinoSanfilippo@gmx.de> References: <20220407111849.5676-1-LinoSanfilippo@gmx.de> MIME-Version: 1.0 X-Provags-ID: V03:K1:FzMuKNvm6dS35SO6rkbhftmjLdUeXo2aqe2ZmdcqrQqrf0MokiI shHN1DzUjcnCv78nR1ksVywGQmCb5tjnexe8hVPeubK5GlAwxVPP3q9jqhMfCboQ60TO2I1 Gg8xYp6+2keopdrgJZwLSZZHLrTGRCZLsZ5Xt982SK2jxoPsXwCaxw0Jijm5KxfMn1MZw9H 6U1XuqVNTewXGyYcrqShw== X-UI-Out-Filterresults: notjunk:1;V03:K0:RIsNoZL7xWc=:8ygGBqWgNrkvYQpNvAyFzl OdpNnF52cSDMXnvcn5h57tBlwfo2L90zLjgUpyRnvIcBN4rNYEkKIgSazM3v6jDxwDsoyWYKc TcodKbGjPav5EZPnTv34v1zHjcP+W2k0jauNR5Kerqis4rXC4KDBhIUBRhm+aX+sXiK6xhlhb QuRK+yFCGDtXJSS6ylaSeW5dOqzHsPgyJFwHdfsAM8+3hvuKh6/E/cn7UQrDlBVgdTJXUeQbY nqkDFfHCd4RhHtloNCV0SkTbSSu4IOgaVy8XmAfwU6QMOWPRZGbrY2xPSk91RmAl4hlM3duK0 Qp8ufMIiG6576XG8MeF8MD38UfhMXDid6Vi45iQgFY2GNKaaHEgu8xjTYwLbnqVb9cYaDeN42 FQjqhw1I/HJGCSyK4Jt9+zPofk11htqq063x8yZaBQdqJbaRzkrNnE5K0betp94X/Tf/uRfRn M7nZ8ePilYcKCjZ+ZUH8OI9bDYweXKoiR5r4yY9F5VKywqAIRjG4bx4ogUvOIaJIQYjEr2ewz BILMDNQAdzK28m7HVsR+MvAbrr4uyuJaSuLuDyJdlA/f5P6PnGQJzn0InFcbu05K53kQjwV3Q saOpu7m6QENjujWkN6bCoi5tiVNLxrln2tGMaLWTBm7W3hNdaxmUv3rqJa6qVHPfFedoFekYZ mZymW4UaaP04cCjzXylnE+YMtEMJVzJq910oKTTW3Xg1nTribr18Ivk0xbVyn4v58+HuaIqmE 0rd6eNfqAVMl/Yp5bLcHc4YvYJ4USGvvOeLrio7ZK3Mmoomd1Xs5Mi6AGx8gPWxjH8evXbTaU NR9WTylJl83LJIvIWsgvHlshhYrBkFGCAbaOVwgMHVM8jQiv3QQELOl7+qR764bOZfU/cstzH D/DWtzyOz2XGHopShDd0iFegqRpeUzH841T8xmdbrwhAmGdk2CEupOJL69zF6luhisWZ3U/yj 3ezj8dYuyxST5nOHcLwDtomAh1t6N5/oi3qV7byA8UXHx09W7vD5QAgLYWRnWhfd0I3pZZ76Z /ULt0+nKxC8vPP+bXvfkGwFkh/FeQbsA4yDhaV3HwXHeJDVQxykKMnEfqXkBHj0lL2K1rKltH zj94hhKx+OQ98o= Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Provide implementations for the tpm phy operations set_reset and unset_reset. Taking the chip out of reset requires a certain sequence of line assertions and deassertions with respective minimum wait intervals: deassert RST wait at least 60 ms assert RST wait at least 2 usecs deassert RST wait at least 60 ms assert RST wait at least 2 usecs deassert RST wait at least 60 ms before issuing the first TPM command According to the Infineon SLB 9670VQ2.0 datasheet this sequence is needed to avoid triggering the chips defense modes in which it protects itself from dictionary attacks in conjunction with resets. Since the generic probe function tpm_tis_spi_probe only sets the non-optional phy ops provide a custom version in which also set_reset and unset_reset are assigned. Move the implementation of these functions into a new file to separate the SLB9670 specific code from the generic code. Signed-off-by: Lino Sanfilippo --- drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_tis_spi.h | 2 + drivers/char/tpm/tpm_tis_spi_main.c | 4 +- drivers/char/tpm/tpm_tis_spi_slb9670.c | 82 ++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 drivers/char/tpm/tpm_tis_spi_slb9670.c diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 66d39ea6bd10..22c82eb4e382 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_TCG_TIS_SYNQUACER) += tpm_tis_synquacer.o obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o tpm_tis_spi-y := tpm_tis_spi_main.o +tpm_tis_spi-y += tpm_tis_spi_slb9670.o tpm_tis_spi-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o obj-$(CONFIG_TCG_TIS_I2C_CR50) += tpm_tis_i2c_cr50.o diff --git a/drivers/char/tpm/tpm_tis_spi.h b/drivers/char/tpm/tpm_tis_spi.h index 8f4331d8a4dd..b90848832da4 100644 --- a/drivers/char/tpm/tpm_tis_spi.h +++ b/drivers/char/tpm/tpm_tis_spi.h @@ -51,6 +51,8 @@ static inline int cr50_spi_probe(struct spi_device *spi) } #endif +extern int slb9670_spi_probe(struct spi_device *spi); + #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_TCG_TIS_SPI_CR50) extern int tpm_tis_spi_resume(struct device *dev); #else diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c index b2d13b844659..50da1f6eeaea 100644 --- a/drivers/char/tpm/tpm_tis_spi_main.c +++ b/drivers/char/tpm/tpm_tis_spi_main.c @@ -264,7 +264,7 @@ static void tpm_tis_spi_remove(struct spi_device *dev) static const struct spi_device_id tpm_tis_spi_id[] = { { "st33htpm-spi", (unsigned long)tpm_tis_spi_probe }, - { "slb9670", (unsigned long)tpm_tis_spi_probe }, + { "slb9670", (unsigned long)slb9670_spi_probe }, { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe }, { "tpm_tis-spi", (unsigned long)tpm_tis_spi_probe }, { "cr50", (unsigned long)cr50_spi_probe }, @@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id); static const struct of_device_id of_tis_spi_match[] = { { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe }, - { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe }, + { .compatible = "infineon,slb9670", .data = slb9670_spi_probe }, { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe }, { .compatible = "google,cr50", .data = cr50_spi_probe }, {} diff --git a/drivers/char/tpm/tpm_tis_spi_slb9670.c b/drivers/char/tpm/tpm_tis_spi_slb9670.c new file mode 100644 index 000000000000..ba9cd54e8bff --- /dev/null +++ b/drivers/char/tpm/tpm_tis_spi_slb9670.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * tpm_tis_spi_slb9670.c + * + * Copyright (C) 2022 KUNBUS GmbH + * + */ + +#include +#include +#include + +#include "tpm_tis_core.h" +#include "tpm_tis_spi.h" + +/* + * Time intervals used in the reset sequence. + * RSTIN: minimum time to hold the reset line deasserted. + * WRST: minimum time to hold the reset line asserted. + */ +#define SLB9670_TIME_RSTIN 60 /* time in ms */ +#define SLB9670_TIME_WRST 2 /* time in usecs */ + +int slb9670_spi_unset_reset(struct tpm_tis_data *data) +{ + /* + * Perform the reset sequence: we have to deassert and assert the reset + * line two times and wait the respective time intervals. + * After a last wait interval of RSTIN the chip is ready to receive the + * first command. + */ + gpiod_set_value(data->reset_gpio, 0); + msleep(SLB9670_TIME_RSTIN); + gpiod_set_value(data->reset_gpio, 1); + udelay(SLB9670_TIME_WRST); + gpiod_set_value(data->reset_gpio, 0); + msleep(SLB9670_TIME_RSTIN); + gpiod_set_value(data->reset_gpio, 1); + udelay(SLB9670_TIME_WRST); + gpiod_set_value(data->reset_gpio, 0); + msleep(SLB9670_TIME_RSTIN); + + return 0; +} + +int slb9670_spi_set_reset(struct tpm_tis_data *data) +{ + gpiod_set_value(data->reset_gpio, 1); + return 0; +} + +static const struct tpm_tis_phy_ops slb9670_spi_phy_ops = { + .read_bytes = tpm_tis_spi_read_bytes, + .write_bytes = tpm_tis_spi_write_bytes, + .read16 = tpm_tis_spi_read16, + .read32 = tpm_tis_spi_read32, + .write32 = tpm_tis_spi_write32, + .set_reset = slb9670_spi_set_reset, + .unset_reset = slb9670_spi_unset_reset, +}; + +int slb9670_spi_probe(struct spi_device *spi) +{ + struct tpm_tis_spi_phy *phy; + int irq; + + phy = devm_kzalloc(&spi->dev, sizeof(struct tpm_tis_spi_phy), + GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->flow_control = tpm_tis_spi_flow_control; + + /* If the SPI device has an IRQ then use that */ + if (spi->irq > 0) + irq = spi->irq; + else + irq = -1; + + init_completion(&phy->ready); + return tpm_tis_spi_init(spi, phy, irq, &slb9670_spi_phy_ops); +}