aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrent Piepho <tpiepho@gmail.com>2013-10-01 16:14:50 -0400
committerMark Brown <broonie@linaro.org>2013-10-17 20:00:29 -0400
commit28cad125881cb10172895774d4c3a04e748bf6bf (patch)
tree70b97772d3e78ef2e2336b6098cd69d9fc351ca5
parent75e73fa24882fb76e8ef89226893728ed0f78870 (diff)
spi: spi-mxs: Change flag arguments in txrx functions to bit flags
There are three flag arguments to the PIO and DMA txrx functions. Two are passed as pointers to integers, even though they are input only and not modified, which makes no sense to do. The third is passed as an integer. The compiler must use an argument register or stack variable for each flag this way. Using bitflags in a single flag argument is more efficient and produces smaller code, since all the flags can fit in a single register. And all the flag arguments get cumbersome, especially when more are added for things like GPIO chipselects. The "first" flag is never used, so can just be deleted. The "last" flag is renamed to DEASSERT_CS, since that's really what it does. The spi_transfer cs_change flag means that CS might be de-asserted on a transfer which is not last and not de-assert on the last transfer, so it is not which transfer is the last we need to know but rather the transfers after which CS should be de-asserted. This also extends the driver to not ignore cs_change when setting the DEASSERT_CS nee "last" flag. 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>
-rw-r--r--drivers/spi/spi-mxs.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index e2a9cc21dff1..090930aa7205 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -57,6 +57,13 @@
57 57
58#define SG_MAXLEN 0xff00 58#define SG_MAXLEN 0xff00
59 59
60/*
61 * Flags for txrx functions. More efficient that using an argument register for
62 * each one.
63 */
64#define TXRX_WRITE (1<<0) /* This is a write */
65#define TXRX_DEASSERT_CS (1<<1) /* De-assert CS at end of txrx */
66
60struct mxs_spi { 67struct mxs_spi {
61 struct mxs_ssp ssp; 68 struct mxs_ssp ssp;
62 struct completion c; 69 struct completion c;
@@ -184,7 +191,7 @@ static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id)
184 191
185static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 192static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
186 unsigned char *buf, int len, 193 unsigned char *buf, int len,
187 int *first, int *last, int write) 194 unsigned int flags)
188{ 195{
189 struct mxs_ssp *ssp = &spi->ssp; 196 struct mxs_ssp *ssp = &spi->ssp;
190 struct dma_async_tx_descriptor *desc = NULL; 197 struct dma_async_tx_descriptor *desc = NULL;
@@ -214,15 +221,19 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
214 ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; 221 ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT;
215 ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); 222 ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs);
216 223
217 if (!write) 224 if (!(flags & TXRX_WRITE))
218 ctrl0 |= BM_SSP_CTRL0_READ; 225 ctrl0 |= BM_SSP_CTRL0_READ;
219 226
220 /* Queue the DMA data transfer. */ 227 /* Queue the DMA data transfer. */
221 for (sg_count = 0; sg_count < sgs; sg_count++) { 228 for (sg_count = 0; sg_count < sgs; sg_count++) {
229 /* Prepare the transfer descriptor. */
222 min = min(len, desc_len); 230 min = min(len, desc_len);
223 231
224 /* Prepare the transfer descriptor. */ 232 /*
225 if ((sg_count + 1 == sgs) && *last) 233 * De-assert CS on last segment if flag is set (i.e., no more
234 * transfers will follow)
235 */
236 if ((sg_count + 1 == sgs) && (flags & TXRX_DEASSERT_CS))
226 ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC; 237 ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC;
227 238
228 if (ssp->devid == IMX23_SSP) { 239 if (ssp->devid == IMX23_SSP) {
@@ -247,7 +258,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
247 258
248 sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min); 259 sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
249 ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1, 260 ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
250 write ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 261 (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
251 262
252 len -= min; 263 len -= min;
253 buf += min; 264 buf += min;
@@ -267,7 +278,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
267 278
268 desc = dmaengine_prep_slave_sg(ssp->dmach, 279 desc = dmaengine_prep_slave_sg(ssp->dmach,
269 &dma_xfer[sg_count].sg, 1, 280 &dma_xfer[sg_count].sg, 1,
270 write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, 281 (flags & TXRX_WRITE) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
271 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 282 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
272 283
273 if (!desc) { 284 if (!desc) {
@@ -304,7 +315,7 @@ err_vmalloc:
304 while (--sg_count >= 0) { 315 while (--sg_count >= 0) {
305err_mapped: 316err_mapped:
306 dma_unmap_sg(ssp->dev, &dma_xfer[sg_count].sg, 1, 317 dma_unmap_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
307 write ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 318 (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
308 } 319 }
309 320
310 kfree(dma_xfer); 321 kfree(dma_xfer);
@@ -314,7 +325,7 @@ err_mapped:
314 325
315static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, 326static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
316 unsigned char *buf, int len, 327 unsigned char *buf, int len,
317 int *first, int *last, int write) 328 unsigned int flags)
318{ 329{
319 struct mxs_ssp *ssp = &spi->ssp; 330 struct mxs_ssp *ssp = &spi->ssp;
320 331
@@ -324,7 +335,7 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
324 mxs_spi_set_cs(spi, cs); 335 mxs_spi_set_cs(spi, cs);
325 336
326 while (len--) { 337 while (len--) {
327 if (*last && len == 0) 338 if (len == 0 && (flags & TXRX_DEASSERT_CS))
328 writel(BM_SSP_CTRL0_IGNORE_CRC, 339 writel(BM_SSP_CTRL0_IGNORE_CRC,
329 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); 340 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
330 341
@@ -337,7 +348,7 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
337 writel(1, ssp->base + HW_SSP_XFER_SIZE); 348 writel(1, ssp->base + HW_SSP_XFER_SIZE);
338 } 349 }
339 350
340 if (write) 351 if (flags & TXRX_WRITE)
341 writel(BM_SSP_CTRL0_READ, 352 writel(BM_SSP_CTRL0_READ,
342 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); 353 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
343 else 354 else
@@ -350,13 +361,13 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
350 if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1)) 361 if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
351 return -ETIMEDOUT; 362 return -ETIMEDOUT;
352 363
353 if (write) 364 if (flags & TXRX_WRITE)
354 writel(*buf, ssp->base + HW_SSP_DATA(ssp)); 365 writel(*buf, ssp->base + HW_SSP_DATA(ssp));
355 366
356 writel(BM_SSP_CTRL0_DATA_XFER, 367 writel(BM_SSP_CTRL0_DATA_XFER,
357 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); 368 ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
358 369
359 if (!write) { 370 if (!(flags & TXRX_WRITE)) {
360 if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp), 371 if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp),
361 BM_SSP_STATUS_FIFO_EMPTY, 0)) 372 BM_SSP_STATUS_FIFO_EMPTY, 0))
362 return -ETIMEDOUT; 373 return -ETIMEDOUT;
@@ -381,13 +392,11 @@ static int mxs_spi_transfer_one(struct spi_master *master,
381{ 392{
382 struct mxs_spi *spi = spi_master_get_devdata(master); 393 struct mxs_spi *spi = spi_master_get_devdata(master);
383 struct mxs_ssp *ssp = &spi->ssp; 394 struct mxs_ssp *ssp = &spi->ssp;
384 int first, last;
385 struct spi_transfer *t, *tmp_t; 395 struct spi_transfer *t, *tmp_t;
396 unsigned int flag;
386 int status = 0; 397 int status = 0;
387 int cs; 398 int cs;
388 399
389 first = last = 0;
390
391 cs = m->spi->chip_select; 400 cs = m->spi->chip_select;
392 401
393 list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { 402 list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
@@ -396,10 +405,9 @@ static int mxs_spi_transfer_one(struct spi_master *master,
396 if (status) 405 if (status)
397 break; 406 break;
398 407
399 if (&t->transfer_list == m->transfers.next) 408 /* De-assert on last transfer, inverted by cs_change flag */
400 first = 1; 409 flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ?
401 if (&t->transfer_list == m->transfers.prev) 410 TXRX_DEASSERT_CS : 0;
402 last = 1;
403 if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) { 411 if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) {
404 dev_err(ssp->dev, 412 dev_err(ssp->dev,
405 "Cannot send and receive simultaneously\n"); 413 "Cannot send and receive simultaneously\n");
@@ -424,11 +432,11 @@ static int mxs_spi_transfer_one(struct spi_master *master,
424 if (t->tx_buf) 432 if (t->tx_buf)
425 status = mxs_spi_txrx_pio(spi, cs, 433 status = mxs_spi_txrx_pio(spi, cs,
426 (void *)t->tx_buf, 434 (void *)t->tx_buf,
427 t->len, &first, &last, 1); 435 t->len, flag | TXRX_WRITE);
428 if (t->rx_buf) 436 if (t->rx_buf)
429 status = mxs_spi_txrx_pio(spi, cs, 437 status = mxs_spi_txrx_pio(spi, cs,
430 t->rx_buf, t->len, 438 t->rx_buf, t->len,
431 &first, &last, 0); 439 flag);
432 } else { 440 } else {
433 writel(BM_SSP_CTRL1_DMA_ENABLE, 441 writel(BM_SSP_CTRL1_DMA_ENABLE,
434 ssp->base + HW_SSP_CTRL1(ssp) + 442 ssp->base + HW_SSP_CTRL1(ssp) +
@@ -437,11 +445,11 @@ static int mxs_spi_transfer_one(struct spi_master *master,
437 if (t->tx_buf) 445 if (t->tx_buf)
438 status = mxs_spi_txrx_dma(spi, cs, 446 status = mxs_spi_txrx_dma(spi, cs,
439 (void *)t->tx_buf, t->len, 447 (void *)t->tx_buf, t->len,
440 &first, &last, 1); 448 flag | TXRX_WRITE);
441 if (t->rx_buf) 449 if (t->rx_buf)
442 status = mxs_spi_txrx_dma(spi, cs, 450 status = mxs_spi_txrx_dma(spi, cs,
443 t->rx_buf, t->len, 451 t->rx_buf, t->len,
444 &first, &last, 0); 452 flag);
445 } 453 }
446 454
447 if (status) { 455 if (status) {
@@ -450,7 +458,6 @@ static int mxs_spi_transfer_one(struct spi_master *master,
450 } 458 }
451 459
452 m->actual_length += t->len; 460 m->actual_length += t->len;
453 first = last = 0;
454 } 461 }
455 462
456 m->status = status; 463 m->status = status;