Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Tegra TPM driver with HW flow control

Merge series from Krishna Yarlagadda <kyarlagadda@nvidia.com>:

TPM devices may insert wait state on last clock cycle of ADDR phase.
For SPI controllers that support full-duplex transfers, this can be
detected using software by reading the MISO line. For SPI controllers
that only support half-duplex transfers, such as the Tegra QSPI, it is
not possible to detect the wait signal from software. The QSPI
controller in Tegra234 and Tegra241 implement hardware detection of the
wait signal which can be enabled in the controller for TPM devices.

Add a flag for this in the SPI core and implement support in the Tegra
QuadSPI driver.

+27 -3
+14
drivers/spi/spi-tegra210-quad.c
··· 142 142 143 143 #define QSPI_GLOBAL_CONFIG 0X1a4 144 144 #define QSPI_CMB_SEQ_EN BIT(0) 145 + #define QSPI_TPM_WAIT_POLL_EN BIT(1) 145 146 146 147 #define QSPI_CMB_SEQ_ADDR 0x1a8 147 148 #define QSPI_ADDRESS_VALUE_SET(X) (((x) & 0xFFFF) << 0) ··· 165 164 struct tegra_qspi_soc_data { 166 165 bool has_dma; 167 166 bool cmb_xfer_capable; 167 + bool supports_tpm; 168 168 unsigned int cs_count; 169 169 }; 170 170 ··· 1067 1065 1068 1066 /* Enable Combined sequence mode */ 1069 1067 val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); 1068 + if (spi->mode & SPI_TPM_HW_FLOW) { 1069 + if (tqspi->soc_data->supports_tpm) 1070 + val |= QSPI_TPM_WAIT_POLL_EN; 1071 + else 1072 + return -EIO; 1073 + } 1070 1074 val |= QSPI_CMB_SEQ_EN; 1071 1075 tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG); 1072 1076 /* Process individual transfer list */ ··· 1204 1196 /* Disable Combined sequence mode */ 1205 1197 val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); 1206 1198 val &= ~QSPI_CMB_SEQ_EN; 1199 + if (tqspi->soc_data->supports_tpm) 1200 + val &= ~QSPI_TPM_WAIT_POLL_EN; 1207 1201 tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG); 1208 1202 list_for_each_entry(transfer, &msg->transfers, transfer_list) { 1209 1203 struct spi_transfer *xfer = transfer; ··· 1464 1454 static struct tegra_qspi_soc_data tegra210_qspi_soc_data = { 1465 1455 .has_dma = true, 1466 1456 .cmb_xfer_capable = false, 1457 + .supports_tpm = false, 1467 1458 .cs_count = 1, 1468 1459 }; 1469 1460 1470 1461 static struct tegra_qspi_soc_data tegra186_qspi_soc_data = { 1471 1462 .has_dma = true, 1472 1463 .cmb_xfer_capable = true, 1464 + .supports_tpm = false, 1473 1465 .cs_count = 1, 1474 1466 }; 1475 1467 1476 1468 static struct tegra_qspi_soc_data tegra234_qspi_soc_data = { 1477 1469 .has_dma = false, 1478 1470 .cmb_xfer_capable = true, 1471 + .supports_tpm = true, 1479 1472 .cs_count = 1, 1480 1473 }; 1481 1474 1482 1475 static struct tegra_qspi_soc_data tegra241_qspi_soc_data = { 1483 1476 .has_dma = false, 1484 1477 .cmb_xfer_capable = true, 1478 + .supports_tpm = true, 1485 1479 .cs_count = 4, 1486 1480 }; 1487 1481
+13 -3
include/linux/spi/spi.h
··· 184 184 u8 chip_select; 185 185 u8 bits_per_word; 186 186 bool rt; 187 - #define SPI_NO_TX BIT(31) /* No transmit wire */ 188 - #define SPI_NO_RX BIT(30) /* No receive wire */ 187 + #define SPI_NO_TX BIT(31) /* No transmit wire */ 188 + #define SPI_NO_RX BIT(30) /* No receive wire */ 189 + /* 190 + * TPM specification defines flow control over SPI. Client device 191 + * can insert a wait state on MISO when address is transmitted by 192 + * controller on MOSI. Detecting the wait state in software is only 193 + * possible for full duplex controllers. For controllers that support 194 + * only half-duplex, the wait state detection needs to be implemented 195 + * in hardware. TPM devices would set this flag when hardware flow 196 + * control is expected from SPI controller. 197 + */ 198 + #define SPI_TPM_HW_FLOW BIT(29) /* TPM HW flow control */ 189 199 /* 190 200 * All bits defined above should be covered by SPI_MODE_KERNEL_MASK. 191 201 * The SPI_MODE_KERNEL_MASK has the SPI_MODE_USER_MASK counterpart, ··· 205 195 * These bits must not overlap. A static assert check should make sure of that. 206 196 * If adding extra bits, make sure to decrease the bit index below as well. 207 197 */ 208 - #define SPI_MODE_KERNEL_MASK (~(BIT(30) - 1)) 198 + #define SPI_MODE_KERNEL_MASK (~(BIT(29) - 1)) 209 199 u32 mode; 210 200 int irq; 211 201 void *controller_state;