From patchwork Fri Sep 20 18:32:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 11154783 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9226914ED for ; Fri, 20 Sep 2019 18:33:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 70A8E21A4C for ; Fri, 20 Sep 2019 18:33:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="E2eibxj8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406582AbfITScp (ORCPT ); Fri, 20 Sep 2019 14:32:45 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:45011 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406279AbfITSco (ORCPT ); Fri, 20 Sep 2019 14:32:44 -0400 Received: by mail-pf1-f196.google.com with SMTP id q21so5039774pfn.11 for ; Fri, 20 Sep 2019 11:32:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oyE0lW4jziioV/J2I+7J0Vx8oaL6QC9YS1SJmLa32Os=; b=E2eibxj8my5Dp1jxc+KoYQACiZUC0OFoR9GaGM/J3hIS0zRM4vSRbkysgba9lXdTZL xTdQ7FDQwPL9Ih3+86mwVQMtG0mMaoDjt3NVu9Cwmb7n+GUycQ2UgmVgOZz83WZHf/52 /GznKVv8v3jAxGvGSRakY9iH/C3Uciv4mMza8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oyE0lW4jziioV/J2I+7J0Vx8oaL6QC9YS1SJmLa32Os=; b=S14N4/yoYP+KNOtyIrg6l8JhtzBsy7HWGJ9RHajJMgt98Yo//LRk5UEV4NCjxcvaFN EEcn0NNV5mYq+aOVHmVOWzkLIx0eSbFzxSJ9eMehjw8zsIj9k2rl8w9cOPbAFIY5P1Nc 3oW8DArMFLEnU1FhKHDCPaBMjG4qelG6hJ9MaN0AxqZYUuU7HPpn1RmfiBY0/wDRrw5n odOxI37CCZ+rfCLDHJY5Y54KIgr/Op2fdYdqKwVx8XOvBj4IGI2Q06c0tr3yIQ5t6MHb Q+t5AtBHfWPqira5CWNdbaFhsJLO+30G/tSWOJ3JE3DJUsw8uO0whrbQJ3I+mWA85pmU 9QPg== X-Gm-Message-State: APjAAAWMc+dpvn2PnrFJOZzBonCHALovp/jj5jVbAz2gwpafDlETzWlz HbCybh2rL4V0v+kFY1j0ljiOmg== X-Google-Smtp-Source: APXvYqyEpnhnEiGd4gIQfC2yEjPQ+Cs/cq/kw9SdUkcIz7yiWyUxh4iISf5kbtfmrVH3anNGaf7eXg== X-Received: by 2002:a62:7d8c:: with SMTP id y134mr19187475pfc.257.1569004363189; Fri, 20 Sep 2019 11:32:43 -0700 (PDT) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id b69sm4436072pfb.132.2019.09.20.11.32.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Sep 2019 11:32:42 -0700 (PDT) From: Stephen Boyd To: Peter Huewe , Jarkko Sakkinen Cc: Andrey Pronin , linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, Duncan Laurie , Jason Gunthorpe , Arnd Bergmann , Greg Kroah-Hartman , Guenter Roeck , Alexander Steffen , Heiko Stuebner , Rob Herring Subject: [PATCH v7 1/6] dt-bindings: tpm: document properties for cr50 Date: Fri, 20 Sep 2019 11:32:35 -0700 Message-Id: <20190920183240.181420-2-swboyd@chromium.org> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog In-Reply-To: <20190920183240.181420-1-swboyd@chromium.org> References: <20190920183240.181420-1-swboyd@chromium.org> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Andrey Pronin Add TPM2.0 PTP FIFO compatible SPI interface for chips with Cr50 firmware. Cc: Andrey Pronin Cc: Duncan Laurie Cc: Jason Gunthorpe Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Guenter Roeck Cc: Alexander Steffen Cc: Heiko Stuebner Signed-off-by: Andrey Pronin Reviewed-by: Rob Herring Acked-by: Jarkko Sakkinen Signed-off-by: Stephen Boyd --- .../bindings/security/tpm/google,cr50.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Documentation/devicetree/bindings/security/tpm/google,cr50.txt diff --git a/Documentation/devicetree/bindings/security/tpm/google,cr50.txt b/Documentation/devicetree/bindings/security/tpm/google,cr50.txt new file mode 100644 index 000000000000..cd69c2efdd37 --- /dev/null +++ b/Documentation/devicetree/bindings/security/tpm/google,cr50.txt @@ -0,0 +1,19 @@ +* H1 Secure Microcontroller with Cr50 Firmware on SPI Bus. + +H1 Secure Microcontroller running Cr50 firmware provides several +functions, including TPM-like functionality. It communicates over +SPI using the FIFO protocol described in the PTP Spec, section 6. + +Required properties: +- compatible: Should be "google,cr50". +- spi-max-frequency: Maximum SPI frequency. + +Example: + +&spi0 { + tpm@0 { + compatible = "google,cr50"; + reg = <0>; + spi-max-frequency = <800000>; + }; +}; From patchwork Fri Sep 20 18:32:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 11154773 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AE2AE14ED for ; Fri, 20 Sep 2019 18:32:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8D4CA208C3 for ; Fri, 20 Sep 2019 18:32:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Ziu3zpd4" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406604AbfITScq (ORCPT ); Fri, 20 Sep 2019 14:32:46 -0400 Received: from mail-pg1-f196.google.com ([209.85.215.196]:46457 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406279AbfITScq (ORCPT ); Fri, 20 Sep 2019 14:32:46 -0400 Received: by mail-pg1-f196.google.com with SMTP id a3so4268553pgm.13 for ; Fri, 20 Sep 2019 11:32:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2FOFa9cgK5baQpD0SfGUwU5l0g13GQ3zevtR0etuAJA=; b=Ziu3zpd4aifAB/blDZvNK/zLz8RvWAe1xaGd2eZQXbE8hu4ifk4lRzjZ3qNv//qBoC /mPrcPsMTMlcg0YSjh/iF8fUNI9axGjsSl7z7Q6QxdT6x8N5hEowIwTTOvqxnIRMn6Hq iRyQuGWjV7V5G5Bw/p2F4O06HcBEyaJ/+MG+E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2FOFa9cgK5baQpD0SfGUwU5l0g13GQ3zevtR0etuAJA=; b=JMAHB5MgP0f0UFptq4r/Z7Y+tDDArwM44iKaXHBXlJtHOBI0WGNi3wesbzxzwgrJ0j zbeitvkL1HbGnrh9aCXihN7Fdb/uw5FlFMiD8tXzGjvWlC7b8nzmWDKyvrqRiMopelIu rlGYkS2+q9Lo5zfCSnOe2FIS9TbS1yyulCzGzh7A7zh3EOj2PLBc4mlbqWE3QibrXcEk vmrfNXNRriSvQzPNYQDC/FopLWWLMhFxRNHB6igiMksW3b5CfP1ETL2Iyau9IapVJCRE dfO//r4woVZf8uKTo3d3UnPx6YmRfVh6VjF0zBXAfTMGIY33Lc1DxaW/jEJ+uIoIwmZW wSNg== X-Gm-Message-State: APjAAAW1LrtqvY5M0m1SCChril0CN6km1cuHW0hUpt7OgpCWZI8kS4Ci vlM+jm5BBzrbe+iJIr7usmFZbQ== X-Google-Smtp-Source: APXvYqy/78meG18vRVNX7WuMywGXbUxonJGjsyju6ogxEWs43Im8alaQjdMsS7f0HaO0Ibt/Vd4x4w== X-Received: by 2002:a17:90a:7348:: with SMTP id j8mr6253223pjs.63.1569004364278; Fri, 20 Sep 2019 11:32:44 -0700 (PDT) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id b69sm4436072pfb.132.2019.09.20.11.32.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Sep 2019 11:32:43 -0700 (PDT) From: Stephen Boyd To: Peter Huewe , Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, Andrey Pronin , Duncan Laurie , Jason Gunthorpe , Arnd Bergmann , Greg Kroah-Hartman , Guenter Roeck , Alexander Steffen , Heiko Stuebner Subject: [PATCH v7 2/6] tpm: Add a flag to indicate TPM power is managed by firmware Date: Fri, 20 Sep 2019 11:32:36 -0700 Message-Id: <20190920183240.181420-3-swboyd@chromium.org> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog In-Reply-To: <20190920183240.181420-1-swboyd@chromium.org> References: <20190920183240.181420-1-swboyd@chromium.org> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org On some platforms, the TPM power is managed by firmware and therefore we don't need to stop the TPM on suspend when going to a light version of suspend such as S0ix ("freeze" suspend state). Add a chip flag, TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED, to indicate this so that certain platforms can probe for the usage of this light suspend and avoid touching the TPM state across suspend/resume. Cc: Andrey Pronin Cc: Duncan Laurie Cc: Jason Gunthorpe Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Guenter Roeck Cc: Alexander Steffen Cc: Heiko Stuebner Reviewed-by: Jarkko Sakkinen Signed-off-by: Stephen Boyd --- drivers/char/tpm/tpm-interface.c | 8 +++++++- drivers/char/tpm/tpm.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1b4f95c13e00..0b3def8e8186 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -395,7 +396,11 @@ int tpm_pm_suspend(struct device *dev) return -ENODEV; if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) - return 0; + goto suspended; + + if ((chip->flags & TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED) && + !pm_suspend_via_firmware()) + goto suspended; if (!tpm_chip_start(chip)) { if (chip->flags & TPM_CHIP_FLAG_TPM2) @@ -406,6 +411,7 @@ int tpm_pm_suspend(struct device *dev) tpm_chip_stop(chip); } +suspended: return rc; } EXPORT_SYMBOL_GPL(tpm_pm_suspend); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index a7fea3e0ca86..f3bf2f7f755c 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -162,6 +162,7 @@ enum tpm_chip_flags { TPM_CHIP_FLAG_VIRTUAL = BIT(3), TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), + TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED = BIT(6), }; #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) From patchwork Fri Sep 20 18:32:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 11154781 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BA92D16B1 for ; Fri, 20 Sep 2019 18:33:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8E3BD2080F for ; Fri, 20 Sep 2019 18:33:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="J2EFF13K" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406602AbfITScq (ORCPT ); Fri, 20 Sep 2019 14:32:46 -0400 Received: from mail-pg1-f193.google.com ([209.85.215.193]:46456 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406540AbfITScp (ORCPT ); Fri, 20 Sep 2019 14:32:45 -0400 Received: by mail-pg1-f193.google.com with SMTP id a3so4268579pgm.13 for ; Fri, 20 Sep 2019 11:32:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rBbuZ1/hGmJSVpkE9Mk+PjVfNnVUpgjwmAPJurf50Uw=; b=J2EFF13K/jXVBj5kVcGXkf4RTeD2hgA/FBTQUufm3ZAyBcJfDNoM8BEXyhVSeaM97J 3NRdzMCsebNhpUDgWPIQNpcHCSuN31/lsVomrYDqdzdwIbdbvK4+amEAIc6puo1dzF2E SkZZGJgtjwUySa44m9f4HcJZ5Kv+RLrasmrrs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rBbuZ1/hGmJSVpkE9Mk+PjVfNnVUpgjwmAPJurf50Uw=; b=C0rxxwNS23qepdrTjd4MFDQLVSJUsqvXpGE6xHMYj3jKZyAIhl46ASNffbkjmH5LlW GlOasHaRLdX/inwm5e/iApHtbW0cH15AkI3ubGfuS1VlMaBgfe/rx/34sERuUYkugRuX eXqlePNeCrYU5hypJBkELj/i0QflMEhktj4wMGoVG7ShcccKgejSDr+LHFjTbQMkdmu6 gWWPmDC29mcoMvpav+Qyb7pHvZf06RSsDX4NHya5y9MYBI9vR474EtfJB0nEbJDfffF4 Duj8l6cRJfxHOA8c7q1f2DSV4boKRBUGMyOZ3TLniuwEtZ8LB3uzrgapom6CKDKBpQdS yBsA== X-Gm-Message-State: APjAAAWOFcJkMt8M/jwGXzZ9/A29fInXRD/JQwUHSzqKpOxm9Nj0/o7B TTboifPYWGjpr1OwcNHhGDu3Nw== X-Google-Smtp-Source: APXvYqynrv4peJetxnAo9QWlTFtoQAG24ppGCJoY2oeM0C/YlX0ZUTXBo5O8AkbLJU88NgBvfrKtBA== X-Received: by 2002:a17:90a:24a8:: with SMTP id i37mr6241044pje.123.1569004365164; Fri, 20 Sep 2019 11:32:45 -0700 (PDT) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id b69sm4436072pfb.132.2019.09.20.11.32.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Sep 2019 11:32:44 -0700 (PDT) From: Stephen Boyd To: Peter Huewe , Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, Andrey Pronin , Duncan Laurie , Jason Gunthorpe , Arnd Bergmann , Greg Kroah-Hartman , Guenter Roeck , Alexander Steffen , Heiko Stuebner Subject: [PATCH v7 3/6] tpm: tpm_tis_spi: Introduce a flow control callback Date: Fri, 20 Sep 2019 11:32:37 -0700 Message-Id: <20190920183240.181420-4-swboyd@chromium.org> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog In-Reply-To: <20190920183240.181420-1-swboyd@chromium.org> References: <20190920183240.181420-1-swboyd@chromium.org> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Cr50 firmware has a different flow control protocol than the one used by this TPM PTP SPI driver. Introduce a flow control callback so we can override the standard sequence with the custom one that Cr50 uses. Cc: Andrey Pronin Cc: Duncan Laurie Cc: Jason Gunthorpe Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Guenter Roeck Cc: Alexander Steffen Cc: Heiko Stuebner Reviewed-by: Jarkko Sakkinen Signed-off-by: Stephen Boyd --- drivers/char/tpm/tpm_tis_spi.c | 62 ++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 19513e622053..b3ed85671dd8 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -42,6 +42,8 @@ struct tpm_tis_spi_phy { struct tpm_tis_data priv; struct spi_device *spi_device; + int (*flow_control)(struct tpm_tis_spi_phy *phy, + struct spi_transfer *xfer); u8 *iobuf; }; @@ -50,12 +52,46 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da return container_of(data, struct tpm_tis_spi_phy, priv); } +/* + * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short, + * keep trying to read from the device until MISO goes high indicating the + * wait state has ended. + * + * [1] https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ + */ +static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy, + struct spi_transfer *spi_xfer) +{ + struct spi_message m; + int ret, i; + + if ((phy->iobuf[3] & 0x01) == 0) { + // handle SPI wait states + phy->iobuf[0] = 0; + + for (i = 0; i < TPM_RETRY; i++) { + spi_xfer->len = 1; + spi_message_init(&m); + spi_message_add_tail(spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + return ret; + if (phy->iobuf[0] & 0x01) + break; + } + + if (i == TPM_RETRY) + return -ETIMEDOUT; + } + + return 0; +} + static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, u8 *in, const u8 *out) { struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); int ret = 0; - int i; struct spi_message m; struct spi_transfer spi_xfer; u8 transfer_len; @@ -82,26 +118,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, if (ret < 0) goto exit; - if ((phy->iobuf[3] & 0x01) == 0) { - // handle SPI wait states - phy->iobuf[0] = 0; - - for (i = 0; i < TPM_RETRY; i++) { - spi_xfer.len = 1; - spi_message_init(&m); - spi_message_add_tail(&spi_xfer, &m); - ret = spi_sync_locked(phy->spi_device, &m); - if (ret < 0) - goto exit; - if (phy->iobuf[0] & 0x01) - break; - } - - if (i == TPM_RETRY) { - ret = -ETIMEDOUT; - goto exit; - } - } + ret = phy->flow_control(phy, &spi_xfer); + if (ret < 0) + goto exit; spi_xfer.cs_change = 0; spi_xfer.len = transfer_len; @@ -207,6 +226,7 @@ static int tpm_tis_spi_probe(struct spi_device *dev) phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); if (!phy->iobuf) return -ENOMEM; + phy->flow_control = tpm_tis_spi_flow_control; /* If the SPI device has an IRQ then use that */ if (dev->irq > 0) From patchwork Fri Sep 20 18:32:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 11154779 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 73B9216B1 for ; Fri, 20 Sep 2019 18:33:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 33A7A208C3 for ; Fri, 20 Sep 2019 18:33:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="JHfQMgEa" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406685AbfITSdB (ORCPT ); Fri, 20 Sep 2019 14:33:01 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:35822 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406606AbfITScr (ORCPT ); Fri, 20 Sep 2019 14:32:47 -0400 Received: by mail-pf1-f193.google.com with SMTP id 205so5082844pfw.2 for ; Fri, 20 Sep 2019 11:32:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UE07B1hI6JcNXMhFPZlTiRRj1Rb9daBX3Y9cn+PKEVg=; b=JHfQMgEa5LfbbGHYbBRbATj5TjaLId4il8pc7nPyzbuOCHgtdLr+qqluKMuwV9+obq XLGFLgBgwx4VahxofFVxjeNucoQLle8bMFlgcu4islNN6Oi1NjUyCO2sGC1IJcpkNrOb 11zlG+F6/CBj2nwGsYPA38tGgfz41RLzajE74= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UE07B1hI6JcNXMhFPZlTiRRj1Rb9daBX3Y9cn+PKEVg=; b=WDqJAAGIgUGHHZMtSj2+fy307gC0yuMoOe9JsrXGGPQx63CPJjNmjSWvpvhjX5mACI swRwk4YP9bglP80RNLAqRkKZQBeix8p6ATFOG+br3qxZTK7GmO9wUnoR4JclPcGUeY+G +8Ka4XJj70VyzvnfuhzR8Ilq6l+mHux+B2XJaVuc1OTy7htfc3h7nAZrguPtdf2m0WRt PDVEwxUYonvXzxisaINkgSqwjgVtphG62syrBJGB+m+2UOtdrOs5k4LVWhhqoZxv6BiF +HZ0+VRqllSGcONsu7TK2DpFRjMEBbzUW9oQdsaCpXCz5cnEw00ikL2jO4fWtozdoteh Rxvg== X-Gm-Message-State: APjAAAW0WGqexCMVHG0MxyET4eoTiMVVnTq2NQUjT/NQ2KTHxyVn+M2g BDdUqfdiTntPOk63AGvx170YFQ== X-Google-Smtp-Source: APXvYqxsvMxyCnuZ2IvfUA1CXl3rvEJ6kGN51NcEvIkYCgSvAN/qkYuyolt81dbm+3Mm/lxzM2Oh8Q== X-Received: by 2002:a63:1c4b:: with SMTP id c11mr13900052pgm.216.1569004366144; Fri, 20 Sep 2019 11:32:46 -0700 (PDT) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id b69sm4436072pfb.132.2019.09.20.11.32.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Sep 2019 11:32:45 -0700 (PDT) From: Stephen Boyd To: Peter Huewe , Jarkko Sakkinen Cc: Andrey Pronin , linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, Duncan Laurie , Jason Gunthorpe , Arnd Bergmann , Greg Kroah-Hartman , Guenter Roeck , Alexander Steffen , Heiko Stuebner Subject: [PATCH v7 4/6] tpm: tpm_tis_spi: Support cr50 devices Date: Fri, 20 Sep 2019 11:32:38 -0700 Message-Id: <20190920183240.181420-5-swboyd@chromium.org> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog In-Reply-To: <20190920183240.181420-1-swboyd@chromium.org> References: <20190920183240.181420-1-swboyd@chromium.org> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Andrey Pronin Add TPM2.0 PTP FIFO compatible SPI interface for chips with Cr50 firmware. The firmware running on the currently supported H1 Secure Microcontroller requires a special driver to handle its specifics: - need to ensure a certain delay between SPI transactions, or else the chip may miss some part of the next transaction - if there is no SPI activity for some time, it may go to sleep, and needs to be waken up before sending further commands - access to vendor-specific registers Cr50 firmware has a requirement to wait for the TPM to wakeup before sending commands over the SPI bus. Otherwise, the firmware could be in deep sleep and not respond. The method to wait for the device to wakeup is slightly different than the usual flow control mechanism described in the TCG SPI spec. Add a completion to tpm_tis_spi_transfer() before we start a SPI transfer so we can keep track of the last time the TPM driver accessed the SPI bus to support the flow control mechanism. Split the cr50 logic off into a different file to keep it out of the normal code flow of the existing SPI driver while making it all part of the same module when the code is optionally compiled into the same module. Export a new function, tpm_tis_spi_init(), and the associated read/write/transfer APIs so that we can do this. Make the cr50 code wrap the tpm_tis_spi_phy struct with its own struct to override the behavior of tpm_tis_spi_transfer() by supplying a custom flow control hook. This shares the most code between the core driver and the cr50 support without combining everything into the core driver or exporting module symbols. Signed-off-by: Andrey Pronin Cc: Andrey Pronin Cc: Duncan Laurie Cc: Jason Gunthorpe Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Guenter Roeck Cc: Alexander Steffen Cc: Heiko Stuebner [swboyd@chromium.org: Replace boilerplate with SPDX tag, drop suspended bit and remove ifdef checks in cr50.h, migrate to functions exported in tpm_tis_spi.h, combine into one module instead of two] Signed-off-by: Stephen Boyd Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/Kconfig | 7 + drivers/char/tpm/Makefile | 4 +- drivers/char/tpm/tpm_tis_spi.c | 78 ++++--- drivers/char/tpm/tpm_tis_spi.h | 53 +++++ drivers/char/tpm/tpm_tis_spi_cr50.c | 321 ++++++++++++++++++++++++++++ 5 files changed, 431 insertions(+), 32 deletions(-) create mode 100644 drivers/char/tpm/tpm_tis_spi.h create mode 100644 drivers/char/tpm/tpm_tis_spi_cr50.c diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 88a3c06fc153..ecbffae14941 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -67,6 +67,13 @@ config TCG_TIS_SPI within Linux. To compile this driver as a module, choose M here; the module will be called tpm_tis_spi. +config TCG_TIS_SPI_CR50 + bool "Cr50 SPI Interface" + depends on TCG_TIS_SPI + ---help--- + If you have a H1 secure module running Cr50 firmware on SPI bus, + say Yes and it will be accessible from within Linux. + config TCG_TIS_I2C_ATMEL tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)" depends on I2C diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index a01c4cab902a..c96439f11c85 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -21,7 +21,9 @@ tpm-$(CONFIG_EFI) += eventlog/efi.o tpm-$(CONFIG_OF) += eventlog/of.o obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o obj-$(CONFIG_TCG_TIS) += tpm_tis.o -obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o +obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi_mod.o +tpm_tis_spi_mod-y := tpm_tis_spi.o +tpm_tis_spi_mod-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index b3ed85671dd8..5e4253e7c080 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -20,6 +20,7 @@ * Dorn and Kyleen Hall and Jarko Sakkinnen. */ +#include #include #include #include @@ -31,27 +32,16 @@ #include #include +#include #include #include #include #include "tpm.h" #include "tpm_tis_core.h" +#include "tpm_tis_spi.h" #define MAX_SPI_FRAMESIZE 64 -struct tpm_tis_spi_phy { - struct tpm_tis_data priv; - struct spi_device *spi_device; - int (*flow_control)(struct tpm_tis_spi_phy *phy, - struct spi_transfer *xfer); - u8 *iobuf; -}; - -static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) -{ - return container_of(data, struct tpm_tis_spi_phy, priv); -} - /* * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short, * keep trying to read from the device until MISO goes high indicating the @@ -87,8 +77,8 @@ static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy, return 0; } -static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, - u8 *in, const u8 *out) +int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *in, const u8 *out) { struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); int ret = 0; @@ -136,6 +126,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, spi_message_init(&m); spi_message_add_tail(&spi_xfer, &m); + reinit_completion(&phy->ready); ret = spi_sync_locked(phy->spi_device, &m); if (ret < 0) goto exit; @@ -165,7 +156,7 @@ static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, return tpm_tis_spi_transfer(data, addr, len, NULL, value); } -static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) +int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { __le16 result_le; int rc; @@ -178,7 +169,7 @@ static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) return rc; } -static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) +int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { __le32 result_le; int rc; @@ -191,7 +182,7 @@ static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) return rc; } -static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) +int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) { __le32 value_le; int rc; @@ -203,6 +194,18 @@ static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) return rc; } +int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy, + int irq, const struct tpm_tis_phy_ops *phy_ops) +{ + phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); + if (!phy->iobuf) + return -ENOMEM; + + phy->spi_device = spi; + + return tpm_tis_core_init(&spi->dev, &phy->priv, irq, phy_ops, NULL); +} + static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { .read_bytes = tpm_tis_spi_read_bytes, .write_bytes = tpm_tis_spi_write_bytes, @@ -221,11 +224,6 @@ static int tpm_tis_spi_probe(struct spi_device *dev) if (!phy) return -ENOMEM; - phy->spi_device = dev; - - phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); - if (!phy->iobuf) - return -ENOMEM; phy->flow_control = tpm_tis_spi_flow_control; /* If the SPI device has an IRQ then use that */ @@ -234,11 +232,27 @@ static int tpm_tis_spi_probe(struct spi_device *dev) else irq = -1; - return tpm_tis_core_init(&dev->dev, &phy->priv, irq, &tpm_spi_phy_ops, - NULL); + init_completion(&phy->ready); + return tpm_tis_spi_init(dev, phy, irq, &tpm_spi_phy_ops); +} + +typedef int (*tpm_tis_spi_probe_func)(struct spi_device *); + +static int tpm_tis_spi_driver_probe(struct spi_device *spi) +{ + const struct spi_device_id *spi_dev_id = spi_get_device_id(spi); + tpm_tis_spi_probe_func probe_func; + + probe_func = of_device_get_match_data(&spi->dev); + if (!probe_func && spi_dev_id) + probe_func = (tpm_tis_spi_probe_func)spi_dev_id->driver_data; + if (!probe_func) + return -ENODEV; + + return probe_func(spi); } -static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); +static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume); static int tpm_tis_spi_remove(struct spi_device *dev) { @@ -250,15 +264,17 @@ static int tpm_tis_spi_remove(struct spi_device *dev) } static const struct spi_device_id tpm_tis_spi_id[] = { - {"tpm_tis_spi", 0}, + { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe }, + { "cr50", (unsigned long)cr50_spi_probe }, {} }; MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id); static const struct of_device_id of_tis_spi_match[] = { - { .compatible = "st,st33htpm-spi", }, - { .compatible = "infineon,slb9670", }, - { .compatible = "tcg,tpm_tis-spi", }, + { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe }, + { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe }, + { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe }, + { .compatible = "google,cr50", .data = cr50_spi_probe }, {} }; MODULE_DEVICE_TABLE(of, of_tis_spi_match); @@ -277,7 +293,7 @@ static struct spi_driver tpm_tis_spi_driver = { .of_match_table = of_match_ptr(of_tis_spi_match), .acpi_match_table = ACPI_PTR(acpi_tis_spi_match), }, - .probe = tpm_tis_spi_probe, + .probe = tpm_tis_spi_driver_probe, .remove = tpm_tis_spi_remove, .id_table = tpm_tis_spi_id, }; diff --git a/drivers/char/tpm/tpm_tis_spi.h b/drivers/char/tpm/tpm_tis_spi.h new file mode 100644 index 000000000000..bba73979c368 --- /dev/null +++ b/drivers/char/tpm/tpm_tis_spi.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2015 Infineon Technologies AG + * Copyright (C) 2016 STMicroelectronics SAS + */ + +#ifndef TPM_TIS_SPI_H +#define TPM_TIS_SPI_H + +#include "tpm_tis_core.h" + +struct tpm_tis_spi_phy { + struct tpm_tis_data priv; + struct spi_device *spi_device; + int (*flow_control)(struct tpm_tis_spi_phy *phy, + struct spi_transfer *xfer); + struct completion ready; + unsigned long wake_after; + + u8 *iobuf; +}; + +static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) +{ + return container_of(data, struct tpm_tis_spi_phy, priv); +} + +extern int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy, + int irq, const struct tpm_tis_phy_ops *phy_ops); + +extern int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *in, const u8 *out); + +extern int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result); +extern int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result); +extern int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value); + +#ifdef CONFIG_TCG_TIS_SPI_CR50 +extern int cr50_spi_probe(struct spi_device *spi); +#else +static inline int cr50_spi_probe(struct spi_device *spi) +{ + return -ENODEV; +} +#endif + +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_TCG_TIS_SPI_CR50) +extern int tpm_tis_spi_resume(struct device *dev); +#else +#define tpm_tis_spi_resume NULL +#endif + +#endif diff --git a/drivers/char/tpm/tpm_tis_spi_cr50.c b/drivers/char/tpm/tpm_tis_spi_cr50.c new file mode 100644 index 000000000000..187a023c2556 --- /dev/null +++ b/drivers/char/tpm/tpm_tis_spi_cr50.c @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016 Google, Inc + * + * This device driver implements a TCG PTP FIFO interface over SPI for chips + * with Cr50 firmware. + * It is based on tpm_tis_spi driver by Peter Huewe and Christophe Ricard. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tpm_tis_core.h" +#include "tpm_tis_spi.h" + +/* + * Cr50 timing constants: + * - can go to sleep not earlier than after CR50_SLEEP_DELAY_MSEC. + * - needs up to CR50_WAKE_START_DELAY_USEC to wake after sleep. + * - requires waiting for "ready" IRQ, if supported; or waiting for at least + * CR50_NOIRQ_ACCESS_DELAY_MSEC between transactions, if IRQ is not supported. + * - waits for up to CR50_FLOW_CONTROL for flow control 'ready' indication. + */ +#define CR50_SLEEP_DELAY_MSEC 1000 +#define CR50_WAKE_START_DELAY_USEC 1000 +#define CR50_NOIRQ_ACCESS_DELAY msecs_to_jiffies(2) +#define CR50_READY_IRQ_TIMEOUT msecs_to_jiffies(TPM2_TIMEOUT_A) +#define CR50_FLOW_CONTROL msecs_to_jiffies(TPM2_TIMEOUT_A) +#define MAX_IRQ_CONFIRMATION_ATTEMPTS 3 + +#define TPM_CR50_FW_VER(l) (0x0f90 | ((l) << 12)) +#define TPM_CR50_MAX_FW_VER_LEN 64 + +struct cr50_spi_phy { + struct tpm_tis_spi_phy spi_phy; + + struct mutex time_track_mutex; + unsigned long last_access; + + unsigned long access_delay; + + unsigned int irq_confirmation_attempt; + bool irq_needs_confirmation; + bool irq_confirmed; +}; + +static inline struct cr50_spi_phy *to_cr50_spi_phy(struct tpm_tis_spi_phy *phy) +{ + return container_of(phy, struct cr50_spi_phy, spi_phy); +} + +/* + * The cr50 interrupt handler just signals waiting threads that the + * interrupt was asserted. It does not do any processing triggered + * by interrupts but is instead used to avoid fixed delays. + */ +static irqreturn_t cr50_spi_irq_handler(int dummy, void *dev_id) +{ + struct cr50_spi_phy *cr50_phy = dev_id; + + cr50_phy->irq_confirmed = true; + complete(&cr50_phy->spi_phy.ready); + + return IRQ_HANDLED; +} + +/* + * Cr50 needs to have at least some delay between consecutive + * transactions. Make sure we wait. + */ +static void cr50_ensure_access_delay(struct cr50_spi_phy *phy) +{ + unsigned long allowed_access = phy->last_access + phy->access_delay; + unsigned long time_now = jiffies; + struct device *dev = &phy->spi_phy.spi_device->dev; + + /* + * Note: There is a small chance, if Cr50 is not accessed in a few days, + * that time_in_range will not provide the correct result after the wrap + * around for jiffies. In this case, we'll have an unneeded short delay, + * which is fine. + */ + if (time_in_range_open(time_now, phy->last_access, allowed_access)) { + unsigned long remaining, timeout = allowed_access - time_now; + + remaining = wait_for_completion_timeout(&phy->spi_phy.ready, + timeout); + if (!remaining && phy->irq_confirmed) + dev_warn(dev, "Timeout waiting for TPM ready IRQ\n"); + } + + if (phy->irq_needs_confirmation) { + unsigned int attempt = ++phy->irq_confirmation_attempt; + + if (phy->irq_confirmed) { + phy->irq_needs_confirmation = false; + phy->access_delay = CR50_READY_IRQ_TIMEOUT; + dev_info(dev, "TPM ready IRQ confirmed on attempt %u\n", + attempt); + } else if (attempt > MAX_IRQ_CONFIRMATION_ATTEMPTS) { + phy->irq_needs_confirmation = false; + dev_warn(dev, "IRQ not confirmed - will use delays\n"); + } + } +} + +/* + * Cr50 might go to sleep if there is no SPI activity for some time and + * miss the first few bits/bytes on the bus. In such case, wake it up + * by asserting CS and give it time to start up. + */ +static bool cr50_needs_waking(struct cr50_spi_phy *phy) +{ + /* + * Note: There is a small chance, if Cr50 is not accessed in a few days, + * that time_in_range will not provide the correct result after the wrap + * around for jiffies. In this case, we'll probably timeout or read + * incorrect value from TPM_STS and just retry the operation. + */ + return !time_in_range_open(jiffies, phy->last_access, + phy->spi_phy.wake_after); +} + +static void cr50_wake_if_needed(struct cr50_spi_phy *cr50_phy) +{ + struct tpm_tis_spi_phy *phy = &cr50_phy->spi_phy; + + if (cr50_needs_waking(cr50_phy)) { + /* Assert CS, wait 1 msec, deassert CS */ + struct spi_transfer spi_cs_wake = { .delay_usecs = 1000 }; + + spi_sync_transfer(phy->spi_device, &spi_cs_wake, 1); + /* Wait for it to fully wake */ + usleep_range(CR50_WAKE_START_DELAY_USEC, + CR50_WAKE_START_DELAY_USEC * 2); + } + + /* Reset the time when we need to wake Cr50 again */ + phy->wake_after = jiffies + msecs_to_jiffies(CR50_SLEEP_DELAY_MSEC); +} + +/* + * Flow control: clock the bus and wait for cr50 to set LSB before + * sending/receiving data. TCG PTP spec allows it to happen during + * the last byte of header, but cr50 never does that in practice, + * and earlier versions had a bug when it was set too early, so don't + * check for it during header transfer. + */ +static int cr50_spi_flow_control(struct tpm_tis_spi_phy *phy, + struct spi_transfer *spi_xfer) +{ + struct device *dev = &phy->spi_device->dev; + unsigned long timeout = jiffies + CR50_FLOW_CONTROL; + struct spi_message m; + int ret; + + spi_xfer->len = 1; + + do { + spi_message_init(&m); + spi_message_add_tail(spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + return ret; + + if (time_after(jiffies, timeout)) { + dev_warn(dev, "Timeout during flow control\n"); + return -EBUSY; + } + } while (!(phy->iobuf[0] & 0x01)); + + return 0; +} + +static int tpm_tis_spi_cr50_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *in, const u8 *out) +{ + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + struct cr50_spi_phy *cr50_phy = to_cr50_spi_phy(phy); + int ret; + + mutex_lock(&cr50_phy->time_track_mutex); + /* + * Do this outside of spi_bus_lock in case cr50 is not the + * only device on that spi bus. + */ + cr50_ensure_access_delay(cr50_phy); + cr50_wake_if_needed(cr50_phy); + + ret = tpm_tis_spi_transfer(data, addr, len, in, out); + + cr50_phy->last_access = jiffies; + mutex_unlock(&cr50_phy->time_track_mutex); + + return ret; +} + +static int tpm_tis_spi_cr50_read_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *result) +{ + return tpm_tis_spi_cr50_transfer(data, addr, len, result, NULL); +} + +static int tpm_tis_spi_cr50_write_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, const u8 *value) +{ + return tpm_tis_spi_cr50_transfer(data, addr, len, NULL, value); +} + +static const struct tpm_tis_phy_ops tpm_spi_cr50_phy_ops = { + .read_bytes = tpm_tis_spi_cr50_read_bytes, + .write_bytes = tpm_tis_spi_cr50_write_bytes, + .read16 = tpm_tis_spi_read16, + .read32 = tpm_tis_spi_read32, + .write32 = tpm_tis_spi_write32, +}; + +static void cr50_print_fw_version(struct tpm_tis_data *data) +{ + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + int i, len = 0; + char fw_ver[TPM_CR50_MAX_FW_VER_LEN + 1]; + char fw_ver_block[4]; + + /* + * Write anything to TPM_CR50_FW_VER to start from the beginning + * of the version string + */ + tpm_tis_write8(data, TPM_CR50_FW_VER(data->locality), 0); + + /* Read the string, 4 bytes at a time, until we get '\0' */ + do { + tpm_tis_read_bytes(data, TPM_CR50_FW_VER(data->locality), 4, + fw_ver_block); + for (i = 0; i < 4 && fw_ver_block[i]; ++len, ++i) + fw_ver[len] = fw_ver_block[i]; + } while (i == 4 && len < TPM_CR50_MAX_FW_VER_LEN); + fw_ver[len] = '\0'; + + dev_info(&phy->spi_device->dev, "Cr50 firmware version: %s\n", fw_ver); +} + +int cr50_spi_probe(struct spi_device *spi) +{ + struct tpm_tis_spi_phy *phy; + struct cr50_spi_phy *cr50_phy; + int ret; + struct tpm_chip *chip; + + cr50_phy = devm_kzalloc(&spi->dev, sizeof(*cr50_phy), GFP_KERNEL); + if (!cr50_phy) + return -ENOMEM; + + phy = &cr50_phy->spi_phy; + phy->flow_control = cr50_spi_flow_control; + phy->wake_after = jiffies; + init_completion(&phy->ready); + + cr50_phy->access_delay = CR50_NOIRQ_ACCESS_DELAY; + cr50_phy->last_access = jiffies; + mutex_init(&cr50_phy->time_track_mutex); + + if (spi->irq > 0) { + ret = devm_request_irq(&spi->dev, spi->irq, cr50_spi_irq_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "cr50_spi", cr50_phy); + if (ret < 0) { + if (ret == -EPROBE_DEFER) + return ret; + dev_warn(&spi->dev, "Requesting IRQ %d failed: %d\n", + spi->irq, ret); + /* + * This is not fatal, the driver will fall back to + * delays automatically, since ready will never + * be completed without a registered irq handler. + * So, just fall through. + */ + } else { + /* + * IRQ requested, let's verify that it is actually + * triggered, before relying on it. + */ + cr50_phy->irq_needs_confirmation = true; + } + } else { + dev_warn(&spi->dev, + "No IRQ - will use delays between transactions.\n"); + } + + ret = tpm_tis_spi_init(spi, phy, -1, &tpm_spi_cr50_phy_ops); + if (ret) + return ret; + + cr50_print_fw_version(&phy->priv); + + chip = dev_get_drvdata(&spi->dev); + chip->flags |= TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED; + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +int tpm_tis_spi_resume(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_tis_data *data = dev_get_drvdata(&chip->dev); + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + /* + * Jiffies not increased during suspend, so we need to reset + * the time to wake Cr50 after resume. + */ + phy->wake_after = jiffies; + + return tpm_tis_resume(dev); +} +#endif From patchwork Fri Sep 20 18:32:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 11154777 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7473C14ED for ; Fri, 20 Sep 2019 18:33:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5527021907 for ; Fri, 20 Sep 2019 18:33:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="IfK8t/nU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406623AbfITScs (ORCPT ); Fri, 20 Sep 2019 14:32:48 -0400 Received: from mail-pf1-f194.google.com ([209.85.210.194]:38499 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406616AbfITScr (ORCPT ); Fri, 20 Sep 2019 14:32:47 -0400 Received: by mail-pf1-f194.google.com with SMTP id h195so5068990pfe.5 for ; Fri, 20 Sep 2019 11:32:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nP7l7HPSlZ4edHh/gvYjfiqgqZG+4NVrpc/qCXzCjyo=; b=IfK8t/nU0xPo02/ZMcqNy5ARLWAwNxBsqvy4wqEvgbiXc3DM/mBx9JIMecP35NYtLY d6oZ4r7PnCsXhl9Pb0b3d7dlH/m5Hm9IPYMV/EiNhfkR+LcbVpPuYCyqERLt8fUHC6q1 3StMkPgqAKCAu6i77204oJx8VRRPsEZFB3aLs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nP7l7HPSlZ4edHh/gvYjfiqgqZG+4NVrpc/qCXzCjyo=; b=eecud+g4IuZSrHMUjbugx/CFw+2HRjlcqDcAe+geI7P178Qsn04ttrTTriss/keBwJ iZlaE8TUQhV8OyuJGZSUbvLNRWW8m7mgbzUozXTGCxmjxIKt7cpvUBjTL3XO26c/hbRa zqgrrQT0Ozh+4HqcS1ZfbUvBxY4pP78w+mSkUocNQWSTc1AW/TOxy3kVA8O6rgBDNjib zdOnbaVXnT06ynJYMnvLkggBpGni1GcJliV6HoEYSZrcArwAIKPHs2z4FMYEXXdZe+HF MSvG3K7Pbzt/EMNQAyUECL5l8wU67bG8VTCVS/zrRdlo16YIoIi+k4hY/72DJSPyggte 2kzQ== X-Gm-Message-State: APjAAAVKaye4DsPibBxiAVEsRzJLlzI1uFWghbTf2hVg01ntD3qaHFQc ycHnjp3R9qWUl2gYW1+ePBeXpg== X-Google-Smtp-Source: APXvYqwvjlTaUG+/BiPqEzp4X98x1fEsnlQky9Xq/O2jses1JwEdzhOGp2Ea852+u1y8xsoZzPxwQA== X-Received: by 2002:a63:1904:: with SMTP id z4mr7163391pgl.403.1569004367160; Fri, 20 Sep 2019 11:32:47 -0700 (PDT) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id b69sm4436072pfb.132.2019.09.20.11.32.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Sep 2019 11:32:46 -0700 (PDT) From: Stephen Boyd To: Peter Huewe , Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, Andrey Pronin , Duncan Laurie , Jason Gunthorpe , Arnd Bergmann , Greg Kroah-Hartman , Guenter Roeck , Alexander Steffen , Heiko Stuebner Subject: [PATCH v7 5/6] tpm: tpm_tis_spi: Cleanup includes Date: Fri, 20 Sep 2019 11:32:39 -0700 Message-Id: <20190920183240.181420-6-swboyd@chromium.org> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog In-Reply-To: <20190920183240.181420-1-swboyd@chromium.org> References: <20190920183240.181420-1-swboyd@chromium.org> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Some of these includes aren't used, for example of_gpio.h and freezer.h, or they are missing, for example kernel.h for min_t() usage. Add missing headers and remove unused ones so that we don't have to expand all these headers into this file when they're not actually necessary. Cc: Andrey Pronin Cc: Duncan Laurie Cc: Jason Gunthorpe Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Guenter Roeck Cc: Alexander Steffen Cc: Heiko Stuebner Signed-off-by: Stephen Boyd Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis_spi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 5e4253e7c080..ec703aee7e7d 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -20,22 +20,18 @@ * Dorn and Kyleen Hall and Jarko Sakkinnen. */ +#include #include #include +#include +#include #include -#include #include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include #include + #include "tpm.h" #include "tpm_tis_core.h" #include "tpm_tis_spi.h" From patchwork Fri Sep 20 18:32:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 11154775 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7ECA714ED for ; Fri, 20 Sep 2019 18:33:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5E5BC217F5 for ; Fri, 20 Sep 2019 18:33:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="b+RPPisf" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406592AbfITSct (ORCPT ); Fri, 20 Sep 2019 14:32:49 -0400 Received: from mail-pg1-f196.google.com ([209.85.215.196]:40605 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406624AbfITScs (ORCPT ); Fri, 20 Sep 2019 14:32:48 -0400 Received: by mail-pg1-f196.google.com with SMTP id w10so4292141pgj.7 for ; Fri, 20 Sep 2019 11:32:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=p7IfU61KE2txhnLC8mG/Pzm9PBv785Nvfxd4FYtvCwc=; b=b+RPPisf/2hxQhW05ru7RW/KG9Jpf2rSHMmfrV2LDB4v3ZsUDOhf+sdejyVBzrvSFQ f7PXa7Z0tMhC7VqrXtpsCmIcaOL6hs00kaYfKCIgi/MFzGo3tYmK8XJZ23HZWuaZjrfv Z6mFQHxasieOupjhCYo951/yeGWwoYwlMJlu4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=p7IfU61KE2txhnLC8mG/Pzm9PBv785Nvfxd4FYtvCwc=; b=nfa0FzecvUoYhasfkgRI2BFQt+utb7L5PRbeUQX0BvQi3cSD6t2aMYGzdYFpC2ZO2f cGjkTK+DliskNpjINjVl57OSvHb/ixXzc73KUSxJBrphUG8q+Fl/x1ysQFSr1k906Mjt ibL8QmFuM7CeW3p0sv3Buh1C4tHmcT2ssWixBbNi5qMU9DKpePr8295HFcfSoMQEeZTF fYPHjnCYR8oPc00ry/cheYPSkqKa9qsGGDe9IirTr/fCfojpgGNujrnVKCeyc2gv4DBS KVQgSLwKAHV7Fx2OHGuRyS2IwQETLuwcR1GI6yH9aMnJcqbRn2+rry4Ge29phUloFBzV BDpQ== X-Gm-Message-State: APjAAAVZ7pNkTdDRKJ7rfUIa76nIyhEsFk4MVSXBdSzMRO4tG02y+sJM 5Wcz1ahzYujEodLz/cUTRMz9uA== X-Google-Smtp-Source: APXvYqy8nLBGPA5Ce5MY1hxDTwMj6VGdu3MYCiEfKtWTCTtQj3T/I+08bq/MEAKVkaCJRyy09HhEEQ== X-Received: by 2002:a63:5d0e:: with SMTP id r14mr16656526pgb.15.1569004368198; Fri, 20 Sep 2019 11:32:48 -0700 (PDT) Received: from smtp.gmail.com ([2620:15c:202:1:fa53:7765:582b:82b9]) by smtp.gmail.com with ESMTPSA id b69sm4436072pfb.132.2019.09.20.11.32.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Sep 2019 11:32:47 -0700 (PDT) From: Stephen Boyd To: Peter Huewe , Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, Andrey Pronin , Duncan Laurie , Jason Gunthorpe , Arnd Bergmann , Greg Kroah-Hartman , Guenter Roeck , Alexander Steffen , Heiko Stuebner Subject: [PATCH v7 6/6] tpm: tpm_tis_spi: Drop THIS_MODULE usage from driver struct Date: Fri, 20 Sep 2019 11:32:40 -0700 Message-Id: <20190920183240.181420-7-swboyd@chromium.org> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog In-Reply-To: <20190920183240.181420-1-swboyd@chromium.org> References: <20190920183240.181420-1-swboyd@chromium.org> MIME-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org The module_spi_driver() macro already inserts THIS_MODULE into the driver .owner field. Remove it to save a line. Cc: Andrey Pronin Cc: Duncan Laurie Cc: Jason Gunthorpe Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Guenter Roeck Cc: Alexander Steffen Cc: Heiko Stuebner Signed-off-by: Stephen Boyd Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis_spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index ec703aee7e7d..d1754fd6c573 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -283,7 +283,6 @@ MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match); static struct spi_driver tpm_tis_spi_driver = { .driver = { - .owner = THIS_MODULE, .name = "tpm_tis_spi", .pm = &tpm_tis_pm, .of_match_table = of_match_ptr(of_tis_spi_match),