From patchwork Sun Mar 20 19:34:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Ricard X-Patchwork-Id: 8628651 Return-Path: X-Original-To: patchwork-tpmdd-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4F2F5C0553 for ; Sun, 20 Mar 2016 19:35:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DE0632021B for ; Sun, 20 Mar 2016 19:35:18 +0000 (UTC) Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 85202201FE for ; Sun, 20 Mar 2016 19:35:16 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1ahj86-00009h-4k; Sun, 20 Mar 2016 19:35:14 +0000 Received: from sog-mx-1.v43.ch3.sourceforge.com ([172.29.43.191] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1ahj85-00009a-Cj for tpmdd-devel@lists.sourceforge.net; Sun, 20 Mar 2016 19:35:13 +0000 Received-SPF: pass (sog-mx-1.v43.ch3.sourceforge.com: domain of gmail.com designates 74.125.82.54 as permitted sender) client-ip=74.125.82.54; envelope-from=christophe.ricard@gmail.com; helo=mail-wm0-f54.google.com; Received: from mail-wm0-f54.google.com ([74.125.82.54]) by sog-mx-1.v43.ch3.sourceforge.com with esmtps (TLSv1:RC4-SHA:128) (Exim 4.76) id 1ahj84-0005B5-09 for tpmdd-devel@lists.sourceforge.net; Sun, 20 Mar 2016 19:35:13 +0000 Received: by mail-wm0-f54.google.com with SMTP id l68so86891304wml.0 for ; Sun, 20 Mar 2016 12:35:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=g4bM2IDOTIXyWmoqRhAak5BEImW5kZWlBFfrkyvMo6E=; b=TlQlKVwRubfavu/SfFYn0zKTbgYuxVSK766toZ8oA9s1WoYYALi5T+Z/YrqLeCucl2 xqsZmLsUc2dk1V161zcMFkrztpPfcA2dubQEsBez2OTlcjalJLMQ3kdP9VgD/8NFhx+P 15T0QNRNTWXPB82PfMuuxX+V/WPPmNILEvqUCsgzt77JaJPU16ggiYTzNFfMBdgaubzQ lI0LvCIHrxM+yUvjqlHY31qWB80H4ei4KwlXwmGsmZxFTrMPKLUyf3k+u6F3TOM+1eEq SqsY6RlK3SUXX/ZeaDREZitmT3fbDDS/hCWAxsSRBBn/V7lG5YY9kl7FdBESJ4JEkl6n 0JbA== X-Gm-Message-State: AD7BkJLYHQKZu7AoPx9ZBpcQ5DoVisxV6wk3+FtRPaTt5YFD3D0BI2++/HVKKG6a4DQzOA== X-Received: by 10.194.242.202 with SMTP id ws10mr26499061wjc.3.1458502505956; Sun, 20 Mar 2016 12:35:05 -0700 (PDT) Received: from localhost.localdomain (AMarseille-654-1-498-218.w86-210.abo.wanadoo.fr. [86.210.138.218]) by smtp.gmail.com with ESMTPSA id w203sm7560646wmg.14.2016.03.20.12.35.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 20 Mar 2016 12:35:04 -0700 (PDT) From: Christophe Ricard X-Google-Original-From: Christophe Ricard To: jarkko.sakkinen@linux.intel.com Date: Sun, 20 Mar 2016 20:34:41 +0100 Message-Id: <1458502483-16887-11-git-send-email-christophe-h.ricard@st.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1458502483-16887-1-git-send-email-christophe-h.ricard@st.com> References: <1458502483-16887-1-git-send-email-christophe-h.ricard@st.com> X-Spam-Score: -1.6 (-) X-Headers-End: 1ahj84-0005B5-09 Cc: jean-luc.blanc@st.com, ashley@ashleylai.com, tpmdd-devel@lists.sourceforge.net, christophe-h.ricard@st.com, Peter Huewe , benoit.houyere@st.com Subject: [tpmdd-devel] [PATCH 10/12] tpm/tpm_tis_spi: Add support for spi phy X-BeenThere: tpmdd-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Tpm Device Driver maintainance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: tpmdd-devel-bounces@lists.sourceforge.net X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,HK_RANDOM_ENVFROM,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A spi protocol standardized by the TCG is now supported by most of TPM vendors. It supports wait cycle on MISO line. Signed-off-by: Peter Huewe Signed-off-by: Christophe Ricard --- .../bindings/security/tpm/tpm_tis_spi.txt | 28 +++ drivers/char/tpm/Kconfig | 12 +- drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_tis_spi.c | 279 +++++++++++++++++++++ 4 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt create mode 100644 drivers/char/tpm/tpm_tis_spi.c diff --git a/Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt b/Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt new file mode 100644 index 0000000..e0464b0 --- /dev/null +++ b/Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt @@ -0,0 +1,28 @@ +Required properties: +- compatible: Should be "st,st33htpm-spi" or "infineon,slb9670" or "tcg,tpm_tis-spi" +- spi-max-frequency: Maximum SPI frequency (depends on TPMs). + +Optional TPM_TIS SPI Properties: +- interrupt-parent: phandle for the interrupt gpio controller +- interrupts: GPIO interrupt to which the chip is connected + +Optional SoC Specific Properties: +- pinctrl-names: Contains only one value - "default". +- pintctrl-0: Specifies the pin control groups used for this controller. + +Example (for ARM-based BeagleBoard xM with TPM_TIS on SPI4): + +&mcspi4 { + + status = "okay"; + + tpm_tis@0 { + + compatible = "tcg,tpm_tis-spi"; + + spi-max-frequency = <10000000>; + + interrupt-parent = <&gpio5>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; + }; +}; diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 3b84a8b..6fbe7468 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -26,7 +26,6 @@ if TCG_TPM config TCG_TIS tristate "TPM Interface Specification 1.2 Interface / TPM 2.0 FIFO Interface" - depends on X86 ---help--- If you have a TPM security chip that is compliant with the TCG TIS 1.2 TPM specification (TPM1.2) or the TCG PTP FIFO @@ -64,6 +63,17 @@ config TCG_TIS_I2C_NUVOTON To compile this driver as a module, choose M here; the module will be called tpm_i2c_nuvoton. +config TCG_TIS_SPI + tristate "TPM Interface Specification 1.3 Interface / TPM 2.0 FIFO Interface - (SPI)" + depends on SPI + ---help--- + If you have a TPM security chip which is connected to a regular, + non-tcg SPI master (i.e. most embedded platforms) that is compliant with the + TCG TIS 1.3 TPM specification (TPM1.2) or the TCG PTP FIFO + specification (TPM2.0) say Yes and it will be accessible from + within Linux. To compile this driver as a module, choose M here; + the module will be called tpm_spi_tis. + config TCG_NSC tristate "National Semiconductor TPM Interface" depends on X86 diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index c6a4cea..69508ef 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_TCG_TIS) += tpm_tis.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 +obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o obj-$(CONFIG_TCG_NSC) += tpm_nsc.o obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c new file mode 100644 index 0000000..3cdc3a8 --- /dev/null +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2015 Infineon Technologies AG + * Copyright (C) 2016 STMicroelectronics SAS + * + * Authors: + * Peter Huewe + * Christophe Ricard + * + * Maintained by: + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native + * SPI access_. + * + * It is based on the original tpm_tis device driver from Leendert van + * Dorn and Kyleen Hall and Jarko Sakkinnen. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "tpm.h" +#include "tpm_tis_core.h" + +#define MAX_SPI_FRAMESIZE 64 + +struct tpm_tis_spi_phy { + struct spi_device *spi_device; + struct mutex phy_lock; + + u8 tx_buf[MAX_SPI_FRAMESIZE + 4]; + u8 rx_buf[MAX_SPI_FRAMESIZE + 4]; +}; + +static int tpm_tis_spi_read_bytes(struct tpm_chip *chip, u32 addr, + size_t len, u8 size, u8 *result) +{ + int ret; + struct tpm_tis_spi_phy *phy = tpm_get_vendordata(chip); + struct spi_message m; + struct spi_transfer spi_xfer = { + .tx_buf = phy->tx_buf, + .rx_buf = phy->rx_buf, + .len = 4, + }; + + if (len > MAX_SPI_FRAMESIZE) + return -ENOMEM; + + phy->tx_buf[0] = 0x80 | (len * size - 1); + phy->tx_buf[1] = 0xd4; + phy->tx_buf[2] = (addr >> 8) & 0xFF; + phy->tx_buf[3] = addr & 0xFF; + + spi_xfer.cs_change = 1; + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + + mutex_lock(&phy->phy_lock); + spi_bus_lock(phy->spi_device->master); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + + memset(phy->tx_buf, 0, len * size); + + /* According to TCG PTP specification, if there is no TPM present at + * all, then the design has a weak pull-up on MISO. If a TPM is not + * present, a pull-up on MISO means that the SB controller sees a 1, + * and will latch in 0xFF on the read. + */ + for ( ; (phy->rx_buf[0] & 0x01) == 0 ; ) { + 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; + } + + spi_xfer.cs_change = 0; + spi_xfer.len = len * size; + spi_xfer.rx_buf = result; + + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + +exit: + spi_bus_unlock(phy->spi_device->master); + mutex_unlock(&phy->phy_lock); + return ret; +} + +static int tpm_tis_spi_write_bytes(struct tpm_chip *chip, u32 addr, + size_t len, u8 size, u8 *value) +{ + int ret; + struct tpm_tis_spi_phy *phy = tpm_get_vendordata(chip); + struct spi_message m; + struct spi_transfer spi_xfer = { + .tx_buf = phy->tx_buf, + .rx_buf = phy->rx_buf, + .len = 4, + }; + + if (len > MAX_SPI_FRAMESIZE) + return -ENOMEM; + + phy->tx_buf[0] = len * size - 1; + phy->tx_buf[1] = 0xd4; + phy->tx_buf[2] = (addr >> 8) & 0xFF; + phy->tx_buf[3] = addr & 0xFF; + + spi_xfer.cs_change = 1; + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + + mutex_lock(&phy->phy_lock); + spi_bus_lock(phy->spi_device->master); + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; + + memset(phy->tx_buf, 0, len * size); + + /* According to TCG PTP specification, if there is no TPM present at + * all, then the design has a weak pull-up on MISO. If a TPM is not + * present, a pull-up on MISO means that the SB controller sees a 1, + * and will latch in 0xFF on the read. + */ + for ( ; (phy->rx_buf[0] & 0x01) == 0 ; ) { + 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; + } + + spi_xfer.len = len * size; + spi_xfer.tx_buf = value; + spi_xfer.cs_change = 0; + spi_xfer.tx_buf = value; + spi_message_init(&m); + spi_message_add_tail(&spi_xfer, &m); + ret = spi_sync_locked(phy->spi_device, &m); + +exit: + spi_bus_unlock(phy->spi_device->master); + mutex_unlock(&phy->phy_lock); + return ret; +} + +static const struct tpm_class_ops tpm_tis = { + .status = tpm_tis_status, + .recv = tpm_tis_recv, + .send = tpm_tis_send, + .cancel = tpm_tis_ready, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_canceled = tpm_tis_req_canceled, + .read_bytes = tpm_tis_spi_read_bytes, + .write_bytes = tpm_tis_spi_write_bytes, +}; + +static SIMPLE_DEV_PM_OPS(tpm_tis_spi_pm, tpm_pm_suspend, tpm_tis_resume); + +static int tpm_tis_spi_probe(struct spi_device *dev) +{ + struct tpm_tis_spi_phy *phy; + struct tpm_chip *chip; + unsigned int irq_polarity = IRQ_TYPE_NONE; + int ret, irq = -1; + + /* Check SPI platform functionnalities */ + if (!dev) { + pr_err("%s: dev is NULL. Device is not accessible.\n", + __func__); + return -ENODEV; + } + + phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy), + GFP_KERNEL); + if (!phy) + return -ENOMEM; + + chip = tpmm_chip_alloc(&dev->dev, &tpm_tis); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + phy->spi_device = dev; + mutex_init(&phy->phy_lock); + tpm_set_vendordata(chip, phy); + + if (dev->irq > 0) { + irq = dev->irq; + irq_polarity = irq_get_trigger_type(irq); + if (irq_polarity > 0) + irq_polarity |= IRQF_ONESHOT; + else + irq = -1; + } + + ret = tpm_tis_init_core(&dev->dev, chip, irq, irq_polarity); + if (ret < 0) + goto out_err; + + return ret; + +out_err: + tpm_tis_remove(chip); + return ret; +} + +static int tpm_tis_spi_remove(struct spi_device *dev) +{ + struct tpm_chip *chip = spi_get_drvdata(dev); + + tpm_chip_unregister(chip); + return 0; +} + +static const struct spi_device_id tpm_tis_spi_id[] = { + {"tpm_tis_spi", 0}, + {} +}; +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", }, + {} +}; +MODULE_DEVICE_TABLE(of, of_tis_spi_match); + +static const struct acpi_device_id acpi_tis_spi_match[] = { + {"SMO0768", 0}, + {} +}; +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_spi_pm, + .of_match_table = of_match_ptr(of_tis_spi_match), + .acpi_match_table = ACPI_PTR(acpi_tis_spi_match), + }, + .probe = tpm_tis_spi_probe, + .remove = tpm_tis_spi_remove, + .id_table = tpm_tis_spi_id, +}; +module_spi_driver(tpm_tis_spi_driver); + +MODULE_DESCRIPTION("TPM Driver for native SPI access"); +MODULE_LICENSE("GPL");