Skip to content

Commit d9f3a60

Browse files
committed
Tegra TPM driver with HW flow control
Merge series from Krishna Yarlagadda <[email protected]>: 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.
2 parents 25f0617 + 967ca91 commit d9f3a60

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

drivers/spi/spi-tegra210-quad.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@
142142

143143
#define QSPI_GLOBAL_CONFIG 0X1a4
144144
#define QSPI_CMB_SEQ_EN BIT(0)
145+
#define QSPI_TPM_WAIT_POLL_EN BIT(1)
145146

146147
#define QSPI_CMB_SEQ_ADDR 0x1a8
147148
#define QSPI_ADDRESS_VALUE_SET(X) (((x) & 0xFFFF) << 0)
@@ -164,6 +165,7 @@
164165
struct tegra_qspi_soc_data {
165166
bool has_dma;
166167
bool cmb_xfer_capable;
168+
bool supports_tpm;
167169
unsigned int cs_count;
168170
};
169171

@@ -1065,6 +1067,12 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
10651067

10661068
/* Enable Combined sequence mode */
10671069
val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG);
1070+
if (spi->mode & SPI_TPM_HW_FLOW) {
1071+
if (tqspi->soc_data->supports_tpm)
1072+
val |= QSPI_TPM_WAIT_POLL_EN;
1073+
else
1074+
return -EIO;
1075+
}
10681076
val |= QSPI_CMB_SEQ_EN;
10691077
tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG);
10701078
/* Process individual transfer list */
@@ -1196,6 +1204,8 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi,
11961204
/* Disable Combined sequence mode */
11971205
val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG);
11981206
val &= ~QSPI_CMB_SEQ_EN;
1207+
if (tqspi->soc_data->supports_tpm)
1208+
val &= ~QSPI_TPM_WAIT_POLL_EN;
11991209
tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG);
12001210
list_for_each_entry(transfer, &msg->transfers, transfer_list) {
12011211
struct spi_transfer *xfer = transfer;
@@ -1454,24 +1464,28 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data)
14541464
static struct tegra_qspi_soc_data tegra210_qspi_soc_data = {
14551465
.has_dma = true,
14561466
.cmb_xfer_capable = false,
1467+
.supports_tpm = false,
14571468
.cs_count = 1,
14581469
};
14591470

14601471
static struct tegra_qspi_soc_data tegra186_qspi_soc_data = {
14611472
.has_dma = true,
14621473
.cmb_xfer_capable = true,
1474+
.supports_tpm = false,
14631475
.cs_count = 1,
14641476
};
14651477

14661478
static struct tegra_qspi_soc_data tegra234_qspi_soc_data = {
14671479
.has_dma = false,
14681480
.cmb_xfer_capable = true,
1481+
.supports_tpm = true,
14691482
.cs_count = 1,
14701483
};
14711484

14721485
static struct tegra_qspi_soc_data tegra241_qspi_soc_data = {
14731486
.has_dma = false,
14741487
.cmb_xfer_capable = true,
1488+
.supports_tpm = true,
14751489
.cs_count = 4,
14761490
};
14771491

include/linux/spi/spi.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,18 @@ struct spi_device {
184184
u8 chip_select;
185185
u8 bits_per_word;
186186
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 */
189199
/*
190200
* All bits defined above should be covered by SPI_MODE_KERNEL_MASK.
191201
* The SPI_MODE_KERNEL_MASK has the SPI_MODE_USER_MASK counterpart,
@@ -195,7 +205,7 @@ struct spi_device {
195205
* These bits must not overlap. A static assert check should make sure of that.
196206
* If adding extra bits, make sure to decrease the bit index below as well.
197207
*/
198-
#define SPI_MODE_KERNEL_MASK (~(BIT(30) - 1))
208+
#define SPI_MODE_KERNEL_MASK (~(BIT(29) - 1))
199209
u32 mode;
200210
int irq;
201211
void *controller_state;

0 commit comments

Comments
 (0)