Skip to content

Commit a34e035

Browse files
Villemoesbroonie
authored andcommitted
spi: spi-imx: fix mixing of native and gpio chipselects for imx51/imx53/imx6 variants
Commit 87c6141 (spi: spi-imx: fix MX51_ECSPI_* macros when cs > 3) ensured that the argument passed to the macros was masked with &3, so that we no longer write outside the intended fields in the various control registers. When all chip selects are gpios, this works just fine. However, when a mix of native and gpio chip selects are in use, that masking is too naive. Say, for example, that SS0 is muxed as native chip select, and there is also a chip at 4 (obviously with a gpio cs). In that case, when accessing the latter chip, both the SS0 pin and the gpio pin will be asserted low. The fix for this is to use the ->unused_native_cs value as channel number for any spi device which uses a gpio as chip select. Signed-off-by: Rasmus Villemoes <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 20c475d commit a34e035

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

drivers/spi/spi-imx.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,13 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
517517
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
518518
}
519519

520+
static int mx51_ecspi_channel(const struct spi_device *spi)
521+
{
522+
if (!spi_get_csgpiod(spi, 0))
523+
return spi_get_chipselect(spi, 0);
524+
return spi->controller->unused_native_cs;
525+
}
526+
520527
static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
521528
struct spi_message *msg)
522529
{
@@ -527,6 +534,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
527534
u32 testreg, delay;
528535
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
529536
u32 current_cfg = cfg;
537+
int channel = mx51_ecspi_channel(spi);
530538

531539
/* set Master or Slave mode */
532540
if (spi_imx->slave_mode)
@@ -541,7 +549,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
541549
ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
542550

543551
/* set chip select to use */
544-
ctrl |= MX51_ECSPI_CTRL_CS(spi_get_chipselect(spi, 0));
552+
ctrl |= MX51_ECSPI_CTRL_CS(channel);
545553

546554
/*
547555
* The ctrl register must be written first, with the EN bit set other
@@ -562,27 +570,27 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
562570
* BURST_LENGTH + 1 bits are received
563571
*/
564572
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
565-
cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0));
573+
cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(channel);
566574
else
567-
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0));
575+
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(channel);
568576

569577
if (spi->mode & SPI_CPOL) {
570-
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0));
571-
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0));
578+
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(channel);
579+
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(channel);
572580
} else {
573-
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0));
574-
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0));
581+
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(channel);
582+
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(channel);
575583
}
576584

577585
if (spi->mode & SPI_MOSI_IDLE_LOW)
578-
cfg |= MX51_ECSPI_CONFIG_DATACTL(spi_get_chipselect(spi, 0));
586+
cfg |= MX51_ECSPI_CONFIG_DATACTL(channel);
579587
else
580-
cfg &= ~MX51_ECSPI_CONFIG_DATACTL(spi_get_chipselect(spi, 0));
588+
cfg &= ~MX51_ECSPI_CONFIG_DATACTL(channel);
581589

582590
if (spi->mode & SPI_CS_HIGH)
583-
cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0));
591+
cfg |= MX51_ECSPI_CONFIG_SSBPOL(channel);
584592
else
585-
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0));
593+
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(channel);
586594

587595
if (cfg == current_cfg)
588596
return 0;
@@ -627,14 +635,15 @@ static void mx51_configure_cpha(struct spi_imx_data *spi_imx,
627635
bool cpha = (spi->mode & SPI_CPHA);
628636
bool flip_cpha = (spi->mode & SPI_RX_CPHA_FLIP) && spi_imx->rx_only;
629637
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
638+
int channel = mx51_ecspi_channel(spi);
630639

631640
/* Flip cpha logical value iff flip_cpha */
632641
cpha ^= flip_cpha;
633642

634643
if (cpha)
635-
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0));
644+
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(channel);
636645
else
637-
cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0));
646+
cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(channel);
638647

639648
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
640649
}

0 commit comments

Comments
 (0)