Skip to content

Commit faef0c6

Browse files
committed
spi: spi-nxp-fspi: add DTR mode support
Merge series from Haibo Chen <[email protected]>: this patch set add DTR mode support for flexspi. For DTR mode, flexspi only support 8D-8D-8D mode. Patch 1~2 extract nxp_fspi_dll_override(), prepare for adding the DTR mode. in nor suspend, it will disable DTR mode, and enable DTR mode back in nor resume. this require the flexspi driver has the ability to set back to dll override mode in STR mode when clock rate < 100MHz. Patch 3 Add the DDR LUT command support. flexspi use LUT command to handle the dtr/str mode. Patch 4 add the logic of sample clock source selection for STR/DTR mode STR use the default mode 0, sample based on the internal dummy pad. DTR use the mode 3, sample based on the external DQS pad, so this board and device connect the DQS pad. adjust the clock rate for DTR mode, when detect the DDR LUT command, flexspi will automatically div 2 of the root clock and output to device. Patch 5 finally add the DTR support in default after the upper 4 patches's prepareation. Since lx2160a do not implement DQS pad, so can't support this DTR mode.
2 parents a24802b + 0f67557 commit faef0c6

1 file changed

Lines changed: 98 additions & 17 deletions

File tree

drivers/spi/spi-nxp-fspi.c

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@
330330

331331
/* Access flash memory using IP bus only */
332332
#define FSPI_QUIRK_USE_IP_ONLY BIT(0)
333+
/* Disable DTR */
334+
#define FSPI_QUIRK_DISABLE_DTR BIT(1)
333335

334336
struct nxp_fspi_devtype_data {
335337
unsigned int rxfifo;
@@ -344,7 +346,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
344346
.rxfifo = SZ_512, /* (64 * 64 bits) */
345347
.txfifo = SZ_1K, /* (128 * 64 bits) */
346348
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
347-
.quirks = 0,
349+
.quirks = FSPI_QUIRK_DISABLE_DTR,
348350
.lut_num = 32,
349351
.little_endian = true, /* little-endian */
350352
};
@@ -399,7 +401,8 @@ struct nxp_fspi {
399401
struct mutex lock;
400402
struct pm_qos_request pm_qos_req;
401403
int selected;
402-
#define FSPI_NEED_INIT (1 << 0)
404+
#define FSPI_NEED_INIT BIT(0)
405+
#define FSPI_DTR_MODE BIT(1)
403406
int flags;
404407
};
405408

@@ -559,20 +562,29 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
559562
u32 target_lut_reg;
560563

561564
/* cmd */
562-
lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
563-
op->cmd.opcode);
565+
if (op->cmd.dtr) {
566+
lutval[0] |= LUT_DEF(0, LUT_CMD_DDR, LUT_PAD(op->cmd.buswidth),
567+
op->cmd.opcode >> 8);
568+
lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_CMD_DDR,
569+
LUT_PAD(op->cmd.buswidth),
570+
op->cmd.opcode & 0xFF);
571+
lutidx++;
572+
} else {
573+
lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
574+
op->cmd.opcode);
575+
}
564576

565577
/* addr bytes */
566578
if (op->addr.nbytes) {
567-
lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
579+
lutval[lutidx / 2] |= LUT_DEF(lutidx, op->addr.dtr ? LUT_ADDR_DDR : LUT_ADDR,
568580
LUT_PAD(op->addr.buswidth),
569581
op->addr.nbytes * 8);
570582
lutidx++;
571583
}
572584

573585
/* dummy bytes, if needed */
574586
if (op->dummy.nbytes) {
575-
lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_DUMMY,
587+
lutval[lutidx / 2] |= LUT_DEF(lutidx, op->dummy.dtr ? LUT_DUMMY_DDR : LUT_DUMMY,
576588
/*
577589
* Due to FlexSPI controller limitation number of PAD for dummy
578590
* buswidth needs to be programmed as equal to data buswidth.
@@ -587,7 +599,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
587599
if (op->data.nbytes) {
588600
lutval[lutidx / 2] |= LUT_DEF(lutidx,
589601
op->data.dir == SPI_MEM_DATA_IN ?
590-
LUT_NXP_READ : LUT_NXP_WRITE,
602+
(op->data.dtr ? LUT_READ_DDR : LUT_NXP_READ) :
603+
(op->data.dtr ? LUT_WRITE_DDR : LUT_NXP_WRITE),
591604
LUT_PAD(op->data.buswidth),
592605
0);
593606
lutidx++;
@@ -645,6 +658,40 @@ static void nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
645658
return;
646659
}
647660

661+
/*
662+
* Sample Clock source selection for Flash Reading
663+
* Four modes defined by fspi:
664+
* mode 0: Dummy Read strobe generated by FlexSPI Controller
665+
* and loopback internally
666+
* mode 1: Dummy Read strobe generated by FlexSPI Controller
667+
* and loopback from DQS pad
668+
* mode 2: Reserved
669+
* mode 3: Flash provided Read strobe and input from DQS pad
670+
*
671+
* fspi default use mode 0 after reset
672+
*/
673+
static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f,
674+
bool op_is_dtr)
675+
{
676+
u32 reg;
677+
678+
/*
679+
* For 8D-8D-8D mode, need to use mode 3 (Flash provided Read
680+
* strobe and input from DQS pad), otherwise read operaton may
681+
* meet issue.
682+
* This mode require flash device connect the DQS pad on board.
683+
* For other modes, still use mode 0, keep align with before.
684+
* spi_nor_suspend will disable 8D-8D-8D mode, also need to
685+
* change the mode back to mode 0.
686+
*/
687+
reg = fspi_readl(f, f->iobase + FSPI_MCR0);
688+
if (op_is_dtr)
689+
reg |= FSPI_MCR0_RXCLKSRC(3);
690+
else /*select mode 0 */
691+
reg &= ~FSPI_MCR0_RXCLKSRC(3);
692+
fspi_writel(f, reg, f->iobase + FSPI_MCR0);
693+
}
694+
648695
static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
649696
{
650697
int ret;
@@ -674,6 +721,17 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
674721
dev_warn(f->dev, "DLL lock failed, please fix it!\n");
675722
}
676723

724+
/*
725+
* Config the DLL register to default value, enable the target clock delay
726+
* line delay cell override mode, and use 1 fixed delay cell in DLL delay
727+
* chain, this is the suggested setting when clock rate < 100MHz.
728+
*/
729+
static void nxp_fspi_dll_override(struct nxp_fspi *f)
730+
{
731+
fspi_writel(f, FSPI_DLLACR_OVRDEN, f->iobase + FSPI_DLLACR);
732+
fspi_writel(f, FSPI_DLLBCR_OVRDEN, f->iobase + FSPI_DLLBCR);
733+
}
734+
677735
/*
678736
* In FlexSPI controller, flash access is based on value of FSPI_FLSHXXCR0
679737
* register and start base address of the target device.
@@ -715,15 +773,18 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f)
715773
static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
716774
const struct spi_mem_op *op)
717775
{
776+
/* flexspi only support one DTR mode: 8D-8D-8D */
777+
bool op_is_dtr = op->cmd.dtr && op->addr.dtr && op->dummy.dtr && op->data.dtr;
718778
unsigned long rate = op->max_freq;
719779
int ret;
720780
uint64_t size_kb;
721781

722782
/*
723783
* Return, if previously selected target device is same as current
724-
* requested target device.
784+
* requested target device. Also the DTR or STR mode do not change.
725785
*/
726-
if (f->selected == spi_get_chipselect(spi, 0))
786+
if ((f->selected == spi_get_chipselect(spi, 0)) &&
787+
(!!(f->flags & FSPI_DTR_MODE) == op_is_dtr))
727788
return;
728789

729790
/* Reset FLSHxxCR0 registers */
@@ -740,6 +801,18 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
740801

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

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

745818
ret = clk_set_rate(f->clk, rate);
@@ -756,6 +829,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi,
756829
*/
757830
if (rate > 100000000)
758831
nxp_fspi_dll_calibration(f);
832+
else
833+
nxp_fspi_dll_override(f);
759834

760835
f->selected = spi_get_chipselect(spi, 0);
761836
}
@@ -1071,13 +1146,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
10711146
/* Disable the module */
10721147
fspi_writel(f, FSPI_MCR0_MDIS, base + FSPI_MCR0);
10731148

1074-
/*
1075-
* Config the DLL register to default value, enable the target clock delay
1076-
* line delay cell override mode, and use 1 fixed delay cell in DLL delay
1077-
* chain, this is the suggested setting when clock rate < 100MHz.
1078-
*/
1079-
fspi_writel(f, FSPI_DLLACR_OVRDEN, base + FSPI_DLLACR);
1080-
fspi_writel(f, FSPI_DLLBCR_OVRDEN, base + FSPI_DLLBCR);
1149+
nxp_fspi_dll_override(f);
10811150

10821151
/* enable module */
10831152
fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) |
@@ -1164,6 +1233,13 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = {
11641233
};
11651234

11661235
static const struct spi_controller_mem_caps nxp_fspi_mem_caps = {
1236+
.dtr = true,
1237+
.swap16 = false,
1238+
.per_op_freq = true,
1239+
};
1240+
1241+
static const struct spi_controller_mem_caps nxp_fspi_mem_caps_disable_dtr = {
1242+
.dtr = false,
11671243
.per_op_freq = true,
11681244
};
11691245

@@ -1279,7 +1355,12 @@ static int nxp_fspi_probe(struct platform_device *pdev)
12791355
ctlr->bus_num = -1;
12801356
ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT;
12811357
ctlr->mem_ops = &nxp_fspi_mem_ops;
1282-
ctlr->mem_caps = &nxp_fspi_mem_caps;
1358+
1359+
if (f->devtype_data->quirks & FSPI_QUIRK_DISABLE_DTR)
1360+
ctlr->mem_caps = &nxp_fspi_mem_caps_disable_dtr;
1361+
else
1362+
ctlr->mem_caps = &nxp_fspi_mem_caps;
1363+
12831364
ctlr->dev.of_node = np;
12841365

12851366
ret = devm_add_action_or_reset(dev, nxp_fspi_cleanup, f);

0 commit comments

Comments
 (0)