11// SPDX-License-Identifier: GPL-2.0+
22//
33// Copyright 2013 Freescale Semiconductor, Inc.
4- // Copyright 2020 NXP
4+ // Copyright 2020-2025 NXP
55//
66// Freescale DSPI driver
77// This file contains a driver for the Freescale DSPI
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 ;
@@ -962,6 +975,8 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
962975 SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF ,
963976 SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF );
964977
978+ regmap_write (dspi -> regmap , SPI_SR , SPI_SR_CLEAR );
979+
965980 spi_take_timestamp_pre (dspi -> ctlr , dspi -> cur_transfer ,
966981 dspi -> progress , !dspi -> irq );
967982
@@ -988,6 +1003,15 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
9881003 dspi_deassert_cs (spi , & cs );
9891004 }
9901005
1006+ if (status || !cs_change ) {
1007+ /* Put DSPI in stop mode */
1008+ regmap_update_bits (dspi -> regmap , SPI_MCR ,
1009+ SPI_MCR_HALT , SPI_MCR_HALT );
1010+ while (regmap_read (dspi -> regmap , SPI_SR , & val ) >= 0 &&
1011+ val & SPI_SR_TXRXS )
1012+ ;
1013+ }
1014+
9911015 message -> status = status ;
9921016 spi_finalize_current_message (ctlr );
9931017
@@ -1167,6 +1191,20 @@ static int dspi_resume(struct device *dev)
11671191
11681192static SIMPLE_DEV_PM_OPS (dspi_pm , dspi_suspend , dspi_resume ) ;
11691193
1194+ static const struct regmap_range dspi_yes_ranges [] = {
1195+ regmap_reg_range (SPI_MCR , SPI_MCR ),
1196+ regmap_reg_range (SPI_TCR , SPI_CTAR (3 )),
1197+ regmap_reg_range (SPI_SR , SPI_TXFR3 ),
1198+ regmap_reg_range (SPI_RXFR0 , SPI_RXFR3 ),
1199+ regmap_reg_range (SPI_CTARE (0 ), SPI_CTARE (3 )),
1200+ regmap_reg_range (SPI_SREX , SPI_SREX ),
1201+ };
1202+
1203+ static const struct regmap_access_table dspi_access_table = {
1204+ .yes_ranges = dspi_yes_ranges ,
1205+ .n_yes_ranges = ARRAY_SIZE (dspi_yes_ranges ),
1206+ };
1207+
11701208static const struct regmap_range dspi_volatile_ranges [] = {
11711209 regmap_reg_range (SPI_MCR , SPI_TCR ),
11721210 regmap_reg_range (SPI_SR , SPI_SR ),
@@ -1184,6 +1222,8 @@ static const struct regmap_config dspi_regmap_config = {
11841222 .reg_stride = 4 ,
11851223 .max_register = 0x88 ,
11861224 .volatile_table = & dspi_volatile_table ,
1225+ .rd_table = & dspi_access_table ,
1226+ .wr_table = & dspi_access_table ,
11871227};
11881228
11891229static const struct regmap_range dspi_xspi_volatile_ranges [] = {
@@ -1205,6 +1245,8 @@ static const struct regmap_config dspi_xspi_regmap_config[] = {
12051245 .reg_stride = 4 ,
12061246 .max_register = 0x13c ,
12071247 .volatile_table = & dspi_xspi_volatile_table ,
1248+ .rd_table = & dspi_access_table ,
1249+ .wr_table = & dspi_access_table ,
12081250 },
12091251 {
12101252 .name = "pushr" ,
@@ -1227,6 +1269,8 @@ static int dspi_init(struct fsl_dspi *dspi)
12271269 if (!spi_controller_is_target (dspi -> ctlr ))
12281270 mcr |= SPI_MCR_HOST ;
12291271
1272+ mcr |= SPI_MCR_HALT ;
1273+
12301274 regmap_write (dspi -> regmap , SPI_MCR , mcr );
12311275 regmap_write (dspi -> regmap , SPI_SR , SPI_SR_CLEAR );
12321276
0 commit comments