Skip to content

drivers: flash: spi_nor: optimizations and better Micron flash support #88467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

robhancocksed
Copy link
Contributor

  • Avoid providing redundant TX buffers to the SPI driver for the data portion of read commands where the TX data is not used. This is more efficient and also avoids passing uninitialized data to an external device.
  • Add support for the flag status register used on some Micron flash devices, which improves error detection and in some cases must be read for the flash device to function properly.
  • Add support for fast read commands using a dummy byte between the address and data phases, which often allows the flash device to operate at a higher SPI clock rate.

Note, there might be a compliance error raised, as I wasn't able to satisfy both clang-format and checkpatch with regard to how one line was formatted..

@robhancocksed
Copy link
Contributor Author

Looks like the drivers.console.line_splitting.plus.some_option test is currently failing, for presumably unrelated reasons..

@robhancocksed
Copy link
Contributor Author

Ping.. any feedback?

Comment on lines 385 to 403
struct spi_buf spi_buf[2] = {
{
.buf = buf,
.len = 1,
},
{
.buf = data,
.len = length
}
};
bool has_dummy = (access & NOR_ACCESS_DUMMY_BYTE) != 0U;
uint8_t cmd_buf[6] = {opcode};
struct spi_buf spi_buf_tx[2] = {{
.buf = cmd_buf,
.len = 1,
},
{.buf = is_write ? data : NULL, .len = length}};
struct spi_buf spi_buf_rx[2] = {{
.buf = NULL,
.len = 1,
},
{.buf = data, .len = length}};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Decide on one style of initialization, preferably where definition is split to several lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, though for some reason the clang-format formatting wanted it this way. Will see if the compliance checks will flag it if I use the multi-line style.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ended up just using "clang-format off" to stop it from wanting to change this block of code.

Comment on lines 49 to 55
#define ANY_INST_HAS_DPD DT_ANY_INST_HAS_BOOL_STATUS_OKAY(has_dpd)
#define ANY_INST_HAS_T_EXIT_DPD DT_ANY_INST_HAS_PROP_STATUS_OKAY(t_exit_dpd)
#define ANY_INST_HAS_DPD_WAKEUP_SEQUENCE DT_ANY_INST_HAS_PROP_STATUS_OKAY(dpd_wakeup_sequence)
#define ANY_INST_HAS_RESET_GPIOS DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
#define ANY_INST_HAS_WP_GPIOS DT_ANY_INST_HAS_PROP_STATUS_OKAY(wp_gpios)
#define ANY_INST_HAS_HOLD_GPIOS DT_ANY_INST_HAS_PROP_STATUS_OKAY(hold_gpios)
#define ANY_INST_USE_4B_ADDR_OPCODES DT_ANY_INST_HAS_BOOL_STATUS_OKAY(use_4b_addr_opcodes)
#define ANY_INST_HAS_DPD DT_ANY_INST_HAS_BOOL_STATUS_OKAY(has_dpd)
#define ANY_INST_HAS_T_EXIT_DPD DT_ANY_INST_HAS_PROP_STATUS_OKAY(t_exit_dpd)
#define ANY_INST_HAS_DPD_WAKEUP_SEQUENCE DT_ANY_INST_HAS_PROP_STATUS_OKAY(dpd_wakeup_sequence)
#define ANY_INST_HAS_RESET_GPIOS DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
#define ANY_INST_HAS_WP_GPIOS DT_ANY_INST_HAS_PROP_STATUS_OKAY(wp_gpios)
#define ANY_INST_HAS_HOLD_GPIOS DT_ANY_INST_HAS_PROP_STATUS_OKAY(hold_gpios)
#define ANY_INST_USE_4B_ADDR_OPCODES DT_ANY_INST_HAS_BOOL_STATUS_OKAY(use_4b_addr_opcodes)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Change in formatting is not related to topic of the pr. Don't do unrelated changes like, even if it is style only - it makes it bloats pr. Style changes on lines with no logical changes should get own pr.

Copy link
Collaborator

Choose a reason for hiding this comment

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

use-fast-read should have one of these too, and if there is not device in a system setup that has the property this should evaluate to false.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a case where clang-format wanted the new code formatted differently, and so I ended up updating the surrounding block of code to match. I can leave the other lines alone if preferred.

Copy link
Collaborator

@de-nordic de-nordic Apr 25, 2025

Choose a reason for hiding this comment

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

Don't run clang-format on pre-existing units. Overall style fix should be done in separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ended up using "clang-format off" here as well.

Comment on lines 507 to 508
* status register since it allows better error detection (and some devices
* that have it require it to be read after a program operation).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
* status register since it allows better error detection (and some devices
* that have it require it to be read after a program operation).
* status register since it allows better error detection; some devices,
* which have the register, require it to be read after a program operation.

What was the point of () ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reworded this.

Comment on lines 555 to 558
if (IS_ENABLED(CONFIG_SPI_NOR_SLEEP_WHILE_WAITING_UNTIL_READY)) {
/* Don't monopolise the CPU while waiting for ready */
k_sleep(poll_delay);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

}
};
bool has_dummy = (access & NOR_ACCESS_DUMMY_BYTE) != 0U;
uint8_t cmd_buf[6] = {opcode};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Needless variable name spawns unneeded changes in lines 419 and 423. Any style changes, renames got to other PR. Needless changes eclipse the subject of PR changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed variable rename.

.len = length
}
};
uint8_t cmd_buf[5] = {opcode};
Copy link
Collaborator

Choose a reason for hiding this comment

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

This line gets modified in two separate commits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure how you suggest handling this? Please have a look at the current change set.

if (addr > SPI_NOR_3B_ADDR_MAX) {
ret = spi_nor_cmd_addr_read_4b(dev, SPI_NOR_CMD_READ_4B, addr, dest, size);
if (cfg->use_fast_read) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be conditional on existence of device that have the fast read. I you have a system that does not have fast read or you do not want is (and do not enable it in dts), then this should not be compiled in.
Example here may be MCUboot, where users may prefer to choose smaller driver at a cost of slower boot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

This driver was providing SPI buffers for both TX and RX on the data
payload portion of read transfers, even though the TX buffer is not
meaningful in these cases. As well as being less efficient, this also
caused likely uninitialized data to be transferred to the device, which
is possibly problematic.

Update to specify the TX buffer as NULL for the data payload SPI
transfer, so that the SPI driver can generate dummy TX data internally.

Signed-off-by: Robert Hancock <[email protected]>
Some Micron (and possibly other) SPI NOR devices implement a flag status
register which provides more information on the success/failure of erase
and program operations. In addition to better error checking, some of
these devices actually don't function properly if the flag status
register is not read after a program operation (subsequent reads will
only return 0xFF bytes).

Add a device tree parameter to indicate that the flag status register is
supported. When specified, the flag status register will be used for
ready/error checks rather than the standard status register.

Signed-off-by: Robert Hancock <[email protected]>
Most SPI NOR flash devices support a "fast read" command which uses
dummy bits between the address and the start of the data transfer. In
many cases, the maximum SPI clock speed of the device is lower for the
regular read command due to the limited time between the address and
data phases, so using the fast read command will remove this restriction
and allow for faster transfers.

Add a device tree flag to indicate that fast reads should be used for
the device.

Signed-off-by: Robert Hancock <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants