From: dan tan <dantan@linux.ibm.com>
To: undisclosed-recipients:;
Subject: Re: [PATCH v5 1/3] tpm/tpm_tis_spi: Support TPM for SPI (Serial Peripheral Interface)
Date: Mon, 04 Nov 2024 09:26:20 -0600 [thread overview]
Message-ID: <876abd2fae19ac99e8c385baa4889430@linux.ibm.com> (raw)
In-Reply-To: <1ffda8d1-06ba-4e8a-b62a-9b02f2844a6f@linux.ibm.com>
On 2024-11-04 09:14, Stefan Berger wrote:
> On 11/4/24 1:43 AM, dan tan wrote:
>> Implement support for TPM via SPI interface. The SPI bus master
>> is provided by PowerNV SPI device which is an SSI peripheral.
>> It can uses the tpm_emulator driver backend with the external
>> swtpm.
>>
>> Although the implementation is endian neutral, the SPI
>> bus master provider, pnv_spi.c is only supported on the
>> PowerNV platform, thus, is big endian specific.
>
> I am not sure whether and how this sentence is related to this
> implementation. I think you can remove it.
>
done.
>>
>> Signed-off-by: dan tan <dantan@linux.ibm.com>
>> ---
>>
>> v3:
>> - moved variable tis_addr from TPMStateSPI struct to local
>> - added the VM suspend/resume support:
>> - added vmstate_tpm_tis_spi declaration
>> - added tpm_tis_spi_pre_save() function
>> - fixed trace formatting string
>>
>> v4:
>> - git commit amend only
>>
>> v5:
>> - removed DEFINE_PROP_UINT32("irq", TPMStateSPI, tpm_state.irq_num, 0)
>> from tpm_tis_spi_properties
>> - In tpm.rst document, under section 'The QEMU TPM emulator device',
>> moved the 'PowerNV machine' section to immeidately below 'pSeriese
>> machine'.
>> ---
>> docs/specs/tpm.rst | 15 ++
>> include/sysemu/tpm.h | 3 +
>> hw/tpm/tpm_tis_spi.c | 359
>> +++++++++++++++++++++++++++++++++++++++++++
>> hw/tpm/Kconfig | 6 +
>> hw/tpm/meson.build | 1 +
>> hw/tpm/trace-events | 7 +
>> 6 files changed, 391 insertions(+)
>> create mode 100644 hw/tpm/tpm_tis_spi.c
>>
>> diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
>> index 1ad36ad709..d92e7eed6f 100644
>> --- a/docs/specs/tpm.rst
>> +++ b/docs/specs/tpm.rst
>> @@ -24,6 +24,7 @@ QEMU files related to TPM TIS interface:
>> - ``hw/tpm/tpm_tis_isa.c``
>> - ``hw/tpm/tpm_tis_sysbus.c``
>> - ``hw/tpm/tpm_tis_i2c.c``
>> + - ``hw/tpm/tpm_tis_spi.c``
>> - ``hw/tpm/tpm_tis.h``
>> Both an ISA device and a sysbus device are available. The former
>> is
>> @@ -33,6 +34,9 @@ Arm virt machine.
>> An I2C device support is also provided which can be instantiated in
>> the Arm
>> based emulation machines. This device only supports the TPM 2
>> protocol.
>> +A Serial Peripheral Interface (SPI) device support has been added
>> to the
>> +PowerNV emulation machines. This device only supports the TPM 2
>> protocol.
>> +
>> CRB interface
>> -------------
>> @@ -339,6 +343,17 @@ In case a pSeries machine is emulated, use the
>> following command line:
>> -device
>> virtio-blk-pci,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0
>> \
>> -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
>> +In case a PowerNV machine is emulated and you want to use a TPM
>> device
>> +attached to SPI bus, use the following command line (SPI bus master
>> is
>> +provided by PowerNV SPI device):
>> +
>> +.. code-block:: console
>> +
>> + qemu-system-ppc64 -m 2G -machine powernv10 -nographic \
>> + -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
>> + -tpmdev emulator,id=tpm0,chardev=chrtpm \
>> + -device tpm-tis-spi,tpmdev=tpm0,bus=pnv-spi-bus.4
>> +
>> In case an Arm virt machine is emulated, use the following command
>> line:
>> .. code-block:: console
>> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
>> index 1ee568b3b6..22b05110e2 100644
>> --- a/include/sysemu/tpm.h
>> +++ b/include/sysemu/tpm.h
>> @@ -49,6 +49,7 @@ struct TPMIfClass {
>> #define TYPE_TPM_CRB "tpm-crb"
>> #define TYPE_TPM_SPAPR "tpm-spapr"
>> #define TYPE_TPM_TIS_I2C "tpm-tis-i2c"
>> +#define TYPE_TPM_TIS_SPI "tpm-tis-spi"
>> #define TPM_IS_TIS_ISA(chr) \
>> object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_ISA)
>> @@ -60,6 +61,8 @@ struct TPMIfClass {
>> object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
>> #define TPM_IS_TIS_I2C(chr) \
>> object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_I2C)
>> +#define TPM_IS_TIS_SPI(chr) \
>> + object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SPI)
>> /* returns NULL unless there is exactly one TPM device */
>> static inline TPMIf *tpm_find(void)
>> diff --git a/hw/tpm/tpm_tis_spi.c b/hw/tpm/tpm_tis_spi.c
>> new file mode 100644
>> index 0000000000..87acbaaaf8
>> --- /dev/null
>> +++ b/hw/tpm/tpm_tis_spi.c
>> @@ -0,0 +1,359 @@
>> +/*
>> + * QEMU PowerPC SPI TPM 2.0 model
>
> I would say that this implementation is generic enough to work with
> other architectures as well. So you could drop 'PowerPC'.
>
OK
>> + *
>> + * Copyright (c) 2024, IBM Corporation.
>> + *
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + */
>> +
>> +#define IBM_PONQ
>
> Did I miss this before? Is this necessary and what does it do?
>
Sorry, it was added when I tried to do Linux boot test.
Removed
>> +
>> +#include "qemu/osdep.h"
>> +#include "qemu/log.h"
>> +#include "hw/sysbus.h"
>> +#include "hw/acpi/tpm.h"
>> +#include "tpm_prop.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +#include "tpm_tis.h"
>> +#include "hw/ssi/ssi.h"
>> +#include "migration/vmstate.h"
>> +
>> +typedef struct TPMStateSPI {
>> + /*< private >*/
>> + SSIPeripheral parent_object;
>> +
>> + uint8_t byte_offset; /* byte offset in transfer */
>> + uint8_t wait_state_cnt; /* wait state counter */
>> + uint8_t xfer_size; /* data size of transfer */
>> + uint32_t reg_addr; /* register address of transfer */
>> +
>> + uint8_t spi_state; /* READ / WRITE / IDLE */
>> +#define SPI_STATE_IDLE 0
>> +#define SPI_STATE_WRITE 1
>> +#define SPI_STATE_READ 2
>> +
>> + bool command;
>> +
>> + /*< public >*/
>> + TPMState tpm_state; /* not a QOM object */
>> +
>> +} TPMStateSPI;
>> +
>> +#define CMD_BYTE_WRITE (1 << 7)
>> +#define CMD_BYTE_XFER_SZ_MASK 0x1f
>> +#define TIS_SPI_HIGH_ADDR_BYTE 0xd4
>> +
>> +DECLARE_INSTANCE_CHECKER(TPMStateSPI, TPM_TIS_SPI, TYPE_TPM_TIS_SPI)
>> +
>> +static int tpm_tis_spi_pre_save(void *opaque)
>> +{
>> + TPMStateSPI *spist = opaque;
>> +
>> + return tpm_tis_pre_save(&spist->tpm_state);
>> +}
>> +
>> +static const VMStateDescription vmstate_tpm_tis_spi = {
>> + .name = "tpm-tis-spi",
>> + .version_id = 0,
>> + .pre_save = tpm_tis_spi_pre_save,
>> + .fields = (const VMStateField[]) {
>> + VMSTATE_BUFFER(tpm_state.buffer, TPMStateSPI),
>> + VMSTATE_UINT16(tpm_state.rw_offset, TPMStateSPI),
>> + VMSTATE_UINT8(tpm_state.active_locty, TPMStateSPI),
>> + VMSTATE_UINT8(tpm_state.aborting_locty, TPMStateSPI),
>> + VMSTATE_UINT8(tpm_state.next_locty, TPMStateSPI),
>> +
>> + VMSTATE_STRUCT_ARRAY(tpm_state.loc, TPMStateSPI,
>> + TPM_TIS_NUM_LOCALITIES, 0,
>> + vmstate_locty, TPMLocality),
>> +
>> + /* spi specifics */
>> + VMSTATE_UINT8(byte_offset, TPMStateSPI),
>> + VMSTATE_UINT8(wait_state_cnt, TPMStateSPI),
>> + VMSTATE_UINT8(xfer_size, TPMStateSPI),
>> + VMSTATE_UINT32(reg_addr, TPMStateSPI),
>> + VMSTATE_UINT8(spi_state, TPMStateSPI),
>> + VMSTATE_BOOL(command, TPMStateSPI),
>> +
>> + VMSTATE_END_OF_LIST()
>> + }
>> +};
>> +
>> +static inline void tpm_tis_spi_clear_data(TPMStateSPI *spist)
>> +{
>> + spist->spi_state = SPI_STATE_IDLE;
>> + spist->byte_offset = 0;
>> + spist->wait_state_cnt = 0;
>> + spist->xfer_size = 0;
>> + spist->reg_addr = 0;
>> +
>> + return;
>> +}
>> +
>> +/* Callback from TPM to indicate that response is copied */
>> +static void tpm_tis_spi_request_completed(TPMIf *ti, int ret)
>> +{
>> + TPMStateSPI *spist = TPM_TIS_SPI(ti);
>> + TPMState *s = &spist->tpm_state;
>> +
>> + /* Inform the common code. */
>> + tpm_tis_request_completed(s, ret);
>> +}
>> +
>> +static enum TPMVersion tpm_tis_spi_get_tpm_version(TPMIf *ti)
>> +{
>> + TPMStateSPI *spist = TPM_TIS_SPI(ti);
>> + TPMState *s = &spist->tpm_state;
>> +
>> + return tpm_tis_get_tpm_version(s);
>> +}
>> +
>> +/*
>> + * TCG PC Client Platform TPM Profile Specification for TPM 2.0 ver
>> 1.05 rev 14
>> + *
>> + * For system Software, the TPM has a 64-bit address of
>> 0x0000_0000_FED4_xxxx.
>> + * On SPI, the chipset passes the least significant 24 bits to the
>> TPM.
>> + * The upper bytes will be used by the chipset to select the TPM’s
>> SPI CS#
>> + * signal. Table 9 shows the locality based on the 16 least
>> significant address
>> + * bits and assume that either the LPC TPM sync or SPI TPM CS# is
>> used.
>> + *
>> + */
>> +static void tpm_tis_spi_write(TPMStateSPI *spist, uint32_t addr,
>> uint8_t val)
>> +{
>> + TPMState *tpm_st = &spist->tpm_state;
>> +
>> + trace_tpm_tis_spi_write(addr, val);
>> + tpm_tis_write_data(tpm_st, addr, val, 1);
>> +}
>> +
>> +static uint8_t tpm_tis_spi_read(TPMStateSPI *spist, uint32_t addr)
>> +{
>> + TPMState *tpm_st = &spist->tpm_state;
>> + uint8_t data;
>> +
>> + data = tpm_tis_read_data(tpm_st, addr, 1);
>> + trace_tpm_tis_spi_read(addr, data);
>> + return data;
>> +}
>> +
>> +static Property tpm_tis_spi_properties[] = {
>> + DEFINE_PROP_TPMBE("tpmdev", TPMStateSPI, tpm_state.be_driver),
>> + DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void tpm_tis_spi_reset(DeviceState *dev)
>> +{
>> + TPMStateSPI *spist = TPM_TIS_SPI(dev);
>> + TPMState *s = &spist->tpm_state;
>> +
>> + tpm_tis_spi_clear_data(spist);
>> + return tpm_tis_reset(s);
>> +}
>> +
>> +static uint32_t tpm_transfer(SSIPeripheral *ss, uint32_t tx)
>
> rename to tpm_tis_spi_transfer
>
All function names are corrected to comply with the convention.
>> +{
>> + TPMStateSPI *spist = TPM_TIS_SPI(ss);
>> + uint32_t rx = 0;
>> + uint8_t byte; /* reversed byte value */
>> + uint8_t offset = 0; /* offset of byte in payload */
>> + uint8_t index; /* index of data byte in transfer */
>> + uint32_t tis_addr; /* tis address including locty */
>> +
>> + /* new transfer or not */
>> + if (spist->command) { /* new transfer start */
>> + if (spist->spi_state != SPI_STATE_IDLE) {
>> + qemu_log_mask(LOG_GUEST_ERROR, "unexpected new
>> transfer\n");
>> + }
>> + spist->byte_offset = 0;
>> + spist->wait_state_cnt = 0;
>> + }
>> + /*
>> + * Explanation of wait_state:
>> + * The original TPM model did not have wait state or "flow
>> control" support
>> + * built in. If you wanted to read a TPM register through SPI
>> you sent
>> + * the first byte with the read/write bit and size, then three
>> address bytes
>> + * and any additional bytes after that were don't care bytes for
>> reads and
>> + * the model would begin returning byte data to the SPI reader
>> from the
>> + * register address provided. In the real world this would mean
>> that a
>> + * TPM device had only the time between the 31st clock and the
>> 32nd clock
>> + * to fetch the register data that it had to provide to SPI MISO
>> starting
>> + * with the 32nd clock.
>> + *
>> + * In reality the TPM begins introducing a wait state at the 31st
>> clock
>> + * by holding MISO low. This is how it controls the "flow" of
>> the
>> + * operation. Once the data the TPM needs to return is ready it
>> will
>> + * select bit 31 + (8*N) to send back a 1 which indicates that it
>> will
>> + * now start returning data on MISO.
>> + *
>> + * The same wait states are applied to writes. In either the
>> read or write
>> + * case the wait state occurs between the command+address (4
>> bytes) and the
>> + * data (1-n bytes) sections of the SPI frame. The code below
>> introduces
>> + * the support for a 32 bit wait state for P10. All reads and
>> writes
>> + * through the SPI interface MUST now be aware of the need to do
>> flow
>> + * control in order to use the TPM via SPI.
>> + *
>> + * In conjunction with these changes there were changes made to
>> the SPIM
>> + * engine that was introduced in P10 to support the 6x op code
>> which is
>> + * used to receive wait state 0s on the MISO line until it sees
>> the b'1'
>> + * come back before continuing to read real data from the SPI
>> device(TPM).
>> + */
>> +
>> + trace_tpm_tis_spi_transfer_data("Payload byte_offset",
>> spist->byte_offset);
>> + /* process payload data */
>> + while (offset < 4) {
>> + spist->command = false;
>> + byte = (tx >> (24 - 8 * offset)) & 0xFF;
>> + trace_tpm_tis_spi_transfer_data("Extracted byte", byte);
>> + trace_tpm_tis_spi_transfer_data("Payload offset", offset);
>> + switch (spist->byte_offset) {
>> + case 0: /* command byte */
>> + if ((byte & CMD_BYTE_WRITE) == 0) { /* bit-7 */
>> + spist->spi_state = SPI_STATE_WRITE;
>> + trace_tpm_tis_spi_transfer_event("spi write");
>> + } else {
>> + spist->spi_state = SPI_STATE_READ;
>> + trace_tpm_tis_spi_transfer_event("spi read");
>> + }
>> + spist->xfer_size = (byte & CMD_BYTE_XFER_SZ_MASK) + 1;
>> + trace_tpm_tis_spi_transfer_data("xfer_size",
>> spist->xfer_size);
>> + break;
>> + case 1: /* 1st address byte */
>> + if (byte != TIS_SPI_HIGH_ADDR_BYTE) {
>> + qemu_log_mask(LOG_GUEST_ERROR, "incorrect high
>> address 0x%x\n",
>> + byte);
>> + }
>> + spist->reg_addr = byte << 16;
>> + trace_tpm_tis_spi_transfer_data("first addr byte", byte);
>> + trace_tpm_tis_spi_transfer_addr("reg_addr",
>> spist->reg_addr);
>> + break;
>> + case 2: /* 2nd address byte */
>> + spist->reg_addr |= byte << 8;
>> + trace_tpm_tis_spi_transfer_data("second addr byte",
>> byte);
>> + trace_tpm_tis_spi_transfer_addr("reg_addr",
>> spist->reg_addr);
>> + break;
>> + case 3: /* 3rd address byte */
>> + spist->reg_addr |= byte;
>> + trace_tpm_tis_spi_transfer_data("third addr byte", byte);
>> + trace_tpm_tis_spi_transfer_addr("reg_addr",
>> spist->reg_addr);
>> + break;
>> + default: /* data bytes */
>> + if (spist->wait_state_cnt < 4) {
>> + spist->wait_state_cnt++;
>> + if (spist->wait_state_cnt == 4) {
>> + trace_tpm_tis_spi_transfer_data("wait complete,
>> count",
>> +
>> spist->wait_state_cnt);
>> + rx = rx | (0x01 << (24 - offset * 8));
>> + return rx;
>> + } else {
>> + trace_tpm_tis_spi_transfer_data("in wait state,
>> count",
>> +
>> spist->wait_state_cnt);
>> + rx = 0;
>> + }
>> + } else {
>> + index = spist->byte_offset - 4;
>> + trace_tpm_tis_spi_transfer_data("index", index);
>> + trace_tpm_tis_spi_transfer_data("data byte", byte);
>> + trace_tpm_tis_spi_transfer_addr("reg_addr",
>> spist->reg_addr);
>> + if (index >= spist->xfer_size) {
>> + /*
>> + * SPI SSI framework limits both rx and tx
>> + * to fixed 4-byte with each xfer
>> + */
>> + trace_tpm_tis_spi_transfer_event("index exceeds
>> xfer_size");
>> + return rx;
>> + }
>> + tis_addr = spist->reg_addr + (index % 4);
>> + if (spist->spi_state == SPI_STATE_WRITE) {
>> + tpm_tis_spi_write(spist, tis_addr, byte);
>> + } else {
>> + byte = tpm_tis_spi_read(spist, tis_addr);
>> + rx = rx | (byte << (24 - offset * 8));
>> + trace_tpm_tis_spi_transfer_data("byte added to
>> response",
>> + byte);
>> + trace_tpm_tis_spi_transfer_data("offset",
>> offset);
>> + }
>> + }
>> + break;
>> + }
>> + if ((spist->wait_state_cnt == 0) || (spist->wait_state_cnt ==
>> 4)) {
>> + offset++;
>> + spist->byte_offset++;
>> + } else {
>> + break;
>> + }
>> + }
>> + return rx;
>> +}
>> +
>> +static int tpm_cs(SSIPeripheral *ss, bool select)
>
> tpm_tis_spi_cs
>
>> +{
>> + TPMStateSPI *spist = TPM_TIS_SPI(ss);
>> +
>> + if (select) {
>> + spist->command = false;
>> + spist->spi_state = SPI_STATE_IDLE;
>> + } else {
>> + spist->command = true;
>> + }
>> + return 0;
>> +}
>> +
>> +static void tpm_realize(SSIPeripheral *dev, Error **errp)
>
> tpm_tis_spi_realize
>
>> +{
>> + TPMStateSPI *spist = TPM_TIS_SPI(dev);
>> + TPMState *s = &spist->tpm_state;
>> +
>> + if (!tpm_find()) {
>> + error_setg(errp, "at most one TPM device is permitted");
>> + return;
>> + }
>> +
>> + s->be_driver = qemu_find_tpm_be("tpm0");
>> +
>> + if (!s->be_driver) {
>> + error_setg(errp, "unable to find tpm backend device");
>> + return;
>> + }
>> +}
>> +
>> +static void tpm_tis_spi_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + TPMIfClass *tc = TPM_IF_CLASS(klass);
>> + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
>> +
>> + k->transfer = tpm_transfer;
>> + k->realize = tpm_realize;
>> + k->set_cs = tpm_cs;
>> + k->cs_polarity = SSI_CS_LOW;
>> +
>> + device_class_set_legacy_reset(dc, tpm_tis_spi_reset);
>> + device_class_set_props(dc, tpm_tis_spi_properties);
>> + set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>> +
>> + dc->desc = "SPI TPM";
>> + dc->vmsd = &vmstate_tpm_tis_spi;
>> +
>> + tc->model = TPM_MODEL_TPM_TIS;
>> + tc->request_completed = tpm_tis_spi_request_completed;
>> + tc->get_version = tpm_tis_spi_get_tpm_version;
>> +}
>> +
>> +static const TypeInfo tpm_tis_spi_info = {
>> + .name = TYPE_TPM_TIS_SPI,
>> + .parent = TYPE_SSI_PERIPHERAL,
>> + .instance_size = sizeof(TPMStateSPI),
>> + .class_init = tpm_tis_spi_class_init,
>> + .interfaces = (InterfaceInfo[]) {
>> + { TYPE_TPM_IF },
>> + { }
>> + }
>> +};
>> +
>> +static void tpm_tis_spi_register_types(void)
>> +{
>> + type_register_static(&tpm_tis_spi_info);
>> +}
>> +
>> +type_init(tpm_tis_spi_register_types)
>> diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
>> index a46663288c..5951c225cc 100644
>> --- a/hw/tpm/Kconfig
>> +++ b/hw/tpm/Kconfig
>> @@ -5,6 +5,12 @@ config TPM_TIS_I2C
>> select I2C
>> select TPM_TIS
>> +config TPM_TIS_SPI
>> + bool
>> + depends on TPM
>> + select TPM_BACKEND
>> + select TPM_TIS
>> +
>> config TPM_TIS_ISA
>> bool
>> depends on TPM && ISA_BUS
>> diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
>> index 6968e60b3f..e03cfb11b9 100644
>> --- a/hw/tpm/meson.build
>> +++ b/hw/tpm/meson.build
>> @@ -2,6 +2,7 @@ system_ss.add(when: 'CONFIG_TPM_TIS', if_true:
>> files('tpm_tis_common.c'))
>> system_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true:
>> files('tpm_tis_isa.c'))
>> system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true:
>> files('tpm_tis_sysbus.c'))
>> system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true:
>> files('tpm_tis_i2c.c'))
>> +system_ss.add(when: 'CONFIG_TPM_TIS_SPI', if_true:
>> files('tpm_tis_spi.c'))
>> system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
>> system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
>> system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
>> diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
>> index fa882dfefe..0324ceb6d0 100644
>> --- a/hw/tpm/trace-events
>> +++ b/hw/tpm/trace-events
>> @@ -42,3 +42,10 @@ tpm_tis_i2c_recv(uint8_t data) "TPM I2C read: 0x%X"
>> tpm_tis_i2c_send(uint8_t data) "TPM I2C write: 0x%X"
>> tpm_tis_i2c_event(const char *event) "TPM I2C event: %s"
>> tpm_tis_i2c_send_reg(const char *name, int reg) "TPM I2C write
>> register: %s(0x%X)"
>> +
>> +# tpm_tis_spi.c
>> +tpm_tis_spi_write(uint32_t addr, uint8_t val) "TPM SPI write -
>> addr:0x%08X 0x%02x"
>> +tpm_tis_spi_read(uint32_t addr, uint8_t val) "TPM SPI read -
>> addr:0x%08X 0x%02x"
>> +tpm_tis_spi_transfer_event(const char *event) "TPM SPI XFER event:
>> %s"
>> +tpm_tis_spi_transfer_data(const char *name, uint8_t val) "TPM SPI
>> XFER: %s = 0x%02x"
>> +tpm_tis_spi_transfer_addr(const char *name, uint32_t addr) "TPM SPI
>> XFER: %s = 0x%08x"
next prev parent reply other threads:[~2024-11-04 15:26 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-04 6:43 [PATCH v5 0/3] TPM TIS SPI Support dan tan
2024-11-04 6:43 ` [PATCH v5 1/3] tpm/tpm_tis_spi: Support TPM for SPI (Serial Peripheral Interface) dan tan
2024-11-04 15:14 ` Stefan Berger
2024-11-04 15:26 ` dan tan [this message]
2024-11-04 6:43 ` [PATCH v5 2/3] tpm/tpm_tis_spi: activation for the PowerNV machines dan tan
2024-11-04 6:43 ` [PATCH v5 3/3] tests/qtest/tpm: add unit test to tis-spi dan tan
2024-11-04 15:20 ` Stefan Berger
2024-11-04 15:30 ` dan tan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=876abd2fae19ac99e8c385baa4889430@linux.ibm.com \
--to=dantan@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).