Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions drivers/flash/flash_mcux_flexspi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,86 @@ static int flash_flexspi_nor_octal_enable(struct flash_flexspi_nor_data *data,
/* Wait for QE bit to complete programming */
return flash_flexspi_nor_wait_bus_busy(data);
}

static int flash_flexspi_nor_octal_enable_s2b3(struct flash_flexspi_nor_data *data,
uint32_t (*flexspi_lut)[MEMC_FLEXSPI_CMD_PER_SEQ])
{
int ret;
uint32_t buffer = 0;
flexspi_transfer_t transfer = {
.deviceAddress = 0x02,
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number 0x02 as deviceAddress appears to be a register address for reading Status Register 2, but lacks explanation. Consider adding a comment or defining this as a named constant like SR2_ADDRESS or STATUS_REG2_ADDR to clarify its purpose.

Copilot uses AI. Check for mistakes.
.port = data->port,
.SeqNumber = 1,
.data = &buffer,
};
const flexspi_device_config_t config = {
.flexspiRootClk = MHZ(50),
.flashSize = FLEXSPI_FLSHCR0_FLSHSZ_MASK,
.ARDSeqNumber = 1,
.ARDSeqIndex = READ,
};

flexspi_lut[SCRATCH_CMD][0] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x65,
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x08);
Comment on lines +765 to +767
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number 0x65 appears to be a Read Register command but is not defined as a named constant like other SPI NOR commands (e.g., SPI_NOR_CMD_WRSR2 on line 775). Consider defining this as a named constant such as SPI_NOR_CMD_RDREG or similar to improve code readability and maintainability.

Copilot uses AI. Check for mistakes.
flexspi_lut[SCRATCH_CMD][1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08,
kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x01);
Comment on lines +769 to +770
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic numbers 0x08 (dummy cycles/bits) appears twice in this function (lines 770, 772) without explanation. Consider defining these as named constants or adding comments to explain why 8 dummy cycles are required for this specific read register command.

Copilot uses AI. Check for mistakes.
flexspi_lut[SCRATCH_CMD2][0] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_WRSR2,
kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x01);

ret = memc_flexspi_set_device_config(&data->controller, &config, (uint32_t *)flexspi_lut,
FLEXSPI_INSTR_END * MEMC_FLEXSPI_CMD_PER_SEQ,
data->port);
if (ret < 0) {
return ret;
}

transfer.dataSize = 1;
transfer.seqIndex = SCRATCH_CMD;
transfer.cmdType = kFLEXSPI_Read;
ret = memc_flexspi_transfer(&data->controller, &transfer);
if (ret < 0) {
return ret;
}

Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check verifies if bit 3 of Status Register 2 is already set (indicating octal mode is already enabled), but lacks a comment explaining this. Consider adding a comment like '/* Check if octal mode is already enabled (SR2 bit 3) */' to improve code clarity.

Suggested change
/* Check if octal mode is already enabled (SR2 bit 3) */

Copilot uses AI. Check for mistakes.
if ((buffer & BIT(3)) != 0U) {
return 0;
}

ret = flash_flexspi_nor_write_enable(data);
if (ret < 0) {
return ret;
}

Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line sets bit 3 to enable octal mode but lacks a comment explaining the purpose. Consider adding a comment like '/* Set bit 3 to enable octal mode */' to improve code clarity.

Suggested change
/* Set bit 3 to enable octal mode */

Copilot uses AI. Check for mistakes.
buffer |= BIT(3);
transfer.deviceAddress = 0;
transfer.seqIndex = SCRATCH_CMD2;
transfer.cmdType = kFLEXSPI_Write;
ret = memc_flexspi_transfer(&data->controller, &transfer);
if (ret < 0) {
return ret;
}

return flash_flexspi_nor_wait_bus_busy(data);
}

static int
flash_flexspi_nor_handle_octal_requirements(struct flash_flexspi_nor_data *data,
uint32_t (*flexspi_lut)[MEMC_FLEXSPI_CMD_PER_SEQ],
uint8_t oer)
{
switch (oer) {
case JESD216_DW19_OER_VAL_NONE:
return 0;
case JESD216_DW19_OER_VAL_S2B3:
return flash_flexspi_nor_octal_enable_s2b3(data, flexspi_lut);
default:
return -ENOTSUP;
}
}

/*
* This function enables 4 byte addressing, when supported. Otherwise it
* returns an error.
Expand Down Expand Up @@ -865,8 +945,10 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data,
struct jesd216_bfp_dw16 dw16;
struct jesd216_bfp_dw15 dw15;
struct jesd216_bfp_dw14 dw14;
struct jesd216_bfp_dw19 dw19;
uint8_t addr_width;
uint8_t mode_cmd;
uint8_t octal_enable_req = JESD216_DW19_OER_VAL_NONE;
int ret;

/* Read DW14 to determine the polling method we should use while programming */
Expand All @@ -892,6 +974,10 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data,
addr_width = jesd216_bfp_addrbytes(bfp) ==
JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_4B ? 32 : 24;

if (jesd216_bfp_decode_dw19(&header->phdr[0], bfp, &dw19) == 0) {
octal_enable_req = dw19.octal_enable_req;
}

/* Check to see if we can enable 4 byte addressing */
ret = jesd216_bfp_decode_dw16(&header->phdr[0], bfp, &dw16);
if (ret == 0) {
Expand All @@ -915,6 +1001,39 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data,
/* Extract the read command.
* Note- enhanced XIP not currently supported, nor is 4-4-4 mode.
*/
ret = jesd216_bfp_read_support(&header->phdr[0], bfp,
JESD216_MODE_188, &instr);
if (ret > 0) {
ret = flash_flexspi_nor_handle_octal_requirements(data, flexspi_lut,
octal_enable_req);
if (ret < 0) {
if (ret != -ENOTSUP) {
return ret;
}
} else {
LOG_DBG("Enable 188 mode");
if (instr.mode_clocks == 2) {
mode_cmd = kFLEXSPI_Command_MODE8_SDR;
} else if (instr.mode_clocks == 1) {
mode_cmd = kFLEXSPI_Command_MODE4_SDR;
} else if (instr.mode_clocks == 0) {
mode_cmd = kFLEXSPI_Command_DUMMY_SDR;
} else {
return -ENOTSUP;
}
flexspi_lut[READ][0] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, instr.instr,
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, addr_width);
flexspi_lut[READ][1] = FLEXSPI_LUT_SEQ(mode_cmd, kFLEXSPI_8PAD, 0x00,
kFLEXSPI_Command_DUMMY_SDR,
kFLEXSPI_8PAD, instr.wait_states);
flexspi_lut[READ][2] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_8PAD, 0x04,
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0);
return 0;
}
}

if (jesd216_bfp_read_support(&header->phdr[0], bfp,
JESD216_MODE_144, &instr) > 0) {
LOG_DBG("Enable 144 mode");
Expand Down
16 changes: 16 additions & 0 deletions drivers/flash/jesd216.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,19 @@ int jesd216_bfp_decode_dw16(const struct jesd216_param_header *php,

return 0;
}

int jesd216_bfp_decode_dw19(const struct jesd216_param_header *php,
const struct jesd216_bfp *bfp,
struct jesd216_bfp_dw19 *res)
{
/* DW19 introduced in JESD216C */
if (php->len_dw < 19) {
return -ENOTSUP;
}

uint32_t dw19 = sys_le32_to_cpu(bfp->dw10[9]);

res->octal_enable_req = (dw19 >> 20) & BIT_MASK(3);

return 0;
}
27 changes: 27 additions & 0 deletions drivers/flash/jesd216.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ struct jesd216_bfp {
*
* JESD216C (20 DW)
* * DW17-20 (quad/oct support) no API except jesd216_bfp_read_support().
* DW19 also has jesd216_bfp_decode_dw19().
*/

/* Extract the supported address bytes from BFP DW1. */
Expand Down Expand Up @@ -531,6 +532,32 @@ int jesd216_bfp_decode_dw16(const struct jesd216_param_header *php,
const struct jesd216_bfp *bfp,
struct jesd216_bfp_dw16 *res);

/* Decoded data from JESD216 DW19 */
struct jesd216_bfp_dw19 {
/* Bits specifying the status/control sequence required to enable
* octal protocol operation.
*/
unsigned int octal_enable_req: 3;
};

/* Get data from BFP DW19.
*
* @param php pointer to the BFP header.
*
* @param bfp pointer to the BFP table.
*
* @param res pointer to where to store the decoded data.
*
* @retval -ENOTSUP if this information is not available from this BFP table.
* @retval 0 on successful storage into @c *res.
*/
int jesd216_bfp_decode_dw19(const struct jesd216_param_header *php,
const struct jesd216_bfp *bfp,
struct jesd216_bfp_dw19 *res);

#define JESD216_DW19_OER_VAL_NONE 0U
#define JESD216_DW19_OER_VAL_S2B3 1U

/* JESD216D-01 section 6.6: 4-Byte Address Instruction Parameter */
#define JESD216_SFDP_4B_ADDR_DW1_1S_1S_1S_READ_13_SUP BIT(0)
#define JESD216_SFDP_4B_ADDR_DW1_1S_1S_1S_FAST_READ_0C_SUP BIT(1)
Expand Down
13 changes: 13 additions & 0 deletions samples/drivers/jesd216/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,18 @@ static void summarize_dw16(const struct jesd216_param_header *php,
dw16.sr1_interface);
}

static void summarize_dw19(const struct jesd216_param_header *php,
const struct jesd216_bfp *bfp)
{
struct jesd216_bfp_dw19 dw19;

if (jesd216_bfp_decode_dw19(php, bfp, &dw19) != 0) {
return;
}

printf("Octal Enable Requirement: %u\n", dw19.octal_enable_req);
}

/* Indexed from 1 to match JESD216 data word numbering */
static const dw_extractor extractor[] = {
[1] = summarize_dw1,
Expand All @@ -253,6 +265,7 @@ static const dw_extractor extractor[] = {
[14] = summarize_dw14,
[15] = summarize_dw15,
[16] = summarize_dw16,
[19] = summarize_dw19,
};

static void dump_bfp(const struct jesd216_param_header *php,
Expand Down
Loading