spi: Fixes for v6.15

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.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmgySG0ACgkQJNaLcl1U
 h9ClEQf/ViohgWBL0RLAsPdqyfTvSvhLS87V5ze4LWRmzNSYkwUQcGx0fx3QjRCl
 ekZyzHUUzsFY/6yHlgZ8KaP2kgHBtuNc4l4Kefpnmen6GFCOsFjaw6X/3WHkxmLN
 kJOuMjNr4p4he1X0tUE5yZfAqWs2QdsZ91unfx8DejvHV0nzlaqjCp0yaJQEcnAx
 KPx1pkC9Lj9F+SPh2hs2bJeHLkIUmyj6ZRbqhQk4BYGdKTiGpAo7FclmVDjWiztZ
 uWZ3Auzsyd6d0z74RkR95SZHQFmwABzvYoz7/LtMw0QK6MCDq6FAlVuYAi7Rc6OJ
 GkmS9ERJsEGdflfDg0JMYG1wTtiawQ==
 =7jIv
 -----END PGP SIGNATURE-----

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()
This commit is contained in:
Linus Torvalds 2025-05-24 18:48:17 -07:00
commit 95a9580d58
2 changed files with 46 additions and 5 deletions

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright 2013 Freescale Semiconductor, Inc.
// Copyright 2020 NXP
// Copyright 2020-2025 NXP
//
// Freescale DSPI driver
// This file contains a driver for the Freescale DSPI
@ -62,6 +62,7 @@
#define SPI_SR_TFIWF BIT(18)
#define SPI_SR_RFDF BIT(17)
#define SPI_SR_CMDFFF BIT(16)
#define SPI_SR_TXRXS BIT(30)
#define SPI_SR_CLEAR (SPI_SR_TCFQF | \
SPI_SR_TFUF | SPI_SR_TFFF | \
SPI_SR_CMDTCF | SPI_SR_SPEF | \
@ -921,9 +922,20 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
struct spi_transfer *transfer;
bool cs = false;
int status = 0;
u32 val = 0;
bool cs_change = false;
message->actual_length = 0;
/* Put DSPI in running mode if halted. */
regmap_read(dspi->regmap, SPI_MCR, &val);
if (val & SPI_MCR_HALT) {
regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_HALT, 0);
while (regmap_read(dspi->regmap, SPI_SR, &val) >= 0 &&
!(val & SPI_SR_TXRXS))
;
}
list_for_each_entry(transfer, &message->transfers, transfer_list) {
dspi->cur_transfer = transfer;
dspi->cur_msg = message;
@ -953,6 +965,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
dspi->tx_cmd |= SPI_PUSHR_CMD_CONT;
}
cs_change = transfer->cs_change;
dspi->tx = transfer->tx_buf;
dspi->rx = transfer->rx_buf;
dspi->len = transfer->len;
@ -962,6 +975,8 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
dspi->progress, !dspi->irq);
@ -988,6 +1003,15 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
dspi_deassert_cs(spi, &cs);
}
if (status || !cs_change) {
/* Put DSPI in stop mode */
regmap_update_bits(dspi->regmap, SPI_MCR,
SPI_MCR_HALT, SPI_MCR_HALT);
while (regmap_read(dspi->regmap, SPI_SR, &val) >= 0 &&
val & SPI_SR_TXRXS)
;
}
message->status = status;
spi_finalize_current_message(ctlr);
@ -1167,6 +1191,20 @@ static int dspi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume);
static const struct regmap_range dspi_yes_ranges[] = {
regmap_reg_range(SPI_MCR, SPI_MCR),
regmap_reg_range(SPI_TCR, SPI_CTAR(3)),
regmap_reg_range(SPI_SR, SPI_TXFR3),
regmap_reg_range(SPI_RXFR0, SPI_RXFR3),
regmap_reg_range(SPI_CTARE(0), SPI_CTARE(3)),
regmap_reg_range(SPI_SREX, SPI_SREX),
};
static const struct regmap_access_table dspi_access_table = {
.yes_ranges = dspi_yes_ranges,
.n_yes_ranges = ARRAY_SIZE(dspi_yes_ranges),
};
static const struct regmap_range dspi_volatile_ranges[] = {
regmap_reg_range(SPI_MCR, SPI_TCR),
regmap_reg_range(SPI_SR, SPI_SR),
@ -1184,6 +1222,8 @@ static const struct regmap_config dspi_regmap_config = {
.reg_stride = 4,
.max_register = 0x88,
.volatile_table = &dspi_volatile_table,
.rd_table = &dspi_access_table,
.wr_table = &dspi_access_table,
};
static const struct regmap_range dspi_xspi_volatile_ranges[] = {
@ -1205,6 +1245,8 @@ static const struct regmap_config dspi_xspi_regmap_config[] = {
.reg_stride = 4,
.max_register = 0x13c,
.volatile_table = &dspi_xspi_volatile_table,
.rd_table = &dspi_access_table,
.wr_table = &dspi_access_table,
},
{
.name = "pushr",
@ -1227,6 +1269,8 @@ static int dspi_init(struct fsl_dspi *dspi)
if (!spi_controller_is_target(dspi->ctlr))
mcr |= SPI_MCR_HOST;
mcr |= SPI_MCR_HALT;
regmap_write(dspi->regmap, SPI_MCR, mcr);
regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);

View File

@ -249,10 +249,7 @@ struct spi_device {
static_assert((SPI_MODE_KERNEL_MASK & SPI_MODE_USER_MASK) == 0,
"SPI_MODE_USER_MASK & SPI_MODE_KERNEL_MASK must not overlap");
static inline struct spi_device *to_spi_device(const struct device *dev)
{
return dev ? container_of(dev, struct spi_device, dev) : NULL;
}
#define to_spi_device(__dev) container_of_const(__dev, struct spi_device, dev)
/* Most drivers won't need to care about device refcounting */
static inline struct spi_device *spi_dev_get(struct spi_device *spi)