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.c162
1 files changed, 106 insertions, 56 deletions
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index c3038da2648a..8945e201e42e 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -116,9 +116,7 @@
116 (((i)->fifo_lvl_mask + 1))) \ 116 (((i)->fifo_lvl_mask + 1))) \
117 ? 1 : 0) 117 ? 1 : 0)
118 118
119#define S3C64XX_SPI_ST_TX_DONE(v, i) ((((v) >> (i)->rx_lvl_offset) & \ 119#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0)
120 (((i)->fifo_lvl_mask + 1) << 1)) \
121 ? 1 : 0)
122#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask) 120#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
123#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask) 121#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
124 122
@@ -261,15 +259,25 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
261 chcfg |= S3C64XX_SPI_CH_TXCH_ON; 259 chcfg |= S3C64XX_SPI_CH_TXCH_ON;
262 if (dma_mode) { 260 if (dma_mode) {
263 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; 261 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
264 s3c2410_dma_config(sdd->tx_dmach, 1); 262 s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
265 s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, 263 s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
266 xfer->tx_dma, xfer->len); 264 xfer->tx_dma, xfer->len);
267 s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); 265 s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
268 } else { 266 } else {
269 unsigned char *buf = (unsigned char *) xfer->tx_buf; 267 switch (sdd->cur_bpw) {
270 int i = 0; 268 case 32:
271 while (i < xfer->len) 269 iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
272 writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA); 270 xfer->tx_buf, xfer->len / 4);
271 break;
272 case 16:
273 iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
274 xfer->tx_buf, xfer->len / 2);
275 break;
276 default:
277 iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
278 xfer->tx_buf, xfer->len);
279 break;
280 }
273 } 281 }
274 } 282 }
275 283
@@ -286,7 +294,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
286 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) 294 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
287 | S3C64XX_SPI_PACKET_CNT_EN, 295 | S3C64XX_SPI_PACKET_CNT_EN,
288 regs + S3C64XX_SPI_PACKET_CNT); 296 regs + S3C64XX_SPI_PACKET_CNT);
289 s3c2410_dma_config(sdd->rx_dmach, 1); 297 s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
290 s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, 298 s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
291 xfer->rx_dma, xfer->len); 299 xfer->rx_dma, xfer->len);
292 s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); 300 s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
@@ -366,20 +374,26 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
366 return -EIO; 374 return -EIO;
367 } 375 }
368 } else { 376 } else {
369 unsigned char *buf;
370 int i;
371
372 /* If it was only Tx */ 377 /* If it was only Tx */
373 if (xfer->rx_buf == NULL) { 378 if (xfer->rx_buf == NULL) {
374 sdd->state &= ~TXBUSY; 379 sdd->state &= ~TXBUSY;
375 return 0; 380 return 0;
376 } 381 }
377 382
378 i = 0; 383 switch (sdd->cur_bpw) {
379 buf = xfer->rx_buf; 384 case 32:
380 while (i < xfer->len) 385 ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
381 buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA); 386 xfer->rx_buf, xfer->len / 4);
382 387 break;
388 case 16:
389 ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
390 xfer->rx_buf, xfer->len / 2);
391 break;
392 default:
393 ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
394 xfer->rx_buf, xfer->len);
395 break;
396 }
383 sdd->state &= ~RXBUSY; 397 sdd->state &= ~RXBUSY;
384 } 398 }
385 399
@@ -399,13 +413,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
399 413
400static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) 414static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
401{ 415{
416 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
402 void __iomem *regs = sdd->regs; 417 void __iomem *regs = sdd->regs;
403 u32 val; 418 u32 val;
404 419
405 /* Disable Clock */ 420 /* Disable Clock */
406 val = readl(regs + S3C64XX_SPI_CLK_CFG); 421 if (sci->clk_from_cmu) {
407 val &= ~S3C64XX_SPI_ENCLK_ENABLE; 422 clk_disable(sdd->src_clk);
408 writel(val, regs + S3C64XX_SPI_CLK_CFG); 423 } else {
424 val = readl(regs + S3C64XX_SPI_CLK_CFG);
425 val &= ~S3C64XX_SPI_ENCLK_ENABLE;
426 writel(val, regs + S3C64XX_SPI_CLK_CFG);
427 }
409 428
410 /* Set Polarity and Phase */ 429 /* Set Polarity and Phase */
411 val = readl(regs + S3C64XX_SPI_CH_CFG); 430 val = readl(regs + S3C64XX_SPI_CH_CFG);
@@ -429,29 +448,39 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
429 switch (sdd->cur_bpw) { 448 switch (sdd->cur_bpw) {
430 case 32: 449 case 32:
431 val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD; 450 val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
451 val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
432 break; 452 break;
433 case 16: 453 case 16:
434 val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD; 454 val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
455 val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
435 break; 456 break;
436 default: 457 default:
437 val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE; 458 val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
459 val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
438 break; 460 break;
439 } 461 }
440 val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
441 462
442 writel(val, regs + S3C64XX_SPI_MODE_CFG); 463 writel(val, regs + S3C64XX_SPI_MODE_CFG);
443 464
444 /* Configure Clock */ 465 if (sci->clk_from_cmu) {
445 val = readl(regs + S3C64XX_SPI_CLK_CFG); 466 /* Configure Clock */
446 val &= ~S3C64XX_SPI_PSR_MASK; 467 /* There is half-multiplier before the SPI */
447 val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1) 468 clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
448 & S3C64XX_SPI_PSR_MASK); 469 /* Enable Clock */
449 writel(val, regs + S3C64XX_SPI_CLK_CFG); 470 clk_enable(sdd->src_clk);
450 471 } else {
451 /* Enable Clock */ 472 /* Configure Clock */
452 val = readl(regs + S3C64XX_SPI_CLK_CFG); 473 val = readl(regs + S3C64XX_SPI_CLK_CFG);
453 val |= S3C64XX_SPI_ENCLK_ENABLE; 474 val &= ~S3C64XX_SPI_PSR_MASK;
454 writel(val, regs + S3C64XX_SPI_CLK_CFG); 475 val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
476 & S3C64XX_SPI_PSR_MASK);
477 writel(val, regs + S3C64XX_SPI_CLK_CFG);
478
479 /* Enable Clock */
480 val = readl(regs + S3C64XX_SPI_CLK_CFG);
481 val |= S3C64XX_SPI_ENCLK_ENABLE;
482 writel(val, regs + S3C64XX_SPI_CLK_CFG);
483 }
455} 484}
456 485
457static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, 486static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
@@ -499,6 +528,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, 528static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
500 struct spi_message *msg) 529 struct spi_message *msg)
501{ 530{
531 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
502 struct device *dev = &sdd->pdev->dev; 532 struct device *dev = &sdd->pdev->dev;
503 struct spi_transfer *xfer; 533 struct spi_transfer *xfer;
504 534
@@ -514,6 +544,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
514 /* Map until end or first fail */ 544 /* Map until end or first fail */
515 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 545 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
516 546
547 if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
548 continue;
549
517 if (xfer->tx_buf != NULL) { 550 if (xfer->tx_buf != NULL) {
518 xfer->tx_dma = dma_map_single(dev, 551 xfer->tx_dma = dma_map_single(dev,
519 (void *)xfer->tx_buf, xfer->len, 552 (void *)xfer->tx_buf, xfer->len,
@@ -545,6 +578,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, 578static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
546 struct spi_message *msg) 579 struct spi_message *msg)
547{ 580{
581 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
548 struct device *dev = &sdd->pdev->dev; 582 struct device *dev = &sdd->pdev->dev;
549 struct spi_transfer *xfer; 583 struct spi_transfer *xfer;
550 584
@@ -553,6 +587,9 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
553 587
554 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 588 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
555 589
590 if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
591 continue;
592
556 if (xfer->rx_buf != NULL 593 if (xfer->rx_buf != NULL
557 && xfer->rx_dma != XFER_DMAADDR_INVALID) 594 && xfer->rx_dma != XFER_DMAADDR_INVALID)
558 dma_unmap_single(dev, xfer->rx_dma, 595 dma_unmap_single(dev, xfer->rx_dma,
@@ -608,6 +645,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
608 bpw = xfer->bits_per_word ? : spi->bits_per_word; 645 bpw = xfer->bits_per_word ? : spi->bits_per_word;
609 speed = xfer->speed_hz ? : spi->max_speed_hz; 646 speed = xfer->speed_hz ? : spi->max_speed_hz;
610 647
648 if (xfer->len % (bpw / 8)) {
649 dev_err(&spi->dev,
650 "Xfer length(%u) not a multiple of word size(%u)\n",
651 xfer->len, bpw / 8);
652 status = -EIO;
653 goto out;
654 }
655
611 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { 656 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
612 sdd->cur_bpw = bpw; 657 sdd->cur_bpw = bpw;
613 sdd->cur_speed = speed; 658 sdd->cur_speed = speed;
@@ -798,7 +843,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
798 struct s3c64xx_spi_driver_data *sdd; 843 struct s3c64xx_spi_driver_data *sdd;
799 struct s3c64xx_spi_info *sci; 844 struct s3c64xx_spi_info *sci;
800 struct spi_message *msg; 845 struct spi_message *msg;
801 u32 psr, speed;
802 unsigned long flags; 846 unsigned long flags;
803 int err = 0; 847 int err = 0;
804 848
@@ -841,32 +885,37 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
841 } 885 }
842 886
843 /* Check if we can provide the requested rate */ 887 /* Check if we can provide the requested rate */
844 speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */ 888 if (!sci->clk_from_cmu) {
845 889 u32 psr, speed;
846 if (spi->max_speed_hz > speed) 890
847 spi->max_speed_hz = speed; 891 /* Max possible */
848 892 speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
849 psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1; 893
850 psr &= S3C64XX_SPI_PSR_MASK; 894 if (spi->max_speed_hz > speed)
851 if (psr == S3C64XX_SPI_PSR_MASK) 895 spi->max_speed_hz = speed;
852 psr--; 896
897 psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
898 psr &= S3C64XX_SPI_PSR_MASK;
899 if (psr == S3C64XX_SPI_PSR_MASK)
900 psr--;
901
902 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
903 if (spi->max_speed_hz < speed) {
904 if (psr+1 < S3C64XX_SPI_PSR_MASK) {
905 psr++;
906 } else {
907 err = -EINVAL;
908 goto setup_exit;
909 }
910 }
853 911
854 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); 912 speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
855 if (spi->max_speed_hz < speed) { 913 if (spi->max_speed_hz >= speed)
856 if (psr+1 < S3C64XX_SPI_PSR_MASK) { 914 spi->max_speed_hz = speed;
857 psr++; 915 else
858 } else {
859 err = -EINVAL; 916 err = -EINVAL;
860 goto setup_exit;
861 }
862 } 917 }
863 918
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: 919setup_exit:
871 920
872 /* setup() returns with device de-selected */ 921 /* setup() returns with device de-selected */
@@ -888,7 +937,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
888 /* Disable Interrupts - we use Polling if not DMA mode */ 937 /* Disable Interrupts - we use Polling if not DMA mode */
889 writel(0, regs + S3C64XX_SPI_INT_EN); 938 writel(0, regs + S3C64XX_SPI_INT_EN);
890 939
891 writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT, 940 if (!sci->clk_from_cmu)
941 writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
892 regs + S3C64XX_SPI_CLK_CFG); 942 regs + S3C64XX_SPI_CLK_CFG);
893 writel(0, regs + S3C64XX_SPI_MODE_CFG); 943 writel(0, regs + S3C64XX_SPI_MODE_CFG);
894 writel(0, regs + S3C64XX_SPI_PACKET_CNT); 944 writel(0, regs + S3C64XX_SPI_PACKET_CNT);