summaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm-chip.c
diff options
context:
space:
mode:
authorJarkko Sakkinen2018-11-04 20:18:46 +0100
committerJarkko Sakkinen2019-02-13 08:48:33 +0100
commit719b7d81f2048477f89f7303e2b4ddec8197e6e3 (patch)
treeda5983336e23c58d3dba2a85326983baf54a07ce /drivers/char/tpm/tpm-chip.c
parenttpm: remove TPM_TRANSMIT_UNLOCKED flag (diff)
downloadkernel-qcow2-linux-719b7d81f2048477f89f7303e2b4ddec8197e6e3.tar.gz
kernel-qcow2-linux-719b7d81f2048477f89f7303e2b4ddec8197e6e3.tar.xz
kernel-qcow2-linux-719b7d81f2048477f89f7303e2b4ddec8197e6e3.zip
tpm: introduce tpm_chip_start() and tpm_chip_stop()
Encapsulate power gating and locality functionality to tpm_chip_start() and tpm_chip_stop() in order to clean up the branching mess in tpm_transmit(). Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Tested-by: Stefan Berger <stefanb@linux.ibm.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com> Tested-by: Alexander Steffen <Alexander.Steffen@infineon.com>
Diffstat (limited to 'drivers/char/tpm/tpm-chip.c')
-rw-r--r--drivers/char/tpm/tpm-chip.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 157505b0f755..ed673c7216a0 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -37,6 +37,117 @@ struct class *tpm_class;
struct class *tpmrm_class;
dev_t tpm_devt;
+static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags)
+{
+ int rc;
+
+ if (flags & TPM_TRANSMIT_NESTED)
+ return 0;
+
+ if (!chip->ops->request_locality)
+ return 0;
+
+ rc = chip->ops->request_locality(chip, 0);
+ if (rc < 0)
+ return rc;
+
+ chip->locality = rc;
+ return 0;
+}
+
+static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags)
+{
+ int rc;
+
+ if (flags & TPM_TRANSMIT_NESTED)
+ return;
+
+ if (!chip->ops->relinquish_locality)
+ return;
+
+ rc = chip->ops->relinquish_locality(chip, chip->locality);
+ if (rc)
+ dev_err(&chip->dev, "%s: : error %d\n", __func__, rc);
+
+ chip->locality = -1;
+}
+
+static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags)
+{
+ if (flags & TPM_TRANSMIT_NESTED)
+ return 0;
+
+ if (!chip->ops->cmd_ready)
+ return 0;
+
+ return chip->ops->cmd_ready(chip);
+}
+
+static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags)
+{
+ if (flags & TPM_TRANSMIT_NESTED)
+ return 0;
+
+ if (!chip->ops->go_idle)
+ return 0;
+
+ return chip->ops->go_idle(chip);
+}
+
+/**
+ * tpm_chip_start() - power on the TPM
+ * @chip: a TPM chip to use
+ * @flags: TPM transmit flags
+ *
+ * Return:
+ * * The response length - OK
+ * * -errno - A system error
+ */
+int tpm_chip_start(struct tpm_chip *chip, unsigned int flags)
+{
+ int ret;
+
+ if (chip->ops->clk_enable)
+ chip->ops->clk_enable(chip, true);
+
+ if (chip->locality == -1) {
+ ret = tpm_request_locality(chip, flags);
+ if (ret) {
+ chip->ops->clk_enable(chip, false);
+ return ret;
+ }
+ }
+
+ ret = tpm_cmd_ready(chip, flags);
+ if (ret) {
+ tpm_relinquish_locality(chip, flags);
+ if (chip->ops->clk_enable)
+ chip->ops->clk_enable(chip, false);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_start);
+
+/**
+ * tpm_chip_stop() - power off the TPM
+ * @chip: a TPM chip to use
+ * @flags: TPM transmit flags
+ *
+ * Return:
+ * * The response length - OK
+ * * -errno - A system error
+ */
+void tpm_chip_stop(struct tpm_chip *chip, unsigned int flags)
+{
+ tpm_go_idle(chip, flags);
+ tpm_relinquish_locality(chip, flags);
+ if (chip->ops->clk_enable)
+ chip->ops->clk_enable(chip, false);
+}
+EXPORT_SYMBOL_GPL(tpm_chip_stop);
+
/**
* tpm_try_get_ops() - Get a ref to the tpm_chip
* @chip: Chip to ref