[coreboot-gerrit] Patch set updated for coreboot: 3f47c50 tpm: Add ramstage driver and interrupt configuration

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Fri Apr 10 03:26:02 CEST 2015


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9469

-gerrit

commit 3f47c508c934d39156ddcf1190d3fd350b130ebd
Author: Duncan Laurie <dlaurie at chromium.org>
Date:   Thu Oct 30 15:20:19 2014 -0700

    tpm: Add ramstage driver and interrupt configuration
    
    This adds a ramstage driver for the TPM and allows the interrupt
    to be configured in devicetree.cb.
    
    The interrupt vector is set like other PNP devices, and the
    interrupt polarity is set with a register configuration variable.
    
    These values are written into locality 0 TPM_INT_VECTOR and
    TPM_INT_ENABLE and then all interrupts are disabled so they are
    not used in firmware but can be enabled by the OS.
    
    It also adds an ACPI device for the TPM which will configure the
    reported interrupt based on what has been written into the TPM
    during ramstage.  The _STA method returns enabled if CONFIG_LPC_TPM
    is enabled, and the _CRS method will only report an interrupt if one
    has been set in the TPM itself.
    
    The TPM memory address is added by the driver and declared in the
    ACPI code.  In order to access it in ACPI a Kconfig entry is added for
    the default TPM TIS 1.2 base address.  Note that IO address 0x2e is
    required to be declared in ACPI for the kernel driver to probe correctly.
    
    BUG=chrome-os-partner:33385
    BRANCH=samus,auron
    TEST=manual testing on samus:
    1) Add TPM device in devicetree.cb with configured interrupt and
    ensure that it is functional in the OS.
    2) Test with active high and active low, edge triggered and level
    triggered setups.
    3) Ensure that with no device added to devicetree.cb that the TPM
    is still functional in polling mode.
    
    Change-Id: Iee2a1832394dfe32f3ea3700753b8ecc443c7fbf
    Signed-off-by: Stefan Reinauer <reinauer at chromium.org>
    Original-Commit-Id: fc2c106caae939467fb07f3a0207adee71dda48e
    Original-Change-Id: Id8a5a251f193c71ab2209f85fb470120a3b6a80d
    Original-Signed-off-by: Duncan Laurie <dlaurie at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/226661
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
 src/drivers/pc80/tpm/Kconfig      |   9 ++++
 src/drivers/pc80/tpm/Makefile.inc |   1 +
 src/drivers/pc80/tpm/acpi/tpm.asl | 104 ++++++++++++++++++++++++++++++++++++
 src/drivers/pc80/tpm/chip.h       |  35 ++++++++++++
 src/drivers/pc80/tpm/tpm.c        | 108 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 257 insertions(+)

diff --git a/src/drivers/pc80/tpm/Kconfig b/src/drivers/pc80/tpm/Kconfig
index fbb3b42..9630de2 100644
--- a/src/drivers/pc80/tpm/Kconfig
+++ b/src/drivers/pc80/tpm/Kconfig
@@ -5,3 +5,12 @@ config LPC_TPM
 	  Enable this option to enable LPC TPM support in coreboot.
 
 	  If unsure, say N.
+
+config TPM_TIS_BASE_ADDRESS
+	hex "TPM Base Address"
+	default 0xfed40000
+	help
+	  This can be used to adjust the TPM memory base address.
+	  The default is specified by the TCG PC Client Specific TPM
+	  Interface Specification 1.2 and should not be changed unless
+	  the TPM being used does not conform to TPM TIS 1.2.
diff --git a/src/drivers/pc80/tpm/Makefile.inc b/src/drivers/pc80/tpm/Makefile.inc
index 6f973e1..c900fe8 100644
--- a/src/drivers/pc80/tpm/Makefile.inc
+++ b/src/drivers/pc80/tpm/Makefile.inc
@@ -1 +1,2 @@
 romstage-$(CONFIG_LPC_TPM) += tpm.c
+ramstage-$(CONFIG_LPC_TPM) += tpm.c
diff --git a/src/drivers/pc80/tpm/acpi/tpm.asl b/src/drivers/pc80/tpm/acpi/tpm.asl
new file mode 100644
index 0000000..7500211
--- /dev/null
+++ b/src/drivers/pc80/tpm/acpi/tpm.asl
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Trusted Platform Module */
+
+Device (TPM)
+{
+	Name (_HID, EISAID ("PNP0C31"))
+	Name (_CID, 0x310cd041)
+	Name (_UID, 1)
+
+	Method (_STA, 0)
+	{
+		If (CONFIG_LPC_TPM) {
+			Return (0xf)
+		} Else {
+			Return (0x0)
+		}
+	}
+
+	Name (IBUF, ResourceTemplate ()
+	{
+		/* Updated based on TPM interrupt for Locality 0 */
+		Interrupt (ResourceConsumer, Edge, ActiveHigh,
+			   Exclusive, , , TIRQ) { 0 }
+	})
+
+	Name (RBUF, ResourceTemplate ()
+	{
+		IO (Decode16, 0x2e, 0x2e, 0x01, 0x02)
+		Memory32Fixed (ReadWrite, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000)
+	})
+
+	Method (_CRS, 0, NotSerialized)
+	{
+		OperationRegion (TREG, SystemMemory,
+				 CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000)
+		Field (TREG, ByteAcc, NoLock, Preserve)
+		{
+			/* TPM_INT_ENABLE_0 */
+			Offset (0x0008),
+			, 3,
+			ITPL, 2,  /* Interrupt type and polarity */
+
+			/* TPM_INT_VECTOR_0 */
+			Offset (0x000C),
+			IVEC, 4,  /* SERIRQ vector */
+		}
+
+		If (LGreater (IVEC, 0)) {
+			/* Update interrupt vector */
+			CreateField (^IBUF, ^TIRQ._INT, 32, TVEC)
+			Store (IVEC, TVEC)
+
+			/* Update interrupt type and polarity */
+			CreateBitField (^IBUF, ^TIRQ._HE, TTYP)
+			CreateBitField (^IBUF, ^TIRQ._LL, TPOL)
+			CreateBitField (^IBUF, ^TIRQ._SHR, TSHR)
+
+			If (LEqual (ITPL, 0x0)) {
+				/* Active-High Level-Triggered Shared */
+				Store (Zero, TPOL)
+				Store (Zero, TTYP)
+				Store (One, TSHR)
+			} ElseIf (LEqual (ITPL, 0x1)) {
+				/* Active-Low Level-Triggered Shared */
+				Store (One, TPOL)
+				Store (Zero, TTYP)
+				Store (One, TSHR)
+			} ElseIf (LEqual (ITPL, 0x2)) {
+				/* Active-High Edge-Triggered Exclusive */
+				Store (Zero, TPOL)
+				Store (One, TTYP)
+				Store (Zero, TSHR)
+			} ElseIf (LEqual (ITPL, 0x3)) {
+				/* Active-Low Edge-Triggered Exclusive */
+				Store (One, TPOL)
+				Store (One, TTYP)
+				Store (Zero, TSHR)
+			}
+
+			/* Merge IRQ with base address */
+			Return (ConcatenateResTemplate (RBUF, IBUF))
+		} Else {
+			Return (RBUF)
+		}
+	}
+}
diff --git a/src/drivers/pc80/tpm/chip.h b/src/drivers/pc80/tpm/chip.h
new file mode 100644
index 0000000..bcfb877
--- /dev/null
+++ b/src/drivers/pc80/tpm/chip.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.  All Rights Reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#ifndef DRIVERS_PC80_TPM_CHIP_H
+#define DRIVERS_PC80_TPM_CHIP_H
+
+typedef struct drivers_pc80_tpm_config {
+	/*
+	 * TPM Interrupt polarity:
+	 *
+	 *  High Level    0
+	 *  Low Level     1
+	 *  Rising Edge   2
+	 *  Falling Edge  3
+	 */
+	u8 irq_polarity;
+} tpm_config_t;
+
+#endif /* DRIVERS_PC80_TPM_CHIP_H */
diff --git a/src/drivers/pc80/tpm/tpm.c b/src/drivers/pc80/tpm/tpm.c
index c0429dd..f1c5d97 100644
--- a/src/drivers/pc80/tpm/tpm.c
+++ b/src/drivers/pc80/tpm/tpm.c
@@ -35,6 +35,8 @@
 #include <console/console.h>
 #include <tpm.h>
 #include <arch/early_variables.h>
+#include <device/pnp.h>
+#include "chip.h"
 
 #define PREFIX "lpc_tpm: "
 
@@ -211,6 +213,20 @@ static inline u32 tpm_read_did_vid(int locality)
 	return value;
 }
 
+static inline void tpm_write_int_vector(int vector, int locality)
+{
+	TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector);
+	writeb(vector & 0xf, TIS_REG(locality, TIS_REG_INT_VECTOR));
+}
+
+static inline void tpm_write_int_polarity(int polarity, int locality)
+{
+	/* Set polarity and leave all other bits at 0 */
+	u32 value = (polarity & 0x3) << 3;
+	TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value);
+	writel(value, TIS_REG(locality, TIS_REG_INT_ENABLE));
+}
+
 /*
  * tis_wait_sts()
  *
@@ -673,3 +689,95 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
 
 	return tis_readresponse(recvbuf, recv_len);
 }
+
+#ifdef __RAMSTAGE__
+
+/*
+ * tis_setup_interrupt()
+ *
+ * Set up the interrupt vector and polarity for locality 0 and
+ * disable all interrupts so they are unused in firmware but can
+ * be enabled by the OS.
+ *
+ * The values used here must match what is passed in the TPM ACPI
+ * device if ACPI is used on the platform.
+ *
+ * @vector - TPM interrupt vector
+ * @polarity - TPM interrupt polarity
+ *
+ * Returns 0 on success, TPM_DRIVER_ERR on failure.
+ */
+static int tis_setup_interrupt(int vector, int polarity)
+{
+	u8 locality = 0;
+	int has_access = tis_has_access(locality);
+
+	/* Open connection and request access if not already granted */
+	if (!has_access && tis_open() < 0)
+		return TPM_DRIVER_ERR;
+
+	/* Set TPM interrupt vector */
+	tpm_write_int_vector(vector, locality);
+
+	/* Set TPM interupt polarity and disable interrupts */
+	tpm_write_int_polarity(polarity, locality);
+
+	/* Close connection if it was opened */
+	if (!has_access && tis_close() < 0)
+		return TPM_DRIVER_ERR;
+
+	return 0;
+}
+
+static void lpc_tpm_read_resources(struct device *dev)
+{
+	/* Static 5K memory region specified in Kconfig */
+	mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10);
+}
+
+static void lpc_tpm_set_resources(struct device *dev)
+{
+	tpm_config_t *config = (tpm_config_t *)dev->chip_info;
+	struct resource *res;
+
+	for (res = dev->resource_list; res; res = res->next) {
+		if (!(res->flags & IORESOURCE_ASSIGNED))
+			continue;
+
+		if (res->flags & IORESOURCE_IRQ) {
+			/* Set interrupt vector */
+			tis_setup_interrupt((int)res->base,
+					    config->irq_polarity);
+		} else {
+			printk(BIOS_ERR,
+			       "ERROR: %s %02lx unknown resource type\n",
+			       dev_path(dev), res->index);
+			continue;
+		}
+
+		res->flags |= IORESOURCE_STORED;
+		report_resource_stored(dev, res, " <tpm>");
+	}
+}
+
+static struct device_operations lpc_tpm_ops = {
+	.read_resources   = &lpc_tpm_read_resources,
+	.set_resources    = &lpc_tpm_set_resources,
+};
+
+static struct pnp_info pnp_dev_info[] = {
+	{ .flags = PNP_IRQ0 }
+};
+
+static void enable_dev(struct device *dev)
+{
+	pnp_enable_devices(dev, &lpc_tpm_ops,
+			   ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
+}
+
+struct chip_operations drivers_pc80_tpm_ops = {
+	CHIP_NAME("LPC TPM")
+	.enable_dev = enable_dev
+};
+
+#endif /* __RAMSTAGE__ */



More information about the coreboot-gerrit mailing list