diff options
Diffstat (limited to 'drivers/spi/spi-rockchip.c')
-rw-r--r-- | drivers/spi/spi-rockchip.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index f96ea8a38d64..87bc16f491f0 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c | |||
@@ -145,6 +145,9 @@ | |||
145 | #define RXBUSY (1 << 0) | 145 | #define RXBUSY (1 << 0) |
146 | #define TXBUSY (1 << 1) | 146 | #define TXBUSY (1 << 1) |
147 | 147 | ||
148 | /* sclk_out: spi master internal logic in rk3x can support 50Mhz */ | ||
149 | #define MAX_SCLK_OUT 50000000 | ||
150 | |||
148 | enum rockchip_ssi_type { | 151 | enum rockchip_ssi_type { |
149 | SSI_MOTO_SPI = 0, | 152 | SSI_MOTO_SPI = 0, |
150 | SSI_TI_SSP, | 153 | SSI_TI_SSP, |
@@ -325,6 +328,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master, | |||
325 | 328 | ||
326 | spin_unlock_irqrestore(&rs->lock, flags); | 329 | spin_unlock_irqrestore(&rs->lock, flags); |
327 | 330 | ||
331 | spi_enable_chip(rs, 0); | ||
332 | |||
328 | return 0; | 333 | return 0; |
329 | } | 334 | } |
330 | 335 | ||
@@ -381,6 +386,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs) | |||
381 | if (rs->tx) | 386 | if (rs->tx) |
382 | wait_for_idle(rs); | 387 | wait_for_idle(rs); |
383 | 388 | ||
389 | spi_enable_chip(rs, 0); | ||
390 | |||
384 | return 0; | 391 | return 0; |
385 | } | 392 | } |
386 | 393 | ||
@@ -392,8 +399,10 @@ static void rockchip_spi_dma_rxcb(void *data) | |||
392 | spin_lock_irqsave(&rs->lock, flags); | 399 | spin_lock_irqsave(&rs->lock, flags); |
393 | 400 | ||
394 | rs->state &= ~RXBUSY; | 401 | rs->state &= ~RXBUSY; |
395 | if (!(rs->state & TXBUSY)) | 402 | if (!(rs->state & TXBUSY)) { |
403 | spi_enable_chip(rs, 0); | ||
396 | spi_finalize_current_transfer(rs->master); | 404 | spi_finalize_current_transfer(rs->master); |
405 | } | ||
397 | 406 | ||
398 | spin_unlock_irqrestore(&rs->lock, flags); | 407 | spin_unlock_irqrestore(&rs->lock, flags); |
399 | } | 408 | } |
@@ -409,8 +418,10 @@ static void rockchip_spi_dma_txcb(void *data) | |||
409 | spin_lock_irqsave(&rs->lock, flags); | 418 | spin_lock_irqsave(&rs->lock, flags); |
410 | 419 | ||
411 | rs->state &= ~TXBUSY; | 420 | rs->state &= ~TXBUSY; |
412 | if (!(rs->state & RXBUSY)) | 421 | if (!(rs->state & RXBUSY)) { |
422 | spi_enable_chip(rs, 0); | ||
413 | spi_finalize_current_transfer(rs->master); | 423 | spi_finalize_current_transfer(rs->master); |
424 | } | ||
414 | 425 | ||
415 | spin_unlock_irqrestore(&rs->lock, flags); | 426 | spin_unlock_irqrestore(&rs->lock, flags); |
416 | } | 427 | } |
@@ -496,12 +507,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs) | |||
496 | dmacr |= RF_DMA_EN; | 507 | dmacr |= RF_DMA_EN; |
497 | } | 508 | } |
498 | 509 | ||
510 | if (WARN_ON(rs->speed > MAX_SCLK_OUT)) | ||
511 | rs->speed = MAX_SCLK_OUT; | ||
512 | |||
513 | /* the minimum divsor is 2 */ | ||
514 | if (rs->max_freq < 2 * rs->speed) { | ||
515 | clk_set_rate(rs->spiclk, 2 * rs->speed); | ||
516 | rs->max_freq = clk_get_rate(rs->spiclk); | ||
517 | } | ||
518 | |||
499 | /* div doesn't support odd number */ | 519 | /* div doesn't support odd number */ |
500 | div = max_t(u32, rs->max_freq / rs->speed, 1); | 520 | div = max_t(u32, rs->max_freq / rs->speed, 1); |
501 | div = (div + 1) & 0xfffe; | 521 | div = (div + 1) & 0xfffe; |
502 | 522 | ||
503 | spi_enable_chip(rs, 0); | ||
504 | |||
505 | writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); | 523 | writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); |
506 | 524 | ||
507 | writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); | 525 | writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); |
@@ -515,8 +533,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs) | |||
515 | spi_set_clk(rs, div); | 533 | spi_set_clk(rs, div); |
516 | 534 | ||
517 | dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); | 535 | dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); |
518 | |||
519 | spi_enable_chip(rs, 1); | ||
520 | } | 536 | } |
521 | 537 | ||
522 | static int rockchip_spi_transfer_one( | 538 | static int rockchip_spi_transfer_one( |
@@ -524,7 +540,7 @@ static int rockchip_spi_transfer_one( | |||
524 | struct spi_device *spi, | 540 | struct spi_device *spi, |
525 | struct spi_transfer *xfer) | 541 | struct spi_transfer *xfer) |
526 | { | 542 | { |
527 | int ret = 0; | 543 | int ret = 1; |
528 | struct rockchip_spi *rs = spi_master_get_devdata(master); | 544 | struct rockchip_spi *rs = spi_master_get_devdata(master); |
529 | 545 | ||
530 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && | 546 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && |
@@ -556,17 +572,27 @@ static int rockchip_spi_transfer_one( | |||
556 | rs->tmode = CR0_XFM_RO; | 572 | rs->tmode = CR0_XFM_RO; |
557 | 573 | ||
558 | /* we need prepare dma before spi was enabled */ | 574 | /* we need prepare dma before spi was enabled */ |
559 | if (master->can_dma && master->can_dma(master, spi, xfer)) { | 575 | if (master->can_dma && master->can_dma(master, spi, xfer)) |
560 | rs->use_dma = 1; | 576 | rs->use_dma = 1; |
561 | rockchip_spi_prepare_dma(rs); | 577 | else |
562 | } else { | ||
563 | rs->use_dma = 0; | 578 | rs->use_dma = 0; |
564 | } | ||
565 | 579 | ||
566 | rockchip_spi_config(rs); | 580 | rockchip_spi_config(rs); |
567 | 581 | ||
568 | if (!rs->use_dma) | 582 | if (rs->use_dma) { |
583 | if (rs->tmode == CR0_XFM_RO) { | ||
584 | /* rx: dma must be prepared first */ | ||
585 | rockchip_spi_prepare_dma(rs); | ||
586 | spi_enable_chip(rs, 1); | ||
587 | } else { | ||
588 | /* tx or tr: spi must be enabled first */ | ||
589 | spi_enable_chip(rs, 1); | ||
590 | rockchip_spi_prepare_dma(rs); | ||
591 | } | ||
592 | } else { | ||
593 | spi_enable_chip(rs, 1); | ||
569 | ret = rockchip_spi_pio_transfer(rs); | 594 | ret = rockchip_spi_pio_transfer(rs); |
595 | } | ||
570 | 596 | ||
571 | return ret; | 597 | return ret; |
572 | } | 598 | } |