Commit a798a708 authored by Rasmus Villemoes's avatar Rasmus Villemoes Committed by Mark Brown

spi: spi-fsl-spi: allow changing bits_per_word while CS is still active

Commit c9bfcb31 (spi_mpc83xx: much improved driver) introduced
logic to ensure bits_per_word and speed_hz stay the same for a series
of spi_transfers with CS active, arguing that

    The current driver may cause glitches on SPI CLK line since one
    must disable the SPI controller before changing any HW settings.

This sounds quite reasonable. So this is a quite naive attempt at
relaxing this sanity checking to only ensure that speed_hz is
constant - in the faint hope that if we do not causes changes to the
clock-related fields of the SPMODE register (DIV16 and PM), those
glitches won't appear.

The purpose of this change is to allow automatically optimizing large
transfers to use 32 bits-per-word; taking one interrupt for every byte
is extremely slow.
Signed-off-by: default avatarRasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 748fbadf
...@@ -367,7 +367,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master, ...@@ -367,7 +367,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
struct spi_transfer *t, *first; struct spi_transfer *t, *first;
unsigned int cs_change; unsigned int cs_change;
const int nsecs = 50; const int nsecs = 50;
int status; int status, last_bpw;
/* Don't allow changes if CS is active */ /* Don't allow changes if CS is active */
cs_change = 1; cs_change = 1;
...@@ -375,21 +375,22 @@ static int fsl_spi_do_one_msg(struct spi_master *master, ...@@ -375,21 +375,22 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
if (cs_change) if (cs_change)
first = t; first = t;
cs_change = t->cs_change; cs_change = t->cs_change;
if ((first->bits_per_word != t->bits_per_word) || if (first->speed_hz != t->speed_hz) {
(first->speed_hz != t->speed_hz)) {
dev_err(&spi->dev, dev_err(&spi->dev,
"bits_per_word/speed_hz cannot change while CS is active\n"); "speed_hz cannot change while CS is active\n");
return -EINVAL; return -EINVAL;
} }
} }
last_bpw = -1;
cs_change = 1; cs_change = 1;
status = -EINVAL; status = -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
if (cs_change) if (cs_change || last_bpw != t->bits_per_word)
status = fsl_spi_setup_transfer(spi, t); status = fsl_spi_setup_transfer(spi, t);
if (status < 0) if (status < 0)
break; break;
last_bpw = t->bits_per_word;
if (cs_change) { if (cs_change) {
fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE); fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment