We are using a SoM with an i.MX8M-Mini and tried to use the FlexSPI to communicate with an FPGA which simulates a flash memory using 1-1-4 or 1-4-4 transfer mode.
To get that working we had to fix or extend the linux drivers at the following places:
1) ...\linux-imx\drivers\mtd\spi-nor\spi-nor.c
Support of the 1-4-4-DTR read-mode is read from the wrong bit of the SFDP table:
=> inside `static const struct sfdp_bfpt_read sfdp_bfpt_reads[]`
/* Fast Read 1-4-4-DTR */
{
SNOR_HWCAPS_READ_1_4_4_DTR,
BFPT_DWORD(1), BIT(21), /* Supported bit */
BFPT_DWORD(3), 0, /* Settings */
SNOR_PROTO_1_4_4_DTR,
},
to
/* Fast Read 1-4-4-DTR */
{
SNOR_HWCAPS_READ_1_4_4_DTR,
BFPT_DWORD(1), BIT(19), /* Supported bit */
BFPT_DWORD(3), 0, /* Settings */
SNOR_PROTO_1_4_4_DTR,
},
2) ...\linux-imx\drivers\mtd\spi-nor\fsl-flexspi.c
HW-Caps of the controller are missing support for 1-1-4 and 1-4-4:
=> inside `static int fsl_flexspi_probe(struct platform_device *pdev)`
struct spi_nor_hwcaps hwcaps = {
.mask = SNOR_HWCAPS_PP,
};
to
struct spi_nor_hwcaps hwcaps = {
.mask = SNOR_HWCAPS_READ_1_1_4 |
SNOR_HWCAPS_READ_1_4_4 |
SNOR_HWCAPS_PP,
};
3) ...\linux-imx\drivers\mtd\spi-nor\fsl-flexspi.c
LUT-initialization is not performed for 1-4-4:
=> inside `static void fsl_flexspi_init_lut(struct fsl_flexspi *flex)`
/* DDR Quad I/O Read */
} else if (op == SPINOR_OP_READ_1_4_4_DTR || op == SPINOR_OP_READ_1_4_4_DTR_4B) {
/* read mode : 1-4-4, such as Spansion s25fl128s. */
to
/* DDR Quad I/O Read */
} else if (op == SPINOR_OP_READ_1_4_4 || op == SPINOR_OP_READ_1_4_4_4B
|| op == SPINOR_OP_READ_1_4_4_DTR || op == SPINOR_OP_READ_1_4_4_DTR_4B) {
/* read mode : 1-4-4, such as Spansion s25fl128s. */
4) ...\linux-imx\drivers\mtd\spi-nor\fsl-flexspi.c
Sequence Id for 1-4-4 missing
=> inside `static int fsl_flexspi_get_seqid(struct fsl_flexspi *flex, u8 cmd)`
switch (cmd) {
case SPINOR_OP_READ_1_1_4_DTR:
case SPINOR_OP_READ_1_8_8_DTR_4B:
case SPINOR_OP_READ_1_4_4_DTR:
case SPINOR_OP_READ_1_4_4_DTR_4B:
case SPINOR_OP_READ_1_1_4_4B:
case SPINOR_OP_READ_1_1_4:
case SPINOR_OP_READ_4B:
case SPINOR_OP_READ:
return SEQID_QUAD_READ;
to
switch (cmd) {
case SPINOR_OP_READ_1_1_4_DTR:
case SPINOR_OP_READ_1_8_8_DTR_4B:
case SPINOR_OP_READ_1_4_4_DTR:
case SPINOR_OP_READ_1_4_4_DTR_4B:
case SPINOR_OP_READ_1_1_4_4B:
case SPINOR_OP_READ_1_1_4:
case SPINOR_OP_READ_1_4_4_4B:
case SPINOR_OP_READ_1_4_4:
case SPINOR_OP_READ_4B:
case SPINOR_OP_READ:
return SEQID_QUAD_READ;