Message ID | 20230326224426.3918167-3-ninad@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | Add support for TPM devices over I2C bus | expand |
On 3/26/23 18:44, Ninad Palsule wrote: > Qemu already supports devices attached to ISA and sysbus. This drop adds > support for the I2C bus attached TPM devices. > > This commit includes changes for the common code. > - Added support for the new checksum registers which are required for > the I2C support. The checksum calculation is handled in the qemu > common code. > - Added wrapper function for read and write data so that I2C code can > call it without MMIO interface. > > The TPM TIS I2C spec describes in the table in section "Interface Locality > Usage per Register" that the TPM_INT_ENABLE and TPM_INT_STATUS registers > must be writable for any locality even if the locality is not the active > locality. Therefore, remove the checks whether the writing locality is the > active locality for these registers. > > Signed-off-by: Ninad Palsule <ninad@linux.ibm.com> > Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> > --- > V2: > > Incorporated Stephen's comments. > > - Removed checksum enable and checksum get registers. > - Added checksum calculation function which can be called from > i2c layer. > > --- > V3: > Incorporated review comments from Cedric and Stefan. > > - Pass locality to the checksum calculation function and cleanup > - Moved I2C related definations in the acpi/tpm.h > > --- > V4: > > Incorporated review comments by Stefan > > - Remove the check for locality while calculating checksum > - Use bswap16 instead of cpu_ti_be16. > - Rename TPM_I2C register by dropping _TIS_ from it. > > --- > V7: > > Incorporated review comments from Stefan. > > - Removed locality check from INT_ENABLE and INT_STATUS registers write > path. > - Moved TPM_DATA_CSUM_ENABLED define in the tpm.h > --- > hw/tpm/tpm_tis.h | 3 +++ > hw/tpm/tpm_tis_common.c | 36 ++++++++++++++++++++++++++++-------- > include/hw/acpi/tpm.h | 31 +++++++++++++++++++++++++++++++ > 3 files changed, 62 insertions(+), 8 deletions(-) > > diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h > index f6b5872ba6..6f29a508dd 100644 > --- a/hw/tpm/tpm_tis.h > +++ b/hw/tpm/tpm_tis.h > @@ -86,5 +86,8 @@ int tpm_tis_pre_save(TPMState *s); > void tpm_tis_reset(TPMState *s); > enum TPMVersion tpm_tis_get_tpm_version(TPMState *s); > void tpm_tis_request_completed(TPMState *s, int ret); > +uint32_t tpm_tis_read_data(TPMState *s, hwaddr addr, unsigned size); > +void tpm_tis_write_data(TPMState *s, hwaddr addr, uint64_t val, uint32_t size); > +uint16_t tpm_tis_get_checksum(TPMState *s); > > #endif /* TPM_TPM_TIS_H */ > diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c > index 503be2a541..c07c179dbc 100644 > --- a/hw/tpm/tpm_tis_common.c > +++ b/hw/tpm/tpm_tis_common.c > @@ -26,6 +26,8 @@ > #include "hw/irq.h" > #include "hw/isa/isa.h" > #include "qapi/error.h" > +#include "qemu/bswap.h" > +#include "qemu/crc-ccitt.h" > #include "qemu/module.h" > > #include "hw/acpi/tpm.h" > @@ -447,6 +449,23 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, > return val; > } > > +/* > + * A wrapper read function so that it can be directly called without > + * mmio. > + */ > +uint32_t tpm_tis_read_data(TPMState *s, hwaddr addr, unsigned size) > +{ > + return tpm_tis_mmio_read(s, addr, size); > +} > + > +/* > + * Calculate current data buffer checksum > + */ > +uint16_t tpm_tis_get_checksum(TPMState *s) > +{ > + return bswap16(crc_ccitt(0, s->buffer, s->rw_offset)); > +} > + > /* > * Write a value to a register of the TIS interface > * See specs pages 33-63 for description of the registers > @@ -588,10 +607,6 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, > > break; > case TPM_TIS_REG_INT_ENABLE: > - if (s->active_locty != locty) { > - break; > - } > - > s->loc[locty].inte &= mask; > s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | > TPM_TIS_INT_POLARITY_MASK | > @@ -601,10 +616,6 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, > /* hard wired -- ignore */ > break; > case TPM_TIS_REG_INT_STATUS: > - if (s->active_locty != locty) { > - break; > - } > - > /* clearing of interrupt flags */ > if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && > (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { > @@ -767,6 +778,15 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, > } > } > > +/* > + * A wrapper write function so that it can be directly called without > + * mmio. > + */ > +void tpm_tis_write_data(TPMState *s, hwaddr addr, uint64_t val, uint32_t size) > +{ > + tpm_tis_mmio_write(s, addr, val, size); > +} > + > const MemoryRegionOps tpm_tis_memory_ops = { > .read = tpm_tis_mmio_read, > .write = tpm_tis_mmio_write, > diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h > index 559ba6906c..39f1300aa0 100644 > --- a/include/hw/acpi/tpm.h > +++ b/include/hw/acpi/tpm.h > @@ -93,6 +93,7 @@ > #define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) > #define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) > #define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) > +#define TPM_TIS_CAP_BURST_COUNT_STATIC (1 << 8) > #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ > #define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \ > (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ > @@ -209,6 +210,36 @@ REG32(CRB_DATA_BUFFER, 0x80) > #define TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ (4 << 0) > #define TPM_PPI_FUNC_MASK (7 << 0) > > +/* TPM TIS I2C registers */ > +#define TPM_I2C_REG_LOC_SEL 0x00 > +#define TPM_I2C_REG_ACCESS 0x04 > +#define TPM_I2C_REG_INT_ENABLE 0x08 > +#define TPM_I2C_REG_INT_CAPABILITY 0x14 > +#define TPM_I2C_REG_STS 0x18 > +#define TPM_I2C_REG_DATA_FIFO 0x24 > +#define TPM_I2C_REG_INTF_CAPABILITY 0x30 > +#define TPM_I2C_REG_I2C_DEV_ADDRESS 0x38 > +#define TPM_I2C_REG_DATA_CSUM_ENABLE 0x40 > +#define TPM_I2C_REG_DATA_CSUM_GET 0x44 > +#define TPM_I2C_REG_DID_VID 0x48 > +#define TPM_I2C_REG_RID 0x4c > +#define TPM_I2C_REG_UNKNOWN 0xff > + > +/* I2C specific interface capabilities */ > +#define TPM_I2C_CAP_INTERFACE_TYPE (0x2 << 0) /* FIFO interface */ > +#define TPM_I2C_CAP_INTERFACE_VER (0x0 << 4) /* TCG I2C intf 1.0 */ > +#define TPM_I2C_CAP_TPM2_FAMILY (0x1 << 7) /* TPM 2.0 family. */ > +#define TPM_I2C_CAP_DEV_ADDR_CHANGE (0x0 << 27) /* No dev addr chng */ > +#define TPM_I2C_CAP_BURST_COUNT_STATIC (0x1 << 29) /* Burst count static */ > +#define TPM_I2C_CAP_LOCALITY_CAP (0x1 << 25) /* 0-5 locality */ > +#define TPM_I2C_CAP_BUS_SPEED (3 << 21) /* std and fast mode */ > + > +/* TPM_STS mask for read bits 31:26 must be zero */ > +#define TPM_I2C_STS_READ_MASK 0x03ffffff > + > +/* Checksum enabled. */ > +#define TPM_DATA_CSUM_ENABLED 0x1 > + > void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev); > > #endif /* CONFIG_TPM */ Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Tested-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h index f6b5872ba6..6f29a508dd 100644 --- a/hw/tpm/tpm_tis.h +++ b/hw/tpm/tpm_tis.h @@ -86,5 +86,8 @@ int tpm_tis_pre_save(TPMState *s); void tpm_tis_reset(TPMState *s); enum TPMVersion tpm_tis_get_tpm_version(TPMState *s); void tpm_tis_request_completed(TPMState *s, int ret); +uint32_t tpm_tis_read_data(TPMState *s, hwaddr addr, unsigned size); +void tpm_tis_write_data(TPMState *s, hwaddr addr, uint64_t val, uint32_t size); +uint16_t tpm_tis_get_checksum(TPMState *s); #endif /* TPM_TPM_TIS_H */ diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c index 503be2a541..c07c179dbc 100644 --- a/hw/tpm/tpm_tis_common.c +++ b/hw/tpm/tpm_tis_common.c @@ -26,6 +26,8 @@ #include "hw/irq.h" #include "hw/isa/isa.h" #include "qapi/error.h" +#include "qemu/bswap.h" +#include "qemu/crc-ccitt.h" #include "qemu/module.h" #include "hw/acpi/tpm.h" @@ -447,6 +449,23 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, return val; } +/* + * A wrapper read function so that it can be directly called without + * mmio. + */ +uint32_t tpm_tis_read_data(TPMState *s, hwaddr addr, unsigned size) +{ + return tpm_tis_mmio_read(s, addr, size); +} + +/* + * Calculate current data buffer checksum + */ +uint16_t tpm_tis_get_checksum(TPMState *s) +{ + return bswap16(crc_ccitt(0, s->buffer, s->rw_offset)); +} + /* * Write a value to a register of the TIS interface * See specs pages 33-63 for description of the registers @@ -588,10 +607,6 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, break; case TPM_TIS_REG_INT_ENABLE: - if (s->active_locty != locty) { - break; - } - s->loc[locty].inte &= mask; s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | TPM_TIS_INT_POLARITY_MASK | @@ -601,10 +616,6 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, /* hard wired -- ignore */ break; case TPM_TIS_REG_INT_STATUS: - if (s->active_locty != locty) { - break; - } - /* clearing of interrupt flags */ if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { @@ -767,6 +778,15 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, } } +/* + * A wrapper write function so that it can be directly called without + * mmio. + */ +void tpm_tis_write_data(TPMState *s, hwaddr addr, uint64_t val, uint32_t size) +{ + tpm_tis_mmio_write(s, addr, val, size); +} + const MemoryRegionOps tpm_tis_memory_ops = { .read = tpm_tis_mmio_read, .write = tpm_tis_mmio_write, diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h index 559ba6906c..39f1300aa0 100644 --- a/include/hw/acpi/tpm.h +++ b/include/hw/acpi/tpm.h @@ -93,6 +93,7 @@ #define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) #define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) #define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) +#define TPM_TIS_CAP_BURST_COUNT_STATIC (1 << 8) #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ #define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \ (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ @@ -209,6 +210,36 @@ REG32(CRB_DATA_BUFFER, 0x80) #define TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ (4 << 0) #define TPM_PPI_FUNC_MASK (7 << 0) +/* TPM TIS I2C registers */ +#define TPM_I2C_REG_LOC_SEL 0x00 +#define TPM_I2C_REG_ACCESS 0x04 +#define TPM_I2C_REG_INT_ENABLE 0x08 +#define TPM_I2C_REG_INT_CAPABILITY 0x14 +#define TPM_I2C_REG_STS 0x18 +#define TPM_I2C_REG_DATA_FIFO 0x24 +#define TPM_I2C_REG_INTF_CAPABILITY 0x30 +#define TPM_I2C_REG_I2C_DEV_ADDRESS 0x38 +#define TPM_I2C_REG_DATA_CSUM_ENABLE 0x40 +#define TPM_I2C_REG_DATA_CSUM_GET 0x44 +#define TPM_I2C_REG_DID_VID 0x48 +#define TPM_I2C_REG_RID 0x4c +#define TPM_I2C_REG_UNKNOWN 0xff + +/* I2C specific interface capabilities */ +#define TPM_I2C_CAP_INTERFACE_TYPE (0x2 << 0) /* FIFO interface */ +#define TPM_I2C_CAP_INTERFACE_VER (0x0 << 4) /* TCG I2C intf 1.0 */ +#define TPM_I2C_CAP_TPM2_FAMILY (0x1 << 7) /* TPM 2.0 family. */ +#define TPM_I2C_CAP_DEV_ADDR_CHANGE (0x0 << 27) /* No dev addr chng */ +#define TPM_I2C_CAP_BURST_COUNT_STATIC (0x1 << 29) /* Burst count static */ +#define TPM_I2C_CAP_LOCALITY_CAP (0x1 << 25) /* 0-5 locality */ +#define TPM_I2C_CAP_BUS_SPEED (3 << 21) /* std and fast mode */ + +/* TPM_STS mask for read bits 31:26 must be zero */ +#define TPM_I2C_STS_READ_MASK 0x03ffffff + +/* Checksum enabled. */ +#define TPM_DATA_CSUM_ENABLED 0x1 + void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev); #endif /* CONFIG_TPM */