summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Villemoes <rasmus.villemoes@prevas.dk>2019-03-27 14:30:51 +0000
committerMark Brown <broonie@kernel.org>2019-04-02 13:00:54 +0700
commita798a7086c38d91d304132c194cff9f02197f5cd (patch)
treedf4ee1096c8dcd3ea25cfdc356184804d5f882e6
parent748fbadf951a8b32713351e10ef989181a4b47a6 (diff)
spi: spi-fsl-spi: allow changing bits_per_word while CS is still active
Commit c9bfcb315104 (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: Rasmus Villemoes <rasmus.villemoes@prevas.dk> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-fsl-spi.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 481b075689b5..e2b341943796 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -367,7 +367,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
struct spi_transfer *t, *first;
unsigned int cs_change;
const int nsecs = 50;
- int status;
+ int status, last_bpw;
/* Don't allow changes if CS is active */
cs_change = 1;
@@ -375,21 +375,22 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
if (cs_change)
first = t;
cs_change = t->cs_change;
- if ((first->bits_per_word != t->bits_per_word) ||
- (first->speed_hz != t->speed_hz)) {
+ if (first->speed_hz != t->speed_hz) {
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;
}
}
+ last_bpw = -1;
cs_change = 1;
status = -EINVAL;
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);
if (status < 0)
break;
+ last_bpw = t->bits_per_word;
if (cs_change) {
fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);