aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi_s3c64xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi_s3c64xx.c')
-rw-r--r--drivers/spi/spi_s3c64xx.c158
1 files changed, 105 insertions, 53 deletions
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index c3038da2648a..795828b90f45 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -261,15 +261,25 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
261 chcfg |= S3C64XX_SPI_CH_TXCH_ON; 261 chcfg |= S3C64XX_SPI_CH_TXCH_ON;
262 if (dma_mode) { 262 if (dma_mode) {
263 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; 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 s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, 265 s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
266 xfer->tx_dma, xfer->len); 266 xfer->tx_dma, xfer->len);
267 s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); 267 s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
268 } else { 268 } else {
269 unsigned char *buf = (unsigned char *) xfer->tx_buf; 269 switch (sdd->cur_bpw) {
270 int i = 0; 270 case 32:
271 while (i < xfer->len) 271 iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
272 writeb(buf[i++], 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 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
286 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) 296 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
287 | S3C64XX_SPI_PACKET_CNT_EN, 297 | S3C64XX_SPI_PACKET_CNT_EN,
288 regs + S3C64XX_SPI_PACKET_CNT); 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 s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, 300 s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
291 xfer->rx_dma, xfer->len); 301 xfer->rx_dma, xfer->len);
292 s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); 302 s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
@@ -366,20 +376,26 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
366 return -EIO; 376 return -EIO;
367 } 377 }
368 } else { 378 } else {
369 unsigned char *buf;
370 int i;
371
372 /* If it was only Tx */ 379 /* If it was only Tx */
373 if (xfer->rx_buf == NULL) { 380 if (xfer->rx_buf == NULL) {
374 sdd->state &= ~TXBUSY; 381 sdd->state &= ~TXBUSY;
375 return 0; 382 return 0;
376 } 383 }
377 384
378 i = 0; 385 switch (sdd->cur_bpw) {
379 buf = xfer->rx_buf; 386 case 32:
380 while (i < xfer->len) 387 ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
381 buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA); 388 xfer->rx_buf, xfer->len / 4);
382 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 sdd->state &= ~RXBUSY; 399 sdd->state &= ~RXBUSY;
384 } 400 }
385 401
@@ -399,13 +415,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
399 415
400static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) 416static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
401{ 417{
418 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
402 void __iomem *regs = sdd->regs; 419 void __iomem *regs = sdd->regs;
403 u32 val; 420 u32 val;
404 421
405 /* Disable Clock */ 422 /* Disable Clock */
406 val = readl(regs + S3C64XX_SPI_CLK_CFG); 423 if (sci->clk_from_cmu) {
407 val &= ~S3C64XX_SPI_ENCLK_ENABLE; 424 clk_disable(sdd->src_clk);
408 writel(val, regs + S3C64XX_SPI_CLK_CFG); 425 } else {
426 val = readl(regs + S3C64XX_SPI_CLK_CFG);
427 val &= ~S3C64XX_SPI_ENCLK_ENABLE;
428 writel(val, regs + S3C64XX_SPI_CLK_CFG);
429 }
409 430
410 /* Set Polarity and Phase */ 431 /* Set Polarity and Phase */
411 val = readl(regs + S3C64XX_SPI_CH_CFG); 432 val = readl(regs + S3C64XX_SPI_CH_CFG);
@@ -429,29 +450,39 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
429 switch (sdd->cur_bpw) { 450 switch (sdd->cur_bpw) {
430 case 32: 451 case 32:
431 val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD; 452 val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
453 val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
432 break; 454 break;
433 case 16: 455 case 16:
434 val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD; 456 val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
457 val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
435 break; 458 break;
436 default: 459 default:
437 val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE; 460 val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
461 val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
438 break; 462 break;
439 } 463 }
440 val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
441 464
442 writel(val, regs + S3C64XX_SPI_MODE_CFG); 465 writel(val, regs + S3C64XX_SPI_MODE_CFG);
443 466
444 /* Configure Clock */ 467 if (sci->clk_from_cmu) {
445 val = readl(regs + S3C64XX_SPI_CLK_CFG); 468 /* Configure Clock */
446 val &= ~S3C64XX_SPI_PSR_MASK; 469 /* There is half-multiplier before the SPI */
447 val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1) 470 clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
448 & S3C64XX_SPI_PSR_MASK); 471 /* Enable Clock */
449 writel(val, regs + S3C64XX_SPI_CLK_CFG); 472 clk_enable(sdd->src_clk);
450 473 } else {
451 /* Enable Clock */ 474 /* Configure Clock */
452 val = readl(regs + S3C64XX_SPI_CLK_CFG); 475 val = readl(regs + S3C64XX_SPI_CLK_CFG);
453 val |= S3C64XX_SPI_ENCLK_ENABLE; 476 val &= ~S3C64XX_SPI_PSR_MASK;
454 writel(val, regs + S3C64XX_SPI_CLK_CFG); 477 val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
478 & S3C64XX_SPI_PSR_MASK);
479 writel(val, regs + S3C64XX_SPI_CLK_CFG);
480
481 /* Enable Clock */
482 val = readl(regs + S3C64XX_SPI_CLK_CFG);
483 val |= S3C64XX_SPI_ENCLK_ENABLE;
484 writel(val, regs + S3C64XX_SPI_CLK_CFG);
485 }
455} 486}
456 487
457static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, 488static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
@@ -499,6 +530,7 @@ static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
499static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, 530static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
500 struct spi_message *msg) 531 struct spi_message *msg)
501{ 532{
533 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
502 struct device *dev = &sdd->pdev->dev; 534 struct device *dev = &sdd->pdev->dev;
503 struct spi_transfer *xfer; 535 struct spi_transfer *xfer;
504 536
@@ -514,6 +546,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
514 /* Map until end or first fail */ 546 /* Map until end or first fail */
515 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 547 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
516 548
549 if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
550 continue;
551
517 if (xfer->tx_buf != NULL) { 552 if (xfer->tx_buf != NULL) {
518 xfer->tx_dma = dma_map_single(dev, 553 xfer->tx_dma = dma_map_single(dev,
519 (void *)xfer->tx_buf, xfer->len, 554 (void *)xfer->tx_buf, xfer->len,
@@ -545,6 +580,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
545static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, 580static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
546 struct spi_message *msg) 581 struct spi_message *msg)
547{ 582{
583 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
548 struct device *dev = &sdd->pdev->dev; 584 struct device *dev = &sdd->pdev->dev;
549 struct spi_transfer *xfer; 585 struct spi_transfer *xfer;
550 586
@@ -553,6 +589,9 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
553 589
554 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 590 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
555 591
592 if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
593 continue;
594
556 if (xfer->rx_buf != NULL 595 if (xfer->rx_buf != NULL
557 && xfer->rx_dma != XFER_DMAADDR_INVALID) 596 && xfer->rx_dma != XFER_DMAADDR_INVALID)
558 dma_unmap_single(dev, xfer->rx_dma, 597 dma_unmap_single(dev, xfer->rx_dma,
@@ -608,6 +647,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
608 bpw = xfer->bits_per_word ? : spi->bits_per_word; 647 bpw = xfer->bits_per_word ? : spi->bits_per_word;
609 speed = xfer->speed_hz ? : spi->max_speed_hz; 648 speed = xfer->speed_hz ? : spi->max_speed_hz;
610 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 }
657
611 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { 658 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
612 sdd->cur_bpw = bpw; 659 sdd->cur_bpw = bpw;
613 sdd->cur_speed = speed; 660 sdd->cur_speed = speed;
@@ -798,7 +845,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
798 struct s3c64xx_spi_driver_data *sdd; 845 struct s3c64xx_spi_driver_data *sdd;
799 struct s3c64xx_spi_info *sci; 846 struct s3c64xx_spi_info *sci;
800 struct spi_message *msg; 847 struct spi_message *msg;
801 u32 psr, speed;
802 unsigned long flags; 848 unsigned long flags;
803 int err = 0; 849 int err = 0;
804 850
@@ -841,32 +887,37 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
841 } 887 }
842 888
843 /* Check if we can provide the requested rate */ 889 /* Check if we can provide the requested rate */
844 speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */ 890 if (!sci->clk_from_cmu) {
845 891 u32 psr, speed;
846 if (spi->max_speed_hz > speed) 892
847 spi->max_speed_hz = speed; 893 /* Max possible */
848 894 speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
849 psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1; 895
850 psr &= S3C64XX_SPI_PSR_MASK; 896 if (spi->max_speed_hz > speed)
851 if (psr == S3C64XX_SPI_PSR_MASK) 897 spi->max_speed_hz = speed;
852 psr--; 898
899 psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
900 psr &= S3C64XX_SPI_PSR_MASK;
901 if (psr == S3C64XX_SPI_PSR_MASK)
902 psr--;
903
904 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
905 if (spi->max_speed_hz < speed) {
906 if (psr+1 < S3C64XX_SPI_PSR_MASK) {
907 psr++;
908 } else {
909 err = -EINVAL;
910 goto setup_exit;
911 }
912 }
853 913
854 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); 914 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
855 if (spi->max_speed_hz < speed) { 915 if (spi->max_speed_hz >= speed)
856 if (psr+1 < S3C64XX_SPI_PSR_MASK) { 916 spi->max_speed_hz = speed;
857 psr++; 917 else
858 } else {
859 err = -EINVAL; 918 err = -EINVAL;
860 goto setup_exit;
861 }
862 } 919 }
863 920
864 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
865 if (spi->max_speed_hz >= speed)
866 spi->max_speed_hz = speed;
867 else
868 err = -EINVAL;
869
870setup_exit: 921setup_exit:
871 922
872 /* setup() returns with device de-selected */ 923 /* setup() returns with device de-selected */
@@ -888,7 +939,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
888 /* Disable Interrupts - we use Polling if not DMA mode */ 939 /* Disable Interrupts - we use Polling if not DMA mode */
889 writel(0, regs + S3C64XX_SPI_INT_EN); 940 writel(0, regs + S3C64XX_SPI_INT_EN);
890 941
891 writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT, 942 if (!sci->clk_from_cmu)
943 writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
892 regs + S3C64XX_SPI_CLK_CFG); 944 regs + S3C64XX_SPI_CLK_CFG);
893 writel(0, regs + S3C64XX_SPI_MODE_CFG); 945 writel(0, regs + S3C64XX_SPI_MODE_CFG);
894 writel(0, regs + S3C64XX_SPI_PACKET_CNT); 946 writel(0, regs + S3C64XX_SPI_PACKET_CNT);