Skip to content

Commit bd30b99

Browse files
committed
SPI: omap2-mcspi: Fix SPI CS behaviour around
Merge series from Félix Piédallu <[email protected]>: These patches fix the behaviour of the SPI Chip Select of the OMAP2 MCSPI driver used on TI SoCs. The omap2-mcspi driver supports the use of multi mode (multichannel in TI documentation). In this mode, the CS is asserted and deasserted by the hardware. The multi mode is disabled for messages when cs_change=0 for all transfers (e.g when CS is kept asserted between transfers of a same message). The multi mode also needs to be disabled for messages when cs_change=1 on the last transfer (e.g when CS is kept asserted after the WHOLE message), and the message right after. Currently, that is not the case and it CS is deasserted by hardware when it shouldn't. This breaks peripheral drivers that send multiple messages with the CS asserted in between. Patch 1 ensures that multi mode is disabled when cs_change=1 on the last transfer of the message. Patch 2 ensures that multi mode is disable on a message following one with cs_change=1 on the last transfer. This is the case for the TPM TIS SPI driver that uses this logic for flow control purposes. Tested on an AM6442 platform with a TPM ST33HTPH2X32AHE4.
2 parents cf2c3ec + 10c24e0 commit bd30b99

File tree

1 file changed

+18
-12
lines changed

1 file changed

+18
-12
lines changed

drivers/spi/spi-omap2-mcspi.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ struct omap2_mcspi {
134134
size_t max_xfer_len;
135135
u32 ref_clk_hz;
136136
bool use_multi_mode;
137+
bool last_msg_kept_cs;
137138
};
138139

139140
struct omap2_mcspi_cs {
@@ -1269,6 +1270,10 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
12691270
* multi-mode is applicable.
12701271
*/
12711272
mcspi->use_multi_mode = true;
1273+
1274+
if (mcspi->last_msg_kept_cs)
1275+
mcspi->use_multi_mode = false;
1276+
12721277
list_for_each_entry(tr, &msg->transfers, transfer_list) {
12731278
if (!tr->bits_per_word)
12741279
bits_per_word = msg->spi->bits_per_word;
@@ -1287,18 +1292,19 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
12871292
mcspi->use_multi_mode = false;
12881293
}
12891294

1290-
/* Check if transfer asks to change the CS status after the transfer */
1291-
if (!tr->cs_change)
1292-
mcspi->use_multi_mode = false;
1293-
1294-
/*
1295-
* If at least one message is not compatible, switch back to single mode
1296-
*
1297-
* The bits_per_word of certain transfer can be different, but it will have no
1298-
* impact on the signal itself.
1299-
*/
1300-
if (!mcspi->use_multi_mode)
1301-
break;
1295+
if (list_is_last(&tr->transfer_list, &msg->transfers)) {
1296+
/* Check if transfer asks to keep the CS status after the whole message */
1297+
if (tr->cs_change) {
1298+
mcspi->use_multi_mode = false;
1299+
mcspi->last_msg_kept_cs = true;
1300+
} else {
1301+
mcspi->last_msg_kept_cs = false;
1302+
}
1303+
} else {
1304+
/* Check if transfer asks to change the CS status after the transfer */
1305+
if (!tr->cs_change)
1306+
mcspi->use_multi_mode = false;
1307+
}
13021308
}
13031309

13041310
omap2_mcspi_set_mode(ctlr);

0 commit comments

Comments
 (0)