Commit 609bb002 authored by Francois Ramu's avatar Francois Ramu Committed by Fabio Baltieri
Browse files

drivers: flash: stm32 ospi flash driver waits for full chip erase



Add a function to wait for the full (bulk) Nor-octoflah erase command.
When erasing the full octo-flash, the drivers waits until
the operation is ready and the external NOR mem becomes ready itself.
The full (bulk) erase operation lasts for several seconds.

Signed-off-by: default avatarFrancois Ramu <francois.ramu@st.com>
parent 861a7639
Loading
Loading
Loading
Loading
+63 −3
Original line number Diff line number Diff line
@@ -502,6 +502,58 @@ static bool ospi_address_is_valid(const struct device *dev, off_t addr,
	return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size);
}

/*
 * This function Polls the WEL (write enable latch) bit to become to 0
 * When the Chip Erase Cycle is completed, the Write Enable Latch (WEL) bit is cleared.
 * in nor_mode SPI/OPI OSPI_SPI_MODE or OSPI_OPI_MODE
 * and nor_rate transfer STR/DTR OSPI_STR_TRANSFER or OSPI_DTR_TRANSFER
 */
static int stm32_ospi_mem_erased(OSPI_HandleTypeDef *hospi, uint8_t nor_mode, uint8_t nor_rate)
{
	OSPI_AutoPollingTypeDef s_config = {0};
	OSPI_RegularCmdTypeDef s_command = ospi_prepare_cmd(nor_mode, nor_rate);

	/* Configure automatic polling mode command to wait for memory ready */
	if (nor_mode == OSPI_OPI_MODE) {
		s_command.Instruction = SPI_NOR_OCMD_RDSR;
		s_command.DummyCycles = (nor_rate == OSPI_DTR_TRANSFER)
					? SPI_NOR_DUMMY_REG_OCTAL_DTR
					: SPI_NOR_DUMMY_REG_OCTAL;
	} else {
		s_command.Instruction = SPI_NOR_CMD_RDSR;
		/* force 1-line InstructionMode for any non-OSPI transfer */
		s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
		s_command.AddressMode = HAL_OSPI_ADDRESS_NONE;
		/* force 1-line DataMode for any non-OSPI transfer */
		s_command.DataMode = HAL_OSPI_DATA_1_LINE;
		s_command.DummyCycles = 0;
	}
	s_command.NbData = ((nor_rate == OSPI_DTR_TRANSFER) ? 2U : 1U);
	s_command.Address = 0U;

	/* Set the mask to  0x02 to mask all Status REG bits except WEL */
	/* Set the match to 0x00 to check if the WEL bit is Reset */
	s_config.Match              = SPI_NOR_WEL_MATCH;
	s_config.Mask               = SPI_NOR_WEL_MASK; /* Write Enable Latch */

	s_config.MatchMode          = HAL_OSPI_MATCH_MODE_AND;
	s_config.Interval           = SPI_NOR_AUTO_POLLING_INTERVAL;
	s_config.AutomaticStop      = HAL_OSPI_AUTOMATIC_STOP_ENABLE;

	if (HAL_OSPI_Command(hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
		LOG_ERR("OSPI AutoPoll command (WEL) failed");
		return -EIO;
	}

	/* Start Automatic-Polling mode to wait until the memory is totally erased */
	if (HAL_OSPI_AutoPolling(hospi, &s_config, STM32_OSPI_BULK_ERASE_MAX_TIME) != HAL_OK) {
		LOG_ERR("OSPI AutoPoll (WEL) failed");
		return -EIO;
	}

	return 0;
}

/*
 * This function Polls the WIP(Write In Progress) bit to become to 0
 * in nor_mode SPI/OPI OSPI_SPI_MODE or OSPI_OPI_MODE
@@ -917,8 +969,6 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,

	/* Maximise erase size : means the complete chip */
	if (size > dev_cfg->flash_size) {
		/* Reset addr in that case */
		addr = 0;
		size = dev_cfg->flash_size;
	}

@@ -974,14 +1024,23 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,
		if (size == dev_cfg->flash_size) {
			/* Chip erase */
			LOG_DBG("Chip Erase");

			cmd_erase.Address = 0;
			cmd_erase.Instruction = (dev_cfg->data_mode == OSPI_OPI_MODE)
					? SPI_NOR_OCMD_BULKE
					: SPI_NOR_CMD_BULKE;
			cmd_erase.AddressMode = HAL_OSPI_ADDRESS_NONE;
			/* Full chip erase command */
			/* Full chip erase (Bulk) command */
			ospi_send_cmd(dev, &cmd_erase);

			size -= dev_cfg->flash_size;
			/* Chip (Bulk) erase started, wait until WEL becomes 0 */
			ret = stm32_ospi_mem_erased(&dev_data->hospi,
						   dev_cfg->data_mode, dev_cfg->data_rate);
			if (ret != 0) {
				LOG_ERR("Chip Erase failed");
				break;
			}
		} else {
			/* Sector erase */
			LOG_DBG("Sector Erase");
@@ -1044,6 +1103,7 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,
			ret = stm32_ospi_mem_ready(&dev_data->hospi,
						   dev_cfg->data_mode, dev_cfg->data_rate);
		}

	}

	ospi_unlock_thread(dev);
+3 −0
Original line number Diff line number Diff line
@@ -84,6 +84,9 @@
#define SPI_NOR_WREN_MATCH    0x02
#define SPI_NOR_WREN_MASK     0x02

#define SPI_NOR_WEL_MATCH     0x00
#define SPI_NOR_WEL_MASK      0x02

#define SPI_NOR_MEM_RDY_MATCH 0x00
#define SPI_NOR_MEM_RDY_MASK  0x01