Commit 32a6b619 authored by Peter Huewe's avatar Peter Huewe Committed by Greg Kroah-Hartman

tpm_tis_spi: Remove limitation of transfers to MAX_SPI_FRAMESIZE bytes

commit 591e48c2 upstream.

Limiting transfers to MAX_SPI_FRAMESIZE was not expected by the upper
layers, as tpm_tis has no such limitation. Add a loop to hide that
limitation.

v2: Moved scope of spi_message to the top as requested by Jarkko
Fixes: 0edbfea5 ("tpm/tpm_tis_spi: Add support for spi phy")
Signed-off-by: default avatarAlexander Steffen <Alexander.Steffen@infineon.com>
Signed-off-by: default avatarPeter Huewe <peter.huewe@infineon.com>
Reviewed-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarBenoit Houyere <benoit.houyere@st.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e2fbfd47
...@@ -60,67 +60,76 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, ...@@ -60,67 +60,76 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
u8 *buffer, u8 direction) u8 *buffer, u8 direction)
{ {
struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
int ret, i; int ret = 0;
int i;
struct spi_message m; struct spi_message m;
struct spi_transfer spi_xfer = { struct spi_transfer spi_xfer;
.tx_buf = phy->tx_buf, u8 transfer_len;
.rx_buf = phy->rx_buf,
.len = 4,
.cs_change = 1,
};
if (len > MAX_SPI_FRAMESIZE)
return -ENOMEM;
phy->tx_buf[0] = direction | (len - 1); spi_bus_lock(phy->spi_device->master);
phy->tx_buf[1] = 0xd4;
phy->tx_buf[2] = addr >> 8;
phy->tx_buf[3] = addr;
spi_message_init(&m); while (len) {
spi_message_add_tail(&spi_xfer, &m); transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
spi_bus_lock(phy->spi_device->master); phy->tx_buf[0] = direction | (transfer_len - 1);
ret = spi_sync_locked(phy->spi_device, &m); phy->tx_buf[1] = 0xd4;
if (ret < 0) phy->tx_buf[2] = addr >> 8;
goto exit; phy->tx_buf[3] = addr;
if ((phy->rx_buf[3] & 0x01) == 0) { memset(&spi_xfer, 0, sizeof(spi_xfer));
// handle SPI wait states spi_xfer.tx_buf = phy->tx_buf;
phy->tx_buf[0] = 0; spi_xfer.rx_buf = phy->rx_buf;
spi_xfer.len = 4;
for (i = 0; i < TPM_RETRY; i++) { spi_xfer.cs_change = 1;
spi_xfer.len = 1;
spi_message_init(&m); spi_message_init(&m);
spi_message_add_tail(&spi_xfer, &m); spi_message_add_tail(&spi_xfer, &m);
ret = spi_sync_locked(phy->spi_device, &m); ret = spi_sync_locked(phy->spi_device, &m);
if (ret < 0) if (ret < 0)
goto exit;
if ((phy->rx_buf[3] & 0x01) == 0) {
// handle SPI wait states
phy->tx_buf[0] = 0;
for (i = 0; i < TPM_RETRY; i++) {
spi_xfer.len = 1;
spi_message_init(&m);
spi_message_add_tail(&spi_xfer, &m);
ret = spi_sync_locked(phy->spi_device, &m);
if (ret < 0)
goto exit;
if (phy->rx_buf[0] & 0x01)
break;
}
if (i == TPM_RETRY) {
ret = -ETIMEDOUT;
goto exit; goto exit;
if (phy->rx_buf[0] & 0x01) }
break;
} }
if (i == TPM_RETRY) { spi_xfer.cs_change = 0;
ret = -ETIMEDOUT; spi_xfer.len = transfer_len;
goto exit;
if (direction) {
spi_xfer.tx_buf = NULL;
spi_xfer.rx_buf = buffer;
} else {
spi_xfer.tx_buf = buffer;
spi_xfer.rx_buf = NULL;
} }
}
spi_xfer.cs_change = 0; spi_message_init(&m);
spi_xfer.len = len; spi_message_add_tail(&spi_xfer, &m);
ret = spi_sync_locked(phy->spi_device, &m);
if (ret < 0)
goto exit;
if (direction) { len -= transfer_len;
spi_xfer.tx_buf = NULL; buffer += transfer_len;
spi_xfer.rx_buf = buffer;
} else {
spi_xfer.tx_buf = buffer;
spi_xfer.rx_buf = NULL;
} }
spi_message_init(&m);
spi_message_add_tail(&spi_xfer, &m);
ret = spi_sync_locked(phy->spi_device, &m);
exit: exit:
spi_bus_unlock(phy->spi_device->master); spi_bus_unlock(phy->spi_device->master);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment