Skip to content

Commit a9f3ac6

Browse files
committed
spi: spi-nxp-fspi: add the support for sample data from DQS pad
JIRA: https://issues.redhat.com/browse/RHEL-104570 commit c07f270 Author: Haibo Chen <haibo.chen@nxp.com> Date: Wed Sep 17 15:27:09 2025 +0800 spi: spi-nxp-fspi: add the support for sample data from DQS pad flexspi define four mode for sample clock source selection. Here is the list of modes: mode 0: Dummy Read strobe generated by FlexSPI Controller and loopback internally mode 1: Dummy Read strobe generated by FlexSPI Controller and loopback from DQS pad mode 2: Reserved mode 3: Flash provided Read strobe and input from DQS pad In default, flexspi use mode 0 after reset. And for DTR mode, flexspi only support 8D-8D-8D mode. For 8D-8D-8D mode, IC suggest to use mode 3, otherwise read always get incorrect data. For DTR mode, flexspi will automatically div 2 of the root clock and output to device. the formula is: device_clock = root_clock / (is_dtr ? 2 : 1) So correct the clock rate setting for DTR mode to get the max performance. Signed-off-by: Haibo Chen <haibo.chen@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/20250917-flexspi-ddr-v2-4-bb9fe2a01889@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Mattijs Korpershoek <mkorpershoek@redhat.com>
1 parent 3fede03 commit a9f3ac6

File tree

1 file changed

+53
-3
lines changed

1 file changed

+53
-3
lines changed

drivers/spi/spi-nxp-fspi.c

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,8 @@ struct nxp_fspi {
399399
struct mutex lock;
400400
struct pm_qos_request pm_qos_req;
401401
int selected;
402-
#define FSPI_NEED_INIT (1 << 0)
402+
#define FSPI_NEED_INIT BIT(0)
403+
#define FSPI_DTR_MODE BIT(1)
403404
int flags;
404405
};
405406

@@ -655,6 +656,40 @@ static void nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
655656
return;
656657
}
657658

659+
/*
660+
* Sample Clock source selection for Flash Reading
661+
* Four modes defined by fspi:
662+
* mode 0: Dummy Read strobe generated by FlexSPI Controller
663+
* and loopback internally
664+
* mode 1: Dummy Read strobe generated by FlexSPI Controller
665+
* and loopback from DQS pad
666+
* mode 2: Reserved
667+
* mode 3: Flash provided Read strobe and input from DQS pad
668+
*
669+
* fspi default use mode 0 after reset
670+
*/
671+
static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
672+
bool op_is_dtr)
673+
{
674+
u32 reg;
675+
676+
/*
677+
* For 8D-8D-8D mode, need to use mode 3 (Flash provided Read
678+
* strobe and input from DQS pad), otherwise read operaton may
679+
* meet issue.
680+
* This mode require flash device connect the DQS pad on board.
681+
* For other modes, still use mode 0, keep align with before.
682+
* spi_nor_suspend will disable 8D-8D-8D mode, also need to
683+
* change the mode back to mode 0.
684+
*/
685+
reg = fspi_readl(f, f->iobase + FSPI_MCR0);
686+
if (op_is_dtr)
687+
reg |= FSPI_MCR0_RXCLKSRC(3);
688+
else /*select mode 0 */
689+
reg &= ~FSPI_MCR0_RXCLKSRC(3);
690+
fspi_writel(f, reg, f->iobase + FSPI_MCR0);
691+
}
692+
658693
static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
659694
{
660695
int ret;
@@ -736,15 +771,18 @@ static void nxp_fspi_dll_override(struct nxp_fspi *f)
736771
static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
737772
const struct spi_mem_op *op)
738773
{
774+
/* flexspi only support one DTR mode: 8D-8D-8D */
775+
bool op_is_dtr = op->cmd.dtr && op->addr.dtr && op->dummy.dtr && op->data.dtr;
739776
unsigned long rate = op->max_freq;
740777
int ret;
741778
uint64_t size_kb;
742779

743780
/*
744781
* Return, if previously selected target device is same as current
745-
* requested target device.
782+
* requested target device. Also the DTR or STR mode do not change.
746783
*/
747-
if (f->selected == spi_get_chipselect(spi, 0))
784+
if ((f->selected == spi_get_chipselect(spi, 0)) &&
785+
(!!(f->flags & FSPI_DTR_MODE) == op_is_dtr))
748786
return;
749787

750788
/* Reset FLSHxxCR0 registers */
@@ -761,6 +799,18 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
761799

762800
dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0));
763801

802+
nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr);
803+
804+
if (op_is_dtr) {
805+
f->flags |= FSPI_DTR_MODE;
806+
/* For DTR mode, flexspi will default div 2 and output to device.
807+
* so here to config the root clock to 2 * device rate.
808+
*/
809+
rate = rate * 2;
810+
} else {
811+
f->flags &= ~FSPI_DTR_MODE;
812+
}
813+
764814
nxp_fspi_clk_disable_unprep(f);
765815

766816
ret = clk_set_rate(f->clk, rate);

0 commit comments

Comments
 (0)