aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.vnet.ibm.com>2011-03-30 12:13:30 -0400
committerRajiv Andrade <srajiv@linux.vnet.ibm.com>2011-07-12 17:53:08 -0400
commit45baa1d1fa3926510ead93c96e6b0baa5ad79bd3 (patch)
treeaa90dcb72b808efc5392aba368ad60a07f58d587 /drivers/char
parent5a79444f24cb169b79f0f346482a42ab28329bae (diff)
tpm_tis: Re-enable interrupts upon (S3) resume
This patch makes sure that if the TPM TIS interface is run in interrupt mode (rather than polling mode) that all interrupts are enabled in the TPM's interrupt enable register after a resume from ACPI S3 suspend. The registers may either have been cleared by the TPM loosing its state during device sleep or by the BIOS leaving the TPM in polling mode (after sending a command to the TPM for starting it up again) You may want to check if your TPM runs with interrupts by doing cat /proc/interrupts | grep -i tpm and see whether there is an entry or otherwise for it to use interrupts: modprobe tpm_tis interrupts=1 [add 'itpm=1' for Intel TPM ] v2: - the patch was adapted to work with the pnp and platform driver implementations in tpm_tis.c Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm_tis.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index a84108cd932f..88de8fc41586 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -649,11 +649,36 @@ static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
649 return tpm_pm_suspend(&dev->dev, msg); 649 return tpm_pm_suspend(&dev->dev, msg);
650} 650}
651 651
652static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
653{
654 u32 intmask;
655
656 /* reenable interrupts that device may have lost or
657 BIOS/firmware may have disabled */
658 iowrite8(chip->vendor.irq, chip->vendor.iobase +
659 TPM_INT_VECTOR(chip->vendor.locality));
660
661 intmask =
662 ioread32(chip->vendor.iobase +
663 TPM_INT_ENABLE(chip->vendor.locality));
664
665 intmask |= TPM_INTF_CMD_READY_INT
666 | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
667 | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
668
669 iowrite32(intmask,
670 chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
671}
672
673
652static int tpm_tis_pnp_resume(struct pnp_dev *dev) 674static int tpm_tis_pnp_resume(struct pnp_dev *dev)
653{ 675{
654 struct tpm_chip *chip = pnp_get_drvdata(dev); 676 struct tpm_chip *chip = pnp_get_drvdata(dev);
655 int ret; 677 int ret;
656 678
679 if (chip->vendor.irq)
680 tpm_tis_reenable_interrupts(chip);
681
657 ret = tpm_pm_resume(&dev->dev); 682 ret = tpm_pm_resume(&dev->dev);
658 if (!ret) 683 if (!ret)
659 tpm_continue_selftest(chip); 684 tpm_continue_selftest(chip);
@@ -706,6 +731,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
706 731
707static int tpm_tis_resume(struct platform_device *dev) 732static int tpm_tis_resume(struct platform_device *dev)
708{ 733{
734 struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
735
736 if (chip->vendor.irq)
737 tpm_tis_reenable_interrupts(chip);
738
709 return tpm_pm_resume(&dev->dev); 739 return tpm_pm_resume(&dev->dev);
710} 740}
711static struct platform_driver tis_drv = { 741static struct platform_driver tis_drv = {