This is an automated email from Gerrit.

"Brandon Martin <marti...@mothictech.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7349

-- gerrit

commit e06632de30de6c01a7745b352e1e713568482d20
Author: Brandon Martin <marti...@mothictech.com>
Date:   Mon Oct 31 16:43:30 2022 -0400

    flash/nor/fsl_flexspi: Support chip erase
    
    This is a useful capability, but it appears that it has to be
    implemented as a driver-specific command, so it has been kept separate
    for now.
    
    Signed-off-by: Brandon Martin <marti...@mothictech.com>
    Change-Id: I060f7442c1341cc13754531226c13d51011aca93

diff --git a/src/flash/nor/fsl_flexspi.c b/src/flash/nor/fsl_flexspi.c
index 67e9c31b91..1d7e6248f3 100644
--- a/src/flash/nor/fsl_flexspi.c
+++ b/src/flash/nor/fsl_flexspi.c
@@ -52,7 +52,8 @@
 
 #define TIMEOUT_EXEC_IPCMD                     100
 #define TIMEOUT_RESET                          100
-#define TIMEOUT_FLASH_ERASE                    2000
+#define TIMEOUT_FLASH_ERASE_SECTOR     1000
+#define TIMEOUT_FLASH_ERASE_CHIP       90000
 #define TIMEOUT_FLASH_PROGRAM          250
 
 /* These are the base addresses used on the IMXRT1020 */
@@ -748,7 +749,7 @@ static int erase_sector(struct flash_bank *bank, unsigned 
int sector)
        LOG_DEBUG("erasing sector %4u", sector);
 
        /* Poll the flash device for end of internally timed Sector Erase 
operation */
-       ret = poll_flash_status(bank, 0, SPIFLASH_BSY_BIT, TIMEOUT_FLASH_ERASE);
+       ret = poll_flash_status(bank, 0, SPIFLASH_BSY_BIT, 
TIMEOUT_FLASH_ERASE_SECTOR);
        if (ret != ERROR_OK)
                goto err;
 
@@ -836,6 +837,94 @@ err:
        return ret;
 }
 
+COMMAND_HANDLER(fsl_flexspi_handle_mass_erase_command)
+{
+       struct target *target = NULL;
+       struct flash_bank *bank;
+       struct fsl_flexspi_flash_bank *flexspi_info;
+       unsigned int sector;
+       uint8_t status;
+       long long starttime;
+       int ret;
+
+       LOG_DEBUG("%s", __func__);
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       ret = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+       if (ret != ERROR_OK)
+               goto err;
+
+       flexspi_info = bank->driver_priv;
+       target = bank->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               ret = ERROR_TARGET_NOT_HALTED;
+               goto err;
+       }
+
+       if (!(flexspi_info->probed)) {
+               LOG_ERROR("Flash bank not probed");
+               ret = ERROR_FLASH_BANK_NOT_PROBED;
+               goto err;
+       }
+
+       if (flexspi_info->dev.chip_erase_cmd == 0x00) {
+               LOG_ERROR("Mass erase not available for this device");
+               ret = ERROR_FLASH_OPER_UNSUPPORTED;
+               goto err;
+       }
+
+       for (sector = 0; sector < bank->num_sectors; sector++) {
+               if (bank->sectors[sector].is_protected) {
+                       LOG_ERROR("Flash sector %u protected", sector);
+                       ret = ERROR_FLASH_PROTECTED;
+                       goto err;
+               }
+       }
+
+       ret = write_enable(bank);
+       if (ret != ERROR_OK)
+               goto err;
+
+       starttime = timeval_ms();
+
+       ret = execute_ipcmd_read(bank, flexspi_info->dev.chip_erase_cmd, NULL, 
0);
+       if (ret != ERROR_OK)
+               goto err;
+
+       /*
+        * Check status register to see if the flash device appears to have
+        * accepted the command and is now executing it.  If BSY and WE are 
clear,
+        * we assume erase already completed.  If BSY is clear but WE is still 
set,
+        * the command wasn't accepted.
+        */
+       ret = read_status_reg(bank, &status);
+       if (ret != ERROR_OK)
+               goto err;
+
+       if (((status & SPIFLASH_BSY_BIT) == 0) && ((status & SPIFLASH_WE_BIT) 
!= 0)) {
+               LOG_ERROR("Chip erase command not accepted by flash. 
status=0x%02x", status);
+               ret = ERROR_FLASH_OPERATION_FAILED;
+               goto err;
+       }
+
+       LOG_INFO("Waiting for chip erase to finish");
+
+       ret = poll_flash_status(bank, 0, SPIFLASH_BSY_BIT, 
TIMEOUT_FLASH_ERASE_CHIP);
+       if (ret != ERROR_OK)
+               goto err;
+
+       LOG_INFO("Chip erase completed in %lldms", timeval_ms() - starttime);
+
+       return ERROR_OK;
+
+err:
+       return ret;
+}
+
 static int fsl_flexspi_erase(struct flash_bank *bank, unsigned int first,
                unsigned int last)
 {
@@ -1207,8 +1296,31 @@ 
FLASH_BANK_COMMAND_HANDLER(fsl_flexspi_flash_bank_command)
        return ERROR_OK;
 }
 
+static const struct command_registration fsl_flexspi_exec_command_handlers[] = 
{
+       {
+               .name = "mass_erase",
+               .handler = fsl_flexspi_handle_mass_erase_command,
+               .mode = COMMAND_EXEC,
+               .usage = "bank_id",
+               .help = "Mass erase entire flash device.",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration fsl_flexspi_command_handlers[] = {
+       {
+               .name = "fsl_flexspi",
+               .mode = COMMAND_ANY,
+               .help = "fsl_flexspi flash command group",
+               .usage = "",
+               .chain = fsl_flexspi_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
 struct flash_driver fsl_flexspi_flash = {
        .name = "fsl_flexspi",
+       .commands = fsl_flexspi_command_handlers,
        .flash_bank_command = fsl_flexspi_flash_bank_command,
        .erase = fsl_flexspi_erase,
        .protect = fsl_flexspi_protect,

-- 

Reply via email to