aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-mxs.c
diff options
context:
space:
mode:
authorTrent Piepho <tpiepho@gmail.com>2013-10-01 16:15:04 -0400
committerMark Brown <broonie@linaro.org>2013-10-17 20:00:30 -0400
commit0b782f70b51b9e611a69b9d4533b44d66b2e3e75 (patch)
treef52e36ea91cf2432af35ca1d80bbe0f716def1ff /drivers/spi/spi-mxs.c
parentdf23286e57ceefe427d7ff925193283a8fafe9f3 (diff)
spi: spi-mxs: Fix chip select control bits in DMA mode
In DMA mode the chip select control bits would be ORed into the CTRL0 register without first clearing the bits. This means that after addressing slave 1, the CTRL0 bit to address slave 1 would be still be set when addressing slave 0, resulting in slave 1 continuing to be addressed. The message handling function would pass the CS value to the txrx function, which would re-program the bits on each transfer in the message. The selected CS does not change during a message so this is inefficient. It also means there are two different sets of code for selecting the CS, one for PIO that worked and one for DMA that didn't. Change the code to set the CS bits in the message handling function once. Now the DMA and PIO txrx functions don't need to care about CS at all. Signed-off-by: Trent Piepho <tpiepho@gmail.com> Cc: Marek Vasut <marex@denx.de> Cc: Fabio Estevam <fabio.estevam@freescale.com> Cc: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi-mxs.c')
-rw-r--r--drivers/spi/spi-mxs.c36
1 files changed, 13 insertions, 23 deletions
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 68ea5078a9cf..a9a273e20fd2 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -140,18 +140,6 @@ static uint32_t mxs_spi_cs_to_reg(unsigned cs)
140 return select; 140 return select;
141} 141}
142 142
143static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs)
144{
145 const uint32_t mask =
146 BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ;
147 uint32_t select;
148 struct mxs_ssp *ssp = &spi->ssp;
149
150 writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
151 select = mxs_spi_cs_to_reg(cs);
152 writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
153}
154
155static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set) 143static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set)
156{ 144{
157 const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT); 145 const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT);
@@ -189,7 +177,7 @@ static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id)
189 return IRQ_HANDLED; 177 return IRQ_HANDLED;
190} 178}
191 179
192static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 180static int mxs_spi_txrx_dma(struct mxs_spi *spi,
193 unsigned char *buf, int len, 181 unsigned char *buf, int len,
194 unsigned int flags) 182 unsigned int flags)
195{ 183{
@@ -217,10 +205,11 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
217 205
218 INIT_COMPLETION(spi->c); 206 INIT_COMPLETION(spi->c);
219 207
208 /* Chip select was already programmed into CTRL0 */
220 ctrl0 = readl(ssp->base + HW_SSP_CTRL0); 209 ctrl0 = readl(ssp->base + HW_SSP_CTRL0);
221 ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC | 210 ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC |
222 BM_SSP_CTRL0_READ); 211 BM_SSP_CTRL0_READ);
223 ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); 212 ctrl0 |= BM_SSP_CTRL0_DATA_XFER;
224 213
225 if (!(flags & TXRX_WRITE)) 214 if (!(flags & TXRX_WRITE))
226 ctrl0 |= BM_SSP_CTRL0_READ; 215 ctrl0 |= BM_SSP_CTRL0_READ;
@@ -324,7 +313,7 @@ err_mapped:
324 return ret; 313 return ret;
325} 314}
326 315
327static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, 316static int mxs_spi_txrx_pio(struct mxs_spi *spi,
328 unsigned char *buf, int len, 317 unsigned char *buf, int len,
329 unsigned int flags) 318 unsigned int flags)
330{ 319{
@@ -333,8 +322,6 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
333 writel(BM_SSP_CTRL0_IGNORE_CRC, 322 writel(BM_SSP_CTRL0_IGNORE_CRC,
334 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); 323 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
335 324
336 mxs_spi_set_cs(spi, cs);
337
338 while (len--) { 325 while (len--) {
339 if (len == 0 && (flags & TXRX_DEASSERT_CS)) 326 if (len == 0 && (flags & TXRX_DEASSERT_CS))
340 writel(BM_SSP_CTRL0_IGNORE_CRC, 327 writel(BM_SSP_CTRL0_IGNORE_CRC,
@@ -396,9 +383,12 @@ static int mxs_spi_transfer_one(struct spi_master *master,
396 struct spi_transfer *t, *tmp_t; 383 struct spi_transfer *t, *tmp_t;
397 unsigned int flag; 384 unsigned int flag;
398 int status = 0; 385 int status = 0;
399 int cs;
400 386
401 cs = m->spi->chip_select; 387 /* Program CS register bits here, it will be used for all transfers. */
388 writel(BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ,
389 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
390 writel(mxs_spi_cs_to_reg(m->spi->chip_select),
391 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
402 392
403 list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { 393 list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
404 394
@@ -431,11 +421,11 @@ static int mxs_spi_transfer_one(struct spi_master *master,
431 STMP_OFFSET_REG_CLR); 421 STMP_OFFSET_REG_CLR);
432 422
433 if (t->tx_buf) 423 if (t->tx_buf)
434 status = mxs_spi_txrx_pio(spi, cs, 424 status = mxs_spi_txrx_pio(spi,
435 (void *)t->tx_buf, 425 (void *)t->tx_buf,
436 t->len, flag | TXRX_WRITE); 426 t->len, flag | TXRX_WRITE);
437 if (t->rx_buf) 427 if (t->rx_buf)
438 status = mxs_spi_txrx_pio(spi, cs, 428 status = mxs_spi_txrx_pio(spi,
439 t->rx_buf, t->len, 429 t->rx_buf, t->len,
440 flag); 430 flag);
441 } else { 431 } else {
@@ -444,11 +434,11 @@ static int mxs_spi_transfer_one(struct spi_master *master,
444 STMP_OFFSET_REG_SET); 434 STMP_OFFSET_REG_SET);
445 435
446 if (t->tx_buf) 436 if (t->tx_buf)
447 status = mxs_spi_txrx_dma(spi, cs, 437 status = mxs_spi_txrx_dma(spi,
448 (void *)t->tx_buf, t->len, 438 (void *)t->tx_buf, t->len,
449 flag | TXRX_WRITE); 439 flag | TXRX_WRITE);
450 if (t->rx_buf) 440 if (t->rx_buf)
451 status = mxs_spi_txrx_dma(spi, cs, 441 status = mxs_spi_txrx_dma(spi,
452 t->rx_buf, t->len, 442 t->rx_buf, t->len,
453 flag); 443 flag);
454 } 444 }