[PATCH v6 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()

2017-12-06 Thread Azhar Shaikh
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell
systems") disabled CLKRUN protocol during TPM transactions and re-enabled
once the transaction is completed. But there were still some corner cases
observed where, reading of TPM header failed for savestate command
while going to suspend, which resulted in suspend failure.
To fix this issue keep the CLKRUN protocol disabled for the entire
duration of a single TPM command and not disabling and re-enabling
again for every TPM transaction. For the other TPM accesses outside
TPM command flow, add a higher level of disabling and re-enabling
the CLKRUN protocol, instead of doing for every TPM transaction.

Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems")

Signed-off-by: Azhar Shaikh 
---
 drivers/char/tpm/tpm-interface.c |  6 +++
 drivers/char/tpm/tpm_tis.c   | 86 +---
 drivers/char/tpm/tpm_tis_core.c  | 95 +---
 drivers/char/tpm/tpm_tis_core.h  |  4 ++
 include/linux/tpm.h  |  1 +
 5 files changed, 111 insertions(+), 81 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ebe0a1d36d8c..6e19e3dd98e4 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
if (chip->dev.parent)
pm_runtime_get_sync(chip->dev.parent);
 
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, true);
+
/* Store the decision as chip->locality will be changed. */
need_locality = chip->locality == -1;
 
@@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
chip->locality = -1;
}
 out_no_locality:
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, false);
+
if (chip->dev.parent)
pm_runtime_put_sync(chip->dev.parent);
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 923f8f2cbaca..d29add49b033 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_X86
-#define LPC_CNTRL_OFFSET   0x84
-#define LPC_CLKRUN_EN  (1 << 2)
-
-/**
- * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
- */
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Disable LPC CLKRUN# */
-   clkrun_val &= ~LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-
-/**
- * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
- */
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Enable LPC CLKRUN# */
-   clkrun_val |= LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-#else
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-}
-
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-}
-#endif
-
 static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
  u8 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
*result++ = ioread8(phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, 
u32 addr, u16 len,
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
iowrite8(*value++, phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -228,12 +165,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 
addr, u16 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 

[PATCH v6 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()

2017-12-06 Thread Azhar Shaikh
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell
systems") disabled CLKRUN protocol during TPM transactions and re-enabled
once the transaction is completed. But there were still some corner cases
observed where, reading of TPM header failed for savestate command
while going to suspend, which resulted in suspend failure.
To fix this issue keep the CLKRUN protocol disabled for the entire
duration of a single TPM command and not disabling and re-enabling
again for every TPM transaction. For the other TPM accesses outside
TPM command flow, add a higher level of disabling and re-enabling
the CLKRUN protocol, instead of doing for every TPM transaction.

Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems")

Signed-off-by: Azhar Shaikh 
---
 drivers/char/tpm/tpm-interface.c |  6 +++
 drivers/char/tpm/tpm_tis.c   | 86 +---
 drivers/char/tpm/tpm_tis_core.c  | 95 +---
 drivers/char/tpm/tpm_tis_core.h  |  4 ++
 include/linux/tpm.h  |  1 +
 5 files changed, 111 insertions(+), 81 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ebe0a1d36d8c..6e19e3dd98e4 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
if (chip->dev.parent)
pm_runtime_get_sync(chip->dev.parent);
 
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, true);
+
/* Store the decision as chip->locality will be changed. */
need_locality = chip->locality == -1;
 
@@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
chip->locality = -1;
}
 out_no_locality:
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, false);
+
if (chip->dev.parent)
pm_runtime_put_sync(chip->dev.parent);
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 923f8f2cbaca..d29add49b033 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_X86
-#define LPC_CNTRL_OFFSET   0x84
-#define LPC_CLKRUN_EN  (1 << 2)
-
-/**
- * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
- */
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Disable LPC CLKRUN# */
-   clkrun_val &= ~LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-
-/**
- * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
- */
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Enable LPC CLKRUN# */
-   clkrun_val |= LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-#else
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-}
-
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-}
-#endif
-
 static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
  u8 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
*result++ = ioread8(phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, 
u32 addr, u16 len,
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
iowrite8(*value++, phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -228,12 +165,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 
addr, u16 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   

[PATCH v6 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()

2017-11-29 Thread Azhar Shaikh
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell
systems") disabled CLKRUN protocol during TPM transactions and re-enabled
once the transaction is completed. But there were still some corner cases
observed where, reading of TPM header failed for savestate command
while going to suspend, which resulted in suspend failure.
To fix this issue keep the CLKRUN protocol disabled for the entire
duration of a single TPM command and not disabling and re-enabling
again for every TPM transaction. For the other TPM accesses outside
TPM command flow, add a higher level of disabling and re-enabling
the CLKRUN protocol, instead of doing for every TPM transaction.

Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems")

Signed-off-by: Azhar Shaikh 
---
 drivers/char/tpm/tpm-interface.c |  6 +++
 drivers/char/tpm/tpm_tis.c   | 86 +---
 drivers/char/tpm/tpm_tis_core.c  | 95 +---
 drivers/char/tpm/tpm_tis_core.h  |  4 ++
 include/linux/tpm.h  |  1 +
 5 files changed, 111 insertions(+), 81 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ebe0a1d36d8c..6e19e3dd98e4 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
if (chip->dev.parent)
pm_runtime_get_sync(chip->dev.parent);
 
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, true);
+
/* Store the decision as chip->locality will be changed. */
need_locality = chip->locality == -1;
 
@@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
chip->locality = -1;
}
 out_no_locality:
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, false);
+
if (chip->dev.parent)
pm_runtime_put_sync(chip->dev.parent);
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 923f8f2cbaca..d29add49b033 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_X86
-#define LPC_CNTRL_OFFSET   0x84
-#define LPC_CLKRUN_EN  (1 << 2)
-
-/**
- * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
- */
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Disable LPC CLKRUN# */
-   clkrun_val &= ~LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-
-/**
- * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
- */
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Enable LPC CLKRUN# */
-   clkrun_val |= LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-#else
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-}
-
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-}
-#endif
-
 static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
  u8 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
*result++ = ioread8(phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, 
u32 addr, u16 len,
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
iowrite8(*value++, phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -228,12 +165,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 
addr, u16 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 

[PATCH v6 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()

2017-11-29 Thread Azhar Shaikh
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell
systems") disabled CLKRUN protocol during TPM transactions and re-enabled
once the transaction is completed. But there were still some corner cases
observed where, reading of TPM header failed for savestate command
while going to suspend, which resulted in suspend failure.
To fix this issue keep the CLKRUN protocol disabled for the entire
duration of a single TPM command and not disabling and re-enabling
again for every TPM transaction. For the other TPM accesses outside
TPM command flow, add a higher level of disabling and re-enabling
the CLKRUN protocol, instead of doing for every TPM transaction.

Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems")

Signed-off-by: Azhar Shaikh 
---
 drivers/char/tpm/tpm-interface.c |  6 +++
 drivers/char/tpm/tpm_tis.c   | 86 +---
 drivers/char/tpm/tpm_tis_core.c  | 95 +---
 drivers/char/tpm/tpm_tis_core.h  |  4 ++
 include/linux/tpm.h  |  1 +
 5 files changed, 111 insertions(+), 81 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ebe0a1d36d8c..6e19e3dd98e4 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
if (chip->dev.parent)
pm_runtime_get_sync(chip->dev.parent);
 
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, true);
+
/* Store the decision as chip->locality will be changed. */
need_locality = chip->locality == -1;
 
@@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
chip->locality = -1;
}
 out_no_locality:
+   if (chip->ops->clk_enable != NULL)
+   chip->ops->clk_enable(chip, false);
+
if (chip->dev.parent)
pm_runtime_put_sync(chip->dev.parent);
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 923f8f2cbaca..d29add49b033 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_X86
-#define LPC_CNTRL_OFFSET   0x84
-#define LPC_CLKRUN_EN  (1 << 2)
-
-/**
- * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
- */
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Disable LPC CLKRUN# */
-   clkrun_val &= ~LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-
-/**
- * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
- */
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-   u32 clkrun_val;
-
-   if (!is_bsw())
-   return;
-
-   clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /* Enable LPC CLKRUN# */
-   clkrun_val |= LPC_CLKRUN_EN;
-   iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
-
-   /*
-* Write any random value on port 0x80 which is on LPC, to make
-* sure LPC clock is running before sending any TPM command.
-*/
-   outb(0xCC, 0x80);
-
-}
-#else
-static void tpm_platform_begin_xfer(struct tpm_tis_data *data)
-{
-}
-
-static void tpm_platform_end_xfer(struct tpm_tis_data *data)
-{
-}
-#endif
-
 static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
  u8 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
*result++ = ioread8(phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, 
u32 addr, u16 len,
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-   tpm_platform_begin_xfer(data);
+   if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE))
+   WARN(1, "CLKRUN not enabled!\n");
 
while (len--)
iowrite8(*value++, phy->iobase + addr);
 
-   tpm_platform_end_xfer(data);
-
return 0;
 }
 
@@ -228,12 +165,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 
addr, u16 *result)
 {
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
-