Commit 0c92ecf10d9fb80b1798d2a9adfdea17f8f5e6d9

Authored by Jassi Brar
Committed by Grant Likely
1 parent b42a81ca0f

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;