Commit 29bc5bf1 authored by Andrzej Głąbek's avatar Andrzej Głąbek Committed by Benjamin Cabé
Browse files

drivers: flash_mspi_nor: Get info from dts SFDP arrays



Get parameters for used flash commands and requirements for enabling
Quad and Octal modes from dts uint8-arrays containing data read from
SFDP tables for particular flash chips.
Also introduce `pre_init` quirk that allows alteration of the above
parameters or complementation of them in a specific way for particular
flash chip families.

Signed-off-by: default avatarAndrzej Głąbek <andrzej.glabek@nordicsemi.no>
parent 8e6521a1
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -279,6 +279,13 @@ slot3_partition: &cpurad_slot1_partition {
			30 b0 30 b0  f4 bd d5 5c  00 00 00 ff  10 10 00 20
			30 b0 30 b0  f4 bd d5 5c  00 00 00 ff  10 10 00 20
			00 00 00 00  00 00 7c 23  48 00 00 00  00 00 88 88
			00 00 00 00  00 00 7c 23  48 00 00 00  00 00 88 88
		];
		];
		sfdp-ff05 = [
			00 ee c0 69  72 72 71 71  00 d8 f7 f6  00 0a 00 00
			14 45 98 80
		];
		sfdp-ff84 = [
			43 06 0f 00  21 dc ff ff
		];
		size = <67108864>;
		size = <67108864>;
		has-dpd;
		has-dpd;
		t-enter-dpd = <10000>;
		t-enter-dpd = <10000>;
+7 −0
Original line number Original line Diff line number Diff line
@@ -259,6 +259,13 @@ ipc0: &cpuapp_cpurad_ipc {
			30 b0 30 b0  f4 bd d5 5c  00 00 00 ff  10 10 00 20
			30 b0 30 b0  f4 bd d5 5c  00 00 00 ff  10 10 00 20
			00 00 00 00  00 00 7c 23  48 00 00 00  00 00 88 88
			00 00 00 00  00 00 7c 23  48 00 00 00  00 00 88 88
		];
		];
		sfdp-ff05 = [
			00 ee c0 69  72 72 71 71  00 d8 f7 f6  00 0a 00 00
			14 45 98 80
		];
		sfdp-ff84 = [
			43 06 0f 00  21 dc ff ff
		];
		size = <67108864>;
		size = <67108864>;
		has-dpd;
		has-dpd;
		t-enter-dpd = <10000>;
		t-enter-dpd = <10000>;
+18 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,24 @@ menuconfig FLASH_MSPI_NOR


if FLASH_MSPI_NOR
if FLASH_MSPI_NOR


config FLASH_MSPI_NOR_USE_SFDP
	bool "Use Serial Flash Discoverable Parameters (SFDP)"
	default $(dt_compat_any_has_prop,$(DT_COMPAT_JEDEC_MSPI_NOR),sfdp-bfp)
	help
	  Use information from SFDP for setting up flash command transfers
	  and for configuring the flash chip.

	  Currently, only build time processing of SFDP structures is supported,
	  based on dts arrays provided as flash node properties like `sfdp-bfp`,
	  `sfdp-ff05`, and `sfdp-ff84`. Depending on the IO mode used, some or
	  all of these properties are required for building the flash driver.
	  Data for these properties can be obtained with the `drivers/jesd216`
	  sample. If a given SFDP table is not available in a flash chip,
	  the related property can be defined as an empty array - this will
	  prevent a related build assertion from failing and default values
	  will be assigned to parameters that would otherwise be read from
	  that SFDP table.

config FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE
config FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE
	int "Page size to use for FLASH_LAYOUT feature"
	int "Page size to use for FLASH_LAYOUT feature"
	depends on FLASH_PAGE_LAYOUT
	depends on FLASH_PAGE_LAYOUT
+29 −17
Original line number Original line Diff line number Diff line
@@ -12,10 +12,12 @@
#include <zephyr/pm/device_runtime.h>
#include <zephyr/pm/device_runtime.h>


#include "flash_mspi_nor.h"
#include "flash_mspi_nor.h"
#include "flash_mspi_nor_quirks.h"
#include "flash_mspi_nor_sfdp.h"


LOG_MODULE_REGISTER(flash_mspi_nor, CONFIG_FLASH_LOG_LEVEL);
LOG_MODULE_REGISTER(flash_mspi_nor, CONFIG_FLASH_LOG_LEVEL);


#include "flash_mspi_nor_quirks.h"

void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd)
void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd)
{
{
	struct flash_mspi_nor_data *dev_data = dev->data;
	struct flash_mspi_nor_data *dev_data = dev->data;
@@ -110,7 +112,9 @@ static inline uint32_t dev_flash_size(const struct device *dev)


static inline uint16_t dev_page_size(const struct device *dev)
static inline uint16_t dev_page_size(const struct device *dev)
{
{
	return SPI_NOR_PAGE_SIZE;
	const struct flash_mspi_nor_config *dev_config = dev->config;

	return dev_config->page_size;
}
}


static int api_read(const struct device *dev, off_t addr, void *dest,
static int api_read(const struct device *dev, off_t addr, void *dest,
@@ -534,7 +538,7 @@ static int quad_enable_set(const struct device *dev, bool enable)
		return rc;
		return rc;
	}
	}


	if (dev_config->dw15_qer == JESD216_DW15_QER_VAL_S1B6) {
	if (dev_data->switch_info.quad_enable_req == JESD216_DW15_QER_VAL_S1B6) {
		const struct flash_mspi_nor_cmd cmd_status = {
		const struct flash_mspi_nor_cmd cmd_status = {
			.dir = MSPI_TX,
			.dir = MSPI_TX,
			.cmd = SPI_NOR_CMD_WRSR,
			.cmd = SPI_NOR_CMD_WRSR,
@@ -570,10 +574,11 @@ static int quad_enable_set(const struct device *dev, bool enable)
static int default_io_mode(const struct device *dev)
static int default_io_mode(const struct device *dev)
{
{
	const struct flash_mspi_nor_config *dev_config = dev->config;
	const struct flash_mspi_nor_config *dev_config = dev->config;
	struct flash_mspi_nor_data *dev_data = dev->data;
	enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode;
	enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode;
	int rc = 0;
	int rc = 0;


	if (dev_config->dw15_qer != JESD216_DW15_QER_VAL_NONE) {
	if (dev_data->switch_info.quad_enable_req != JESD216_DW15_QER_VAL_NONE) {
		/* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined
		/* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined
		 * in JEDEC216 BFP DW15 QER
		 * in JEDEC216 BFP DW15 QER
		 */
		 */
@@ -657,7 +662,7 @@ static int flash_chip_init(const struct device *dev)
	/* Some chips reuse RESET pin for data in Quad modes:
	/* Some chips reuse RESET pin for data in Quad modes:
	 * force single line mode before resetting.
	 * force single line mode before resetting.
	 */
	 */
	if (dev_config->dw15_qer != JESD216_DW15_QER_VAL_NONE &&
	if (dev_data->switch_info.quad_enable_req != JESD216_DW15_QER_VAL_NONE &&
	    (io_mode == MSPI_IO_MODE_SINGLE ||
	    (io_mode == MSPI_IO_MODE_SINGLE ||
	     io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
	     io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
	     io_mode == MSPI_IO_MODE_QUAD_1_4_4)) {
	     io_mode == MSPI_IO_MODE_QUAD_1_4_4)) {
@@ -685,6 +690,11 @@ static int flash_chip_init(const struct device *dev)
	}
	}
#endif
#endif


	if (dev_config->quirks != NULL &&
	    dev_config->quirks->pre_init != NULL) {
		rc = dev_config->quirks->pre_init(dev);
	}

	flash_mspi_command_set(dev, &commands_single.id);
	flash_mspi_command_set(dev, &commands_single.id);
	dev_data->packet.data_buf  = id;
	dev_data->packet.data_buf  = id;
	dev_data->packet.num_bytes = sizeof(id);
	dev_data->packet.num_bytes = sizeof(id);
@@ -749,6 +759,11 @@ static int drv_init(const struct device *dev)
		return -ENODEV;
		return -ENODEV;
	}
	}


	memcpy(dev_data->erase_types, dev_config->default_erase_types,
	       sizeof(dev_data->erase_types));
	dev_data->cmd_info = dev_config->default_cmd_info;
	dev_data->switch_info = dev_config->default_switch_info;

	rc = pm_device_runtime_get(dev_config->bus);
	rc = pm_device_runtime_get(dev_config->bus);
	if (rc < 0) {
	if (rc < 0) {
		LOG_ERR("pm_device_runtime_get() failed: %d", rc);
		LOG_ERR("pm_device_runtime_get() failed: %d", rc);
@@ -800,8 +815,6 @@ static DEVICE_API(flash, drv_api) = {
	.dqs_enable = false,						\
	.dqs_enable = false,						\
}
}


#define FLASH_SIZE_INST(inst) (DT_INST_PROP(inst, size) / 8)

/* Define copies of mspi_io_mode enum values, so they can be used inside
/* Define copies of mspi_io_mode enum values, so they can be used inside
 * the COND_CODE_1 macros.
 * the COND_CODE_1 macros.
 */
 */
@@ -836,23 +849,17 @@ extern const struct flash_mspi_nor_cmds mspi_io_mode_not_supported;


#define FLASH_QUIRKS(inst) FLASH_MSPI_QUIRKS_GET(DT_DRV_INST(inst))
#define FLASH_QUIRKS(inst) FLASH_MSPI_QUIRKS_GET(DT_DRV_INST(inst))


#define FLASH_DW15_QER_VAL(inst) _CONCAT(JESD216_DW15_QER_VAL_, \
	DT_INST_STRING_TOKEN(inst, quad_enable_requirements))
#define FLASH_DW15_QER(inst) COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, quad_enable_requirements), \
	(FLASH_DW15_QER_VAL(inst)), (JESD216_DW15_QER_VAL_NONE))


#if defined(CONFIG_FLASH_PAGE_LAYOUT)
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
BUILD_ASSERT((CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE % 4096) == 0,
BUILD_ASSERT((CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE % 4096) == 0,
	"MSPI_NOR_FLASH_LAYOUT_PAGE_SIZE must be multiple of 4096");
	"MSPI_NOR_FLASH_LAYOUT_PAGE_SIZE must be multiple of 4096");
#define FLASH_PAGE_LAYOUT_DEFINE(inst) \
#define FLASH_PAGE_LAYOUT_DEFINE(inst) \
	.layout = { \
	.layout = { \
		.pages_size = CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE, \
		.pages_size = CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE, \
		.pages_count = FLASH_SIZE_INST(inst) \
		.pages_count = FLASH_SIZE(inst) \
			     / CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE, \
			     / CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE, \
	},
	},
#define FLASH_PAGE_LAYOUT_CHECK(inst) \
#define FLASH_PAGE_LAYOUT_CHECK(inst) \
BUILD_ASSERT((FLASH_SIZE_INST(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == 0, \
BUILD_ASSERT((FLASH_SIZE(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == 0, \
	"MSPI_NOR_FLASH_LAYOUT_PAGE_SIZE incompatible with flash size, instance " #inst);
	"MSPI_NOR_FLASH_LAYOUT_PAGE_SIZE incompatible with flash size, instance " #inst);
#else
#else
#define FLASH_PAGE_LAYOUT_DEFINE(inst)
#define FLASH_PAGE_LAYOUT_DEFINE(inst)
@@ -874,11 +881,14 @@ BUILD_ASSERT((FLASH_SIZE_INST(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) ==
		     (DT_INST_ENUM_IDX(inst, mspi_io_mode) ==			\
		     (DT_INST_ENUM_IDX(inst, mspi_io_mode) ==			\
		      MSPI_IO_MODE_OCTAL),					\
		      MSPI_IO_MODE_OCTAL),					\
		"Only 1x, 1-4-4 and 8x I/O modes are supported for now");	\
		"Only 1x, 1-4-4 and 8x I/O modes are supported for now");	\
	SFDP_BUILD_ASSERTS(inst);						\
	PM_DEVICE_DT_INST_DEFINE(inst, dev_pm_action_cb);			\
	PM_DEVICE_DT_INST_DEFINE(inst, dev_pm_action_cb);			\
	DEFAULT_ERASE_TYPES_DEFINE(inst);					\
	static struct flash_mspi_nor_data dev##inst##_data;			\
	static struct flash_mspi_nor_data dev##inst##_data;			\
	static const struct flash_mspi_nor_config dev##inst##_config = {	\
	static const struct flash_mspi_nor_config dev##inst##_config = {	\
		.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),			\
		.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),			\
		.flash_size = FLASH_SIZE_INST(inst),				\
		.flash_size = FLASH_SIZE(inst),					\
		.page_size = FLASH_PAGE_SIZE(inst),				\
		.mspi_id = MSPI_DEVICE_ID_DT_INST(inst),			\
		.mspi_id = MSPI_DEVICE_ID_DT_INST(inst),			\
		.mspi_nor_cfg = MSPI_DEVICE_CONFIG_DT_INST(inst),		\
		.mspi_nor_cfg = MSPI_DEVICE_CONFIG_DT_INST(inst),		\
		.mspi_nor_init_cfg = FLASH_INITIAL_CONFIG(inst),		\
		.mspi_nor_init_cfg = FLASH_INITIAL_CONFIG(inst),		\
@@ -899,7 +909,9 @@ BUILD_ASSERT((FLASH_SIZE_INST(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) ==
		.jedec_id = DT_INST_PROP(inst, jedec_id),			\
		.jedec_id = DT_INST_PROP(inst, jedec_id),			\
		.jedec_cmds = FLASH_CMDS(inst),					\
		.jedec_cmds = FLASH_CMDS(inst),					\
		.quirks = FLASH_QUIRKS(inst),					\
		.quirks = FLASH_QUIRKS(inst),					\
		.dw15_qer = FLASH_DW15_QER(inst),				\
		.default_erase_types = DEFAULT_ERASE_TYPES(inst),		\
		.default_cmd_info = DEFAULT_CMD_INFO(inst),			\
		.default_switch_info = DEFAULT_SWITCH_INFO(inst),		\
	};									\
	};									\
	FLASH_PAGE_LAYOUT_CHECK(inst)						\
	FLASH_PAGE_LAYOUT_CHECK(inst)						\
	DEVICE_DT_INST_DEFINE(inst,						\
	DEVICE_DT_INST_DEFINE(inst,						\
+49 −1
Original line number Original line Diff line number Diff line
@@ -20,9 +20,52 @@ extern "C" {
#define WITH_RESET_GPIO 1
#define WITH_RESET_GPIO 1
#endif
#endif


#define CMD_EXTENSION_NONE    0
#define CMD_EXTENSION_SAME    1
#define CMD_EXTENSION_INVERSE 2

#define OCTAL_ENABLE_REQ_NONE 0
#define OCTAL_ENABLE_REQ_S2B3 1

#define ENTER_4BYTE_ADDR_NONE  0
#define ENTER_4BYTE_ADDR_B7    1
#define ENTER_4BYTE_ADDR_06_B7 2

struct flash_mspi_nor_cmd_info {
	uint8_t read_cmd;
	uint8_t read_mode_bit_cycles : 3;
	uint8_t read_dummy_cycles    : 5;
	uint8_t pp_cmd;
	bool    uses_4byte_addr : 1;
	/* BFP, 18th DWORD, bits 30-29 */
	uint8_t cmd_extension   : 2;
	/* xSPI Profile 1.0 (ID FF05), 1st DWORD: */
	/* - Read SFDP command address bytes: 4 (true) or 3 */
	bool    sfdp_addr_4     : 1;
	/* - Read SDFP command dummy cycles: 20 (true) or 8 */
	bool    sfdp_dummy_20   : 1;
	/* - Read Status Register command address bytes: 4 (true) or 0 */
	bool    rdsr_addr_4     : 1;
	/* - Read Status Register command dummy cycles: 0, 4, or 8 */
	uint8_t rdsr_dummy      : 4;
	/* - Read JEDEC ID command parameters; not sure where to get their
	 *   values from, but since for many flash chips they are the same
	 *   as for RDSR, those are taken as defaults, see DEFAULT_CMD_INFO()
	 */
	bool    rdid_addr_4     : 1;
	uint8_t rdid_dummy      : 4;
};

struct flash_mspi_nor_switch_info {
	uint8_t quad_enable_req  : 3;
	uint8_t octal_enable_req : 3;
	uint8_t enter_4byte_addr : 2;
};

struct flash_mspi_nor_config {
struct flash_mspi_nor_config {
	const struct device *bus;
	const struct device *bus;
	uint32_t flash_size;
	uint32_t flash_size;
	uint16_t page_size;
	struct mspi_dev_id mspi_id;
	struct mspi_dev_id mspi_id;
	struct mspi_dev_cfg mspi_nor_cfg;
	struct mspi_dev_cfg mspi_nor_cfg;
	struct mspi_dev_cfg mspi_nor_init_cfg;
	struct mspi_dev_cfg mspi_nor_init_cfg;
@@ -42,7 +85,9 @@ struct flash_mspi_nor_config {
	uint8_t jedec_id[SPI_NOR_MAX_ID_LEN];
	uint8_t jedec_id[SPI_NOR_MAX_ID_LEN];
	const struct flash_mspi_nor_cmds *jedec_cmds;
	const struct flash_mspi_nor_cmds *jedec_cmds;
	struct flash_mspi_nor_quirks *quirks;
	struct flash_mspi_nor_quirks *quirks;
	uint8_t dw15_qer;
	const struct jesd216_erase_type *default_erase_types;
	struct flash_mspi_nor_cmd_info default_cmd_info;
	struct flash_mspi_nor_switch_info default_switch_info;
};
};


struct flash_mspi_nor_data {
struct flash_mspi_nor_data {
@@ -50,6 +95,9 @@ struct flash_mspi_nor_data {
	struct mspi_xfer_packet packet;
	struct mspi_xfer_packet packet;
	struct mspi_xfer xfer;
	struct mspi_xfer xfer;
	struct mspi_dev_cfg *curr_cfg;
	struct mspi_dev_cfg *curr_cfg;
	struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES];
	struct flash_mspi_nor_cmd_info cmd_info;
	struct flash_mspi_nor_switch_info switch_info;
};
};


struct flash_mspi_nor_cmd {
struct flash_mspi_nor_cmd {
Loading