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).
  *