Message ID | 1417672518-4530-9-git-send-email-jarkko.sakkinen@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Jarkko, On Thu, 4 Dec 2014, Jarkko Sakkinen wrote: > From: Will Arthur <will.c.arthur@intel.com> > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > instead of calling tpm_get_timeouts(), assign duration and timeout > values defined in the TPM 2.0 PTP specification. > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > --- > drivers/char/tpm/tpm_tis.c | 80 ++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 67 insertions(+), 13 deletions(-) > > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c > index 89e1abb..71cbb2d 100644 > --- a/drivers/char/tpm/tpm_tis.c > +++ b/drivers/char/tpm/tpm_tis.c > @@ -1,5 +1,6 @@ > /* > * Copyright (C) 2005, 2006 IBM Corporation > + * Copyright (C) 2014 Intel Corporation > * > * Authors: > * Leendert van Doorn <leendert@watson.ibm.com> > @@ -44,6 +45,10 @@ enum tis_status { > TPM_STS_DATA_EXPECT = 0x08, > }; > > +enum tis_status3 { > + TPM_STS3_TPM2_FAM = 0x04, > +}; > + > enum tis_int_flags { > TPM_GLOBAL_INT_ENABLE = 0x80000000, > TPM_INTF_BURST_COUNT_STATIC = 0x100, > @@ -70,6 +75,7 @@ enum tis_defaults { > #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) > #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) > #define TPM_STS(l) (0x0018 | ((l) << 12)) > +#define TPM_STS3(l) (0x001b | ((l) << 12)) > #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) > > #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) > @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) > { > int rc; > u32 ordinal; > + unsigned long dur; > > rc = tpm_tis_send_data(chip, buf, len); > if (rc < 0) > @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) > > if (chip->vendor.irq) { > ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); > + > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > + dur = tpm2_calc_ordinal_duration(chip, ordinal); > + else > + dur = tpm_calc_ordinal_duration(chip, ordinal); > + > if (wait_for_tpm_stat > - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, > - tpm_calc_ordinal_duration(chip, ordinal), > + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, > &chip->vendor.read_queue, false) < 0) { > rc = -ETIME; > goto out_err; > @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > int rc, i, irq_s, irq_e, probe; > struct tpm_chip *chip; > struct priv_data *priv; > + u8 sts3; > > priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); > if (priv == NULL) > @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > if (!chip->vendor.iobase) > return -EIO; > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > + chip->flags = TPM_CHIP_FLAG_TPM2; > + > /* Default timeouts */ > - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + if (chip->flags & TPM_CHIP_FLAG_TPM2) { > + chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A); > + chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B); > + chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C); > + chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D); > + chip->vendor.duration[TPM_SHORT] = > + usecs_to_jiffies(TPM2_DURATION_SHORT); > + chip->vendor.duration[TPM_MEDIUM] = > + usecs_to_jiffies(TPM2_DURATION_MEDIUM); > + chip->vendor.duration[TPM_LONG] = > + usecs_to_jiffies(TPM2_DURATION_LONG); > + } else { > + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + } > > if (wait_startup(chip, 0) != 0) { > rc = -ENODEV; > @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); > chip->vendor.manufacturer_id = vendor; > > - dev_info(dev, > - "1.2 TPM (device-id 0x%X, rev-id %d)\n", > + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", > + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", > vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); > > if (!itpm) { > @@ -665,6 +695,23 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > if (intfcaps & TPM_INTF_DATA_AVAIL_INT) > dev_dbg(dev, "\tData Avail Int Support\n"); > > + /* get the timeouts before testing for irqs */ > + if (!(chip->flags & TPM_CHIP_FLAG_TPM2) && tpm_get_timeouts(chip)) { > + dev_err(dev, "Could not get TPM timeouts and durations\n"); > + rc = -ENODEV; > + goto out_err; > + } > + > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > + rc = tpm2_do_selftest(chip); > + else > + rc = tpm_do_selftest(chip); > + if (rc) { > + dev_err(dev, "TPM self test failed\n"); > + rc = -ENODEV; > + goto out_err; > + } > + > /* INTERRUPT Setup */ > init_waitqueue_head(&chip->vendor.read_queue); > init_waitqueue_head(&chip->vendor.int_queue); In Peter's for-james branch, commit 0e6cb01, the v1.2 calls to tpm_get_timeouts and tpm_do_selftest were moved toward the end of tpm_tis_init. > @@ -720,7 +767,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > chip->vendor.probed_irq = 0; > > /* Generate Interrupts */ > - tpm_gen_interrupt(chip); > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > + tpm2_gen_interrupt(chip); > + else > + tpm_gen_interrupt(chip); > > chip->vendor.irq = chip->vendor.probed_irq; > > @@ -808,14 +858,18 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) > static int tpm_tis_resume(struct device *dev) > { > struct tpm_chip *chip = dev_get_drvdata(dev); > - int ret; > + int ret = 0; > > if (chip->vendor.irq) > tpm_tis_reenable_interrupts(chip); > > - ret = tpm_pm_resume(dev); > - if (!ret) > - tpm_do_selftest(chip); > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > + tpm2_do_selftest(chip); > + else { > + ret = tpm_pm_resume(dev); > + if (!ret) > + tpm_do_selftest(chip); > + } > > return ret; > } > -- > 2.1.0 > ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: > From: Will Arthur <will.c.arthur@intel.com> > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > instead of calling tpm_get_timeouts(), assign duration and timeout > values defined in the TPM 2.0 PTP specification. > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > --- Should we change the KConfig string? TPM Interface Specification 1.2 Interface is not quite accurate anymore after applying this patch. Thanks, Peter ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Hi Jarkko, Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: > From: Will Arthur <will.c.arthur@intel.com> > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > instead of calling tpm_get_timeouts(), assign duration and timeout > values defined in the TPM 2.0 PTP specification. > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > --- > drivers/char/tpm/tpm_tis.c | 80 > ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 > insertions(+), 13 deletions(-) > > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c > index 89e1abb..71cbb2d 100644 > --- a/drivers/char/tpm/tpm_tis.c > +++ b/drivers/char/tpm/tpm_tis.c > @@ -1,5 +1,6 @@ > /* > * Copyright (C) 2005, 2006 IBM Corporation > + * Copyright (C) 2014 Intel Corporation > * > * Authors: > * Leendert van Doorn <leendert@watson.ibm.com> > @@ -44,6 +45,10 @@ enum tis_status { > TPM_STS_DATA_EXPECT = 0x08, > }; > > +enum tis_status3 { > + TPM_STS3_TPM2_FAM = 0x04, > +}; > + > enum tis_int_flags { > TPM_GLOBAL_INT_ENABLE = 0x80000000, > TPM_INTF_BURST_COUNT_STATIC = 0x100, > @@ -70,6 +75,7 @@ enum tis_defaults { > #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) > #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) > #define TPM_STS(l) (0x0018 | ((l) << 12)) > +#define TPM_STS3(l) (0x001b | ((l) << 12)) > #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) > > #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) > @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 > *buf, size_t len) { > int rc; > u32 ordinal; > + unsigned long dur; > > rc = tpm_tis_send_data(chip, buf, len); > if (rc < 0) > @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 > *buf, size_t len) > > if (chip->vendor.irq) { > ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); > + > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > + dur = tpm2_calc_ordinal_duration(chip, ordinal); > + else > + dur = tpm_calc_ordinal_duration(chip, ordinal); > + > if (wait_for_tpm_stat > - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, > - tpm_calc_ordinal_duration(chip, ordinal), > + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, > &chip->vendor.read_queue, false) < 0) { > rc = -ETIME; > goto out_err; > @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle > acpi_dev_handle, int rc, i, irq_s, irq_e, probe; > struct tpm_chip *chip; > struct priv_data *priv; > + u8 sts3; > > priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); > if (priv == NULL) > @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, > acpi_handle acpi_dev_handle, if (!chip->vendor.iobase) > return -EIO; > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > + chip->flags = TPM_CHIP_FLAG_TPM2; > + > /* Default timeouts */ > - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + if (chip->flags & TPM_CHIP_FLAG_TPM2) { > + chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A); > + chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B); > + chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C); > + chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D); > + chip->vendor.duration[TPM_SHORT] = > + usecs_to_jiffies(TPM2_DURATION_SHORT); > + chip->vendor.duration[TPM_MEDIUM] = > + usecs_to_jiffies(TPM2_DURATION_MEDIUM); > + chip->vendor.duration[TPM_LONG] = > + usecs_to_jiffies(TPM2_DURATION_LONG); > + } else { > + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > + } > > if (wait_startup(chip, 0) != 0) { > rc = -ENODEV; > @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle > acpi_dev_handle, vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); > chip->vendor.manufacturer_id = vendor; > > - dev_info(dev, > - "1.2 TPM (device-id 0x%X, rev-id %d)\n", > + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", > + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", > vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); > When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios integration, it fets detected as a TPM2.0 chip :/ sudo rmmod tpm_tis # modprobe tpm_tis force=1 modprobe: ERROR: could not insert 'tpm_tis': No such device # dmesg [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16) [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest [ 263.948120] tpm_tis tpm_tis: TPM self test failed sts3 is reported as 0xff from my TPM1.2 Thanks, Peter ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
Am Donnerstag, 4. Dezember 2014, 23:18:33 schrieb Peter Hüwe: > Hi Jarkko, > > Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: > > From: Will Arthur <will.c.arthur@intel.com> > > > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > > instead of calling tpm_get_timeouts(), assign duration and timeout > > values defined in the TPM 2.0 PTP specification. > > > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > > --- > > > > drivers/char/tpm/tpm_tis.c | 80 > > > > ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 > > insertions(+), 13 deletions(-) > > > > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c > > index 89e1abb..71cbb2d 100644 > > --- a/drivers/char/tpm/tpm_tis.c > > +++ b/drivers/char/tpm/tpm_tis.c > > @@ -1,5 +1,6 @@ > > > > /* > > > > * Copyright (C) 2005, 2006 IBM Corporation > > > > + * Copyright (C) 2014 Intel Corporation > > > > * > > * Authors: > > * Leendert van Doorn <leendert@watson.ibm.com> > > > > @@ -44,6 +45,10 @@ enum tis_status { > > > > TPM_STS_DATA_EXPECT = 0x08, > > > > }; > > > > +enum tis_status3 { > > + TPM_STS3_TPM2_FAM = 0x04, > > +}; > > + > > > > enum tis_int_flags { > > > > TPM_GLOBAL_INT_ENABLE = 0x80000000, > > TPM_INTF_BURST_COUNT_STATIC = 0x100, > > > > @@ -70,6 +75,7 @@ enum tis_defaults { > > > > #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) > > #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) > > #define TPM_STS(l) (0x0018 | ((l) << 12)) > > > > +#define TPM_STS3(l) (0x001b | ((l) << 12)) > > > > #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) > > > > #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) > > > > @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, > > u8 *buf, size_t len) { > > > > int rc; > > u32 ordinal; > > > > + unsigned long dur; > > > > rc = tpm_tis_send_data(chip, buf, len); > > if (rc < 0) > > > > @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, > > u8 *buf, size_t len) > > > > if (chip->vendor.irq) { > > > > ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); > > > > + > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > > + dur = tpm2_calc_ordinal_duration(chip, ordinal); > > + else > > + dur = tpm_calc_ordinal_duration(chip, ordinal); > > + > > > > if (wait_for_tpm_stat > > > > - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, > > - tpm_calc_ordinal_duration(chip, ordinal), > > + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, > > > > &chip->vendor.read_queue, false) < 0) { > > > > rc = -ETIME; > > goto out_err; > > > > @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, > > acpi_handle acpi_dev_handle, int rc, i, irq_s, irq_e, probe; > > > > struct tpm_chip *chip; > > struct priv_data *priv; > > > > + u8 sts3; > > > > priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); > > if (priv == NULL) > > > > @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, > > acpi_handle acpi_dev_handle, if (!chip->vendor.iobase) > > > > return -EIO; > > > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > > + chip->flags = TPM_CHIP_FLAG_TPM2; > > + > > > > /* Default timeouts */ > > > > - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > > - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) { > > + chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A); > > + chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B); > > + chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C); > > + chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D); > > + chip->vendor.duration[TPM_SHORT] = > > + usecs_to_jiffies(TPM2_DURATION_SHORT); > > + chip->vendor.duration[TPM_MEDIUM] = > > + usecs_to_jiffies(TPM2_DURATION_MEDIUM); > > + chip->vendor.duration[TPM_LONG] = > > + usecs_to_jiffies(TPM2_DURATION_LONG); > > + } else { > > + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > > + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + } > > > > if (wait_startup(chip, 0) != 0) { > > > > rc = -ENODEV; > > > > @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, > > acpi_handle acpi_dev_handle, vendor = ioread32(chip->vendor.iobase + > > TPM_DID_VID(0)); > > > > chip->vendor.manufacturer_id = vendor; > > > > - dev_info(dev, > > - "1.2 TPM (device-id 0x%X, rev-id %d)\n", > > + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", > > + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", > > > > vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); > > When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios > integration, it fets detected as a TPM2.0 chip :/ > > sudo rmmod tpm_tis > # modprobe tpm_tis force=1 > modprobe: ERROR: could not insert 'tpm_tis': No such device > # dmesg > [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16) > [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest > [ 263.948120] tpm_tis tpm_tis: TPM self test failed > > > sts3 is reported as 0xff from my TPM1.2 > Hmm, my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a machine without bios integration) [ 307.095344] sts3 ff [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16) [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest [ 307.140056] tpm_tis tpm_tis: TPM self test failed Peter ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
On Thu, Dec 04, 2014 at 03:25:12PM +0000, Scot Doyle wrote: > Hi Jarkko, > > On Thu, 4 Dec 2014, Jarkko Sakkinen wrote: > > From: Will Arthur <will.c.arthur@intel.com> > > > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > > instead of calling tpm_get_timeouts(), assign duration and timeout > > values defined in the TPM 2.0 PTP specification. > > > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > > --- > > drivers/char/tpm/tpm_tis.c | 80 ++++++++++++++++++++++++++++++++++++++-------- > > 1 file changed, 67 insertions(+), 13 deletions(-) > > > > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c > > index 89e1abb..71cbb2d 100644 > > --- a/drivers/char/tpm/tpm_tis.c > > +++ b/drivers/char/tpm/tpm_tis.c > > @@ -1,5 +1,6 @@ > > /* > > * Copyright (C) 2005, 2006 IBM Corporation > > + * Copyright (C) 2014 Intel Corporation > > * > > * Authors: > > * Leendert van Doorn <leendert@watson.ibm.com> > > @@ -44,6 +45,10 @@ enum tis_status { > > TPM_STS_DATA_EXPECT = 0x08, > > }; > > > > +enum tis_status3 { > > + TPM_STS3_TPM2_FAM = 0x04, > > +}; > > + > > enum tis_int_flags { > > TPM_GLOBAL_INT_ENABLE = 0x80000000, > > TPM_INTF_BURST_COUNT_STATIC = 0x100, > > @@ -70,6 +75,7 @@ enum tis_defaults { > > #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) > > #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) > > #define TPM_STS(l) (0x0018 | ((l) << 12)) > > +#define TPM_STS3(l) (0x001b | ((l) << 12)) > > #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) > > > > #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) > > @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) > > { > > int rc; > > u32 ordinal; > > + unsigned long dur; > > > > rc = tpm_tis_send_data(chip, buf, len); > > if (rc < 0) > > @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) > > > > if (chip->vendor.irq) { > > ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); > > + > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > > + dur = tpm2_calc_ordinal_duration(chip, ordinal); > > + else > > + dur = tpm_calc_ordinal_duration(chip, ordinal); > > + > > if (wait_for_tpm_stat > > - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, > > - tpm_calc_ordinal_duration(chip, ordinal), > > + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, > > &chip->vendor.read_queue, false) < 0) { > > rc = -ETIME; > > goto out_err; > > @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > > int rc, i, irq_s, irq_e, probe; > > struct tpm_chip *chip; > > struct priv_data *priv; > > + u8 sts3; > > > > priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); > > if (priv == NULL) > > @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > > if (!chip->vendor.iobase) > > return -EIO; > > > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > > + chip->flags = TPM_CHIP_FLAG_TPM2; > > + > > /* Default timeouts */ > > - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > > - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) { > > + chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A); > > + chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B); > > + chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C); > > + chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D); > > + chip->vendor.duration[TPM_SHORT] = > > + usecs_to_jiffies(TPM2_DURATION_SHORT); > > + chip->vendor.duration[TPM_MEDIUM] = > > + usecs_to_jiffies(TPM2_DURATION_MEDIUM); > > + chip->vendor.duration[TPM_LONG] = > > + usecs_to_jiffies(TPM2_DURATION_LONG); > > + } else { > > + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); > > + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); > > + } > > > > if (wait_startup(chip, 0) != 0) { > > rc = -ENODEV; > > @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > > vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); > > chip->vendor.manufacturer_id = vendor; > > > > - dev_info(dev, > > - "1.2 TPM (device-id 0x%X, rev-id %d)\n", > > + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", > > + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", > > vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); > > > > if (!itpm) { > > @@ -665,6 +695,23 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > > if (intfcaps & TPM_INTF_DATA_AVAIL_INT) > > dev_dbg(dev, "\tData Avail Int Support\n"); > > > > + /* get the timeouts before testing for irqs */ > > + if (!(chip->flags & TPM_CHIP_FLAG_TPM2) && tpm_get_timeouts(chip)) { > > + dev_err(dev, "Could not get TPM timeouts and durations\n"); > > + rc = -ENODEV; > > + goto out_err; > > + } > > + > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > > + rc = tpm2_do_selftest(chip); > > + else > > + rc = tpm_do_selftest(chip); > > + if (rc) { > > + dev_err(dev, "TPM self test failed\n"); > > + rc = -ENODEV; > > + goto out_err; > > + } > > + > > /* INTERRUPT Setup */ > > init_waitqueue_head(&chip->vendor.read_queue); > > init_waitqueue_head(&chip->vendor.int_queue); > > In Peter's for-james branch, commit 0e6cb01, the v1.2 calls to > tpm_get_timeouts and tpm_do_selftest were moved toward the end of > tpm_tis_init. Right. My bad. Could this be reverted with a separate fix or do I prepare a new patch set? I would propose the former... > > @@ -720,7 +767,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, > > chip->vendor.probed_irq = 0; > > > > /* Generate Interrupts */ > > - tpm_gen_interrupt(chip); > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > > + tpm2_gen_interrupt(chip); > > + else > > + tpm_gen_interrupt(chip); > > > > chip->vendor.irq = chip->vendor.probed_irq; > > > > @@ -808,14 +858,18 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) > > static int tpm_tis_resume(struct device *dev) > > { > > struct tpm_chip *chip = dev_get_drvdata(dev); > > - int ret; > > + int ret = 0; > > > > if (chip->vendor.irq) > > tpm_tis_reenable_interrupts(chip); > > > > - ret = tpm_pm_resume(dev); > > - if (!ret) > > - tpm_do_selftest(chip); > > + if (chip->flags & TPM_CHIP_FLAG_TPM2) > > + tpm2_do_selftest(chip); > > + else { > > + ret = tpm_pm_resume(dev); > > + if (!ret) > > + tpm_do_selftest(chip); > > + } > > > > return ret; > > } > > -- > > 2.1.0 > > /Jarkko ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
On Thu, Dec 04, 2014 at 10:46:25PM +0100, Peter Hüwe wrote: > Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: > > From: Will Arthur <will.c.arthur@intel.com> > > > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > > instead of calling tpm_get_timeouts(), assign duration and timeout > > values defined in the TPM 2.0 PTP specification. > > > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > > --- > Should we change the KConfig string? > TPM Interface Specification 1.2 Interface > is not quite accurate anymore after applying this patch. Would make sense. Does this require a new patch set? > Thanks, > Peter /Jarkko ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
> > > Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: > > > From: Will Arthur <will.c.arthur@intel.com> > > > > > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > > > instead of calling tpm_get_timeouts(), assign duration and timeout > > > values defined in the TPM 2.0 PTP specification. > > > > > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > > > > > > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > > > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > > > + chip->flags = TPM_CHIP_FLAG_TPM2; > > > + > > > > > > > > When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios > > integration, it fets detected as a TPM2.0 chip :/ > > > > sudo rmmod tpm_tis > > # modprobe tpm_tis force=1 > > modprobe: ERROR: could not insert 'tpm_tis': No such device > > # dmesg > > [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16) > > [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest > > [ 263.948120] tpm_tis tpm_tis: TPM self test failed > > > > > > sts3 is reported as 0xff from my TPM1.2 > > > > > Hmm, > my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a > machine without bios integration) > > [ 307.095344] sts3 ff > [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16) > [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest > [ 307.140056] tpm_tis tpm_tis: TPM self test failed You are reading "sts3" - before requesting the locality and thus it returns 0xff for a TPM20 chip as well. --> You have to have an active locality first. For a TPM2.0 0xFF is not a valid value (if active locality is set), since reading commandCancel and resetEstablishment bit always return 0 on reads (according to spec). --> 0xFF should be treated as a TPM1.2 (older tpms with TIS 1.2) --> 0x04 should be treated as TPM 2.0 --> 0x08 should be treated as TPM1.2 (newer tpms with TIS1.3 enhanced) Thanks, Peter ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
On 12/05/2014 10:01 AM, Peter Huewe wrote: >>> Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: >>>> From: Will Arthur <will.c.arthur@intel.com> >>>> >>>> Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, >>>> instead of calling tpm_get_timeouts(), assign duration and timeout >>>> values defined in the TPM 2.0 PTP specification. >>>> >>>> Signed-off-by: Will Arthur <will.c.arthur@intel.com> >>>> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> >>>> + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); >>>> + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) >>>> + chip->flags = TPM_CHIP_FLAG_TPM2; >>>> + >>>> >>> When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios >>> integration, it fets detected as a TPM2.0 chip :/ >>> >>> sudo rmmod tpm_tis >>> # modprobe tpm_tis force=1 >>> modprobe: ERROR: could not insert 'tpm_tis': No such device >>> # dmesg >>> [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16) >>> [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest >>> [ 263.948120] tpm_tis tpm_tis: TPM self test failed >>> >>> >>> sts3 is reported as 0xff from my TPM1.2 >>> >> >> Hmm, >> my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a >> machine without bios integration) >> >> [ 307.095344] sts3 ff >> [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16) >> [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest >> [ 307.140056] tpm_tis tpm_tis: TPM self test failed > > You are reading "sts3" - before requesting the locality and thus it returns 0xff for a TPM20 chip as well. > --> You have to have an active locality first. > > > For a TPM2.0 0xFF is not a valid value (if active locality is set), since reading commandCancel and resetEstablishment bit always return 0 on reads (according to spec). > > --> 0xFF should be treated as a TPM1.2 (older tpms with TIS 1.2) > --> 0x04 should be treated as TPM 2.0 > --> 0x08 should be treated as TPM1.2 (newer tpms with TIS1.3 enhanced) > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > + chip->flags = TPM_CHIP_FLAG_TPM2; #define TPM_STS3_TPM2_FAM_MASK = 0x0c then: if ((sts3 & TPM_STS3_TPM2_FAM_MASK) == TPM_STS3_TPM2_FAM) ... [see my previous review on this] Stefan > > > > Thanks, > Peter > > ------------------------------------------------------------------------------ > Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server > from Actuate! Instantly Supercharge Your Business Reports and Dashboards > with Interactivity, Sharing, Native Excel Exports, App Integration & more > Get technology previously reserved for billion-dollar corporations, FREE > http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk > _______________________________________________ > tpmdd-devel mailing list > tpmdd-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tpmdd-devel > ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
On Fri, Dec 05, 2014 at 04:01:01PM +0100, Peter Huewe wrote: > > > > > Am Donnerstag, 4. Dezember 2014, 06:55:18 schrieb Jarkko Sakkinen: > > > > From: Will Arthur <will.c.arthur@intel.com> > > > > > > > > Detect TPM 2.0 by using the extended STS (STS3) register. For TPM 2.0, > > > > instead of calling tpm_get_timeouts(), assign duration and timeout > > > > values defined in the TPM 2.0 PTP specification. > > > > > > > > Signed-off-by: Will Arthur <will.c.arthur@intel.com> > > > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > > > > > > > > > > + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); > > > > + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) > > > > + chip->flags = TPM_CHIP_FLAG_TPM2; > > > > + > > > > > > > > > > > > When loading tpm_tis force=1 with my tpm1.2 chip on a machine without bios > > > integration, it fets detected as a TPM2.0 chip :/ > > > > > > sudo rmmod tpm_tis > > > # modprobe tpm_tis force=1 > > > modprobe: ERROR: could not insert 'tpm_tis': No such device > > > # dmesg > > > [ 263.903828] tpm_tis tpm_tis: 2.0 TPM (device-id 0xB, rev-id 16) > > > [ 263.948049] tpm_tis tpm_tis: A TPM error (10) occurred continue selftest > > > [ 263.948120] tpm_tis tpm_tis: TPM self test failed > > > > > > > > > sts3 is reported as 0xff from my TPM1.2 > > > > > > > > > Hmm, > > my TPM2.0 chip also reports sts3 as 0xff (when loading with force=1 on a > > machine without bios integration) > > > > [ 307.095344] sts3 ff > > [ 307.095366] tpm_tis tpm_tis: 2.0 TPM (device-id 0x1A, rev-id 16) > > [ 307.140047] tpm_tis tpm_tis: A TPM error (256) occurred continue selftest > > [ 307.140056] tpm_tis tpm_tis: TPM self test failed > > > You are reading "sts3" - before requesting the locality and thus > it returns 0xff for a TPM20 chip as well. > --> You have to have an active locality first. > > > For a TPM2.0 0xFF is not a valid value (if active locality is > set), since reading commandCancel and resetEstablishment bit > always return 0 on reads (according to spec). > > --> 0xFF should be treated as a TPM1.2 (older tpms with TIS 1.2) > --> 0x04 should be treated as TPM 2.0 > --> 0x08 should be treated as TPM1.2 (newer tpms with TIS1.3 enhanced) Correct. I discussed with some people and verified the reason to be such that if firmware does nothing, the locality is unopened. I have access today to similar setup and can fix this regression and verify my fix. Thanks for pointing this out! > Thanks, > Peter /Jarkko ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 89e1abb..71cbb2d 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2005, 2006 IBM Corporation + * Copyright (C) 2014 Intel Corporation * * Authors: * Leendert van Doorn <leendert@watson.ibm.com> @@ -44,6 +45,10 @@ enum tis_status { TPM_STS_DATA_EXPECT = 0x08, }; +enum tis_status3 { + TPM_STS3_TPM2_FAM = 0x04, +}; + enum tis_int_flags { TPM_GLOBAL_INT_ENABLE = 0x80000000, TPM_INTF_BURST_COUNT_STATIC = 0x100, @@ -70,6 +75,7 @@ enum tis_defaults { #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) #define TPM_STS(l) (0x0018 | ((l) << 12)) +#define TPM_STS3(l) (0x001b | ((l) << 12)) #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) @@ -363,6 +369,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) { int rc; u32 ordinal; + unsigned long dur; rc = tpm_tis_send_data(chip, buf, len); if (rc < 0) @@ -374,9 +381,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) if (chip->vendor.irq) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + dur = tpm2_calc_ordinal_duration(chip, ordinal); + else + dur = tpm_calc_ordinal_duration(chip, ordinal); + if (wait_for_tpm_stat - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, - tpm_calc_ordinal_duration(chip, ordinal), + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, &chip->vendor.read_queue, false) < 0) { rc = -ETIME; goto out_err; @@ -588,6 +600,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, int rc, i, irq_s, irq_e, probe; struct tpm_chip *chip; struct priv_data *priv; + u8 sts3; priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); if (priv == NULL) @@ -604,11 +617,28 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, if (!chip->vendor.iobase) return -EIO; + sts3 = ioread8(chip->vendor.iobase + TPM_STS3(1)); + if ((sts3 & TPM_STS3_TPM2_FAM) == TPM_STS3_TPM2_FAM) + chip->flags = TPM_CHIP_FLAG_TPM2; + /* Default timeouts */ - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + if (chip->flags & TPM_CHIP_FLAG_TPM2) { + chip->vendor.timeout_a = usecs_to_jiffies(TPM2_TIMEOUT_A); + chip->vendor.timeout_b = usecs_to_jiffies(TPM2_TIMEOUT_B); + chip->vendor.timeout_c = usecs_to_jiffies(TPM2_TIMEOUT_C); + chip->vendor.timeout_d = usecs_to_jiffies(TPM2_TIMEOUT_D); + chip->vendor.duration[TPM_SHORT] = + usecs_to_jiffies(TPM2_DURATION_SHORT); + chip->vendor.duration[TPM_MEDIUM] = + usecs_to_jiffies(TPM2_DURATION_MEDIUM); + chip->vendor.duration[TPM_LONG] = + usecs_to_jiffies(TPM2_DURATION_LONG); + } else { + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + } if (wait_startup(chip, 0) != 0) { rc = -ENODEV; @@ -623,8 +653,8 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); chip->vendor.manufacturer_id = vendor; - dev_info(dev, - "1.2 TPM (device-id 0x%X, rev-id %d)\n", + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); if (!itpm) { @@ -665,6 +695,23 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, if (intfcaps & TPM_INTF_DATA_AVAIL_INT) dev_dbg(dev, "\tData Avail Int Support\n"); + /* get the timeouts before testing for irqs */ + if (!(chip->flags & TPM_CHIP_FLAG_TPM2) && tpm_get_timeouts(chip)) { + dev_err(dev, "Could not get TPM timeouts and durations\n"); + rc = -ENODEV; + goto out_err; + } + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc = tpm2_do_selftest(chip); + else + rc = tpm_do_selftest(chip); + if (rc) { + dev_err(dev, "TPM self test failed\n"); + rc = -ENODEV; + goto out_err; + } + /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); @@ -720,7 +767,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, chip->vendor.probed_irq = 0; /* Generate Interrupts */ - tpm_gen_interrupt(chip); + if (chip->flags & TPM_CHIP_FLAG_TPM2) + tpm2_gen_interrupt(chip); + else + tpm_gen_interrupt(chip); chip->vendor.irq = chip->vendor.probed_irq; @@ -808,14 +858,18 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) static int tpm_tis_resume(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - int ret; + int ret = 0; if (chip->vendor.irq) tpm_tis_reenable_interrupts(chip); - ret = tpm_pm_resume(dev); - if (!ret) - tpm_do_selftest(chip); + if (chip->flags & TPM_CHIP_FLAG_TPM2) + tpm2_do_selftest(chip); + else { + ret = tpm_pm_resume(dev); + if (!ret) + tpm_do_selftest(chip); + } return ret; }