Skip to content

Commit 625de18

Browse files
LeSpockybroonie
authored andcommitted
spi: atmel-quadspi: Add cs_hold and cs_inactive setting support
spi-cs-inactive-delay-ns in dts is cs_inactive in spi core, and it maps to DLYCS (Minimum Inactive QCS Delay) in QSPI Mode Register (QSPI_MR). spi-cs-hold-delay-ns in dts is cs_hold in spi core, and it maps to DLYBCT (Delay Between Consecutive Transfers) in QSPI_MR. That one can be set to other values than 0 only if the chip is not in Serial Memory Mode (SMM), it must be written to '0' however when in SMM. Tested on SAM9X60 based board with FPGA implementing custom SPI Memory protocol. Signed-off-by: Alexander Dahl <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 7a4b3eb commit 625de18

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

drivers/spi/atmel-quadspi.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,21 +516,45 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
516516
struct spi_controller *ctrl = spi->controller;
517517
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
518518
unsigned long clk_rate;
519+
u32 cs_inactive;
519520
u32 cs_setup;
521+
u32 cs_hold;
520522
int delay;
521523
int ret;
522524

523-
delay = spi_delay_to_ns(&spi->cs_setup, NULL);
524-
if (delay <= 0)
525-
return delay;
526-
527525
clk_rate = clk_get_rate(aq->pclk);
528526
if (!clk_rate)
529527
return -EINVAL;
530528

529+
/* hold */
530+
delay = spi_delay_to_ns(&spi->cs_hold, NULL);
531+
if (aq->mr & QSPI_MR_SMM) {
532+
if (delay > 0)
533+
dev_warn(&aq->pdev->dev,
534+
"Ignoring cs_hold, must be 0 in Serial Memory Mode.\n");
535+
cs_hold = 0;
536+
} else {
537+
delay = spi_delay_to_ns(&spi->cs_hold, NULL);
538+
if (delay < 0)
539+
return delay;
540+
541+
cs_hold = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)), 32000);
542+
}
543+
544+
/* setup */
545+
delay = spi_delay_to_ns(&spi->cs_setup, NULL);
546+
if (delay < 0)
547+
return delay;
548+
531549
cs_setup = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)),
532550
1000);
533551

552+
/* inactive */
553+
delay = spi_delay_to_ns(&spi->cs_inactive, NULL);
554+
if (delay < 0)
555+
return delay;
556+
cs_inactive = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)), 1000);
557+
534558
ret = pm_runtime_resume_and_get(ctrl->dev.parent);
535559
if (ret < 0)
536560
return ret;
@@ -539,6 +563,10 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
539563
aq->scr |= QSPI_SCR_DLYBS(cs_setup);
540564
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
541565

566+
aq->mr &= ~(QSPI_MR_DLYBCT_MASK | QSPI_MR_DLYCS_MASK);
567+
aq->mr |= QSPI_MR_DLYBCT(cs_hold) | QSPI_MR_DLYCS(cs_inactive);
568+
atmel_qspi_write(aq->mr, aq, QSPI_MR);
569+
542570
pm_runtime_mark_last_busy(ctrl->dev.parent);
543571
pm_runtime_put_autosuspend(ctrl->dev.parent);
544572

0 commit comments

Comments
 (0)