| From 6c9f0ce0dffe64da2204f38b0fd90f3ae2a8903c Mon Sep 17 00:00:00 2001 |
| From: Javier Martinez Canillas <javierm@redhat.com> |
| Date: Mon, 25 Dec 2017 03:22:51 +0100 |
| Subject: tpm: only attempt to disable the LPC CLKRUN if is already enabled |
| |
| From: Javier Martinez Canillas <javierm@redhat.com> |
| |
| commit 6c9f0ce0dffe64da2204f38b0fd90f3ae2a8903c upstream. |
| |
| Commit 5e572cab92f0 ("tpm: Enable CLKRUN protocol for Braswell systems") |
| added logic in the TPM TIS driver to disable the Low Pin Count CLKRUN |
| signal during TPM transactions. |
| |
| Unfortunately this breaks other devices that are attached to the LPC bus |
| like for example PS/2 mouse and keyboards. |
| |
| One flaw with the logic is that it assumes that the CLKRUN is always |
| enabled, and so it unconditionally enables it after a TPM transaction. |
| |
| But it could be that the CLKRUN# signal was already disabled in the LPC |
| bus and so after the driver probes, CLKRUN_EN will remain enabled which |
| may break other devices that are attached to the LPC bus but don't have |
| support for the CLKRUN protocol. |
| |
| Fixes: 5e572cab92f0 ("tpm: Enable CLKRUN protocol for Braswell systems") |
| Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> |
| Tested-by: James Ettle <james@ettle.org.uk> |
| Tested-by: Jeffery Miller <jmiller@neverware.com> |
| Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/char/tpm/tpm_tis_core.c | 11 ++++++++++- |
| 1 file changed, 10 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/char/tpm/tpm_tis_core.c |
| +++ b/drivers/char/tpm/tpm_tis_core.c |
| @@ -694,7 +694,8 @@ static void tpm_tis_clkrun_enable(struct |
| struct tpm_tis_data *data = dev_get_drvdata(&chip->dev); |
| u32 clkrun_val; |
| |
| - if (!IS_ENABLED(CONFIG_X86) || !is_bsw()) |
| + if (!IS_ENABLED(CONFIG_X86) || !is_bsw() || |
| + !data->ilb_base_addr) |
| return; |
| |
| if (value) { |
| @@ -751,6 +752,7 @@ int tpm_tis_core_init(struct device *dev |
| acpi_handle acpi_dev_handle) |
| { |
| u32 vendor, intfcaps, intmask; |
| + u32 clkrun_val; |
| u8 rid; |
| int rc, probe; |
| struct tpm_chip *chip; |
| @@ -776,6 +778,13 @@ int tpm_tis_core_init(struct device *dev |
| ILB_REMAP_SIZE); |
| if (!priv->ilb_base_addr) |
| return -ENOMEM; |
| + |
| + clkrun_val = ioread32(priv->ilb_base_addr + LPC_CNTRL_OFFSET); |
| + /* Check if CLKRUN# is already not enabled in the LPC bus */ |
| + if (!(clkrun_val & LPC_CLKRUN_EN)) { |
| + iounmap(priv->ilb_base_addr); |
| + priv->ilb_base_addr = NULL; |
| + } |
| } |
| |
| if (chip->ops->clk_enable != NULL) |