#define FLEXRAM 0x14000000
+#define MSCM_OCMDR0 0x40001400
#define FMC_PFB01CR 0x4001f004
#define FTFx_FSTAT 0x40020000
#define FTFx_FCNFG 0x40020001
#define KINETIS_SDID_SERIESID_MASK 0x00F00000
#define KINETIS_SDID_SERIESID_K 0x00000000
#define KINETIS_SDID_SERIESID_KL 0x00100000
+#define KINETIS_SDID_SERIESID_KE 0x00200000
#define KINETIS_SDID_SERIESID_KW 0x00500000
#define KINETIS_SDID_SERIESID_KV 0x00600000
#define KINETIS_SDID_SUBFAMID_KX4 0x04000000
#define KINETIS_SDID_SUBFAMID_KX5 0x05000000
#define KINETIS_SDID_SUBFAMID_KX6 0x06000000
+#define KINETIS_SDID_SUBFAMID_KX7 0x07000000
+#define KINETIS_SDID_SUBFAMID_KX8 0x08000000
#define KINETIS_SDID_FAMILYID_MASK 0xF0000000
#define KINETIS_SDID_FAMILYID_K0X 0x00000000
#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
+#define KINETIS_SDID_PROJECTID_KE1xF 0x00000080
+#define KINETIS_SDID_PROJECTID_KE1xZ 0x00000100
struct kinetis_flash_bank {
bool probed;
enum {
FS_PROGRAM_SECTOR = 1,
FS_PROGRAM_LONGWORD = 2,
- FS_PROGRAM_PHRASE = 4, /* Unsupported */
- FS_INVALIDATE_CACHE_K = 8,
- FS_INVALIDATE_CACHE_L = 0x10,
+ FS_PROGRAM_PHRASE = 4, /* Unsupported */
+ 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;
};
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)
{
}
if (fstat != 0x80) {
/* reset error flags */
- result = target_write_u8(target, FTFx_FSTAT, 0x70);
+ result = kinetis_ftfx_clear_error(target);
}
return result;
}
if (kinfo->flash_support & FS_INVALIDATE_CACHE_K)
target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0);
+ /* Set CINV_WAY bits - request invalidate of all cache ways */
+ /* FMC_PFB0CR has same address and CINV_WAY bits as FMC_PFB01CR */
else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L)
target_write_u8(bank->target, MCM_PLACR + 1, 0x04);
+ /* set bit CFCC - Clear Flash Controller Cache */
+
+ else if (kinfo->flash_support & FS_INVALIDATE_CACHE_MSCM)
+ target_write_u32(bank->target, MSCM_OCMDR0, 0x30);
+ /* disable data prefetch and flash speculate */
return;
}
/* 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:
}
break;
+ case KINETIS_SDID_SERIESID_KE:
+ /* KE1x-series */
+ switch (kinfo->sim_sdid &
+ (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK | KINETIS_SDID_PROJECTID_MASK)) {
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xZ:
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX5 | KINETIS_SDID_PROJECTID_KE1xZ:
+ /* KE1xZ: FTFE, 2kB sectors */
+ pflash_sector_size_bytes = 2<<10;
+ nvm_sector_size_bytes = 2<<10;
+ kinfo->max_flash_prog_size = 1<<9;
+ num_blocks = 2;
+ kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L;
+ break;
+
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xF:
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX6 | KINETIS_SDID_PROJECTID_KE1xF:
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX8 | KINETIS_SDID_PROJECTID_KE1xF:
+ /* KE1xF: FTFE, 4kB sectors */
+ pflash_sector_size_bytes = 4<<10;
+ nvm_sector_size_bytes = 2<<10;
+ kinfo->max_flash_prog_size = 1<<10;
+ num_blocks = 2;
+ kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM;
+ break;
+
+ default:
+ LOG_ERROR("Unsupported KE FAMILYID SUBFAMID");
+ }
+ break;
+
default:
LOG_ERROR("Unsupported K-series");
}
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) {
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;
}
}