Commit 02fa8456 authored by Pete Johanson's avatar Pete Johanson Committed by Alberto Escolar
Browse files

drivers: flash: Enable static/runtime SFDP data for SPIXF driver



Add a new flash for toggling runtime SFDP data fetching, and use static
devicetree properties by default. Clean up various minor items from review.

Signed-off-by: default avatarPete Johanson <pete.johanson@analog.com>
parent 3821e5db
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -319,6 +319,13 @@ pmod_spi: &spi4 {
		reg = <0x08000000 DT_SIZE_M(8)>; /* 64 Mbits */
		qspi-max-frequency = <60000000>;
		jedec-id = [c2 37 25];
		sfdp-bfp = [
			e5 20 f1 ff   ff ff ff 03   44 eb 08 6b   08 3b 04 bb
			fe ff ff ff   ff ff 00 ff   ff ff 44 eb   0c 20 0f 52
			10 d8 00 ff   d3 49 c9 00   83 a6 04 c4   44 03 17 38
			30 b0 30 b0   f7 bd d5 5c   4a 9e 29 ff   f0 d0 ff ff
		];
		page-size = <4096>;
		reset-cmd;
		spi-bus-width = <4>;
		writeoc = "PP_1_1_4";
+18 −0
Original line number Diff line number Diff line
@@ -14,3 +14,21 @@ config FLASH_ADI_MAX32_SPIXF
	select PINCTRL
	help
	  Enable QSPI-NOR support on the MAX32 family of processors.

if FLASH_ADI_MAX32_SPIXF

config FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME
	bool "Read flash parameters at runtime"
	depends on FLASH_ADI_MAX32_SPIXF
	help
	  Read flash device characteristics from the device at runtime.
	  This option should provide functionality for all supported
	  JESD216-compatible devices, with the following notes:
	  - Quad Enable Requirements bitfield (DW15) must be present in the SFDP
	    tables to configure Quad mode. Otherwise it defaults to Dual or
	    Single mode as supported by the device.

	  If not selected, the driver uses a fixed configuration, and the device
	  size, page size, and jedec-id properties must be set in devicetree node.

endif
+72 −21
Original line number Diff line number Diff line
@@ -70,6 +70,18 @@ struct flash_max32_spixf_nor_config {
#if MAX32_QSPI_RESET_GPIO
	const struct gpio_dt_spec reset;
#endif
#if !defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
	/* Length of BFP structure, in 32-bit words. */
	uint8_t bfp_len;

	/* Pointer to the BFP table as read from the device
	 * (little-endian stored words), from sfdp-bfp property
	 */
	const struct jesd216_bfp *bfp;
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
	struct flash_pages_layout layout;
#endif
#endif
#if MAX32_QSPI_HAS_JEDEC_ID
	uint8_t jedec_id[DT_INST_PROP_LEN(0, jedec_id)];
#endif /* jedec_id */
@@ -79,7 +91,7 @@ struct flash_max32_spixf_nor_config {
struct flash_max32_spixf_nor_data {
	struct k_sem sem;
	struct k_sem sync;
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
#if defined(CONFIG_FLASH_PAGE_LAYOUT) && defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
	struct flash_pages_layout layout;
#endif
	struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES];
@@ -360,6 +372,7 @@ static int qspi_write_unprotect(const struct device *dev)
	return ret;
}

#if IS_ENABLED(CONFIG_FLASH_JESD216_API) || IS_ENABLED(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
/*
 * Read Serial Flash Discovery Parameter
 */
@@ -403,6 +416,8 @@ static int qspi_read_sfdp_priv(const struct device *dev, off_t addr, void *data,
	return ret;
}

#endif

#if IS_ENABLED(CONFIG_FLASH_JESD216_API)

static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data, size_t size)
@@ -434,6 +449,11 @@ static int flash_max32_spixf_nor_read(const struct device *dev, off_t addr, void
{
	const struct flash_max32_spixf_nor_config *dev_cfg = dev->config;

	/* read non-zero size */
	if (size == 0) {
		return 0;
	}

	if (!qspi_address_is_valid(dev, addr, size)) {
		LOG_DBG("Error: address or size exceeds expected values: "
			"addr 0x%lx, size %zu",
@@ -441,11 +461,6 @@ static int flash_max32_spixf_nor_read(const struct device *dev, off_t addr, void
		return -EINVAL;
	}

	/* read non-zero size */
	if (size == 0) {
		return 0;
	}

	qspi_lock_thread(dev);

	memcpy(data, (uint8_t *)dev_cfg->spixf_base_addr + addr, size);
@@ -500,6 +515,11 @@ static int flash_max32_spixf_nor_write(const struct device *dev, off_t addr, con
	struct flash_max32_spixf_nor_req_wrapper req = {0};
	uint8_t addr_width, data_width;

	/* write non-zero size */
	if (size == 0) {
		return 0;
	}

	if (!qspi_address_is_valid(dev, addr, size)) {
		LOG_DBG("Error: address or size exceeds expected values: "
			"addr 0x%lx, size %zu",
@@ -507,11 +527,6 @@ static int flash_max32_spixf_nor_write(const struct device *dev, off_t addr, con
		return -EINVAL;
	}

	/* write non-zero size */
	if (size == 0) {
		return 0;
	}

	if (IS_ENABLED(MAX32_QSPI_USE_QUAD_IO)) {
		pp_cmd = dev_data->qspi_write_cmd;
		data_width = MXC_SPIXF_WIDTH_4;
@@ -608,6 +623,11 @@ static int flash_max32_spixf_nor_erase(const struct device *dev, off_t addr, siz
	struct flash_max32_spixf_nor_req_wrapper req = {.req.deass = 1};
	int ret = 0;

	/* erase non-zero size */
	if (size == 0) {
		return 0;
	}

	if (!qspi_address_is_valid(dev, addr, size)) {
		LOG_DBG("Error: address or size exceeds expected values: "
			"addr 0x%lx, size %zu",
@@ -615,11 +635,6 @@ static int flash_max32_spixf_nor_erase(const struct device *dev, off_t addr, siz
		return -EINVAL;
	}

	/* erase non-zero size */
	if (size == 0) {
		return 0;
	}

	qspi_lock_thread(dev);
	MXC_SPIXF_Enable();

@@ -714,8 +729,13 @@ static void flash_max32_spixf_nor_pages_layout(const struct device *dev,
					       size_t *layout_size)
{
	struct flash_max32_spixf_nor_data *dev_data = dev->data;
	const struct flash_max32_spixf_nor_config *dev_cfg = dev->config;

	*layout = &dev_data->layout;
	ARG_UNUSED(dev_data);
	ARG_UNUSED(dev_cfg);

	*layout = COND_CODE_1(IS_ENABLED(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME),
						  (&dev_data->layout), (&dev_cfg->layout));
	*layout_size = 1;
}
#endif
@@ -734,7 +754,7 @@ static DEVICE_API(flash, flash_max32_spixf_nor_driver_api) = {
#endif /* CONFIG_FLASH_JESD216_API */
};

#if defined(CONFIG_FLASH_PAGE_LAYOUT)
#if defined(CONFIG_FLASH_PAGE_LAYOUT) && defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
static int setup_pages_layout(const struct device *dev)
{
	const struct flash_max32_spixf_nor_config *dev_cfg = dev->config;
@@ -813,10 +833,13 @@ static int qspi_program_addr_4b(const struct device *dev, bool write_enable)
	return qspi_send_req(dev, &req);
}

#define WRITE_ENABLE_MAX_RETRIES 4

static int qspi_write_enable(const struct device *dev)
{
	uint8_t reg;
	int ret;
	int retries = 0;

	ret = qspi_send_write_enable(dev);
	if (ret) {
@@ -825,7 +848,7 @@ static int qspi_write_enable(const struct device *dev)

	do {
		ret = qspi_read_status_register(dev, 1U, &reg);
	} while (!ret && !(reg & SPI_NOR_WEL_BIT));
	} while (!ret && !(reg & SPI_NOR_WEL_BIT) && (retries++) < WRITE_ENABLE_MAX_RETRIES);

	if (retries >= WRITE_ENABLE_MAX_RETRIES) {
		LOG_WRN("Timed-out waiting for write-enabled status");
@@ -1119,7 +1142,8 @@ static void flash_max32_spixf_nor_irq_config(const struct device *dev)

static int flash_max32_spixf_nor_fetch_jesd216_details(const struct device *dev)
{
	int ret;
	int ret = 0;
#if defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
	const uint8_t decl_nph = 2;
	union {
		/* We only process BFP so use one parameter block */
@@ -1174,8 +1198,17 @@ static int flash_max32_spixf_nor_fetch_jesd216_details(const struct device *dev)
		}
		++php;
	}
#else
	/* Synthesize a header and process the version from DTS */
	const struct flash_max32_spixf_nor_config *dev_cfg = dev->config;
	struct jesd216_param_header bfp_hdr = {
		.len_dw = dev_cfg->bfp_len,
	};

	return 0;
	ret = spi_nor_process_bfp(dev, &bfp_hdr, dev_cfg->bfp);
#endif

	return ret;
}

static void flash_max32_spixf_update_read_settings(uint8_t cmd_read, uint8_t read_latency)
@@ -1247,6 +1280,7 @@ static int flash_max32_spixf_nor_init(const struct device *dev)
	/* Run NOR init */
	ret = flash_max32_spixf_nor_fetch_jesd216_details(dev);
	if (ret < 0) {
		LOG_WRN("Loading initial flash table details failed (%d)", ret);
		return -ENODEV;
	}

@@ -1258,11 +1292,16 @@ static int flash_max32_spixf_nor_init(const struct device *dev)
#endif

#if defined(CONFIG_FLASH_PAGE_LAYOUT)
#if defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
	ret = setup_pages_layout(dev);
	if (ret != 0) {
		LOG_ERR("layout setup failed: %d", ret);
		return -ENODEV;
	}
#else
	LOG_INF("Default page layout is %d by %d", dev_cfg->layout.pages_count,
		dev_cfg->layout.pages_size);
#endif
#endif /* CONFIG_FLASH_PAGE_LAYOUT */

	ret = qspi_write_unprotect(dev);
@@ -1313,6 +1352,10 @@ static const struct max32_perclk perclkens[] = {
BUILD_ASSERT(DT_INST_PROP_LEN(0, jedec_id) >= 3, "jedec-id must be at least 3 bytes.");
#endif

#if !defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
static const __aligned(4) uint8_t bfp_data[] = DT_INST_PROP(0, sfdp_bfp);
#endif

static const struct flash_max32_spixf_nor_config flash_max32_spixf_nor_cfg = {
	.clock = DEVICE_DT_GET_OR_NULL(DT_CLOCKS_CTLR(MAX32_QSPI_NODE)),
	.perclkens = perclkens,
@@ -1322,6 +1365,14 @@ static const struct flash_max32_spixf_nor_config flash_max32_spixf_nor_cfg = {
	.spixf_base_addr = DT_INST_REG_ADDR(0),
	.pcfg = PINCTRL_DT_DEV_CONFIG_GET(MAX32_QSPI_NODE),
	.force_quad_addr_writes = DT_INST_PROP_OR(0, force_quad_address_write, false),
#if !defined(CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME)
	.bfp_len = sizeof(bfp_data) / 4,
	.bfp = (const struct jesd216_bfp *)bfp_data,
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
	.layout.pages_size = DT_INST_PROP(0, page_size),
	.layout.pages_count = DT_INST_REG_SIZE(0) / DT_INST_PROP(0, page_size),
#endif
#endif
#if MAX32_QSPI_RESET_GPIO
	.reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios),
#endif
+4 −0
Original line number Diff line number Diff line
# Copyright (c) 2025 Analog Devices, Inc
# SPDX-License-Identifier: Apache-2.0

CONFIG_FLASH_ADI_MAX32_SPIXF_SFDP_RUNTIME=y
+7 −0
Original line number Diff line number Diff line
@@ -13,6 +13,13 @@ tests:
    extra_args: DTC_OVERLAY_FILE=boards/apard32690_max32690_m4_spixf_nor.overlay
    integration_platforms:
      - apard32690/max32690/m4
  drivers.flash.common.max32_spixf_nor_sfdp_runtime:
    platform_allow: apard32690/max32690/m4
    extra_args:
      - EXTRA_CONF_FILE=boards/apard32690_max32690_m4_spixf_nor_sfdp_runtime.conf
      - DTC_OVERLAY_FILE=boards/apard32690_max32690_m4_spixf_nor.overlay
    integration_platforms:
      - apard32690/max32690/m4
  drivers.flash.common.nrf_qspi_nor.size_in_bytes:
    platform_allow: nrf52840dk/nrf52840
    extra_args: