Platform: Implement Flash uninitialize function
- This patch introduces an uninitialize function for the QSPI Flash
controller to restore it's default state before passing execution
to runtime image from MCUBoot.
- Implements a basic configuration function for the QSPI Flash
controller and Flash memory that enables operation in single
SPI mode. It is used at the initialization of the Flash controller.
Change-Id: I384d60ec02bb9e9a6da2b08c45e6e634202e5008
Signed-off-by: David Vincze <david.vincze@arm.com>
diff --git a/bl2/ext/mcuboot/bl2_main.c b/bl2/ext/mcuboot/bl2_main.c
index 6b8c090..ed25093 100644
--- a/bl2/ext/mcuboot/bl2_main.c
+++ b/bl2/ext/mcuboot/bl2_main.c
@@ -77,6 +77,11 @@
rsp->br_hdr->ih_hdr_size);
}
+ rc = FLASH_DEV_NAME.Uninitialize();
+ if(rc != ARM_DRIVER_OK) {
+ BOOT_LOG_ERR("Error while uninitializing Flash Interface");
+ }
+
stdio_uninit();
__disable_irq();
@@ -101,8 +106,12 @@
*/
mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf, BL2_MBEDTLS_MEM_BUF_LEN);
- /* Initialize Flash driver */
- FLASH_DEV_NAME.Initialize(NULL);
+ rc = FLASH_DEV_NAME.Initialize(NULL);
+ if(rc != ARM_DRIVER_OK) {
+ BOOT_LOG_ERR("Error while initializing Flash Interface");
+ while (1)
+ ;
+ }
rc = boot_go(&rsp);
if (rc != 0) {
diff --git a/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c b/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c
index 34a5e43..b7af48a 100755
--- a/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c
+++ b/platform/ext/target/musca_a/CMSIS_Driver/Driver_Flash.c
@@ -59,7 +59,7 @@
/**
* \brief Flash status macro definitions \ref ARM_FLASH_STATUS
*/
-/* Busy status values of the Flash driver */
+/* Busy status values of the Flash driver */
#define DRIVER_STATUS_IDLE (0u)
#define DRIVER_STATUS_BUSY (1u)
/* Error status values of the Flash driver */
@@ -137,16 +137,31 @@
static int32_t ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)
{
+ enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
ARG_UNUSED(cb_event);
qspi_ip6514e_enable(ARM_FLASH0_DEV.dev->controller);
+ /* Configure QSPI Flash controller to operate in single SPI mode and
+ * to use fast Flash commands */
+ err = mt25ql_config_mode(ARM_FLASH0_DEV.dev, MT25QL_FUNC_STATE_FAST);
+ if(err != MT25QL_ERR_NONE) {
+ return ARM_DRIVER_ERROR;
+ }
+
return ARM_DRIVER_OK;
}
static int32_t ARM_Flash_Uninitialize(void)
{
- qspi_ip6514e_disable(ARM_FLASH0_DEV.dev->controller);
+ enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
+ /* Restores the QSPI Flash controller and MT25QL to default state */
+ err = mt25ql_restore_default_state(ARM_FLASH0_DEV.dev);
+ if(err != MT25QL_ERR_NONE) {
+ return ARM_DRIVER_ERROR;
+ }
return ARM_DRIVER_OK;
}
diff --git a/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.c b/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.c
index 13ca3f0..cddb487 100644
--- a/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.c
+++ b/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.c
@@ -50,6 +50,7 @@
* to handle those commands.
*/
#define QUAD_OUTPUT_FAST_READ_CMD 0x6BU
+#define FAST_READ_CMD 0x0BU
#define READ_CMD 0x03U
#define QUAD_INPUT_FAST_PROGRAM_CMD 0x32U
#define PAGE_PROGRAM_CMD 0x02U
@@ -72,10 +73,11 @@
* 8 is the minimal number of dummy clock cycles needed to reach the maximal
* frequency of the Quad Output Fast Read Command.
*/
-#define OPTIMAL_READ_DUMMY_CYCLES 8U
-#define CMD_READ_DUMMY_CYCLES 0U
-#define OPTIMAL_WRITE_DUMMY_CYCLES 0U
-#define CMD_WRITE_DUMMY_CYCLES 0U
+#define QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES 8U
+#define FAST_READ_DUMMY_CYCLES 8U
+#define DEFAULT_READ_DUMMY_CYCLES 0U
+#define QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES 0U
+#define PAGE_PROGRAM_DUMMY_CYCLES 0U
/* Only up to 8 bytes can be read or written using the Flash commands. */
#define CMD_DATA_MAX_SIZE 8U
@@ -137,21 +139,23 @@
}
/**
- * \brief Activate the QSPI mode on the flash device and on the controller.
+ * \brief Set SPI mode on the flash device and on the controller.
*
- * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] spi_mode SPI mode to be set on flash device and controller
+ * \ref qspi_ip6514e_spi_mode_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
-static enum mt25ql_error_t activate_qspi_mode(struct mt25ql_dev_t* dev)
+static enum mt25ql_error_t set_spi_mode(struct mt25ql_dev_t* dev,
+ enum qspi_ip6514e_spi_mode_t spi_mode)
{
uint8_t enhanced_volatile_cfg_reg = 0;
enum qspi_ip6514e_error_t controller_error;
- /*
- * Read the Enhanced Volatile Configuration Register, modify it to activate
- * QSPI mode then write back the modified value to the register. This will
- * activate QSPI mode on the flash side.
+ /* Read the Enhanced Volatile Configuration Register, modify it according
+ * to the requested SPI mode then write back the modified value to the
+ * register. This will activate the SPI mode on the flash side.
*/
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
@@ -166,12 +170,31 @@
return (enum mt25ql_error_t)controller_error;
}
- /*
- * Disable the Dual-SPI mode and activate QSPI mode.
- * Clearing the bit enables the mode, setting it disables it.
- */
- SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
- CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+ switch(spi_mode) {
+ case QSPI_IP6514E_SPI_MODE:
+ /* Disable the Dual- and Quad-SPI modes.
+ * Clearing the bit enables the mode, setting it disables it.
+ */
+ SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
+ SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+ break;
+ case QSPI_IP6514E_DSPI_MODE:
+ /* Disable the Quad-SPI mode and activate DSPI mode.
+ * Clearing the bit enables the mode, setting it disables it.
+ */
+ CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
+ SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+ break;
+ case QSPI_IP6514E_QSPI_MODE:
+ /* Disable the Dual-SPI mode and activate QSPI mode.
+ * Clearing the bit enables the mode, setting it disables it.
+ */
+ SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
+ CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+ break;
+ default:
+ return MT25QL_ERR_WRONG_ARGUMENT;
+ }
send_write_enable(dev);
@@ -188,11 +211,11 @@
return (enum mt25ql_error_t)controller_error;
}
- /* Activate the QSPI mode on the controller side as well */
+ /* Activate the requested SPI mode on the controller side as well. */
controller_error = qspi_ip6514e_set_spi_mode(dev->controller,
- QSPI_IP6514E_QSPI_MODE,
- QSPI_IP6514E_QSPI_MODE,
- QSPI_IP6514E_QSPI_MODE);
+ spi_mode,
+ spi_mode,
+ spi_mode);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
@@ -369,35 +392,60 @@
return MT25QL_ERR_NONE;
}
-enum mt25ql_error_t mt25ql_cfg_optimal(struct mt25ql_dev_t* dev)
+enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
+ enum mt25ql_functional_state_t config)
{
+ enum qspi_ip6514e_spi_mode_t spi_mode;
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
+ uint8_t opcode_read;
+ uint8_t opcode_write;
+ uint32_t dummy_cycles_read;
+ uint32_t dummy_cycles_write;
- /*
- * Assuming that the Flash memory starts in single SPI protocol and as the
- * QSPI Flash controller also resets in single SPI mode, this function will
- * first change the Flash memory mode to QSPI and then change the controller
- * to QSPI.
- * It will fail if the two sides do not have the same mode when this
- * function is called.
+ switch(config) {
+ case MT25QL_FUNC_STATE_DEFAULT:
+ spi_mode = QSPI_IP6514E_SPI_MODE;
+ opcode_read = READ_CMD;
+ dummy_cycles_read = DEFAULT_READ_DUMMY_CYCLES;
+ opcode_write = PAGE_PROGRAM_CMD;
+ dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
+ break;
+ case MT25QL_FUNC_STATE_FAST:
+ spi_mode = QSPI_IP6514E_SPI_MODE;
+ opcode_read = FAST_READ_CMD;
+ dummy_cycles_read = FAST_READ_DUMMY_CYCLES;
+ opcode_write = PAGE_PROGRAM_CMD;
+ dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
+ break;
+ case MT25QL_FUNC_STATE_QUAD_FAST:
+ spi_mode = QSPI_IP6514E_QSPI_MODE;
+ opcode_read = QUAD_OUTPUT_FAST_READ_CMD;
+ dummy_cycles_read = QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
+ opcode_write = QUAD_INPUT_FAST_PROGRAM_CMD;
+ dummy_cycles_write = QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
+ break;
+ default:
+ return MT25QL_ERR_WRONG_ARGUMENT;
+ }
+
+ /* This function will first set the Flash memory SPI mode and then set
+ * the controller's SPI mode. It will fail if the two sides do not have
+ * the same mode when this function is called.
*/
- library_error = activate_qspi_mode(dev);
+ library_error = set_spi_mode(dev, spi_mode);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
- /* Change to the optimal number of dummy cycles for read commands. */
- library_error = change_dummy_cycles(dev, OPTIMAL_READ_DUMMY_CYCLES);
+ /* Set the number of dummy cycles for read commands. */
+ library_error = change_dummy_cycles(dev, dummy_cycles_read);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* The rest of the configuration needs the controller to be disabled */
- if (!qspi_ip6514e_is_idle(dev->controller)) {
- return (enum mt25ql_error_t)QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE;
- }
-
+ while(!qspi_ip6514e_is_idle(dev->controller));
qspi_ip6514e_disable(dev->controller);
/* Set the baud rate divisor as configured in the device structure. */
@@ -409,16 +457,16 @@
/* Set opcode and dummy cycles needed for read commands. */
controller_error = qspi_ip6514e_cfg_reads(dev->controller,
- QUAD_OUTPUT_FAST_READ_CMD,
- OPTIMAL_READ_DUMMY_CYCLES);
+ opcode_read,
+ dummy_cycles_read);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set opcode and dummy cycles needed for write commands. */
controller_error = qspi_ip6514e_cfg_writes(dev->controller,
- QUAD_INPUT_FAST_PROGRAM_CMD,
- OPTIMAL_WRITE_DUMMY_CYCLES);
+ opcode_write,
+ dummy_cycles_write);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
@@ -438,7 +486,41 @@
qspi_ip6514e_enable(dev->controller);
- dev->func_state = MT25QL_FUNC_STATE_OPTIMAL;
+ dev->func_state = config;
+
+ return MT25QL_ERR_NONE;
+}
+
+enum mt25ql_error_t mt25ql_restore_default_state(struct mt25ql_dev_t* dev)
+{
+ enum mt25ql_error_t library_error;
+
+ /*
+ * This function will first change the Flash memory mode to single SPI and
+ * then change the controller to single SPI. It will fail if the two sides
+ * do not have the same mode when this function is called.
+ */
+ library_error = set_spi_mode(dev, QSPI_IP6514E_SPI_MODE);
+ if (library_error != MT25QL_ERR_NONE) {
+ return library_error;
+ }
+
+ /* Set the default number of dummy cycles for read commands. */
+ library_error = change_dummy_cycles(dev, DEFAULT_READ_DUMMY_CYCLES);
+ if (library_error != MT25QL_ERR_NONE) {
+ return library_error;
+ }
+
+ /* The rest of the configuration needs the controller to be disabled */
+ while(!qspi_ip6514e_is_idle(dev->controller));
+ qspi_ip6514e_disable(dev->controller);
+
+ /* Restore the default value of the QSPI controller registers. */
+ qspi_ip6514e_reset_regs(dev->controller);
+
+ qspi_ip6514e_enable(dev->controller);
+
+ dev->func_state = MT25QL_FUNC_STATE_DEFAULT;
return MT25QL_ERR_NONE;
}
@@ -619,12 +701,20 @@
uint8_t opcode;
uint32_t dummy_cycles;
- if(dev->func_state == MT25QL_FUNC_STATE_OPTIMAL) {
+ switch (dev->func_state) {
+ case MT25QL_FUNC_STATE_QUAD_FAST:
opcode = QUAD_OUTPUT_FAST_READ_CMD;
- dummy_cycles = OPTIMAL_READ_DUMMY_CYCLES;
- } else {
+ dummy_cycles = QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
+ break;
+ case MT25QL_FUNC_STATE_FAST:
+ opcode = FAST_READ_CMD;
+ dummy_cycles = FAST_READ_DUMMY_CYCLES;
+ break;
+ case MT25QL_FUNC_STATE_DEFAULT:
+ default:
opcode = READ_CMD;
- dummy_cycles = CMD_READ_DUMMY_CYCLES;
+ dummy_cycles = DEFAULT_READ_DUMMY_CYCLES;
+ break;
}
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
@@ -675,12 +765,17 @@
uint8_t opcode;
uint32_t dummy_cycles;
- if(dev->func_state == MT25QL_FUNC_STATE_OPTIMAL) {
+ switch (dev->func_state) {
+ case MT25QL_FUNC_STATE_QUAD_FAST:
opcode = QUAD_INPUT_FAST_PROGRAM_CMD;
- dummy_cycles = OPTIMAL_WRITE_DUMMY_CYCLES;
- } else {
+ dummy_cycles = QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
+ break;
+ case MT25QL_FUNC_STATE_FAST:
+ case MT25QL_FUNC_STATE_DEFAULT:
+ default:
opcode = PAGE_PROGRAM_CMD;
- dummy_cycles = CMD_WRITE_DUMMY_CYCLES;
+ dummy_cycles = PAGE_PROGRAM_DUMMY_CYCLES;
+ break;
}
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
@@ -788,36 +883,36 @@
send_write_enable(dev);
switch (erase_type) {
- case MT25QL_ERASE_ALL_FLASH:
- if (addr != 0) {
- return MT25QL_ERR_ADDR_NOT_ALIGNED;
- }
- erase_cmd = BULK_ERASE_CMD;
- addr_bytes = ARG_NOT_USED;
- break;
- case MT25QL_ERASE_SECTOR_64K:
- erase_cmd = SECTOR_ERASE_CMD;
- addr_bytes = ADDR_BYTES;
- if ((addr % SECTOR_64KB) != 0) {
- return MT25QL_ERR_ADDR_NOT_ALIGNED;
- }
- break;
- case MT25QL_ERASE_SUBSECTOR_32K:
- erase_cmd = SUBSECTOR_ERASE_32KB_CMD;
- addr_bytes = ADDR_BYTES;
- if ((addr % SUBSECTOR_32KB) != 0) {
- return MT25QL_ERR_ADDR_NOT_ALIGNED;
- }
- break;
- case MT25QL_ERASE_SUBSECTOR_4K:
- erase_cmd = SUBSECTOR_ERASE_4KB_CMD;
- addr_bytes = ADDR_BYTES;
- if ((addr % SUBSECTOR_4KB) != 0) {
- return MT25QL_ERR_ADDR_NOT_ALIGNED;
- }
- break;
- default:
- return MT25QL_ERR_WRONG_ARGUMENT;
+ case MT25QL_ERASE_ALL_FLASH:
+ if (addr != 0) {
+ return MT25QL_ERR_ADDR_NOT_ALIGNED;
+ }
+ erase_cmd = BULK_ERASE_CMD;
+ addr_bytes = ARG_NOT_USED;
+ break;
+ case MT25QL_ERASE_SECTOR_64K:
+ erase_cmd = SECTOR_ERASE_CMD;
+ addr_bytes = ADDR_BYTES;
+ if ((addr % SECTOR_64KB) != 0) {
+ return MT25QL_ERR_ADDR_NOT_ALIGNED;
+ }
+ break;
+ case MT25QL_ERASE_SUBSECTOR_32K:
+ erase_cmd = SUBSECTOR_ERASE_32KB_CMD;
+ addr_bytes = ADDR_BYTES;
+ if ((addr % SUBSECTOR_32KB) != 0) {
+ return MT25QL_ERR_ADDR_NOT_ALIGNED;
+ }
+ break;
+ case MT25QL_ERASE_SUBSECTOR_4K:
+ erase_cmd = SUBSECTOR_ERASE_4KB_CMD;
+ addr_bytes = ADDR_BYTES;
+ if ((addr % SUBSECTOR_4KB) != 0) {
+ return MT25QL_ERR_ADDR_NOT_ALIGNED;
+ }
+ break;
+ default:
+ return MT25QL_ERR_WRONG_ARGUMENT;
}
if (addr >= dev->size) {
diff --git a/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.h b/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.h
index d4827bf..f081fb2 100644
--- a/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.h
+++ b/platform/ext/target/musca_a/Libraries/mt25ql_flash_lib.h
@@ -41,7 +41,6 @@
MT25QL_ERR_NONE = QSPI_IP6514E_ERR_NONE,
MT25QL_ERR_WRONG_ARGUMENT = QSPI_IP6514E_ERR_WRONG_ARGUMENT,
MT25QL_ERR_CTRL_NOT_DISABLED = QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
- MT25QL_ERR_CTRL_NOT_IDLE = QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE,
MT25QL_ERR_READ_IN_PROGRESS = QSPI_IP6514E_ERR_READ_IN_PROGRESS,
MT25QL_ERR_WRITE_IN_PROGRESS = QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
MT25QL_ERR_ADDR_NOT_ALIGNED,
@@ -56,8 +55,20 @@
};
enum mt25ql_functional_state_t {
- MT25QL_FUNC_STATE_DEFAULT = 0u,
- MT25QL_FUNC_STATE_OPTIMAL = 1u,
+ MT25QL_FUNC_STATE_DEFAULT = 0U,
+ /*!< The QSPI Flash controller and memory is in default state,
+ * in the same state as after reset.
+ */
+ MT25QL_FUNC_STATE_FAST = 1U,
+ /*!< The QSPI Flash controller and memory is configured to operate in
+ * single SPI mode and fast Flash commands could be used for read and
+ * program operations.
+ */
+ MT25QL_FUNC_STATE_QUAD_FAST = 2U,
+ /*!< The QSPI Flash controller and memory is configured to operate in
+ * Quad SPI mode and fast Flash commands could be used for read and
+ * program operations.
+ */
};
struct mt25ql_dev_t {
@@ -83,24 +94,41 @@
};
/**
- * \brief Configure the QSPI Flash controller and MT25QL for optimal use.
+ * \brief Change configuration of the QSPI Flash controller and MT25QL memory
+ *
+ * Changes the configuration of the QSPI Flash controller and MT25QL
+ * Flash memory to operate in the specified SPI mode and to use the
+ * appropriate Flash commands for read and program operations.
+ * It also sets:
+ * + The number of dummy cycles for each operation
+ * + The bytes per page constant to 256 (MT25QL Flash specific)
+ * + The number of address bytes to 3
+ *
+ * \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] config Operational configuration to be set on flash controller
+ * and device \ref mt25ql_functional_state_t
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function assumes that the Flash memory device and the QSPI Flash
+ * controller operates with the same SPI protocol. This function will fail
+ * if the Flash device is in a different configuration.
+ */
+enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
+ enum mt25ql_functional_state_t config);
+
+/**
+ * \brief Restore the QSPI Flash controller and MT25QL to default state.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*
- * \note This function assumes that the Flash memory device currently operates
- * with single line SPI protocol with Double Data Rate protocol disabled.
- * This function will not work and cause harm if the Flash device is in
- * another configuration.
- * \note The configuration used is the following:
- * * QSPI mode (4 lines for instruction, address and data)
- * * Read command is Quad Output Fast Read with 8 dummy cycles
- * * Write command is Quad Input Fast Program with 0 dummy cycles
- * * Bytes per page set to 256
- * * Number of address bytes set to 3
+ * \note This function assumes that the Flash memory device and the QSPI Flash
+ * controller operates with the same SPI protocol. This function will fail
+ * if the Flash device is in a different configuration.
*/
-enum mt25ql_error_t mt25ql_cfg_optimal(struct mt25ql_dev_t* dev);
+enum mt25ql_error_t mt25ql_restore_default_state(struct mt25ql_dev_t* dev);
/**
* \brief Read bytes from the flash memory (direct access)
diff --git a/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c
index 8b9f541..4b585e5 100644
--- a/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c
+++ b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.c
@@ -125,6 +125,16 @@
#define FLASH_CMD_CTRL_READ_ENABLE_POS 23U
#define FLASH_CMD_CTRL_OPCODE_POS 24U
+/** Default register values of the QSPI Flash controller */
+#define QSPI_CFG_REG_RESET_VALUE (0x80780081U)
+#define DEVICE_READ_INSTR_REG_RESET_VALUE (0x00000003U)
+#define DEVICE_WRITE_INSTR_REG_RESET_VALUE (0x00000002U)
+#define DEVICE_SIZE_CFG_REG_RESET_VALUE (0x00101002U)
+#define REMAP_ADDR_REG_RESET_VALUE (0x00000000U)
+#define FLASH_CMD_CONTROL_REG_RESET_VALUE (0x00000000U)
+#define FLASH_CMD_ADDRESS_REG_RESET_VALUE (0x00000000U)
+#define FLASH_CMD_WRITE_DATA_REG_RESET_VALUE (0x00000000U)
+
/**
* \brief Change specific bits in a 32 bits word.
*
@@ -203,9 +213,11 @@
&(reg_map->device_write_inst);
uint32_t device_read_write_inst_reg_copy = *device_read_write_inst_reg;
- if (!qspi_ip6514e_is_idle(dev)) {
- return QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE;
- }
+ /*
+ * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+ * all low level synchronization has been done.
+ */
+ while(!qspi_ip6514e_is_idle(dev));
if (dummy_cycles > DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
@@ -287,9 +299,11 @@
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
- if (!qspi_ip6514e_is_idle(dev)) {
- return QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE;
- }
+ /*
+ * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+ * all low level synchronization has been done.
+ */
+ while(!qspi_ip6514e_is_idle(dev));
/* div should be an even number. */
if (((div & 1U) == 1) ||
@@ -326,9 +340,11 @@
uint32_t device_read_inst_cpy = reg_map->device_read_inst;
uint32_t device_write_inst_cpy = reg_map->device_write_inst;
- if (!qspi_ip6514e_is_idle(dev)) {
- return QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE;
- }
+ /*
+ * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+ * all low level synchronization has been done.
+ */
+ while(!qspi_ip6514e_is_idle(dev));
/*
* First check that the instruction mode is not SPI. If that is the case,
@@ -406,9 +422,11 @@
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
- if (!qspi_ip6514e_is_idle(dev)) {
- return QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE;
- }
+ /*
+ * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+ * all low level synchronization has been done.
+ */
+ while(!qspi_ip6514e_is_idle(dev));
if (page_size > DEVICE_SIZE_PAGE_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
@@ -429,9 +447,11 @@
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
- if (!qspi_ip6514e_is_idle(dev)) {
- return QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE;
- }
+ /*
+ * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+ * all low level synchronization has been done.
+ */
+ while(!qspi_ip6514e_is_idle(dev));
if (bytes_number < DEVICE_SIZE_ADDR_BYTES_MIN ||
bytes_number > DEVICE_SIZE_ADDR_BYTES_MAX) {
@@ -484,6 +504,39 @@
}
}
+void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev)
+{
+ struct _qspi_ip6514e_reg_map_t *reg_map =
+ (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+ /* Restore the default value of the QSPI Configuration register. */
+ reg_map->qspi_cfg = QSPI_CFG_REG_RESET_VALUE;
+
+ /* Restore the default value of the Device R/W Instruction registers. */
+ reg_map->device_read_inst = DEVICE_READ_INSTR_REG_RESET_VALUE;
+ reg_map->device_write_inst = DEVICE_WRITE_INSTR_REG_RESET_VALUE;
+
+ /* Restore the default value of the Device Size Configuration register. */
+ reg_map->device_size = DEVICE_SIZE_CFG_REG_RESET_VALUE;
+
+ /* Restore the default value of the Remap Address register. */
+ reg_map->remap_addr = REMAP_ADDR_REG_RESET_VALUE;
+
+ /* Restore the default value of the Flash Command Control register. */
+ reg_map->flash_cmd_ctrl = FLASH_CMD_CONTROL_REG_RESET_VALUE;
+ /* Restore the default value of the Flash Command Address register. */
+ reg_map->flash_cmd_addr = FLASH_CMD_ADDRESS_REG_RESET_VALUE;
+
+ /* Restore the default value of the Flash Command Write Data registers. */
+ reg_map->flash_cmd_write_data_lower = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
+ reg_map->flash_cmd_write_data_upper = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
+
+ /*
+ * This function does not affect the Flash Command Read Data registers
+ * which are completely Read-Only.
+ */
+}
+
enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
diff --git a/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h
index 112b9fa..6992925 100644
--- a/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h
+++ b/platform/ext/target/musca_a/Native_Driver/qspi_ip6514e_drv.h
@@ -59,7 +59,6 @@
QSPI_IP6514E_ERR_NONE,
QSPI_IP6514E_ERR_WRONG_ARGUMENT,
QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
- QSPI_IP6514E_ERR_CONTROLLER_NOT_IDLE,
QSPI_IP6514E_ERR_READ_IN_PROGRESS,
QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
/* Any new error should be added to the enumeration type error of
@@ -263,6 +262,15 @@
void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev);
/**
+ * \brief Restore the default value of the QSPI controller registers.
+ *
+ * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ *
+ * \note The QSPI controller should be disabled before calling this function.
+ */
+void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev);
+
+/**
* \brief Send a command to the flash memory device using the Software Triggered
* Instruction Generator (STIG).
*