drivers/i2c/tpm/cr50: Use tis_plat_irq_status for Cr50 IRQ status

The Cr50 TPM uses an IRQ to provide a "status" signal used for hand-shaking
the reception of commands.  Real IRQs are not supported in firmware,
however firmware can still poll interrupt status registers for the same
effect.

Commit 94cc485338a3 ("drivers/i2c/tpm/cr50: Support interrupts for status")
added support for the Cr50 driver on X86 platforms to use a KConfig file
to supply an IRQ which it would poll using acpi_get_gpe.  If the IRQ is
not supplied, the Cr50 driver inserts a 20 ms wait.

Unfortunately this doesn't work so well when using the i2c connected Cr50
on ARM platforms.  Luckily, a more generic implementation to allow a
mainboard to supply a Cr50 IRQ status polling function was solved for SPI
connected Cr50s by commit 19e3d335bddb ("drivers/spi/tpm: using tpm irq to
sync tpm transaction").

Let's refactor the i2c c50 driver to use this same approach, and change
eve and reef boards to make use of DRIVER_TPM_TIS_ACPI_INTERRUPT for
specifying the TPM flow control interrupt.

This essentially reverts these two commits:

48f708d199 drivers/i2c/tpm/cr50: Initialize IRQ status handler before probe
94cc485338 drivers/i2c/tpm/cr50: Support interrupts for status

And ports this commit to i2c/tpm/cr50:

19e3d335bd drivers/spi/tpm: using tpm irq to sync tpm transaction

As a side effect the tpm_vendor_specific IRQ field goes back to its
original usage as the "TPM 1.2 command complete" interrupt, instead of
being repurposed to hold the flow control IRQ.

BRANCH=none
BUG=b:36786804
TEST=Boot reef w/ serial enabled firmware, verify verstage sees
    "cr50 TPM" and does not complain about lack of tis_plat_irq_status().
TEST=Boot eve w/ serial enabled firmware, verify verstage sees
    "cr50 TPM" and does not complain about lack of tis_plat_irq_status().

Change-Id: I004329eae1d8aabda51c46b8504bf210484782b4
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Reviewed-on: https://review.coreboot.org/19363
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Tested-by: build bot (Jenkins)
diff --git a/src/drivers/i2c/tpm/cr50.c b/src/drivers/i2c/tpm/cr50.c
index ce30bf1..aa59f1e 100644
--- a/src/drivers/i2c/tpm/cr50.c
+++ b/src/drivers/i2c/tpm/cr50.c
@@ -42,10 +42,6 @@
 #include <tpm.h>
 #include "tpm.h"
 
-#if IS_ENABLED(CONFIG_ARCH_X86)
-#include <arch/acpi.h>
-#endif
-
 #define CR50_MAX_BUFSIZE	63
 #define CR50_TIMEOUT_LONG_MS	2000	/* Long timeout while waiting for TPM */
 #define CR50_TIMEOUT_SHORT_MS	2	/* Short timeout during transactions */
@@ -61,33 +57,33 @@
 
 static struct tpm_inf_dev g_tpm_dev CAR_GLOBAL;
 
+__attribute__ ((weak)) int tis_plat_irq_status(void)
+{
+	static int warning_displayed CAR_GLOBAL;
+
+	if (!car_get_var(warning_displayed)) {
+		printk(BIOS_WARNING, "WARNING: tis_plat_irq_status() not implemented, wasting 20ms to wait on Cr50!\n");
+		car_set_var(warning_displayed, 1);
+	}
+	mdelay(CR50_TIMEOUT_NOIRQ_MS);
+
+	return 1;
+}
+
 /* Wait for interrupt to indicate the TPM is ready */
 static int cr50_i2c_wait_tpm_ready(struct tpm_chip *chip)
 {
 	struct stopwatch sw;
 
-	if (!chip->vendor.irq_status) {
-		/* Fixed delay if interrupt not supported */
-		mdelay(CR50_TIMEOUT_NOIRQ_MS);
-		return 0;
-	}
-
 	stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_IRQ_MS);
 
-	while (!chip->vendor.irq_status(chip->vendor.irq))
+	while (!tis_plat_irq_status())
 		if (stopwatch_expired(&sw))
 			return -1;
 
 	return 0;
 }
 
-/* Clear pending interrupts */
-static void cr50_i2c_clear_tpm_irq(struct tpm_chip *chip)
-{
-	if (chip->vendor.irq_status)
-		chip->vendor.irq_status(chip->vendor.irq);
-}
-
 /*
  * cr50_i2c_read() - read from TPM register
  *
@@ -111,7 +107,7 @@
 		return -1;
 
 	/* Clear interrupt before starting transaction */
-	cr50_i2c_clear_tpm_irq(chip);
+	tis_plat_irq_status();
 
 	/* Send the register address byte to the TPM */
 	if (i2c_write_raw(tpm_dev->bus, tpm_dev->addr, &addr, 1)) {
@@ -161,7 +157,7 @@
 	memcpy(tpm_dev->buf + 1, buffer, len);
 
 	/* Clear interrupt before starting transaction */
-	cr50_i2c_clear_tpm_irq(chip);
+	tis_plat_irq_status();
 
 	/* Send write request buffer with address */
 	if (i2c_write_raw(tpm_dev->bus, tpm_dev->addr, tpm_dev->buf, len + 1)) {
@@ -418,25 +414,6 @@
 	chip->vendor.recv = &cr50_i2c_tis_recv;
 	chip->vendor.send = &cr50_i2c_tis_send;
 	chip->vendor.cancel = &cr50_i2c_tis_ready;
-	chip->vendor.irq = CONFIG_DRIVER_TPM_I2C_IRQ;
-
-	/*
-	 * Interrupts are not supported this early in firmware,
-	 * use use an arch-specific method to query for interrupt status.
-	 */
-	if (chip->vendor.irq > 0) {
-#if IS_ENABLED(CONFIG_ARCH_X86)
-		/* Query GPE status for interrupt */
-		chip->vendor.irq_status = &acpi_get_gpe;
-#else
-		chip->vendor.irq = -1;
-#endif
-	}
-
-	if (chip->vendor.irq <= 0)
-		printk(BIOS_WARNING,
-		       "%s: No IRQ, will use %ums delay for TPM ready\n",
-		       __func__, CR50_TIMEOUT_NOIRQ_MS);
 }
 
 int tpm_vendor_probe(unsigned int bus, uint32_t addr)
@@ -503,8 +480,8 @@
 		goto out_err;
 	}
 
-	printk(BIOS_DEBUG, "cr50 TPM 2.0 (i2c %u:0x%02x irq %d id 0x%x)\n",
-	       bus, dev_addr, chip->vendor.irq, vendor >> 16);
+	printk(BIOS_DEBUG, "cr50 TPM 2.0 (i2c %u:0x%02x id 0x%x)\n",
+	       bus, dev_addr, vendor >> 16);
 
 	chip->is_open = 1;
 	return 0;