Skip to content

Commit 8a30a6d

Browse files
Bogdan-Gabriel Romanbroonie
authored andcommitted
spi: spi-fsl-dspi: Halt the module after a new message transfer
The XSPI mode implementation in this driver still uses the EOQ flag to signal the last word in a transmission and deassert the PCS signal. However, at speeds lower than ~200kHZ, the PCS signal seems to remain asserted even when SR[EOQF] = 1 indicates the end of a transmission. This is a problem for target devices which require the deassertation of the PCS signal between transfers. Hence, this commit 'forces' the deassertation of the PCS by stopping the module through MCR[HALT] after completing a new transfer. According to the reference manual, the module stops or transitions from the Running state to the Stopped state after the current frame, when any one of the following conditions exist: - The value of SR[EOQF] = 1. - The chip is in Debug mode and the value of MCR[FRZ] = 1. - The value of MCR[HALT] = 1. This shouldn't be done if the last transfer in the message has cs_change set. Fixes: ea93ed4 ("spi: spi-fsl-dspi: Use EOQ for last word in buffer even for XSPI mode") Signed-off-by: Bogdan-Gabriel Roman <[email protected]> Signed-off-by: Larisa Grigore <[email protected]> Signed-off-by: James Clark <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 283ae0c commit 8a30a6d

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

drivers/spi/spi-fsl-dspi.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#define SPI_SR_TFIWF BIT(18)
6363
#define SPI_SR_RFDF BIT(17)
6464
#define SPI_SR_CMDFFF BIT(16)
65+
#define SPI_SR_TXRXS BIT(30)
6566
#define SPI_SR_CLEAR (SPI_SR_TCFQF | \
6667
SPI_SR_TFUF | SPI_SR_TFFF | \
6768
SPI_SR_CMDTCF | SPI_SR_SPEF | \
@@ -921,9 +922,20 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
921922
struct spi_transfer *transfer;
922923
bool cs = false;
923924
int status = 0;
925+
u32 val = 0;
926+
bool cs_change = false;
924927

925928
message->actual_length = 0;
926929

930+
/* Put DSPI in running mode if halted. */
931+
regmap_read(dspi->regmap, SPI_MCR, &val);
932+
if (val & SPI_MCR_HALT) {
933+
regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_HALT, 0);
934+
while (regmap_read(dspi->regmap, SPI_SR, &val) >= 0 &&
935+
!(val & SPI_SR_TXRXS))
936+
;
937+
}
938+
927939
list_for_each_entry(transfer, &message->transfers, transfer_list) {
928940
dspi->cur_transfer = transfer;
929941
dspi->cur_msg = message;
@@ -953,6 +965,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
953965
dspi->tx_cmd |= SPI_PUSHR_CMD_CONT;
954966
}
955967

968+
cs_change = transfer->cs_change;
956969
dspi->tx = transfer->tx_buf;
957970
dspi->rx = transfer->rx_buf;
958971
dspi->len = transfer->len;
@@ -988,6 +1001,15 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
9881001
dspi_deassert_cs(spi, &cs);
9891002
}
9901003

1004+
if (status || !cs_change) {
1005+
/* Put DSPI in stop mode */
1006+
regmap_update_bits(dspi->regmap, SPI_MCR,
1007+
SPI_MCR_HALT, SPI_MCR_HALT);
1008+
while (regmap_read(dspi->regmap, SPI_SR, &val) >= 0 &&
1009+
val & SPI_SR_TXRXS)
1010+
;
1011+
}
1012+
9911013
message->status = status;
9921014
spi_finalize_current_message(ctlr);
9931015

@@ -1245,6 +1267,8 @@ static int dspi_init(struct fsl_dspi *dspi)
12451267
if (!spi_controller_is_target(dspi->ctlr))
12461268
mcr |= SPI_MCR_HOST;
12471269

1270+
mcr |= SPI_MCR_HALT;
1271+
12481272
regmap_write(dspi->regmap, SPI_MCR, mcr);
12491273
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
12501274

0 commit comments

Comments
 (0)