Skip to content

Commit 95a9580

Browse files
committed
Merge tag 'spi-fix-v6.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "A few final fixes for v6.15, some driver fixes for the Freescale DSPI driver pulled over from their vendor code and another instance of the fixes Greg has been sending throughout the kernel for constification of the bus_type in driver core match() functions" * tag 'spi-fix-v6.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi-fsl-dspi: Reset SR flags before sending a new message spi: spi-fsl-dspi: Halt the module after a new message transfer spi: spi-fsl-dspi: restrict register range for regmap access spi: use container_of_cont() for to_spi_device()
2 parents b142743 + 7aba292 commit 95a9580

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

drivers/spi/spi-fsl-dspi.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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
@@ -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;
@@ -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

11681192
static 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+
11701208
static 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

11891229
static 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

include/linux/spi/spi.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,7 @@ struct spi_device {
249249
static_assert((SPI_MODE_KERNEL_MASK & SPI_MODE_USER_MASK) == 0,
250250
"SPI_MODE_USER_MASK & SPI_MODE_KERNEL_MASK must not overlap");
251251

252-
static inline struct spi_device *to_spi_device(const struct device *dev)
253-
{
254-
return dev ? container_of(dev, struct spi_device, dev) : NULL;
255-
}
252+
#define to_spi_device(__dev) container_of_const(__dev, struct spi_device, dev)
256253

257254
/* Most drivers won't need to care about device refcounting */
258255
static inline struct spi_device *spi_dev_get(struct spi_device *spi)

0 commit comments

Comments
 (0)