flash Kinetis: add KL8x family, fix erase check
[fw/openocd] / src / flash / nor / kinetis.c
index 86d3154c56aaccce6dd10fd85287522af4f97825..08f011df4ce6c89ca279c043234d5c0a1cbad2da 100644 (file)
 #define KINETIS_SDID_FAMILYID_K6X   0x60000000
 #define KINETIS_SDID_FAMILYID_K7X   0x70000000
 #define KINETIS_SDID_FAMILYID_K8X   0x80000000
+#define KINETIS_SDID_FAMILYID_KL8X  0x90000000
 
 /* The field originally named DIEID has new name/meaning on KE1x */
 #define KINETIS_SDID_PROJECTID_MASK  KINETIS_SDID_DIEID_MASK
@@ -245,6 +246,7 @@ struct kinetis_flash_bank {
                FS_INVALIDATE_CACHE_K = 8,      /* using FMC->PFB0CR/PFB01CR */
                FS_INVALIDATE_CACHE_L = 0x10,   /* using MCM->PLACR */
                FS_INVALIDATE_CACHE_MSCM = 0x20,
+               FS_NO_CMD_BLOCKSTAT = 0x40,
        } flash_support;
 };
 
@@ -849,6 +851,12 @@ static int kinetis_ftfx_decode_error(uint8_t fstat)
        return ERROR_FLASH_OPERATION_FAILED;
 }
 
+static int kinetis_ftfx_clear_error(struct target *target)
+{
+       /* reset error flags */
+       return target_write_u8(target, FTFx_FSTAT, 0x70);
+}
+
 
 static int kinetis_ftfx_prepare(struct target *target)
 {
@@ -871,7 +879,7 @@ static int kinetis_ftfx_prepare(struct target *target)
        }
        if (fstat != 0x80) {
                /* reset error flags */
-               result = target_write_u8(target, FTFx_FSTAT, 0x70);
+               result = kinetis_ftfx_clear_error(target);
        }
        return result;
 }
@@ -1704,7 +1712,15 @@ static int kinetis_probe(struct flash_bank *bank)
                                /* K80FN256, K81FN256, K82FN256 */
                                pflash_sector_size_bytes = 4<<10;
                                num_blocks = 1;
-                               kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
+                               kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT;
+                               break;
+
+                       case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX1:
+                       case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX2:
+                               /* KL81Z128, KL82Z128 */
+                               pflash_sector_size_bytes = 2<<10;
+                               num_blocks = 1;
+                               kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT;
                                break;
 
                        default:
@@ -2094,23 +2110,26 @@ static int kinetis_blank_check(struct flash_bank *bank)
                return result;
 
        if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) {
-               bool block_dirty = false;
+               bool block_dirty = true;
+               bool use_block_cmd = !(kinfo->flash_support & FS_NO_CMD_BLOCKSTAT);
                uint8_t ftfx_fstat;
 
-               if (kinfo->flash_class == FC_FLEX_NVM) {
+               if (use_block_cmd && kinfo->flash_class == FC_FLEX_NVM) {
                        uint8_t fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f);
                        /* block operation cannot be used on FlexNVM when EEPROM backup partition is set */
                        if (fcfg1_depart != 0xf && fcfg1_depart != 0)
-                               block_dirty = true;
+                               use_block_cmd = false;
                }
 
-               if (!block_dirty) {
+               if (use_block_cmd) {
                        /* check if whole bank is blank */
                        result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, kinfo->prog_base,
                                                         0, 0, 0, 0,  0, 0, 0, 0, &ftfx_fstat);
 
-                       if (result != ERROR_OK || (ftfx_fstat & 0x01))
-                               block_dirty = true;
+                       if (result != ERROR_OK)
+                               kinetis_ftfx_clear_error(bank->target);
+                       else if ((ftfx_fstat & 0x01) == 0)
+                               block_dirty = false;
                }
 
                if (block_dirty) {
@@ -2126,6 +2145,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
                                        bank->sectors[i].is_erased = !(ftfx_fstat & 0x01);
                                } else {
                                        LOG_DEBUG("Ignoring errored PFlash sector blank-check");
+                                       kinetis_ftfx_clear_error(bank->target);
                                        bank->sectors[i].is_erased = -1;
                                }
                        }