#define FTFx_FCCOB3 0x40020004
#define FTFx_FPROT3 0x40020010
#define FTFx_FDPROT 0x40020017
-#define SIM_SDID 0x40048024
-#define SIM_SOPT1 0x40047000
-#define SIM_FCFG1 0x4004804c
-#define SIM_FCFG2 0x40048050
+#define SIM_BASE 0x40047000
+#define SIM_BASE_KL28 0x40074000
#define SIM_COPC 0x40048100
+ /* SIM_COPC does not exist on devices with changed SIM_BASE */
#define WDOG_BASE 0x40052000
#define WDOG32_KE1X 0x40052000
#define WDOG32_KL28 0x40076000
#define SMC_PMCTRL 0x4007E001
#define SMC_PMSTAT 0x4007E003
+#define SMC32_PMCTRL 0x4007E00C
+#define SMC32_PMSTAT 0x4007E014
#define MCM_PLACR 0xF000300C
/* Offsets */
+#define SIM_SOPT1_OFFSET 0x0000
+#define SIM_SDID_OFFSET 0x1024
+#define SIM_FCFG1_OFFSET 0x104c
+#define SIM_FCFG2_OFFSET 0x1050
+
#define WDOG_STCTRLH_OFFSET 0
#define WDOG32_CS_OFFSET 0
uint32_t dflash_size; /* accessible rest of FlexNVM if EEPROM backup uses part of FlexNVM */
uint32_t progr_accel_ram;
+ uint32_t sim_base;
enum {
FS_PROGRAM_SECTOR = 1,
KINETIS_WDOG32_KL28,
} watchdog_type;
+ enum {
+ KINETIS_SMC,
+ KINETIS_SMC32,
+ } sysmodectrlr_type;
+
char name[40];
unsigned num_banks;
return NULL;
}
+static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const char *argv[])
+{
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "-sim-base") == 0) {
+ if (i + 1 < argc)
+ k_chip->sim_base = strtoul(argv[++i], NULL, 0);
+ } else
+ LOG_ERROR("Unsupported flash bank option %s", argv[i]);
+ }
+ return ERROR_OK;
+}
+
FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
{
struct target *target = bank->target;
struct kinetis_chip *k_chip;
struct kinetis_flash_bank *k_bank;
+ int retval;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
}
k_chip->target = target;
+
+ /* only the first defined bank can define chip options */
+ retval = kinetis_chip_options(k_chip, CMD_ARGC - 6, CMD_ARGV + 6);
+ if (retval != ERROR_OK)
+ return retval;
}
if (k_chip->num_banks >= KINETIS_MAX_BANKS) {
}
-static int kinetis_check_run_mode(struct target *target)
+static int kinetis_read_pmstat(struct kinetis_chip *k_chip, uint8_t *pmstat)
+{
+ int result;
+ uint32_t stat32;
+ struct target *target = k_chip->target;
+
+ switch (k_chip->sysmodectrlr_type) {
+ case KINETIS_SMC:
+ result = target_read_u8(target, SMC_PMSTAT, pmstat);
+ return result;
+
+ case KINETIS_SMC32:
+ result = target_read_u32(target, SMC32_PMSTAT, &stat32);
+ if (result == ERROR_OK)
+ *pmstat = stat32 & 0xff;
+ return result;
+ }
+ return ERROR_FAIL;
+}
+
+static int kinetis_check_run_mode(struct kinetis_chip *k_chip)
{
int result, i;
- uint8_t pmctrl, pmstat;
+ uint8_t pmstat;
+ struct target *target;
+
+ if (k_chip == NULL) {
+ LOG_ERROR("Chip not probed.");
+ return ERROR_FAIL;
+ }
+ target = k_chip->target;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
- result = target_read_u8(target, SMC_PMSTAT, &pmstat);
+ result = kinetis_read_pmstat(k_chip, &pmstat);
if (result != ERROR_OK)
return result;
if (pmstat == PM_STAT_VLPR) {
/* It is safe to switch from VLPR to RUN mode without changing clock */
LOG_INFO("Switching from VLPR to RUN mode.");
- pmctrl = PM_CTRL_RUNM_RUN;
- result = target_write_u8(target, SMC_PMCTRL, pmctrl);
+
+ switch (k_chip->sysmodectrlr_type) {
+ case KINETIS_SMC:
+ result = target_write_u8(target, SMC_PMCTRL, PM_CTRL_RUNM_RUN);
+ break;
+
+ case KINETIS_SMC32:
+ result = target_write_u32(target, SMC32_PMCTRL, PM_CTRL_RUNM_RUN);
+ break;
+ }
if (result != ERROR_OK)
return result;
for (i = 100; i; i--) {
- result = target_read_u8(target, SMC_PMSTAT, &pmstat);
+ result = kinetis_read_pmstat(k_chip, &pmstat);
if (result != ERROR_OK)
return result;
{
int result, i;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
+ struct kinetis_chip *k_chip = k_bank->k_chip;
- result = kinetis_check_run_mode(bank->target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
bool set_fcf = false;
int sect = 0;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
+ struct kinetis_chip *k_chip = k_bank->k_chip;
- result = kinetis_check_run_mode(bank->target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
unsigned cpu_mhz = 120;
unsigned idx;
bool use_nvm_marking = false;
- char flash_marking[8], nvm_marking[2];
+ char flash_marking[11], nvm_marking[2];
char name[40];
k_chip->probed = false;
name[0] = '\0';
- result = target_read_u32(target, SIM_SDID, &k_chip->sim_sdid);
+ if (k_chip->sim_base)
+ result = target_read_u32(target, k_chip->sim_base + SIM_SDID_OFFSET, &k_chip->sim_sdid);
+ else {
+ result = target_read_u32(target, SIM_BASE + SIM_SDID_OFFSET, &k_chip->sim_sdid);
+ if (result == ERROR_OK)
+ k_chip->sim_base = SIM_BASE;
+ else {
+ result = target_read_u32(target, SIM_BASE_KL28 + SIM_SDID_OFFSET, &k_chip->sim_sdid);
+ if (result == ERROR_OK)
+ k_chip->sim_base = SIM_BASE_KL28;
+ }
+ }
if (result != ERROR_OK)
return result;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: {
/* MK24FN1M reports as K22, this should detect it (according to errata note 1N83J) */
uint32_t sopt1;
- result = target_read_u32(target, SIM_SOPT1, &sopt1);
+ result = target_read_u32(target, k_chip->sim_base + SIM_SOPT1_OFFSET, &sopt1);
if (result != ERROR_OK)
return result;
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX1: /* errata 7534 - should be K63 */
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX2: /* errata 7534 - should be K64 */
subfamid += 2; /* errata 7534 fix */
+ /* fallthrough */
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX3:
/* K63FN1M0 */
case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX4:
k_chip->watchdog_type = KINETIS_WDOG_COP;
cpu_mhz = 48;
- if (subfamid == 3 && (familyid == 1 || familyid == 2))
+ switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) {
+ case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX3:
+ case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX3:
subfamid = 7;
+ break;
+
+ case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX8:
+ cpu_mhz = 72;
+ k_chip->pflash_sector_size = 2<<10;
+ num_blocks = 2;
+ k_chip->watchdog_type = KINETIS_WDOG32_KL28;
+ k_chip->sysmodectrlr_type = KINETIS_SMC32;
+ break;
+ }
+
snprintf(name, sizeof(name), "MKL%u%uZ%%s%u",
familyid, subfamid, cpu_mhz / 10);
break;
+ case KINETIS_SDID_SERIESID_KW:
+ /* Newer KW-series (all KW series except KW2xD, KW01Z) */
+ cpu_mhz = 48;
+ switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) {
+ case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX0:
+ /* KW40Z */
+ case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0:
+ /* KW30Z */
+ case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX0:
+ /* KW20Z */
+ /* FTFA, 1kB sectors */
+ k_chip->pflash_sector_size = 1<<10;
+ k_chip->nvm_sector_size = 1<<10;
+ /* autodetect 1 or 2 blocks */
+ k_chip->flash_support = FS_PROGRAM_LONGWORD;
+ k_chip->cache_type = KINETIS_CACHE_L;
+ k_chip->watchdog_type = KINETIS_WDOG_COP;
+ break;
+ case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX1:
+ /* KW41Z */
+ case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX1:
+ /* KW31Z */
+ case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX1:
+ /* KW21Z */
+ /* FTFA, 2kB sectors */
+ k_chip->pflash_sector_size = 2<<10;
+ k_chip->nvm_sector_size = 2<<10;
+ /* autodetect 1 or 2 blocks */
+ k_chip->flash_support = FS_PROGRAM_LONGWORD;
+ k_chip->cache_type = KINETIS_CACHE_L;
+ k_chip->watchdog_type = KINETIS_WDOG_COP;
+ break;
+ default:
+ LOG_ERROR("Unsupported KW FAMILYID SUBFAMID");
+ }
+ snprintf(name, sizeof(name), "MKW%u%uZ%%s%u",
+ familyid, subfamid, cpu_mhz / 10);
+ break;
+
case KINETIS_SDID_SERIESID_KV:
/* KV-series */
k_chip->watchdog_type = KINETIS_WDOG_K;
return ERROR_FLASH_OPER_UNSUPPORTED;
}
- result = target_read_u32(target, SIM_FCFG1, &k_chip->sim_fcfg1);
+ result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &k_chip->sim_fcfg1);
if (result != ERROR_OK)
return result;
- result = target_read_u32(target, SIM_FCFG2, &k_chip->sim_fcfg2);
+ result = target_read_u32(target, k_chip->sim_base + SIM_FCFG2_OFFSET, &k_chip->sim_fcfg2);
if (result != ERROR_OK)
return result;
if (num_blocks == 0)
num_blocks = k_chip->fcfg2_maxaddr1_shifted ? 2 : 1;
- else if (k_chip->fcfg2_maxaddr1_shifted == 0 && num_blocks >= 2) {
+ else if (k_chip->fcfg2_maxaddr1_shifted == 0 && num_blocks >= 2 && fcfg2_pflsh) {
+ /* fcfg2_maxaddr1 may be zero due to partitioning whole NVM as EEPROM backup
+ * Do not adjust block count in this case! */
num_blocks = 1;
LOG_WARNING("MAXADDR1 is zero, number of flash banks adjusted to 1");
} else if (k_chip->fcfg2_maxaddr1_shifted != 0 && num_blocks == 1) {
case 0x06:
k_chip->dflash_size = k_chip->nvm_size - (4096 << fcfg1_depart);
break;
+ case 0x07:
case 0x08:
k_chip->dflash_size = 0;
break;
}
switch (fcfg1_pfsize) {
+ case 0x00:
+ k_chip->pflash_size = 8192;
+ break;
+ case 0x01:
case 0x03:
case 0x05:
case 0x07:
break;
case 0x0f:
/* a peculiar case: Freescale states different sizes for 0xf
+ * KL03P24M48SF0RM 32 KB .... duplicate of code 0x3
* K02P64M100SFARM 128 KB ... duplicate of code 0x7
* K22P121M120SF8RM 256 KB ... duplicate of code 0x9
* K22P121M120SF7RM 512 KB ... duplicate of code 0xb
/* Program section size is equal to sector size by default */
}
- k_chip->num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh);
- k_chip->num_nvm_blocks = num_blocks - k_chip->num_pflash_blocks;
+ if (fcfg2_pflsh) {
+ k_chip->num_pflash_blocks = num_blocks;
+ k_chip->num_nvm_blocks = 0;
+ } else {
+ k_chip->num_pflash_blocks = (num_blocks + 1) / 2;
+ k_chip->num_nvm_blocks = num_blocks - k_chip->num_pflash_blocks;
+ }
if (use_nvm_marking) {
nvm_marking[0] = k_chip->num_nvm_blocks ? 'X' : 'N';
* parts with more than 32K of PFlash. For parts with
* less the protection unit is set to 1024 bytes */
k_bank->protection_size = MAX(k_chip->pflash_size / 32, 1024);
- bank->num_prot_blocks = 32 / k_chip->num_pflash_blocks;
+ bank->num_prot_blocks = bank->size / k_bank->protection_size;
k_bank->protection_block = bank->num_prot_blocks * k_bank->bank_number;
size_k = bank->size / 1024;
int result;
/* suprisingly blank check does not work in VLPR and HSRUN modes */
- result = kinetis_check_run_mode(bank->target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
struct kinetis_chip *k_chip;
uint32_t sim_fcfg1;
+ k_chip = kinetis_get_chip(target);
+
if (CMD_ARGC >= 2) {
if (strcmp(CMD_ARGV[0], "dataflash") == 0)
sz_type = DF_SIZE;
}
switch (sz_type) {
case SHOW_INFO:
- result = target_read_u32(target, SIM_FCFG1, &sim_fcfg1);
+ if (k_chip == NULL) {
+ LOG_ERROR("Chip not probed.");
+ return ERROR_FAIL;
+ }
+ result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &sim_fcfg1);
if (result != ERROR_OK)
return result;
LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8,
flex_nvm_partition_code, ee_size_code);
- result = kinetis_check_run_mode(target);
+ result = kinetis_check_run_mode(k_chip);
if (result != ERROR_OK)
return result;
command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU.");
- k_chip = kinetis_get_chip(target);
if (k_chip) {
first_nvm_bank = k_chip->num_pflash_blocks;
num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks;