mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 17:08:10 +00:00
797c0113c9
Add TPM2.0 PTP FIFO compatible SPI interface for chips with Cr50 firmware. The firmware running on the currently supported H1 Secure Microcontroller requires a special driver to handle its specifics: - need to ensure a certain delay between SPI transactions, or else the chip may miss some part of the next transaction - if there is no SPI activity for some time, it may go to sleep, and needs to be waken up before sending further commands - access to vendor-specific registers Cr50 firmware has a requirement to wait for the TPM to wakeup before sending commands over the SPI bus. Otherwise, the firmware could be in deep sleep and not respond. The method to wait for the device to wakeup is slightly different than the usual flow control mechanism described in the TCG SPI spec. Add a completion to tpm_tis_spi_transfer() before we start a SPI transfer so we can keep track of the last time the TPM driver accessed the SPI bus to support the flow control mechanism. Split the cr50 logic off into a different file to keep it out of the normal code flow of the existing SPI driver while making it all part of the same module when the code is optionally compiled into the same module. Export a new function, tpm_tis_spi_init(), and the associated read/write/transfer APIs so that we can do this. Make the cr50 code wrap the tpm_tis_spi_phy struct with its own struct to override the behavior of tpm_tis_spi_transfer() by supplying a custom flow control hook. This shares the most code between the core driver and the cr50 support without combining everything into the core driver or exporting module symbols. Signed-off-by: Andrey Pronin <apronin@chromium.org> Cc: Andrey Pronin <apronin@chromium.org> Cc: Duncan Laurie <dlaurie@chromium.org> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Guenter Roeck <groeck@chromium.org> Cc: Alexander Steffen <Alexander.Steffen@infineon.com> Cc: Heiko Stuebner <heiko@sntech.de> [swboyd@chromium.org: Replace boilerplate with SPDX tag, drop suspended bit and remove ifdef checks in cr50.h, migrate to functions exported in tpm_tis_spi.h, combine into one module instead of two] Signed-off-by: Stephen Boyd <swboyd@chromium.org> Tested-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
53 lines
1.4 KiB
C
53 lines
1.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2015 Infineon Technologies AG
|
|
* Copyright (C) 2016 STMicroelectronics SAS
|
|
*/
|
|
|
|
#ifndef TPM_TIS_SPI_H
|
|
#define TPM_TIS_SPI_H
|
|
|
|
#include "tpm_tis_core.h"
|
|
|
|
struct tpm_tis_spi_phy {
|
|
struct tpm_tis_data priv;
|
|
struct spi_device *spi_device;
|
|
int (*flow_control)(struct tpm_tis_spi_phy *phy,
|
|
struct spi_transfer *xfer);
|
|
struct completion ready;
|
|
unsigned long wake_after;
|
|
|
|
u8 *iobuf;
|
|
};
|
|
|
|
static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
|
|
{
|
|
return container_of(data, struct tpm_tis_spi_phy, priv);
|
|
}
|
|
|
|
extern int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy,
|
|
int irq, const struct tpm_tis_phy_ops *phy_ops);
|
|
|
|
extern int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
|
|
u8 *in, const u8 *out);
|
|
|
|
extern int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result);
|
|
extern int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result);
|
|
extern int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value);
|
|
|
|
#ifdef CONFIG_TCG_TIS_SPI_CR50
|
|
extern int cr50_spi_probe(struct spi_device *spi);
|
|
#else
|
|
static inline int cr50_spi_probe(struct spi_device *spi)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_TCG_TIS_SPI_CR50)
|
|
extern int tpm_tis_spi_resume(struct device *dev);
|
|
#else
|
|
#define tpm_tis_spi_resume NULL
|
|
#endif
|
|
|
|
#endif
|