Commit 0c92ecf10d9fb80b1798d2a9adfdea17f8f5e6d9
Committed by
Grant Likely
1 parent
b42a81ca0f
Exists in
master
and in
39 other branches
spi/s3c64xx: Correction for 16,32 bits bus width
We can't do without setting channel and bus width to same size. In order to do that, use loop read/writes in polling mode and appropriate burst size in DMA mode. Signed-off-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Showing 1 changed file with 41 additions and 15 deletions Side-by-side Diff
drivers/spi/spi_s3c64xx.c
... | ... | @@ -261,15 +261,25 @@ |
261 | 261 | chcfg |= S3C64XX_SPI_CH_TXCH_ON; |
262 | 262 | if (dma_mode) { |
263 | 263 | modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; |
264 | - s3c2410_dma_config(sdd->tx_dmach, 1); | |
264 | + s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8); | |
265 | 265 | s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, |
266 | 266 | xfer->tx_dma, xfer->len); |
267 | 267 | s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); |
268 | 268 | } else { |
269 | - unsigned char *buf = (unsigned char *) xfer->tx_buf; | |
270 | - int i = 0; | |
271 | - while (i < xfer->len) | |
272 | - writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA); | |
269 | + switch (sdd->cur_bpw) { | |
270 | + case 32: | |
271 | + iowrite32_rep(regs + S3C64XX_SPI_TX_DATA, | |
272 | + xfer->tx_buf, xfer->len / 4); | |
273 | + break; | |
274 | + case 16: | |
275 | + iowrite16_rep(regs + S3C64XX_SPI_TX_DATA, | |
276 | + xfer->tx_buf, xfer->len / 2); | |
277 | + break; | |
278 | + default: | |
279 | + iowrite8_rep(regs + S3C64XX_SPI_TX_DATA, | |
280 | + xfer->tx_buf, xfer->len); | |
281 | + break; | |
282 | + } | |
273 | 283 | } |
274 | 284 | } |
275 | 285 | |
... | ... | @@ -286,7 +296,7 @@ |
286 | 296 | writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) |
287 | 297 | | S3C64XX_SPI_PACKET_CNT_EN, |
288 | 298 | regs + S3C64XX_SPI_PACKET_CNT); |
289 | - s3c2410_dma_config(sdd->rx_dmach, 1); | |
299 | + s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8); | |
290 | 300 | s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, |
291 | 301 | xfer->rx_dma, xfer->len); |
292 | 302 | s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); |
293 | 303 | |
... | ... | @@ -366,20 +376,26 @@ |
366 | 376 | return -EIO; |
367 | 377 | } |
368 | 378 | } else { |
369 | - unsigned char *buf; | |
370 | - int i; | |
371 | - | |
372 | 379 | /* If it was only Tx */ |
373 | 380 | if (xfer->rx_buf == NULL) { |
374 | 381 | sdd->state &= ~TXBUSY; |
375 | 382 | return 0; |
376 | 383 | } |
377 | 384 | |
378 | - i = 0; | |
379 | - buf = xfer->rx_buf; | |
380 | - while (i < xfer->len) | |
381 | - buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA); | |
382 | - | |
385 | + switch (sdd->cur_bpw) { | |
386 | + case 32: | |
387 | + ioread32_rep(regs + S3C64XX_SPI_RX_DATA, | |
388 | + xfer->rx_buf, xfer->len / 4); | |
389 | + break; | |
390 | + case 16: | |
391 | + ioread16_rep(regs + S3C64XX_SPI_RX_DATA, | |
392 | + xfer->rx_buf, xfer->len / 2); | |
393 | + break; | |
394 | + default: | |
395 | + ioread8_rep(regs + S3C64XX_SPI_RX_DATA, | |
396 | + xfer->rx_buf, xfer->len); | |
397 | + break; | |
398 | + } | |
383 | 399 | sdd->state &= ~RXBUSY; |
384 | 400 | } |
385 | 401 | |
386 | 402 | |
387 | 403 | |
388 | 404 | |
... | ... | @@ -434,15 +450,17 @@ |
434 | 450 | switch (sdd->cur_bpw) { |
435 | 451 | case 32: |
436 | 452 | val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD; |
453 | + val |= S3C64XX_SPI_MODE_CH_TSZ_WORD; | |
437 | 454 | break; |
438 | 455 | case 16: |
439 | 456 | val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD; |
457 | + val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD; | |
440 | 458 | break; |
441 | 459 | default: |
442 | 460 | val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE; |
461 | + val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; | |
443 | 462 | break; |
444 | 463 | } |
445 | - val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */ | |
446 | 464 | |
447 | 465 | writel(val, regs + S3C64XX_SPI_MODE_CFG); |
448 | 466 | |
... | ... | @@ -628,6 +646,14 @@ |
628 | 646 | /* Only BPW and Speed may change across transfers */ |
629 | 647 | bpw = xfer->bits_per_word ? : spi->bits_per_word; |
630 | 648 | speed = xfer->speed_hz ? : spi->max_speed_hz; |
649 | + | |
650 | + if (xfer->len % (bpw / 8)) { | |
651 | + dev_err(&spi->dev, | |
652 | + "Xfer length(%u) not a multiple of word size(%u)\n", | |
653 | + xfer->len, bpw / 8); | |
654 | + status = -EIO; | |
655 | + goto out; | |
656 | + } | |
631 | 657 | |
632 | 658 | if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { |
633 | 659 | sdd->cur_bpw = bpw; |